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

July 27 (8 years ago)

Edited January 24 (6 years ago)
Jakob
Sheet Author
API Scripter
This is a utility script with a singular purpose: you can supply a list of characters (in multiple ways) and a list of attributes and values, and for all characters in the list the attributes will be set to the values (and created if they did not exist before). The syntax is
!setattr [--options] --attribute1|value1|max1 --attribute2|value2|max2 ...
Alternatively, you can use the following syntax to spread the command out over multiple lines (in this case, you cannot use closing curly braces('}}') anywhere in the values):
!setattr {{
	[--options]
	[--all|--allgm|--allplayers|--sel|--charid id1, id2, ...|--name name1, name2, ...]
	--attribute1|value1|max1
	--attribute2|value2|max2
	...
}}
You can also just use --attribute1|value1 to leave the maximum unchanged. You can also use '#' in place of '|'. More in-depth documentation can be found in the README.

Find the script at Github or via the One-Click library (both v1.7.1).
July 27 (8 years ago)
The Aaron
Pro
API Scripter
Neat! =D
July 28 (8 years ago)
Lithl
Pro
Sheet Author
API Scripter
It appears this script will only set the current value on an attribute. Would be nice if there was some means to set the maximum as well.
July 28 (8 years ago)

Edited July 28 (8 years ago)
Jakob
Sheet Author
API Scripter

Brian said:

It appears this script will only set the current value on an attribute. Would be nice if there was some means to set the maximum as well.
I've been thinking about a good syntax for that. Easiest would be just --max applying to all attributes, but I would like something individual. 

EDIT: I would like
--Strength|12|14
to set maximum Strength to 14 and current Strength to 12, and
--Strength||14
to only set maximum Strength to 14, but then there is no way of clearing current while setting maximum in the same command (repeating one attribute works badly due to the way I've set up parsing). If anyone has any good ideas, I'd be happy to hear them.
July 28 (8 years ago)
Jakob
Sheet Author
API Scripter
Okay, I think I have figured out a way. Updated the OP with new information. One potentially breaking change I made: the option --sel is now required to affect selected tokens. If no option is given at all, the script will simply spit out an error message.
July 28 (8 years ago)
OK, I am going to kick myself because I am sure that I am missing something so obvious that it is right in front of me, but I have been banging my head on the desk trying to get this to work so I am going to ask my stupid question.

First let me say that the script is working great! I can select some tokens and run the script using chat and it will set the value in the Attribute exactly as expected. In this case I am attempting to set an Attribute named "zINIT_ROLL" using a roll query. So I enter this in the chat:
!setattr --sel --zINIT_ROLL|?{Initiative Roll}
And I get this back:
(From John C. (GM)): C. (GM)
Setting zINIT_ROLL to 3 for characters Oleanne, Garyld.
Perfect.

But what I want to do is setup a macro so that I can click on a button in the Macro Bar and run this for all of the selected tokens. So I created my macro ("Initiative Roll_v1") and used the exact same command in the macro that I entered in the char window. When I use the Test Macro button in the Edit Macro window it works fine! But when I Save the changes and click the button in the Macro Bar I get this in the chat window:
John C. (GM): #Initiative Roll_v1

Now, I realize that the name of this script is ChatSetAttr, but does that mean it ONLY works from chat? If not, then what the heck am I doing wrong?!

Thanks in advance far any help that anyone can provide!
July 28 (8 years ago)
Macros that have spaces within their names are not possible to call. You'll want to rename your Macro, maybe to "Initiative_Roll_v1".
July 28 (8 years ago)
See, I knew there was something very simple that I was missing! Thank you for the quick response Silvyre, that fixed it.
This looks really neat. I haven't tried it out yet because I'm in the midst of other prep, but is it be possible to have this affecting repeating section attributes with the list order syntax? A.K.A select an attribute as 'repeating_buff_$2_buff-enable_toggle' instead of 'repeating_buff_-KNoPmPxTXYSfbwuUjKm_buff-enable_toggle'? I imagine that it would take a little leg-work to get running, but it'd be great for turning on mass buffs like Inspire Courage on the Pathfinder sheet once API+SheetWorker synergy is in place. As I said, I haven't tested it - maybe you thought ahead and already did this, but it seemed a question worth asking anyway. :-)
July 30 (8 years ago)
Jakob
Sheet Author
API Scripter

