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

[Script] ChatSetAttr - set character attributes via chat messages

1503075629
Jakob
Sheet Author
API Scripter
Gary W. said: The exact message was something about a possible infinite loop. Will try and be more specific tomorrow.  Yes, that just means that the API is busy for a suspiciously long time, not that there's necessarily an actual infinite loop. But the fact that it happens for non-repeating attributes as well is interesting by itself ... anyway, we'll see once you get to test the other version. 
Realized it wouldn't mess up my campaign tonight to try the issue on the warehouse. Sadly the results were not good. I tried to run the following (shaped sheet default settings for monsters) and it did the infinite loop. !setattr --all {{ --shaped_d20|d20 --initiative_to_tracker|1 --initiative_tie_breaker|1 --show_character_name|{{show_character_name=1}} --attacks_vs_target_ac|1 --attacks_vs_target_name|1 --automatically_roll_damage_for_attacks|0 --automatically_roll_damage_for_saving_throws|0 --critical_damage_houserule|CRITICAL_DAMAGE_IS_MAXIMIZED --inspiration_multiple|1 --medium_armor_max_dex|2 --base_dc|8 --hide_ability_checks|{{hide_ability_checks=0}} --hide_saving_throws|{{hide_saving_throws=0}} --hide_attack|{{hide_attack=0}} --hide_damage|{{hide_damage=0}} --hide_freetext|{{hide_freetext=1}} --hide_recharge|{{hide_recharge=1}} --hide_target_ac|{{hide_target_ac=1}} --hide_saving_throw_dc|{{hide_saving_throw_dc=1}} --hide_saving_throw_success|{{hide_saving_throw_success=0}} --hide_content|{{hide_content=1}} }} Tried the same command with the --startwith A and can confirm it did work- but the feed back came in stages. Something like a chatsetattr received all data message in the api followed by the chat feedback quite a bit later.  
1503086217
Jakob
Sheet Author
API Scripter
Gary W. said: Realized it wouldn't mess up my campaign tonight to try the issue on the warehouse. Sadly the results were not good. I tried to run the following (shaped sheet default settings for monsters) and it did the infinite loop. !setattr --all {{ --shaped_d20|d20 --initiative_to_tracker|1 --initiative_tie_breaker|1 --show_character_name|{{show_character_name=1}} --attacks_vs_target_ac|1 --attacks_vs_target_name|1 --automatically_roll_damage_for_attacks|0 --automatically_roll_damage_for_saving_throws|0 --critical_damage_houserule|CRITICAL_DAMAGE_IS_MAXIMIZED --inspiration_multiple|1 --medium_armor_max_dex|2 --base_dc|8 --hide_ability_checks|{{hide_ability_checks=0}} --hide_saving_throws|{{hide_saving_throws=0}} --hide_attack|{{hide_attack=0}} --hide_damage|{{hide_damage=0}} --hide_freetext|{{hide_freetext=1}} --hide_recharge|{{hide_recharge=1}} --hide_target_ac|{{hide_target_ac=1}} --hide_saving_throw_dc|{{hide_saving_throw_dc=1}} --hide_saving_throw_success|{{hide_saving_throw_success=0}} --hide_content|{{hide_content=1}} }} Tried the same command with the --startwith A and can confirm it did work- but the feed back came in stages. Something like a chatsetattr received all data message in the api followed by the chat feedback quite a bit later.   The feedback in stages would be expected, since I bumped up the delay between each sheet to 200ms. Any API console feedback on the failed attempt, or no message at all?
No message outside of the infinite loop. Was looking for anything to give you, but that just didn't seem to have any value. 
1503387995
Jakob
Sheet Author
API Scripter
I can try and help improve performance so it works even for 600 characters. If you want to help, you could make a copy(!) of your warehouse game, send me a join link and make me a Co-GM so I can fiddle around with the script there.
Sounds like a plan!
many hours later- game still saying copying, please wait :)
1503426410
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
It's probably done. I've never seen a confirmation message when copying a game. It just keeps churning.
Same here Keith- but when I open the copy there are no monsters.
That makes for a horrible tester for a large campaign. :)
1503446187
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Well that sucks. Whenever I have copied a campaign, it never tells me it's finished, but I don't lose any data (other than the API). You might want to try flagging a dev. You are supposed to be able to make a backup coy.
created a new post and flagged a dev for help. 
Has anybody ever tried using ChatSetAttr for setting the level of a character on a shaped sheet? Found @{class_and_level} but !setattr --sel --class and level|Paladin 2  didn't work. Since it is a repeating trait I tried !setattr --sel --repeating_class and level_$0|Paladin 2 didn't work either 
1503761756
Jakob
Sheet Author
API Scripter
Gary W. said: Has anybody ever tried using ChatSetAttr for setting the level of a character on a shaped sheet? Found @{class_and_level} but !setattr --sel --class and level|Paladin 2  didn't work. Since it is a repeating trait I tried !setattr --sel --repeating_class and level_$0|Paladin 2 didn't work either  Seems a bit useless? Anyway, how you'd do it depends on the character's particular situation. class_and_level is just a field that's populated for display, it doesn't actually work for changing the class (as you've seen). If the character is single-classed, then --repeating_class_$0_level|5 should do the trick.
1503762070
Jakob
Sheet Author
API Scripter
I've uploaded a new version of ChatSetAttr. 1.5 Refactored the script to perform attribute retrieval asynchronously. This means that the script should no longer stall the sandbox and lead to an "Infinite loop detected" shutdown even for very large campaigns. It may take a while to execute, but it will  finish.
1503922977

Edited 1503923529
Guy
Plus
Script is pretty sweet! Using it in a macro for Potion of Healing effect (see below). New to roll20 macroing so might be a bit rough. /me uses a healing potion on @{target|character_name} !setattr --silent --replace --name @{target|character_name} --potion_effect|[[2d4+2]] @{target|character_name} is healed @{target|potion_effect}. !setattr --silent --modb --name @{target|character_name} --hp|@{target|potion_effect} Added an extra line or two for some RP "flavoring" and got to thinking... Would it be possible to add something like a --header and --desc that would allow for replacing the "header" and the "description" in the whispered output? Something along the lines of (using the above macro as example) !setattr --header @{target|character_name} is healed @{target|potion_effect} --desc Health is now at *nn* --modb --name @{target|character_name} --hp|@{target|potion_effect} which would provide the following output. With this I might be tempted to want to toggle "whisper" off so it displays to all. Thinking of maybe a macro that would do a group heal and everyone sees result or to direct the whisper to the effect target. Again...great mod and will be looking to use it for all sorts of "effects". Thank you for the effort.
1504083892
Jakob
Sheet Author
API Scripter
@Guy, yes, I think something like that could be done. I'll put it on my list of things to add when I feel like it :).
1504162810

Edited 1504163039
I'm getting this error: TypeError: Assignment to constant variable. at setCharAttributes (apiscript.js:1742:18) at dWork (apiscript.js:1674:6) at delayedGetAndSetAttributes (apiscript.js:1683:4) at handleInput (apiscript.js:2174:7) 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) This is the command I issued in chat: !setattr --charid @{Selected|character_id} --replace --hello|world
1504163331

Edited 1504163418
Jakob
Sheet Author
API Scripter
Christopher B. said: I'm getting this error: TypeError: Assignment to constant variable. at setCharAttributes (apiscript.js:1742:18) at dWork (apiscript.js:1674:6) at delayedGetAndSetAttributes (apiscript.js:1683:4) at handleInput (apiscript.js:2174:7) 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) This is the command I issued in chat: !setattr --charid @{Selected|character_id} --replace --hello|world Oops, this is why I didn't release it to One-click yet. I'll get a fix out. In the meantime, you can use 1.4 unless you have a need to use it on huge campaigns.
1504165568
Jakob
Sheet Author
API Scripter
1.5 Retroactively fixed a bug in the uploaded version that would lead to a TypeError on setting attributes. 1.6 Added --fb-public, --fb-from, --fb-header, and --fb-content options to modify the script's feedback output. The documentation for the new options is in the newly-added  README .
What are the best ways to use ChatSetAttr to actually change names on the sheet? I do not mean using the names as ID parameters, but actually working with the names as attributes. Specifically, I am having trouble changing the name of NPCs pulled out of the Compendium (I can't figure out how the sheet deals with the various name fields for npcs). Let's say I want to take the Rat entry from the Compendium, then use the script to change the name fields on its journal entry to "Tim," because this is a really special fellow. I can get the script to update the npc_name field using !setattr --sel --npc_name|Tim This macro updates the NPC bit, but not the name of the journal/character sheet. What I am I missing?
1504284268

Edited 1504285019
Jakob
Sheet Author
API Scripter
Short answer: you can't. Long answer: A character's name ("Rat" in your example) is a type of pseudo-attribute. You can print it in chat using @{character_name} in abilities, and modify it on the sheet if the sheet author has linked one of the input fields to it, but it's an intrinsic property of the character rather than a separate attribute object (it does not appear on the attributes & abilities tab for that reason). ChatSetAttr isn't setup to edit characters, only attributes. If you were to try !setattr --sel --character_name|Tim, it would create a new attribute called character_name whose value is Tim instead of changing the character's actual name. But then, it would be quite simple to write a script that changes a selected character's name. Not sure if it's easier than just hitting edit and changing the name manually though unless you have to do it en masse. :D.
Thanks Jakob. That's what I expected. Thinking of the character names as pseudo-properties is useful.
Hi Jakob... Have been trying to figure out the new --fb options and not having very much luck. Have tried a number of variations on the following theme: !setattr --fb-from Guy --fb-header testing --fb-content Playing with this --name @{target|character_name} --potion_effect|[[2d4+2]] It appears that regardless of order or syntax subtleties, I get the following result: Would you mind adding an example to the README? Greatly appreciated!
1504376174

Edited 1504378555
Jakob
Sheet Author
API Scripter
Guy said: Hi Jakob... Have been trying to figure out the new --fb options and not having very much luck. Have tried a number of variations on the following theme: !setattr --fb-from Guy --fb-header testing --fb-content Playing with this --name @{target|character_name} --potion_effect|[[2d4+2]] It appears that regardless of order or syntax subtleties, I get the following result: Would you mind adding an example to the README? Greatly appreciated! Are you using 1.6 from Github? It looks as if you're not... (one-click is still at 1.4, so it doesn't know about the fb-X options and it would just about look like in your example).
1504392427

Edited 1504398520
Guy
Plus
And...correct. An obvious failure in my deployment procedures. :) Works and looks great. A sample... PoppaPot (healing potion macro) !setattr --modb --fb-public --fb-from @{selected|character_name} --fb-header @{selected|character_name} gives a healing potion to @{target|character_name}. --fb-content _CHARNAME_ is healed _TCUR0_ points. Health is now _CUR0_. --name @{target|character_name} --hp|[[2d4+2]] Easier and cleaner than the macro it replaced. Plan to add in the inventory updating next. Nice work! And many thanks for implementing so quickly!
I'm trying to use a macro to manage Bardic Inspiration, using both ChatSetAttr and TokenMod APIs, but they're co-mingling poorly in my specific setup. The user selects their Bard token, and clicks my "Bardic Inspiration" macro. This will run the ChatSetAttr script to update the class_resource field with a -1. It will also fire Aaron's TokenMod script, asking the player to select another token, applying a status marker to the targeted token, just to signal it to all the players. To get TokenMod to select a target token, I'm using the  --ignore-selected  command. However, this seems to freak out ChatSetAttr, and it returns the "No Targets Selected" error. They work fine together if I'm not using --ignore-selected . Is there a way I can use Token Mod's --ignore-selected without messing up ChatSetAttr? The macro looks like this: !setattr {{ --sel --mod --class_resource|-1 --silent }} !token-mod {{ --ignore-selected --set statusmarkers|!strong --ids @{target|Bardic Inspiration|token_id} }}
1504893686

