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 .
×
Advertisement Create a free account

[Script Update] TokenMod -- An interface to adjusting properties of a token from a macro or the chat area.

1486190424
Awesome!
1486531050
The Aaron
Forum Champion
API Scripter
Update v0.8.24 -- Added the ability to set the defaulttoken on a character. You must set the represents of the token to a character before using defaulttoken, but it works just as you'd expected: !token-mod --set defaulttoken You can of course chain this with other set commands: !token-mod {{ --set represents|@{bob|character_id} bar1_link|hp bar2_link|speed bar3_link|ac controlledby|tom|sally|nancy statusmarkers|blue:3|red:[[1d6]] defaulttoken }} Be sure to set the default token after all the settings you want preserved. For example, if you set bar3_link after, it won't be set when you drag the token out later. (Thanks Jakob!)
1486545615

Edited 1486547451
Jakob
Sheet Author
API Scripter
Huh, finally :).
1486561187
The Aaron
Forum Champion
API Scripter
Tell me about it!  =D  Nice not to be in a constant state of moving or the like. =D  Maybe I can finally get some things done.
1486770816

Edited 1486771097
Awesome update, Aaron! This has made my setup process so much easier. One weird little quirky is bothering me though - when you link to the 5E OGL sheet's speed using something like: --set bar1_link|npcd_speed, it brings in the entire string of "30 feet." instead of just "30". Manually linking strips off the "feet." part. Is that possible to do via TokenMod? And while I'm begging, is there any way to add support for TokenNameNumber? :) Not sure if its possible to edit the name of the token via the API, but it would be great to automagically turn something like "Ogre" into "Ogre %%NUMBERED%%" Edit: derp, just saw this . never mind the second part :)
1486775878
The Aaron
Forum Champion
API Scripter
For the 30, you could put it in an inline roll. 
1486787392
The Aaron
Forum Champion
API Scripter
Update v0.8.25 -- Fixed bug with defaulttoken where it didn't set correctly on the character. (Thanks Mike B. )
1486787574
The Aaron
Forum Champion
API Scripter
The Aaron said: For the 30, you could put it in an inline roll.  Just reread what you said.  With linking, you're at the mercy of what the attribute has in it.  You could set the value with an inline roll: !token-mod --set bar3_value|[[@{selected|npcd_speed]]
Gotcha - that makes sense. Thanks Aaron!
1489016959

Edited 1489017035
Aaron, Sorry if I missed it before, but is there any way for the players to use this to mark NPCs they don't control? Im looking for a good way to make a Hunter's Mark macro for 5e, something simple like adding the red dot status icon. I tried your old Mark script, but problem with that is it lays the image on top of the NPC token, and doesn't follow the NPC when moved.
1489017786

Edited 1489017817
The Aaron
Forum Champion
API Scripter
Definitely!  You need to turn on the "Players can IDs" setting in the config: !token-mod --help Then they can use: !token-mod --set statusmarkers|!archery-target --ids @{target|token_id} To toggle it on and off. 
I gotta quit taking breaks from roll20... I totally forgot about the --ids @{target|token_id} ability. Thanks man!
1489025277
The Aaron
Forum Champion
API Scripter
No problem!  Happy Rolling!
1489089464