Bennett S. said:

This looks really neat. I haven't tried it out yet because I'm in the midst of other prep, but is it be possible to have this affecting repeating section attributes with the list order syntax? A.K.A select an attribute as 'repeating_buff_$2_buff-enable_toggle' instead of 'repeating_buff_-KNoPmPxTXYSfbwuUjKm_buff-enable_toggle'? I imagine that it would take a little leg-work to get running, but it'd be great for turning on mass buffs like Inspire Courage on the Pathfinder sheet once API+SheetWorker synergy is in place. As I said, I haven't tested it - maybe you thought ahead and already did this, but it seemed a question worth asking anyway. :-)

That would be a great feature! Unfortunately, I just tested it and it doesn't work just by chance. In the end, it comes down to the question: does findObj return the right attribute when you search the name by the row number instead of row id. Apparently it does not. I don't know if/how the API has access to the row number. If it does, I'll certainly try to make it work.
August 02 (8 years ago)

Edited August 02 (8 years ago)
Jakob
Sheet Author
API Scripter
I just pushed 0.7 to Github, which now handles repeating sections better, with the following changes (only affects repeating sections).

  1. Repeating section attributes will never be created if they do not exist yet. The reason for this is that creating repeating section attributes with invalid row ids messes up the sheet and creates ghost repeating rows. Bad news. The downside to this is that you can no longer overwrite defaults for row id items; the attribute must have been created first (e.g. by clicking into the corresponding field once and clicking somewhere else again). I think this is an acceptable compromise for now- maybe in the future I will add some check to see if the row exists, even if the particular attribute for this row does not. The script will fail silently if it doesn't find an existing attribute (i.e. it will still claim to have changed it, but nothing will happen for characters where the attribute does not exist).
  2. You can adress repeating sections by row index ($5). However, this only works if the rows have not been reordered. I.e., this will target rows in order of creation, not in the order they are displayed in. It will also ONLY target the correct attribute if the attribute exists for ALL rows of this type (well, created before the one we are trying to target). There does not currently seem to be a way to find out the real row number of an attribute, so I think this is the best I can do. This uses a bit of fiddling around with regexps, I hope I didn't create too many errors here. As before, this will just do nothing if the corresponding attribute does not exist (for example because the row does not exist).
Phew. This would be so much easier and less prone to user-error if I had some way of getting the id from the row number, but it doesn't seem possible (outside of the sheet author supporting it by explicitly providing the id via sheetworkers).

EDIT: Okay, I've rethought my way of dealing with this and played around a bit to make it work better (0.7.1). It is now possible to create repeating section attributes if they happen to be created in repeating sections that already exist. Also, adressing repeating sections by row index (e.g. $5) will now work as expected even if the attributes don't exist yet. The only problem that seems unsolvable is the fact this method does not care about reordering of repeating rows, so it will find the attributes in order of creation, not in display order. But this should cover most use cases. Now to wait for api/sheetworker integration (and perhaps upgrade the parser at some point, to allow more complicated inputs).
August 04 (8 years ago)

Edited August 04 (8 years ago)
Jakob
Sheet Author
API Scripter
v 0.7.2 adds the option --replace. It allows you to set the values of attributes to be inline rolls, or other attributes (instead of the values of these attributes or inline rolls). When --replace is supplied, the characters <,>,#,~ will be replaced by [,],|,@ when the attributes are set. This allows you to run, for example
!setattr --sel --replace --strength_total | ~{strength} + ~{strength_bonus}
This will set strength_total to "@{strength} + @{strength_bonus}".
Ahh dude! Awesome! Crossing my fingers that reordered rows can be tracked properly soon but even this makes it so much easier! And the new features are sweet too. I'll consider it a birthday present come one day early. :-D
August 11 (8 years ago)
Jakob
Sheet Author
API Scripter
Update 0.8
  • Added new command !delattr, with essentially the same syntax (with attribute values ignored, obviously), that will delete attributes it finds.
  • Added option --nocreate to not create missing attributes, will display an error message instead.
August 25 (8 years ago)

