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

Can TokenMod return the current side of a multisided token?

1615491538
CryptoCartographer
Pro
Marketplace Creator
I'm building some progress clocks, and I'd like to send the updated value to chat whenever I increment or decrement it. Is TokenMod able to return the index of the currently-displayed side? My reading of the documentation has not revealed the trick to me.
1615493227
David M.
Pro
API Scripter
Yep! From the help: SideNumber This is the index of the side to show for Multi-Sided tokens. Indicies start at 1. If you have a 6-sided token, it will have indicies 1, 2, 3, 4, 5 and 6. An empty index is considered to be 1. If a token doesn't have the index specified, it isn't changed. NOTICE:  This only works for images in the User Image library. If your token has images that are stored in the Marketplace Library, they will not be selectable with this command. You can download those images and upload them to your User Image Library to use them with this. Available SideNumber Properties: currentside Setting a token to index 2: !token-mod --set currentside|2 Not specifying an index will set the index to 1, the first image: !token-mod --set currentside| You can shift the image by some amount by using  +  or  -  followed by an optional number. Moving all tokens to the next image: !token-mod --set currentside|+ Moving all tokens back 2 images: !token-mod --set currentside|-2 By default, if you go off either end of the list of images, you will wrap back around to the opposite side. If this token is showing image 3 out of 4 and this command is run, it will be on image 2: !token-mod --set currentside|+3 If you preface the command with a  ? , the index will be bounded to the number of images and not wrap. In the same scenario, this would leave the above token at image 4: !token-mod --set currentside|?+3 In the same scenario, this would leave the above token at image 1: !token-mod --set currentside|?-30 If you want to choose a random image, you can use  * . This will choose one of the valid images at random (all equally weighted): !token-mod --set currentside|*
1615495778
The Aaron
Roll20 Production Team
API Scripter
David is pointing out how you can change it.  You can use the report feature to output the value: !token-mod --report all|"Current side is {currentside}" Report isn't well fleshed out with features yet. Here's the docs: Report Experimental   --report   provides feedback about the changes that were made to each token that a command affects. Arguments to the   --report   command are   |   separated pairs of Who to tell, and what to tell them, with the following format: !token-mod --report Who[:Who ...]|Message You can specify multiple different Who arguments by separating them with a   : . Be sure you have no spaces. Available options for Who player   will whisper the report to the player who issued the command. gm   will whisper the report to the gm. all   will send the report publicly to chat for everyone to see. token   will whisper to whomever controls the token. character   will whisper to whomever controls the character the token represents. control   will whisper to whomever can control the token from either the token or character controlledby list. This is equivalent to specifying   token:character . The Message must be enclosed in quotes if it has spaces in it. The Message can contain any of the properties of the of the token, enclosed in   { } , and they will be replaced with the final value of that property. Additionally, each property may have a modifier to select slightly different information: Available options for Property Modifiers before   -- Show the value of the property before a change was applied. change   -- Show the change that was applied to the property. (Only works on numeric fields, will result in 0 on things like name or imagsrc.) abschange   -- Show the absolute value of the change that was applied to the property. (Only works on numeric fields, will result in 0 on things like name or imagsrc.) Showing the amount of damage done to a token. !token-mod {{   --set     bar1_value|-[[2d6+8]]   --report     all|"{name} takes {bar1_value:abschange} points of damage." }} Showing everyone the results of the hit, but only the gm and the controlling players the actual damage and original hit point value. !token-mod {{   --set     bar1_value|-[[2d6+8]]   --report     all|"{name} takes a vicious wound leaving them at {bar1_value}hp out of {bar1_max}hp."     gm:control|"{name} damage: {bar1_value:change}hp, was at {bar1_value:before}hp" }}
1615498859
David M.
Pro
API Scripter
Derp. Misread post.
1615577986
CryptoCartographer
Pro
Marketplace Creator
Thank you! I was pretty confident it was possible. Not sure how I missed it in the documentation, but then I wasn't 100% certain what I was looking for.
1615588168
CryptoCartographer
Pro
Marketplace Creator
Aaron, thanks for your invaluable and generous contributions to the community. TokenMod more than any other feature of Roll20 has shown me what's possible here and kept me returning to bump up against the limits of my very rusty coding knowledge. You say report isn't well fleshed out yet. Is it possible to use the index value of the current side in calculations? My issue is this: I want to use the actual side number of the token as the true source of my indexing on my clocks. I'm sticking two values into my bars: currentside and numberofsides . Knowing these can get out of sync with the visible state of the token, I want to query the token each time I run the macro and affirm the currentside value. So far so good; I can get currentside into my chat log. But here's my issue: my tokens have a zero side graphic. And of course that uses up "side 1" and gives me an indexing offset of 1. To accurately reflect the current side that my users see , I need to subtract 1 from currentside when I dump the value to chat. This may be a limitation of my macro knowledge, but I've tried various means of extracting currentside , putting values into bars as a variable holder, and so far no joy.
1615590129
The Aaron
Roll20 Production Team
API Scripter
Yeah, that's really not possible with TokenMod.  That said, how about if a script updated the bar with the current side for you: !token-mod --set currentside|+1 !set-side-number-in-bar 2 Would set whatever the current side's index is into the bar2 value on the selected token(s).  Then you could reference it and do math on it all you like (and it would be up to date!). Code: on('ready',()=>{ const processInlinerollsNative = (msg) => { if(msg.hasOwnProperty('inlinerolls')){ return msg.inlinerolls .reduce((m,v,k) => { let ti=v.results.rolls.reduce((m2,v2) => { if(v2.hasOwnProperty('table')){ m2.push(v2.results.reduce((m3,v3) => [...m3,v3.tableItem.name],[]).join(", ")); } return m2; },[]).join(', '); return [...m,{k:`$[[${k}]]`, v:(ti.length && ti) || v.results.total || 0}]; },[]) .reduce((m,o) => m.replace(o.k,o.v), msg.content); } else { return msg.content; } }; const showHelp = (who,errorMsg) => { sendChat('',`/w "${who}" <div><b>Usage:</b> <code>!set-side-number-in-bar NUM</code> Where <code>NUM</code> is 1, 2, or 3 (or the result of an inline roll or attribute reference). The current side number will be written to that bar.</div>${errorMsg ? `<div><b>ERROR:</b> ${errorMsg}</div>`:''}`); }; on('chat:message',msg=>{ if('api'===msg.type && /^!set-side-number-in-bar(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){ let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); let args = processInlinerollsNative(msg).split(/\s+/).slice(1); if(0 === args.length) { showHelp(who); return; } let bar = parseInt(args[0]); if([1,2,3].includes(bar)){ (msg.selected || []) .map(o=>getObj('graphic',o._id)) .filter(g=>undefined !== g) .forEach(g=>g.set(`bar${bar}_value`,g.get('currentSide'))) ; } else { showHelp(who,`Invalid bar number: <code>${args[0]}</code> (<code>${bar}</code>)`); return; } } }); });
1615606683
CryptoCartographer
Pro
Marketplace Creator
Works great. Thanks so much for your help!
1615609568
CryptoCartographer
Pro
Marketplace Creator
While you're thinking about it, is there a similar method to get the total number of a token's assigned sides?
1615644008
The Aaron
Roll20 Production Team
API Scripter
I could certainly add that, do you want it in the max field of the same bar?
1615646318
CryptoCartographer
Pro
Marketplace Creator
I don't want bars to appear for this application, even if the token happens to be configured to show them. (The token itself is a graph of completion %) I've been manually entering the number of sides into the Bar 3 for each token, but this would make doing that unnecessary. So Bar 3, please. And thanks so much for your help!
1615675894
The Aaron
Roll20 Production Team
API Scripter
No problem!  I added a second argument and changed the argument parsing to take the numbers 1,2, or 3, optionally followed by an m or M to designate the max attribute.  That should let you put them pretty much anywhere you like.  The help: Usage:   !set-side-number-in-bar CurrentSideBar NumSidesBar  Where  CurrentSideBar  and  CurrentSideBar  are one of the numbers  1 ,  2 , or  3  (or the result of an inline roll or attribute reference) optionally followed by n  m  or  M  to indicate the max part of the bar. The current side number will be written to the bar indicated in the first argument, the number of sides will be written to the bar in the second argument. For example, to write the current sides to bar 2 and the number of sides to bar2 max you would call  !set-side-number-in-bar 2 2m So you'll probably want to call: !set-side-number-in-bar 2 3 Code: on('ready',()=>{ const processInlinerollsNative = (msg) => { if(msg.hasOwnProperty('inlinerolls')){ return msg.inlinerolls .reduce((m,v,k) => { let ti=v.results.rolls.reduce((m2,v2) => { if(v2.hasOwnProperty('table')){ m2.push(v2.results.reduce((m3,v3) => [...m3,v3.tableItem.name],[]).join(", ")); } return m2; },[]).join(', '); return [...m,{k:`$[[${k}]]`, v:(ti.length && ti) || v.results.total || 0}]; },[]) .reduce((m,o) => m.replace(o.k,o.v), msg.content); } else { return msg.content; } }; const showHelp = (who,errorMsg) => { sendChat('',`/w "${who}" <div><b>Usage:</b> <code>!set-side-number-in-bar CurrentSideBar NumSidesBar</code> Where <code>CurrentSideBar</code> and <code>CurrentSideBar</code> are one of the numbers <code>1</code>, <code>2</code>, or <code>3</code> (or the result of an inline roll or attribute reference) optionally followed by n <code>m</code> or <code>M</code> to indicate the max part of the bar. The current side number will be written to the bar indicated in the first argument, the number of sides will be written to the bar in the second argument. For example, to write the current sides to bar 2 and the number of sides to bar2 max you would call <code>!set-side-number-in-bar 2 2m</code></div>${errorMsg ? `<div><b>ERROR:</b> ${errorMsg}</div>`:''}`); }; const barArgRegex = /^\s*(?<bar>[123])(?<isMax>[mM])?\s*$/; on('chat:message',msg=>{ if('api'===msg.type && /^!set-side-number-in-bar(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){ let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); let args = processInlinerollsNative(msg).split(/\s+/).slice(1); if(args.length < 2) { showHelp(who); return; } let currSide = `${args[0]}`.match(barArgRegex); let numSides = `${args[1]}`.match(barArgRegex); if(currSide && numSides){ (msg.selected || []) .map(o=>getObj('graphic',o._id)) .filter(g=>undefined !== g) .forEach(g=>g.set({ [`bar${currSide[1]}_${currSide[2] ? 'max' : 'value'}`]: g.get('currentSide'), [`bar${numSides[1]}_${numSides[2] ? 'max' : 'value'}`]: decodeURIComponent(g.get('sides')).split(/\|/).length })); } else { showHelp(who,`Invalid argument: ${!currSide ? `CurrentSideBar: <code>${args[0]}</code>` : ''} ${!numSides ? `NumSidesBar: <code>${args[1]}</code>` : ''}`); return; } } }); });
1615693709
CryptoCartographer
Pro
Marketplace Creator
So flexible! Thanks again for your generous attention to this little problem of mine.
1615693864
The Aaron
Roll20 Production Team
API Scripter
No problem!
Hey Aaron, just wanted to clarify something in one of your responses to Jay. Just before you suggested the secondary script, you said "Yeah, that's really not possible with TokenMod." Were you directly answering Jay's question of "Is it possible to use the index value of the current side in calculations?" or were you only indicating that the  report  feature couldn't give the result Jay was looking for? I ask because I have my own ridiculous use case that would be easy to implement if TokenMod does, in fact, handle using the index value of one or more tokens as parameters passed to it. The documentation leads me to believe it's not possible, but I wanted to double-check.
1616889004
The Aaron
Roll20 Production Team
API Scripter
I was referring to using the current side number as part of a calculation, I believe.  What's your wacky use case that you want to do?
I think I'm trying to do the opposite of what Jay was doing.  I want to update the value in a token's bar, and have the token's current side change based off of that.  I thought it would be as easy as: !token-mod --set currentside|bar2_value But I can't seem to get it to parse such that it accepts this command.  I feel like I must be missing something obvious, but I can't for the life of me figure out what it is.  Is this possible via Tokenmod, or with light adjustment?  (I am very new to API scripting, and js in general, apologies)
1616949936