Edited 1489089855
Hey trying to figure this out. So I have specific characters that I want to have affected by a macro. Like a single press. Specifically I'm trying to figure out if there's a way to modify tokens via character name as opposed to token id. Sort of a @{"Character Name 1"|token_id} type of thing This is the macro I have right now. It affects the Lowlight and Darkvision of particular characters. I have one that also turns it off. This toggle is needed since I'm doing a face-to-face game and Roll20 has weird problems with Sight multipliers and multiple tokens controlled by the same player. !token-mod {{ --ignore-selected  --ids -KekZFFMOlXE_D4E68VF --set light_radius|60 }} !token-mod {{ --ignore-selected --ids -KekZFFMOlXE_D4E68VF -KekmGhKlBiwbqJoJoZ5 --set light_multiplier|2 }} This is the macro I want... but maybe this is already possible. But when I try it I just get an error saying "No character was found for 'Character Name 1'". All player tokens are controlled by the same Player account (since it is face to face) and the "Represents" setting is correctly set. !token-mod {{ --ignore-selected  --ids @{"Character Name 1"|token_id} --set light_radius|60 }} !token-mod {{ --ignore-selected --ids @{"Character Name 1"|token_id} @{"Character Name 2"|token_id} --set light_multiplier|2 }} Am I just doing this wrong? Or does such functionality need to be added? I know you already have a way to pull token_ids via character names... Just can't figure out how to do this here. Since I'd rather not manually change the token_ids all the time, if I have to use targeting then I will... but I'd rather be able to do it by name.
1489113593

Edited 1489119830
The Aaron
Forum Champion
API Scripter
Since many tokens can all refer to the same character (one per map often for player characters, many per page for monsters), there is no attribute of token_id on characters.  You'd want to leave the "" off anyway when referring to the character's attributes in general. So, there isn't a way to do this right now.... However, if you change the if check on line 1621 to this:                 if(ids.length){                     _.chain(ids)                     .uniq()                     .map(function(t){                         return {                             id: t,                             token: getObj('graphic',t),                             character: getObj('character',t)                         };                     })                     .reduce(function(m,o){                         if(o.token){                             m.push(o.token.id);                         } else if(o.character){                             m=_.union(m,findObjs({type:'graphic',represents:o.character.id}));                         }                         return m;                     },[])                     .reject(_.isUndefined)                     .each(function(t) {                         applyModListToToken(modlist,t);                     });                 } Then you should be able to do: !token-mod {{ --ignore-selected  --ids @{Character Name 1|character_id} --set light_radius|60 }} !token-mod {{ --ignore-selected --ids @{Character Name 1|character_id} @{Character Name 2|character_id} --set light_multiplier|2 }} and it will find all tokens representing the specified character_id and adjust them on every map in one go.
1489113679
The Aaron
Forum Champion
API Scripter
Note: I've not tested this code yet...
I'll give it a shot, and modifying it on multiple maps is no problem for me. Thanks!
1489118247

Edited 1489119669
So far so good! Works perfectly as far as I can tell. EDIT: Well now it doesn't work when I don't have --ignore-selected in a macro. So it basically doesn't work for the regular functions. I get an error in the API (EDIT2: Redid the error with other scripts disabled. Macro used to reproduce error was !token-mod --flip light_hassight while selecting a token) ReferenceError: t is not defined ReferenceError: t is not defined at apiscript.js:1633:36 at iterator (/home/node/d20-api-server/node_modules/underscore/underscore.js:184:16) at Function.<anonymous> (/home/node/d20-api-server/node_modules/underscore/underscore.js:199:14) at _.(anonymous function) [as reduce] (/home/node/d20-api-server/node_modules/underscore/underscore.js:1496:34) at handleInput (apiscript.js:1631:22) at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:146:34), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:146:34), <anonymous>:70:8) at /home/node/d20-api-server/api.js:1510:12 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
1489119867
The Aaron
Forum Champion
API Scripter
Whoops!  Fixed.  Changed: m.push(t); to m.push(o.token.id);
1489120539

