Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Quick Q - Can Jukebox Sounds be Triggered by Moving a Token?

It would be nice to have my tank units rattle tracks, hear armoured car noises, or infantry on foot make some kind of noise when a player grabs the icon to move it across the hexes. No big deal, if no, I'm trying to think of things I can do while waiting for the roll20 folks to fix the page copy feature. :) Thanks in advance, either way.  All the best to everyone. -- Tim
1608419985

Edited 1608420062
Oosh
Sheet Author
API Scripter
I don't think grabbing the unit itself is possible - but once it's been dropped it can definitely fire a script. I could be wrong on this, I've only ever played with "update on drop", maybe if that's turned off it constantly fires API events? Are all your tokens linked to character sheets? You could use a spare bar on the token to store the audio track name to play, or if they're all linked to character sheets, an Attribute or Ability could hold that instead (or the Bio/Notes section depending on what you do and don't use). Alternately, you could store all the information centrally in a control handout, with token names linked to their appropriate sounds there. This would probably work best, as you could easily change the sound for a bunch of units at once if you find a better effect. Do you use attack rolls in this game? A script could have events for: - token is moved => play movement sound - attack roll made in chat => play attack sound - unit reduced to 0 hp => play death sound Not sure what's appropriate to your game, though. On the point of the copy game thing - I thought you said you have a working API script for that? Is it no longer functional?
Oosh said: I don't think grabbing the unit itself is possible - but once it's been dropped it can definitely fire a script. I could be wrong on this, I've only ever played with "update on drop", maybe if that's turned off it constantly fires API events? Thanks, Oosh.  Well, I'm using the on change method for when lastmove changes, so that's pretty much the update on drop.  All the unit tokens are associated with different unit types which are characters. on("change:token:lastmove", function(obj, prev) { etc I'm experimenting in the D&D game I set up for my friends (one of them is the DM) and gearing towards my character Derp and to play a random South Park clip: I'm trying to use Roll20 Audio Master, but can't get the help to show and the commands I'm testing in the chat tab are giving me errors indicating commands that aren't shown in the list of commands shown in the script library when Roll220 Audio Master is installed.  I'll figure it our somehow. :) And no, the units in the Wargame Campaign are only moved.  "Firing" occurs on the table based on what units come together on the roll20 map: No, the copy game thing was actually the page copy.  I'd been using TrueCopy from the script library to copy the master map after battles (table top games like the above) to a new master map in order to keep track of what happened in turns. -- Tim
1608462887

Edited 1608463246
Oosh
Sheet Author
API Scripter
I had a bit of a play around - I've never used R20AM so I skipped that bit and just played the tracks directly (it's only a single .set() line of code, not really worth passing through to another script unless you need other features of it). There's a handout in the game with an audio link per line (audio track titles are case sensitive) to a character sheet name. If a token representing that character moves, the sound plays... very basic, not much in the way of error handling, and some cheap & nasty chat logging: on('ready', () => { const controlSheet = 'moveAudioControl'; // name of handout with audio links const clog = (txt) => { sendChat('moveAudioBot', txt, null, {noarchive: true}); } let controlArray; let conSheet = findObjs({type: 'handout', name: controlSheet}) if (conSheet.length > 0) controlArray = conSheet[0].get('notes', (notes) => { controlArray = notes.replace(/<\/p>/g,'|break|').replace(/<[^>]*>/g, '').split('|break|').filter((pair) => pair.search(/=/) !== -1); }); on('change:graphic', (g) => { if (g.get('subtype') !== 'token' || g.get('represents') === '') return clog(`${g.id} not a valid linked token.`); clog(`Token: ${g.get('name')} moved...`); let charId = g.get('represents'); let charName = getObj('character', charId).get('name'); let regexPair = new RegExp(`${charName}=(.+)`,'i'); let index = controlArray.findIndex((pair) => pair.search(regexPair) !== -1); if (index === -1) return clog(`No sound set up for ${charName}.`); let soundFile = controlArray[index].match(regexPair)[1]; let tracks = findObjs({type:'jukeboxtrack', title:soundFile}); if (tracks.length > 0) { tracks[0].set({playing:true,softstop:false}); clog(`now playing ${soundFile} for ${charName}'s movement.`); } else clog(`Couldn't find sound file: ${soundFile}`); }); }); And the handout just looks like this: Poor old Bob is walking around to the sound of arrows smacking into the back of his head :(
1608499300