Edited 1616960948
So I managed to figure out my use case, but I'll post my process/results here in case it helps someone (might even help with Gideon's case). I was trying to make a puzzle for my players where they have to match harmonic oscillations by adjusting the amplitude and frequency of two sine waves I'm displaying for them. Each sine wave was a rollable table with 100 values, effectively a 10x10 array flattened to 1x100. There are two dials per sine wave: one for adjusting amplitude and one for adjusting frequency. Each dial is, itself, a rollable table with 10 sides. With that setup, here's what I did: Each dial had a character sheet assigned to it. I named them Red Sine Dial 1, Red Sine Dial 2, Blue Sine Dial 1, and Blue Sine Dial 2. I linked Bar1 to the level attribute in the character sheet. I added the script you designed for Jay that would let one store a side number in a bar value. (In my particular case, I adjusted the script to add 1 to the face value when saving it since I didn't want to use 0 indices for this. You'll see why in a moment.) I gave each dial an ability that looks like the following: !token-mod --set currentside|+ !set-side-number-in-bar 1 !token-mod --set currentside|[[@{Red Sine Dial 1|level}+(10*@{Red Sine Dial 2|level})]] --ids -MWoGy_VrueB1zNL9ZEe This let my players select which dial they want to adjust and use the appropriate ability. That adjusts the dial face, saves it to the bar (and, by extension, to the level attribute for that dial). It then changes the face of the respective sine wave (determined by using its token_id) using the level values of both  dials (worth noting I had to make sure I set that value on both dials before running this). The simple math formula in there is to change to the correct (amplitude, frequency) pair since I had flattened the array. There's 10 values for amplitude and 10 for frequency. I really wanted more values than that but getting 200 total sine wave images set up in 2 different 100-value multisided tables was painful enough. I'll be adding a tiny bit of complexity by letting them move the sine waves up and down, like they're adjusting the y-intercept. So Gideon, there might be an easier way to do what you're looking to do, but it's definitely possible to use the bar value if it's linked to a character sheet attribute and referenced with the @{} syntax. It might be possible to do so without using a character sheet for the token, but if so, I didn't find a way. EDIT:  My actual implementation seems to be... unreliable. Sometimes it works right, sometimes it does the wrong operation. For instance, if I dial amplitude down, then up, it'll evaluate as two instances of down. Not sure why. It doesn't always  do that, but I can't see a reason why it does that at all. EDIT 2:  If I had to hazard a guess, I'd say it's because "attribute references are expanded in all lines before any lines are executed" as Aaron put in another post .
1616962753
The Aaron
Roll20 Production Team
API Scripter
Gideon J. said: I think I'm trying to do the opposite of what Jay was doing.  I want to update the value in a token's bar, and have the token's current side change based off of that.  I thought it would be as easy as: !token-mod --set currentside|bar2_value But I can't seem to get it to parse such that it accepts this command.  I feel like I must be missing something obvious, but I can't for the life of me figure out what it is.  Is this possible via Tokenmod, or with light adjustment?  (I am very new to API scripting, and js in general, apologies) If you're only dealing with one token, you can do: !token-mod --set currentside|@{selected|bar2}
The Aaron said: If you're only dealing with one token, you can do: !token-mod --set currentside|@{selected|bar2} I don't know why bar2_value didn't work, but hooray, this works!  Thanks (For the last long while that I was degubbing and running my head agasint a way, I apparently had the API sandbox turned off, so I thought I had tried this but, aha, you get it...) I have another question, if I may.  I'm trying to create a token action called "scan target", which would essentially let the player select a token that looks like a button, and then press that button.  Once that happens, much like the interface where you append an image face from a specific target, the player would click on a token, and it would reveal the 3 bars, and nameplate of the token. I can get the reveal to work when the token in question is selected with the following code: !token-mod --set {{ showname|yes showplayers_name|yes showplayers_bar1|true showplayers_bar2|true showplayers_bar3|true }} What I can't quite figure out is how the @{target|} syntax works with this to make it so the player can click on another token (whether they control it or not) to make this work.
Gideon J. said: I have another question, if I may.  I'm trying to create a token action called "scan target", which would essentially let the player select a token that looks like a button, and then press that button.  Once that happens, much like the interface where you append an image face from a specific target, the player would click on a token, and it would reveal the 3 bars, and nameplate of the token. I can get the reveal to work when the token in question is selected with the following code: !token-mod --set {{ showname|yes showplayers_name|yes showplayers_bar1|true showplayers_bar2|true showplayers_bar3|true }} What I can't quite figure out is how the @{target|} syntax works with this to make it so the player can click on another token (whether they control it or not) to make this work. If I'm understanding you correctly, I think you want to add this line to your macro: --ids @{target|token_id}