Edited 1489120717
The Aaron said: Whoops!  Fixed.  Changed: m.push(t); to m.push(o.token.id); fixed that for ya m.push(o.token); Got a really odd error when I used !token-mod --flip light_hassight TypeError: token.get is not a function TypeError: token.get is not a function     at applyModListToToken (apiscript.js:1277:36)     at apiscript.js:1641:8     at Function._.each._.forEach (/home/node/d20-api-server/node_modules/underscore/underscore.js:153:9)     at _.(anonymous function) [as each] (/home/node/d20-api-server/node_modules/underscore/underscore.js:1496:34)     at handleInput (apiscript.js:1640:8)     at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:146:34), <anonymous>:65:16)     at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:146:34), <anonymous>:70:8)     at /home/node/d20-api-server/api.js:1510:12     at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560     at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) But changing it to what I mentioned above fixes the problem If only Roll20 fixed the problem with sight multipliers being shared by ALL tokens that a player has control of when only 1 token has it.
1489120948
The Aaron
Forum Champion
API Scripter
Ah, there you go!  Thanks, I'll update my code... I shouldn't try to write code while fighting Strahd!  =D
I am trying to get this to work, but it seems it does not: !token-mod {{ --set bar3_link|spell_save_dc }} Could you add "spell_save_dc" or should it work already? Working fine with hp/ac etc.
1489247463
The Aaron
Forum Champion
API Scripter
Is the token already representing a character?  check if @{selected|spell_save_dc} gives you a reference error in the chat. Also, it's entirely possible the API won't be able to link an attribute that refers to a defaulted attribute which doesn't actually have an Attribute Object created.  If that's the case, I might be able to get it to work by setting the name instead of the id.  Let me know if it still doesn't work with the token representing the character and I'll see what I can do.
1489249269
The Aaron
Forum Champion
API Scripter
Update v0.8.26 -- Added the ability to specify character IDs to --ids and affect all tokens representing that character. (Thanks Hacchinya ) -- Added logic to link a bar to a sheet attribute if an actually Attribute Object doesn't exist. This has one quirk in that it won't set the values of the bars until something happens to cause Roll20 to review the token. Setting the token as a Default Token and dragging it back out causes this to happen, as does updating something that the set attr uses in a calculation (dexterity when it's a part of the initiative_bonus formula for example). You can also set the initial value with --bar1_value|@{selected|attribute} if you're only doing a single character. (Thanks Arno )
Thanks for the superfast response Aaron! The token is repping a character, I get this as output from @{selected|spell_save_dc}: ((floor((10-10)/2))+(8+(ceil((1)/1e10) + ceil((1)/4))+0)) That's also the content it now tries to put into the bar3. Total macro for completeness: !token-mod {{ --on showname light_hassight showplayers_name showplayers_bar1 showplayers_bar2 showplayers_bar3 showplayers_aura1 showplayers_aura2 --set represents|"?{Character Name}" bar2_link|ac bar1_link|hp bar3_value|@{selected|spell_save_dc} light_radius|5 light_dimradius|=-5 }}
1489262262
The Aaron
Forum Champion
API Scripter
The latest version should work for you, it will set it as a sheetattr_, which will allow it to be auto calculated.  If it doesn't work, I can take another look.  You'll have to manually install v0.8.26 until it gets rolled into the repo on Tuesday or the following tuesday.
Yep got it :) "-=> TokenMod v0.8.26 <=- [Sat Mar 11 2017 16:10:51 GMT+0000 (UTC)]" The output from the macro is as expected right? Otherwise ye, not working yet...thanks for your effort so far!
1489263428
The Aaron
Forum Champion
API Scripter
hmm.. wanna pm me an invite to your game and GM me?
1489332557

Edited 1489332830
For anyone keeping track, the work-around right now is to use: !token-mod {{ --on showname light_hassight showplayers_name showplayers_bar1 showplayers_bar2 showplayers_bar3 showplayers_aura1 showplayers_aura2 --set represents|?{Character Name} bar2_link|ac bar1_link|hp bar3_link|spell_save_dc light_radius|5 light_dimradius|=-5 defaulttoken }} After running this, the token needs be re-dragged out of the journal for the tokens to update.
1489434744