Edited August 25 (8 years ago)
This looks amazing.  Any chance it will get added to the Roll20 API Script Library so people can get updates automatically?

Also, is there a way to add abilities via this script?  I've got a lot of  standard power cards  I'd like to add to every character sheet via something like this.... :)

Thank you again for this amazing script.
August 25 (8 years ago)
Tetsuo
Forum Champion

Jakob said:

Brian said:

It appears this script will only set the current value on an attribute. Would be nice if there was some means to set the maximum as well.
I've been thinking about a good syntax for that. Easiest would be just --max applying to all attributes, but I would like something individual. 

EDIT: I would like
--Strength|12|14
to set maximum Strength to 14 and current Strength to 12, and
--Strength||14
to only set maximum Strength to 14, but then there is no way of clearing current while setting maximum in the same command (repeating one attribute works badly due to the way I've set up parsing). If anyone has any good ideas, I'd be happy to hear them.

Maybe try 

--Strength|@{selected|strength}|14

would set max to 14 while keeping current at whatever it already is?
August 25 (8 years ago)

Edited August 25 (8 years ago)
Jakob
Sheet Author
API Scripter

Sudain said:

This looks amazing.  Any chance it will get added to the Roll20 API Script Library so people can get updates automatically?

Also, is there a way to add abilities via this script?  I've got a lot of  standard power cards  I'd like to add to every character sheet via something like this.... :)

Thank you again for this amazing script.

I've been thinking about adding it to the library. Eventually, I'll get around to it...
This script doesn't touch abilities, they are a different type of object than attributes are.

One could hack this script to affect abilities instead of attributes pretty easily, but you would need to do a bit more to implement your plan, because the current syntax does not allow for double dashes inside attribute values (and I think PowerCards needs plenty of those).

@ Franky: I solved this problem quite a while ago. As written in the introductory post, the correct syntax is --Strength||14.
August 25 (8 years ago)
Tetsuo
Forum Champion
Oh. My mistake. I missed that. I thought you were asking for ways it my work. My mistake. 
August 25 (8 years ago)

Edited August 25 (8 years ago)
Jakob
Sheet Author
API Scripter

Franky H. said:

Oh. My mistake. I missed that. I thought you were asking for ways it my work. My mistake. 

No problem, I just wanted to correct so that no one reads your post and thinks there's not yet a solution for this :).
August 25 (8 years ago)

Edited August 25 (8 years ago)
:D  I used this last night with the below macro and this is speeding up my monster character creation time GREATLY.  Thank you again.  I'll try to find a different mod to add abilities; I don't want to hack your working script of time-saving.


!setattr --sel --Init|?{Init}|, AC|?{AC}|, touch|?{touch}|, flat-footed|?{flat-footed}|, hp|?{hp}|, Fort|?{Fort}|, Ref|?{Ref}|, Will|?{Will}|, Speed|?{Land Speed}|, bab|@?{bab}|, CMB|?{CMB}|, CMD|?{CMD}|, Acrobatics|?{Acrobatics}|, Bluff|?{Bluff}|, Climb|?{Climb}|, Diplomacy|?{Diplomacy}|, Disguise|?{Disguise}|, Escape Artist|?{Escape Artist}|, Fly|?{Fly}|, Intimidate|?{Intimidate}|, Perception|?{Perception}|, Ride|?{Ride}|, Sense Motive|?{Sense Motive}|, Stealth|?{Steath}|, Survival|?{Survival}|, Swim|?{Swim}|, Languages|?{Languages}|
August 26 (8 years ago)

Edited August 26 (8 years ago)
Anyone familiar with how the D&D 5E OGL sheet handles the Whisper Rolls to GM setting?  I'm looking for a way to set all my npc's to the option "Query Whisper" but i'm not finding the right attribute to manipulate to make this happen.

Edit:  Looks like it is the wtype attribute and the value is "?{Whisper?|Public Roll,|Whisper Roll,/w gm }"

Edit2:  Looks like there's not a replace option to replace the ? character so i'm not able to add the roll query to the attribute value.

Edit3:  It also doesn't seem to be too happy about commas within the attribute either.   Anywho, this may be something that gets updated by sheet workers  or something as well, so it may be a moot point (Not 100% sure i'm understanding how all this works so take that comment with a grain of salt)