Edited 1608527398
Oosh said: I had a bit of a play around - I've never used R20AM so I skipped that bit and just played the tracks directly (it's only a single .set() line of code, not really worth passing through to another script unless you need other features of it).&nbsp; Wow, that's very useful, thank you for taking the time to work with this. I could not get R20AM to work either (EDIT - because I had master volume in settings set to 0 DUH LOL), so I deleted the code.&nbsp; I am having difficulty getting the .set to work though. Here's a screen shot which includes the track Alcohol.&nbsp; If you're familiar with South Park, it's Mr MacKay saying, "Alcohol is bad". So what I wanted to do, first, before using your code above was just to get a script to run when my Derp character moves.&nbsp; I based the track code below on what you had shown me and realized that my favourite page,&nbsp; <a href="https://roll20.zendesk.com/hc/en-us/articles/360037772793-API-Objects" rel="nofollow">https://roll20.zendesk.com/hc/en-us/articles/360037772793-API-Objects</a> , does, in fact, have a jukebox object. Hurray.&nbsp;&nbsp; on("change:token:lastmove", function(obj, prev) { let charid = obj.get("represents"); if(charid !== null) { let char = getObj("character", charid); //Assigns character object associated with token let charname = char.get("name"); if (charname === "Derp") { sendChat("Derp?", "OMG It's Derp!!!!", null, {noarchive: true}); let track = findObjs({type:'jukeboxtrack', title:"Alcohol"}); track[0].set({playing:true,softstop:false}); } } }); Unfortunately, I can't get the track to run.&nbsp; The exclamation, OMG It's Derp!, pops up just fine in the chat text, but the track.set command throws an error: TypeError: Cannot read property 'set' of undefined Any idea what I'm missing or doing wrong? Thanks in advance,&nbsp; -- Tim
1608500392
Jordan C.
Pro
API Scripter
I may be wrong on this, but do you need to add the track to the game? If that screenshot is of the current state the track I think it is uploaded but not yet added. So I think it should look like this in the side bar to the right in order for the game to see it as an object:
Jordan C. said: I may be wrong on this, but do you need to add the track to the game? If that screenshot is of the current state the track I think it is uploaded but not yet added. So I think it should look like this in the side bar to the right in order for the game to see it as an object: Thank you, Jordan, let me try that.
Jordan, that did the trick.&nbsp; Even though I had the track in my Manage Audio , it was not assigned to the game.&nbsp; The screen shot below shows it playing when Derp, the character, is moved. So hurray, thank you. :)&nbsp;&nbsp; Just have to remember the master volume. Now I can work on the handout approach that Oosh provided. -- Tim
1608521497

Edited 1608521921
Oosh
Sheet Author
API Scripter
Nice one! I'd probably advise improving that format a little if you're going to use something similar - I didn't realise I wouldn't be able to use the newline \n as a split character when I started. Maybe put a comma at the end of each line (or semi-colon.... some punctuation that you won't use in your track names). The notes section puts a bunch of HTML tags in there which need to be sanitised, so using a \n new line as a place to split the entries isn't ideal.... that's why I had this line: controlArray = notes.replace(/&lt;\/p&gt;/g,'|break|').replace(/&lt;[^&gt;]*&gt;/g, '').split('|break|').filter((pair) =&gt; pair.search(/=/) !== -1); Having to turn the &lt;/p&gt; tags into an in-between stage to sanitize the rest of the string is a bit silly. If you use a comma, you can just sanitize &amp; split, and you can also spot any trailing whitespace in your track names, or leave them on the same line. So more like: alice=Door Creak, bob=Arrow Hit 1, zed=none and: controlArray = notes.replace(/&lt;[^&gt;]*&gt;/g,'').split(',').filter((pair) =&gt; pair.search(/=/) !-- -1);