Edited 1504893697
Jakob
Sheet Author
API Scripter
Ah. --sel does not work together with a @{target} statement (this has nothing to do with --ignore-selected), because targeting something actually clears your selection before the message is sent to the API. The solution would be to use "--charid @{selected|character_id}" instead of --sel.
Thanks Jakob, that works. I got it into my head that I needed to use --ignore-selected to make sure both scripts didn't run on both characters (assuming I was using the --sel command to ID). I'm not sure why it didn't occur to me to do it with --charid instead.
1505054044
Jakob
Sheet Author
API Scripter
Chris said: Thanks Jakob, that works. I got it into my head that I needed to use --ignore-selected to make sure both scripts didn't run on both characters (assuming I was using the --sel command to ID). I'm not sure why it didn't occur to me to do it with --charid instead. Well, you're right, you would normally need --ignore-selected, but due to the @{target}, TokenMod (like ChatSetAttr) thinks that you do not have anything selected anyway, so it makes no difference!
1505839303

Edited 1505839521
Kryx
Pro
Sheet Author
API Scripter
Hey Jakob, I tried setting something with curly brackets on 1.6 and it seems to not work: !setattr --allgm --hide_saving_throw_success|{{hide_saving_throw_success=1}} Which results in Setting hide_saving_throw_success to hide_saving_throw_success=1 for character Barbed Devil. I tried escaping the curly brackets as well, but that didn't work. Is there another way I can accomplish this?
1505840101
The Aaron
Pro
API Scripter
if you insert this line at 474: .replace(/\s*$/g, '') .replace(/({{(.*?)\s*}}$)/g, '$2') /* 474 */ .replace(/\\([{}])/g,'$1') .split(/\s+--/) .slice(1) It should let you write that as: !setattr --allgm --hide_saving_throw_success|\{\{hide_saving_throw_success=1\}\}
1505841221