Last Edit (I hope):  I got it to work using the following:

Edited the script a bit by changing line number 157 
From 
returnstr.replace(//g,']').replace(/#/g,'|').replace(/\~/g,'@');
To
return str.replace(//g,']').replace(/#/g,'|').replace(/\~/g,'@').replace(/\=/g,'?').replace(/\^/g,',');

This allowed me to use = in place of ? and ^ in place of ,  at least for the time being.  May want to change those back after this so as not to mess up any future commands.

I then ran the command:
!setattr --allgm --replace --wtype|={Whisper?#Public Roll^#WhisperRoll^/w gm}

And that worked setting the wtype attribute to the ?{Whisper?|Public Roll,|Whisper Roll,/w gm } value.
August 26 (8 years ago)
Jakob
Sheet Author
API Scripter
Hmm, it seems you solved all your problems yourself :) ! Some thoughts:

  • It's true that there's no replacement for ?. I just forgot about that! I'll build something into the script, though I will not use =, since that is also pretty likely to be used by some commands.
  • The commas don't work because the script expects to split multiple attributes by comma. That's unnecessary in theory - one could delete lines 147 and 148 to get rid of that behaviour, and still change multiple attributes at once via --attribute1|value1 --attribute2|value2 et cetera. On the other hand, I don't want to delete it at this point since it looks and will make everyone's macros invalid. (I could put in some sort of replacement instead, like you did, but I feel like I'm running out of characters here.)
August 30 (8 years ago)
Jakob
Sheet Author
API Scripter
FYI, I have submitted a pull request for version 0.9 to the roll20 API repository. I've decided to bite the bullet and make 2 potentially breaking changes for this version (better get it done before I add it to the script library):

  • It's no longer possible to separate attributes by commas. Instead, they must be separated by double dashes (--).
  • The replacer list is changed to: < , > , # , ~ , ; ,  ` being replaced by [,],|,-,?, and @. (In particular, the tilde is no longer replaced by @). I've added an extra variable replacers at the start of the script. If you know a bit what you are doing and do not like my choices, you can change the replacement rules there instead of having to muck about in the script and parse my undocumented code :).

The script is not in the normal place for the moment until I also get to update the documentation above. But one can get it under Link.
August 30 (8 years ago)

Edited August 30 (8 years ago)
Thanks, Jakob! Really enjoying these features!
September 07 (8 years ago)
Awesome!  Thanks for making the updates!
September 07 (8 years ago)
Jakob
Sheet Author
API Scripter
The pull request has been accepted, so in a couple of days(?) the script will be available for One-Click installation. I hope more people will become aware of its existence this way, "I want to make a macro to mod character attributes" seems to be a rather common request.
September 11 (8 years ago)

Edited September 11 (8 years ago)
So, looks like an awesome script, can see using it quite a bit.

One question though, is there a way to pull the value of an attribute in order to set another attribute?  For example, lets say I have an attribute called Temp.  I would like:

!setattr --Strength|@{selected|Temp}|@selected|Temp|max}

NEVERMIND!  Figured out that I needed to use the --sel option!

!setattr --sel --Strength|@{selected|Temp}|@selected|Temp|max}
September 12 (8 years ago)
Jakob
Sheet Author
API Scripter
Yep, that works Kevin. Downside is that everyone's strength will be set to the same value if you have several tokens selected.
September 16 (8 years ago)
Jakob
Sheet Author
API Scripter
  • v0.9.1 adds (among some small cosmetic fixes) the option --mod to adjust (integer-valued) attributes instead of replacing the current value.
September 18 (8 years ago)

Edited September 18 (8 years ago)
This is such a great tool Jakob.  Major kudos to you for making it happen!

I am running into a minor problem while attempting to make a specific case scenario work though.  I am attempting to use this script to toggle a boolean attribute by using a macro button.  Here is the syntax I am attempting to use which is not functioning correctly:

!setattr --sel --replace --repeating_buff_$0_buff-enable_toggle|((`{selected#repeating_buff_$0_buff~enable_toggle} ~ 1) * (`{selected#repeating_buff_$0_buff~enable_toggle} ~ 1))

When I activate this text command it gives the following:

Setting repeating_buff_$0_buff-enable_toggle to ((`{selected>repeating_buff_$0_buff~enable_toggle} ~ 1) * (`{selected>repeating_buff_$0_buff~enable_toggle} ~ 1)) for characters (character name here) (replacing <,>,#,~,;,` by [,],|,-,?,@).

However, the attribute in question is not changing.  Any chance I'm missing something?  Basically I want to set a boolean attribute to the value (b-1)*(b-1) where b=the current value of the attribute.

EDIT:  So I found my first problem.  I needed to be parsing the math before passing it into the script.  So I have adjusted the text command as follows:

!setattr --sel --nocreate --repeating_buff_$0_buff-enable_toggle|(@{selected|repeating_buff_$0_buff-enable_toggle} - 1) * (@{selected|repeating_buff_$0_buff-enable_toggle} - 1)

This still doesn't quite work as when the attribute is set to 0 the returned message is:

Setting repeating_buff_$0_buff-enable_toggle to (0 - 1) * (0 - 1) for characters (character name here).

How can I get the (0-1)*(0-1) to parse before sending to the script?

EDIT2:

SUCCESS!  I found that this script apparently functions with inline rolls!  Here was the final text command used to achieve the desired effect:

!setattr --sel --nocreate --repeating_buff_$0_buff-enable_toggle|[[(@{selected|repeating_buff_$0_buff-enable_toggle} - 1) * (@{selected|repeating_buff_$0_buff-enable_toggle} - 1)]]
September 20 (8 years ago)

Edited September 20 (8 years ago)
Jakob
Sheet Author
API Scripter
v 1.0 (now on Github) features a (possibly very large) performance gain as well as handling of large campaigns (e.g. Storm King's Thunder). If you use --all on many characters at once, it will take some time for the changes to be applied to all characters, but the script will finish and not crash the sandbox due to taking too long (it handles 20 characters per second, because The Aaron said he always uses a delay of 50 ms :)).

Many thanks to The Aaron, who made this version possible. This version is a rewrite of some parts of the script, so it's possible some new errors may have crept in.
September 27 (8 years ago)
Caden
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Love this script! Just wanted to throw this out for Shadowrun people. New players have a habit typing 1d6 into macros instead of just the 1. We noticed typing 1d6 crashes the script. Easy restart but I wanted to let you know. :) Thanks again!
September 27 (8 years ago)

Edited September 27 (8 years ago)

Necoya said:

We noticed typing 1d6 [into macros] crashes the script.

What do you mean? Could you provide an example of a macro that crashes the script?
September 27 (8 years ago)
Jakob
Sheet Author
API Scripter

Necoya said:

Love this script! Just wanted to throw this out for Shadowrun people. New players have a habit typing 1d6 into macros instead of just the 1. We noticed typing 1d6 crashes the script. Easy restart but I wanted to let you know. :) Thanks again!

What Silvyre said, I'd love a reproduction path so I can fix this crash.
September 27 (8 years ago)
Caden
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Of course! How rude of me not to leave you the steps reproduce. :) Due to how wonky Shadowrun's initiative is I use this Macro

!setattr --sel --silent --initiativedice|?{Initiative Dice|1}

If players leave the 1 alone its fine. If they enter 1d6 it results in this:

Could not determine result type of: [{"type":"M","expr":"(5)"},{"type":"C","text":" + ((1d6)d6)"}]
undefined
September 27 (8 years ago)

Edited September 27 (8 years ago)
!setattr --sel --silent --initiativedice|?{Initiative Dice|1}

There's no issues with setting an Attribute to have a Current value of '1d6'. However, there is an issue with rolling '(1d6)d6' within a macro, which is evidently what one of your macros is attempting to do via (@{initiativedice})d6. I recommend using ?{Initiative Dice|1|2|3|4|5} within your CSA macro to prevent this from happening.
September 27 (8 years ago)
Caden
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ah you are complete right. Serves me for multitasking. :)
September 28 (8 years ago)
Jakob
Sheet Author
API Scripter
To be 100% sure: the script is not actually crashing over this, is it?
September 28 (8 years ago)
Caden
Forum Champion
Sheet Author
API Scripter
Compendium Curator
@Jakob. Nope. The crash is coming from the second half of my macro. Silyre was right. Sorry about that. Thanks for looking into it. :) Love the script.
October 05 (8 years ago)
Jakob
Sheet Author
API Scripter
Update: The newest version (also part of 1.0) features some quality-of-life improvements in the parsing: it will automatically get rid of trailing spaces in the input, and it supports input in multiple lines to help make macros more beautiful.
Is there a way to copy the current _Max value to the _value value?
October 18 (8 years ago)
Jakob
Sheet Author
API Scripter

Kevin Flynn said:

Is there a way to copy the current _Max value to the _value value?

Hmm, no. You can do it for a single character by just writing it in manually (e.g. --attrname|@{charname|attribute|max}, but not for multiple characters. Perhaps I should add this as an option.

Jakob said:

Kevin Flynn said:

Is there a way to copy the current _Max value to the _value value?

Hmm, no. You can do it for a single character by just writing it in manually (e.g. --attrname|@{charname|attribute|max}, but not for multiple characters. Perhaps I should add this as an option.

Seems like a function Token-Mod might cover?
October 18 (8 years ago)
Jakob
Sheet Author
API Scripter

Saevar L. "Liquid-Sonic" said:

Jakob said:

Kevin Flynn said:

Is there a way to copy the current _Max value to the _value value?

Hmm, no. You can do it for a single character by just writing it in manually (e.g. --attrname|@{charname|attribute|max}, but not for multiple characters. Perhaps I should add this as an option.

Seems like a function Token-Mod might cover?

Only if it's a linked attribute on a token... (which will cover the most common use cases like hit points).
October 18 (8 years ago)

Edited October 18 (8 years ago)
I want to use it to reset ammo loads, so create a gun then track its ammo, then use the Max score to reload.... so I need to prompt for Gun name (attr), then copy the Max value over to the Value.
October 18 (8 years ago)
Jakob
Sheet Author
API Scripter
If you check out the latest Github (now 1.0.2), I've added a command !resetattr (same syntax as setattr and delattr) that resets all specified attributes to their maximum (value and max are ignored).
Awesome, thanks :)
October 18 (8 years ago)
Jakob
Sheet Author
API Scripter
Oops, forgot to sync. Anyway, it'll be there some time tomorrow.
Am I looking in the right place, from first post, still says 1.0.1
October 19 (8 years ago)

Edited October 19 (8 years ago)
Jakob
Sheet Author
API Scripter

Kevin Flynn said:

Am I looking in the right place, from first post, still says 1.0.1

Jakob said:

Oops, forgot to sync. Anyway, it'll be there some time tomorrow.

OK, online now, sorry for the confusion :).
October 31 (8 years ago)

Edited November 01 (8 years ago)
Jakob
Sheet Author
API Scripter
I just pushed CSA 1.1 to GitHub. This one is a bit experimental, and I'm not putting it into one-click just yet.
Changes are as follows:
  • The !resetattr command has been removed. Its functionality is still available, but only through !setattr ... --attribute|%attribute_max% (this is to avoid a bloat of options to maintain).
  • New option --modb, which works just like --mod with one change: if it's changing the current value of an attribute, it will keep the attribute between 0 and the maximum (if there is a maximum).
  • The script can now fill in values of other attributes into your attribute values. More precisely, any expression of the form %attr% or %attr_max% will be parsed to corresponding character's attribute value or maximum, respectively. Example:
!setattr --mod --sel --attr1|%attr2%
!setattr --sel --attr1|%attr2%|%attr2_max%
The first line will add the value of attr2 to the value of attr1. The second line will copy attr2 into attr1.
  • New, dangerous, nasty option --evaluate. This will try to evaluate math expressions that you put into attribute values. Because this works through Javascript's eval(), this can execute arbitrary code in your API sandbox. So don't put anything crazy in here. Should I limit this to GM use only? Probably! (not yet the case though). I have tried to catch errors resulting from this, but this is impossible to debug. On the other hand, this allows neat stuff like
!setattr --sel --evaluate --attr3|2*%attr1% + 7 - %attr2%