Edited 1489434754
Hey there all! I've got a question, is there a way to limit the bar1_value to not go below 0? Use case if that doesn't make sense: Select all tokens on the page (inevitably, they will sometimes represent different characters with different hp's (aka different bar1_max)) Do damage to all (!token-mod --set bar1_value|-?{How much damage|0}) In this case, tokens with less max hp than others will have negative balance bars (sometimes being comically large and filling half the screen xD ) So, yeah. Anyway to make it so that the bar1_value never goes below 0?
1489435216

Edited 1489435332
Really small api script to keep Bar1 at or above zero, but no higher than the max. on("change:token", function (obj) { if (obj.get("subtype") != "token" || obj.get("isdrawing") == "true") return; if (parseInt(obj.get("bar1_value")) < 0 && parseInt(obj.get("bar1_max")) > 0) obj.set("bar1_value", 0); if (parseInt(obj.get("bar1_value")) > parseInt(obj.get("bar1_max"))) obj.set("bar1_value", parseInt(obj.get("bar1_max"))); });
SkyCaptainXIII said: Really small api script to keep Bar1 at or above zero, but no higher than the max. Thanks for making this! Do I make a new script and put that code in there or do I put this in TokenMod somewhere with a manual install? If the first answer (completely new script), then it isn't working.  : /
1489445041
Oh... ah, that won't trigger off other script changes such as with token mod. There may be an option in token mod to achieve the same thing, not sure. I don't use it myself.
1489456840

Edited 1489456851
The Aaron
Forum Champion
API Scripter
You could actually modify HB's code to get a notification from TokenMod and enforce that constraint: on('ready',function(){ "use strict"; var constrainBar1ToMax = function (obj) { if (obj.get("subtype") != "token" || obj.get("isdrawing") == "true") return; if (parseInt(obj.get("bar1_value")) < 0 && parseInt(obj.get("bar1_max")) > 0) obj.set("bar1_value", 0); if (parseInt(obj.get("bar1_value")) > parseInt(obj.get("bar1_max"))) obj.set("bar1_value", parseInt(obj.get("bar1_max"))); }; on("change:token", constrainBar1ToMax); if('undefined' !== typeof TokenMod && TokenMod.ObserveTokenChange){ TokenMod.ObserveTokenChange(constrainBar1ToMax); } });
The Aaron said: You could actually modify HB's code to get a notification from TokenMod and enforce that constraint: That did it Aaron!  Thanks a lot man!
1489496735
The Aaron
Forum Champion
API Scripter
cool. =D
For the macro above, I am now trying to get Passive perception instead of spell save DC...not sure how that would work though, and not sure how to find out. bar3_link|spell_save_dc --> bar3_link|passive_perception ? Right now I can't even seem to find the list where I got "spell_save_dc" from in the first place.
1489762519
The Aaron
Forum Champion
API Scripter
It depends on what character sheet you're using.  If you find the number on a character sheet and right click, inspect it (in chrome), you can look for a name like 'attr_passive_perception' or the like.  It's that, without the 'attr_'.
The Aaron said: It depends on what character sheet you're using.  If you find the number on a character sheet and right click, inspect it (in chrome), you can look for a name like 'attr_passive_perception' or the like.  It's that, without the 'attr_'. Ah great, thanks for teaching me how to fish, that works :) (n.b. it's passive_wisdom)
1489841791
The Aaron
Forum Champion
API Scripter
No worries. =D 
1490425767

Edited 1490438136
I am trying to use TokenMod for a single damage macro, using the 5e Shaped sheet. @{target|bar1_max} does not work, but that's what Chrome's inspect tells me on the max HP box in the token config panel. Any ideas how to get the character's max health?
1490445608
The Aaron
Forum Champion
API Scripter
This is a quirk of the way character sheet attributes work. Anywhere you see an attribute ending in "_max" on a character sheet, you translate that to "|max" for an attribute reference in chat. Further, with @{target}, you must specify a label to make it work, so your final reference will be: @{target|choose a target|bar1|max} You can replace "choose a target" with whatever you like, that's the label, what gets shown on the query. Any where you use the same label it will only prompt you once, so you could do: @{target|choose a target|character_name} has @{target|choose a target|bar1}/@{target|choose a target|bar1|max} hp. and it would only ask you which token once. 
The Aaron said: This is a quirk of the way character sheet attributes work. Anywhere you see an attribute ending in "_max" on a character sheet, you translate that to "|max" for an attribute reference in chat. Further, with @{target}, you must specify a label to make it work, so your final reference will be: @{target|choose a target|bar1|max} You can replace "choose a target" with whatever you like, that's the label, what gets shown on the query. Any where you use the same label it will only prompt you once, so you could do: @{target|choose a target|character_name} has @{target|choose a target|bar1}/@{target|choose a target|bar1|max} hp. and it would only ask you which token once.  Ah that's it, thanks! If it's useful for anyone else, here's two easy macro's for single-target damage/healing, compatible with HealColors and safe from negative health and over-max-HP-health: Healing !token-mod {{ --set bar1_value|[[ { [[ @{target|target|bar1} + ?{Heal} ]], @{target|target|bar1|max}}dh1 ]] --ids @{target|token_id} }} Damage !token-mod {{ --set bar1_value|[[ { [[ @{target|HP} - ?{Damage} ]], 0}kh1 ]] --ids @{target|token_id} }}
1491219214
The Aaron
Forum Champion
API Scripter
Update v0.8.28 -- Added support for multiply (*) and divide (/) relative change options. Now you can do something like this: !token-mod --set height|*2 width|*2 To double the size of your token, or this: !token-mod --set height|/2 width|/2 To shrink it back down again. Update v0.8.27 -- Fixed method for getting the display name of the current player so it won't crash when other api scripts execute API commands with sendChat() (Thanks Sky ).
1491230448
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
My duergar applaud this feature.
Currently with v0.8.27: !token-mod --help gives me: For reference, the error message generated was: ReferenceError: msg is not defined ReferenceError: msg is not defined     at showHelp (apiscript.js:5721:28)     at handleInput (apiscript.js:7016:8)     at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:65:16)     at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:70:8)     at /home/node/d20-api-server/api.js:1510:12     at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560     at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)     at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546)     at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489)     at Zd.Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425)
1491237561
The Aaron
Forum Champion
API Scripter
Thanks Arno!  That should be fixed now, v0.8.29
1491237944
The Aaron
Forum Champion
API Scripter
Update v0.8.29 -- Fixed bug in who determination in showHelp(). (Thanks Arno )
1491529166
The Aaron
Forum Champion
API Scripter
Update v0.8.30 -- Fixed bug in who determination in showHelp(). (Thanks BGB)
v0.8.31; 5e OGL Sheet (Storm King's Thunder adventure loaded) The Command (per the instructions) !token-mod --set aura1_radius| Produces the following error and crashes the Sandbox TypeError: Cannot read property 'match' of undefined TypeError: Cannot read property 'match' of undefined at parseArguments (apiscript.js:1020:35) at Function._.map._.collect (/home/node/d20-api-server/node_modules/underscore/underscore.js:172:24) at _.(anonymous function) [as map] (/home/node/d20-api-server/node_modules/underscore/underscore.js:1496:34) at parseSetArguments (apiscript.js:1212:5) at handleInput (apiscript.js:1599:20) at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:146:1), <anonymous>:70:8) at /home/node/d20-api-server/api.js:1510:12 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) I can't tell from the instructions if it's been updated with differing commands or not from when it worked before so if I'm using it incorrectly let me know. After some testing (I'm NOT a programmer/coder/etc.) I finally found that the following works as it originally was: !token-mod --set aura1_radius|0 Secondary Slightly Related Effect - From what little I understand, I had thought that the token aura values would need to be blank for the aura to be completely removed.  The API does remove the auras but the method I discovered above opens up a new (almost invisible but manually fixable) problem if I'm not careful.  Upon further testing, if I use !token-mod --set aura1_radius|0 , then open the token properties and then save it with "0" values in the aura radius (as was applied by the API) it will create the slightest colored outline of the token.  I have to manually remove the 0 values first or it creates the colored outline. (I can provide images if I'm not clear in my description). Like I said, I don't understand the code-level design but I suspect the API bugged out because the aura 1_radius command is looking for a number but gets an 'undefined' error when using the original syntax I found in the instructions.