Edited 1505841291
Jakob
Sheet Author
API Scripter
It's a good thing you seem to know my code, Aaron !? :D Stupid question deleted, answer is no. Another way of doing it with the live code is not putting the brackets at the very end: !setattr --allgm --hide_saving_throw_success|'{{hide_saving_throw_success=1}}' This should also do it, I think.
1505842732
The Aaron
Pro
API Scripter
Ah, nice!  I missed that you had the $ on the end.  I don't do that in mine. =D
1506332295
Jakob
Sheet Author
API Scripter
1.6.1 Fixed a bug that prevented the "Players can modify" option from having any effect.
1506409983
Jakob
Sheet Author
API Scripter
Extra tweaks to 1.6.1  before it goes live: Modified the RegEx to require   some whitespace before the closing curly brackets. Which means that Kryx' initial command --hide_saving_throw_success|{{hide_saving_throw_success=1}} would actually work without any further modifications. Added escaping of curly brackets which should allow multi-line input with double curly brackets in values.
1506467943

Edited 1506468192
can chatsetattrib change hte Hit Dice box on the OGL 5E sheet? I need to use a query How many hit die used. I am trying to make a short rest Macro the ask how many hit die then applies it to the target and removes the amount from the Hit Dice box. If I mouse over the box it show @{hit_dice} Can !alter and !setattr use the same query? !alter --target|@{target|token_id} --bar|1 --amount|?{How many Hit Dice? |1,1|2,2|3,3|4,4|5,5|6,6d@{selected|HitDieType}} !setattr --name @{selected|character_name} --modb --@{hit_dice}|-{?{How many Hit Dice? |1,1|2,2|3,3|4,4|5,5|6,6} --silent !power {{ --emote|** @{selected|token_name} Is Rested ** --tokenid|@{selected|token_id} --format|atwill --corners|10 --name| ** Short Rest ** --leftsub|@{selected|character_name} --rightsub| Manages a short reset. --Hit Points|~R **[[@{Selected|HP}]]**  **Max** **[[@{selected|hp|max}]]** ~R --Shortrest:| A short rest is a period of downtime, at least 1 hour long, during which a character does nothing more strenuous than eating, drinking, reading, and tending to wounds. A character can spend one or more Hit Dice at the end of a short rest, up to the character’s maximum number of Hit Dice, which is equal to the character’s level. For each Hit Die spent in this way, the player rolls the die and adds the character’s Constitution modifier to it. The character regains hit points equal to the total. The player can decide to spend an additional Hit Die after each roll. }}
1506502348

Edited 1506502608
Ziechael
Forum Champion
Sheet Author
API Scripter
You are missing a closing } in your first 'how many' query... you also should be able to just list the options without the need for the ', n ' bit (?{How many|1|2|3|4|5|6} will still result in n d n  being rolled, to that end however you might want to put the actual healing in an inline roll [[ ]] to resolve the result of the dice.
I can get this to work seem the issue is the --@{hit_dice} even tho hit_dice is a attrib !setattr --name @{selected|character_name} --modb --@{hit_dice}|-{?{How many Hit Dice? |1|2|3|4|5|6} --silent Help please this is driving me nuts.
1506629880
Ziechael
Forum Champion
Sheet Author
API Scripter
Craven said: I can get this to work seem the issue is the --@{hit_dice} even tho hit_dice is a attrib !setattr --name @{selected|character_name} --modb --@{hit_dice}|-{?{How many Hit Dice? |1|2|3|4|5|6} --silent Help please this is driving me nuts. Should be just --hit_dice|... by using @{hit_dice} it will be resolving to the value of that attribute rather than amending the attribute value... i think..?
Ziechael said: Craven said: I can get this to work seem the issue is the --@{hit_dice} even tho hit_dice is a attrib !setattr --name @{selected|character_name} --modb --@{hit_dice}|-{?{How many Hit Dice? |1|2|3|4|5|6} --silent Help please this is driving me nuts. Should be just --hit_dice|... by using @{hit_dice} it will be resolving to the value of that attribute rather than amending the attribute value... i think..? I get and error
1506637005
Jakob
Sheet Author
API Scripter
--hit_dice|-{?{How many Hit Dice? |1|2|3|4|5|6} has an extra curly bracket after the minus, resulting in the script not recognizing the number. That's the error you are seeing.
Jakob said: --hit_dice|-{?{How many Hit Dice? |1|2|3|4|5|6} has an extra curly bracket after the minus, resulting in the script not recognizing the number. That's the error you are seeing. Thanks
I'm having an issue with using !modbattr on the 5e OGL sheet. I'm trying to create a macro both for long rests and for conversion of sorcery points into spell slots. The attribute for the number of 1st level spell slots left is, rather confusingly, @{lvl1_slots_expended} which doesn't have a max value from the sheet so I entered in a max value of @(lvl1_slots_total}. Now when I try to increase the number of slots remaining with      !modbattr --name Name --lvl1_slots_expended|1      it changes the number of slots remaing to NaN. When I change to !modattr it increases the slots by 1 as it should so this must be an error due to using another attribute as a max value. Does anyone know if there is a workaround for this or if I'm just missing an easy fix, any help would be appreciated? TL;DR How do you get around !modbattr not recognising other attributes as max values?
Ok now I can't seem to reset attributes without getting this error, sorry if I'm being really stupid, I don't fully understand API or know JavaScript at all For reference, the error message generated was: TypeError: str.split is not a function TypeError: str.split is not a function at htmlReplace (apiscript.js:676:15) at Object.entries.map (apiscript.js:832:50) at Array.map (native) at setCharAttributes (apiscript.js:829:57) at dWork (apiscript.js:749:6) at delayedGetAndSetAttributes (apiscript.js:759:4) at handleInput (apiscript.js:1277:7) 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
1506966895
Jakob
Sheet Author
API Scripter
@Kyle For your first problem, I don't know a good solution. Maybe you can bypass the whole modattr situation and use something like !setattr --name Name --lvl1_slots_expended|[[[[{@(lvl1_slots_expended}+1,@(lvl1_slots_total}}]]kl1]] (though I'm not 100% on the dice roll syntax there). For the second problem, that's actually my fault.
If it helps the error only seems to appear when using reset or modb, although I *can* use reset on hp without getting the error. I'll try that workaround I can't see why it wouldn't work. I'm also having an issue with using CSA alongside a roll template in a macro. Roll20 only seems to output either the roll template or CSA whichever comes first but never both. I don't know if this is a thing to do with APIs but a workaround would be appreciated because I would like the attribute to change with the roll.
Jakob said: !setattr --name Name --lvl1_slots_expended|[[[[{@(lvl1_slots_expended}+1,@(lvl1_slots_total}}]]kl1]] For reference this only worked if I set the attributes to reference the character sheet individually, i.e. by replacing @(lvl1_slots_expended} with @(Name|lvl1_slots_expended} and the same with slots total. I don't understand why it would be needed but maybe someone more clever than me can use this info.
1506967985
Jakob
Sheet Author
API Scripter
I know what the error is, it's a one-liner to fix. Not enough type checking on my side :). Fix is online. 1.6.2 Fix TypeError when giving non-string feedback. About the macro, what does the macro look like exactly? Is it a character ability or global macro, and what is the exact text?