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

Creating multiple new rows in a repeating field with ChatSetAttr

So i have an external website set up for character creation for my game, and on there i have a page set up that generates the code needed to import from there to the character sheet i have in roll20. the problem i am facing is if i try to create multiple new entries at once, it overrides the previous entries so only the last thing generated is put in. i tried having my site export the data as multiple chatsetattr commands, but not all of them go through if i copy-paste them as one block. so right now my options seem to be i don't use repeating sections and just have a big table that would be too large for most people and possibly too small for a few people, or i have players do between 3-20 copy paste operations based on their build. is there a way to either: a: have chatsetattr recognize that a new line needs to be created and do so? (i don't see anything in the documentation that implies this is possible) b: set a delay in the pasted code so that roll20 doesn't try to run it all at once? (not sure how this would work) c: have a script that creates however empty rows are needed so chatsetattr can just input the data there? (seems hella complicated to set up) if there is some other way to do this i would love to know. here is the chatsetattr code my site is currently outputting: !setattr {{ [--options] --sel --charname|Sullet Ratatat --profmod|6 --movespeed|6 --threat|3 --manamod|8 --initiative|1 --quickness|1 --might|-2 --cunning|2 --insight|-1 --resolve|0 --defense|10 --physarm|0 --mentarm|0 --repeating_trickattack_-CREATE_trickname| Mundane Mace --repeating_trickattack_-CREATE_trickaccuracy|6 --repeating_trickattack_-CREATE_trickthreat|1 --repeating_trickattack_-CREATE_trickrange|6 --repeating_trickattack_-CREATE_trickdamage|8 --repeating_trickattack_-CREATE_trickname| Improved Rapier --repeating_trickattack_-CREATE_trickaccuracy|6 --repeating_trickattack_-CREATE_trickthreat|2 --repeating_trickattack_-CREATE_trickrange|0 --repeating_trickattack_-CREATE_trickdamage|11 --repeating_trickattack_-CREATE_trickname| Masterwork Rapier --repeating_trickattack_-CREATE_trickaccuracy|6 --repeating_trickattack_-CREATE_trickthreat|3 --repeating_trickattack_-CREATE_trickrange|0 --repeating_trickattack_-CREATE_trickdamage|11 --repeating_maneuverattack_-CREATE_maneuvername| Mundane Mace --repeating_maneuverattack_-CREATE_maneuveraccuracy|0 --repeating_maneuverattack_-CREATE_maneuverthreat|1 --repeating_maneuverattack_-CREATE_maneuverrange|6 --repeating_maneuverattack_-CREATE_maneuverdamage|11 --repeating_maneuverattack_-CREATE_maneuvername| Improved Rapier --repeating_maneuverattack_-CREATE_maneuveraccuracy|0 --repeating_maneuverattack_-CREATE_maneuverthreat|2 --repeating_maneuverattack_-CREATE_maneuverrange|0 --repeating_maneuverattack_-CREATE_maneuverdamage|8 --repeating_maneuverattack_-CREATE_maneuvername| Masterwork Rapier --repeating_maneuverattack_-CREATE_maneuveraccuracy|0 --repeating_maneuverattack_-CREATE_maneuverthreat|3 --repeating_maneuverattack_-CREATE_maneuverrange|0 --repeating_maneuverattack_-CREATE_maneuverdamage|11 }}
1631813199
timmaugh
Pro
API Scripter
There is a known issue with Roll20 dropping multiple commands from a single macro... so you might want to send 20 individual commands but only 12 of them get processed. That's probably what you are running into when you create individual ChatSetAttr commands. I could see a way to do this with meta scripts. If you output your individual ChatSetAttr commands wrapped in Plugger constructions, they would essentially become discrete instructions that Plugger would issue to ChatSetAttr: !{&eval}setattr --.......{&/eval} {&eval}setattr --....{&/eval} The benefit of this is that these are all in the first message, so there's no real chance of part of them getting dropped. However, they are all issued separately, with Plugger issuing the command to ChatSetAttr. You could take this a step further and put them in a Mule, where each entry ALSO had the instruction to get the next variable from the Mule. Each entry in the Mule would look something like (where the Mule is called "ImportMule"): 0=!setattr --repeating_trickattack_-CREATE_trickname|Mundane Mace --repeating_trickattack_-CREATE_trickaccuracy|6 --repeating_trickattack_-CREATE_trickthreat|1 --repeating_trickattack_-CREATE_trickrange|6 --repeating_trickattack_-CREATE_trickdamage|8 {&eval}{&mule ImportMule}get.ImportMule.1/get{&/eval} 1=!setattr --...... {&eval}{&mule ImportMule}get.ImportMule.2/get{&/eval} The last entry in the Mule wouldn't have verbiage to get the next variable; it would just end. That would effectively establish a loop that would continue through the Mule, embedding the next call in the previous. The first option would require Plugger and SelectManager; the second option would require Plugger, Muler, SelectManager, and ZeroFrame.
ok awesome thanks tim! it took a sec for me to grok the layout properly, but this is working swimmingly.
1632002680
timmaugh
Pro
API Scripter
Excellent! Glad it worked for you!
1632003051
GiGs
Pro
Sheet Author
API Scripter
Does anyone know if this is a recent thing? I used to use this kind of chatSetAttr script to import characters a lot (though the most recent would have been a couple years ago), and never had problems like this. It's good that Tim's Meta scripts can solve the problem.
1632006544
timmaugh
Pro
API Scripter
The problem of the dropped commands cropped up a few months ago... with the big updates around June, I think. We started to notice it with Aaron's walls script, because that issues hundreds of commands to draw the walls based on an svg file. I opened a bug report, but obviously it's still an issue.
1632008542
GiGs
Pro
Sheet Author
API Scripter
That makes sense, thanks.
1634581012

Edited 1634584149
timmaugh said: There is a known issue with Roll20 dropping multiple commands from a single macro... so you might want to send 20 individual commands but only 12 of them get processed. That's probably what you are running into when you create individual ChatSetAttr commands. I could see a way to do this with meta scripts. If you output your individual ChatSetAttr commands wrapped in Plugger constructions, they would essentially become discrete instructions that Plugger would issue to ChatSetAttr: !{&eval}setattr --.......{&/eval} {&eval}setattr --....{&/eval} The benefit of this is that these are all in the first message, so there's no real chance of part of them getting dropped. However, they are all issued separately, with Plugger issuing the command to ChatSetAttr. You could take this a step further and put them in a Mule, where each entry ALSO had the instruction to get the next variable from the Mule. Each entry in the Mule would look something like (where the Mule is called "ImportMule"): 0=!setattr --repeating_trickattack_-CREATE_trickname|Mundane Mace --repeating_trickattack_-CREATE_trickaccuracy|6 --repeating_trickattack_-CREATE_trickthreat|1 --repeating_trickattack_-CREATE_trickrange|6 --repeating_trickattack_-CREATE_trickdamage|8 {&eval}{&mule ImportMule}get.ImportMule.1/get{&/eval} 1=!setattr --...... {&eval}{&mule ImportMule}get.ImportMule.2/get{&/eval} The last entry in the Mule wouldn't have verbiage to get the next variable; it would just end. That would effectively establish a loop that would continue through the Mule, embedding the next call in the previous. The first option would require Plugger and SelectManager; the second option would require Plugger, Muler, SelectManager, and ZeroFrame. so i thought i had figured it out, but i am pretty sure the system was just handling my messages slightly different and that i am not using plugger properly. as my project has gotten more complex, i have been adding more scripts to my import process and roll20 is starting to not process all the commands again. reading through the documentation it seems like i need to add code to all my scripts to have them work with plugger, specifically: on('ready', () => {     try {         Plugger.RegisterRule(%%scriptname%%);     } catch (error) {         log(error);     } }); for all my oneclick scripts i would need to find their current versions on github and put this code in there. do i also need to add the "Parse the content String" code to all the scripts i am using with plugger? the only variable that would be need to be kept between calls that i am doing would be the selected token, but that should be kept constant by SelectManager right? to give you an idea of where i am at right now, here is one of the simpler export/import commands !charsheet --Malcolm !{&eval}token-mod --set represents|@{Malcolm|character_id} name|Malcolm bar1_max|9 bar2_max|9 defaulttoken {&/eval} {&eval}setattr --silent --sel --charname|Malcolm --profmod|2 --movespeed|4 --threat|1 --manamod|4 --Initiative|-1 --quickness|-1 --might|1 --cunning|2 --insight|0 --resolve|0 --defense|10 --physarm|1 --mentarm|3 {&/eval} {&eval}setattr --silent --sel --repeating_trickattack_-CREATE_trickname|Improved Cauldron --repeating_trickattack_-CREATE_trickaccuracy|0 --repeating_trickattack_-CREATE_trickthreat|1 --repeating_trickattack_-CREATE_trickrange|1 --repeating_trickattack_-CREATE_trickdamage|11 {&/eval} {&eval}setattr --silent --sel --repeating_maneuverattack_-CREATE_maneuvername|Improved Cauldron --repeating_maneuverattack_-CREATE_maneuveraccuracy|0 --repeating_maneuverattack_-CREATE_maneuverthreat|1 --repeating_maneuverattack_-CREATE_maneuverrange|1 --repeating_maneuverattack_-CREATE_maneuverdamage|11 {&/eval} {&eval}setattr --silent --sel --repeating_spellattack_-CREATE_spellname|Improved Cauldron --repeating_spellattack_-CREATE_spellaccuracy|2 --repeating_spellattack_-CREATE_spellthreat|1 --repeating_spellattack_-CREATE_spellrange|1 --repeating_spellattack_-CREATE_spelldamage|19 {&/eval} {&eval}setattr --silent --sel --repeating_psytechattack_-CREATE_psytechname|Improved Cauldron --repeating_psytechattack_-CREATE_psytechaccuracy|0 --repeating_psytechattack_-CREATE_psytechthreat|1 --repeating_psytechattack_-CREATE_psytechrange|1 --repeating_psytechattack_-CREATE_psytechdamage|11 {&/eval} {&eval}setability --replace --sel --token --Improved Cauldron#\amp{template:default} \q{Damage Type|Maneuver, }} {{name=Improved Cauldron Maneuver Attack}} {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}|Trick, }} {{name=Improved Cauldron Trick Attack}&#125 {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}}{&/eval} {&eval}setability --replace --sel --token --Fancy Cauldron#\amp{template:default} \q{Damage Type|Maneuver, }} {{name=Improved Cauldron Maneuver Attack}} {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}|Trick, }} {{name=Improved Cauldron Trick Attack}&#125 {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}}{&/eval} {&eval}setability --replace --sel --token --Super Cauldron#\amp{template:default} \q{Damage Type|Maneuver, }} {{name=Improved Cauldron Maneuver Attack}} {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}|Trick, }} {{name=Improved Cauldron Trick Attack}&#125 {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}}{&/eval} {&eval}setability --replace --sel --token --Dank Cauldron#\amp{template:default} \q{Damage Type|Maneuver, }} {{name=Improved Cauldron Maneuver Attack}} {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}|Trick, }} {{name=Improved Cauldron Trick Attack}&#125 {{First Roll=\[1d20+0\]}} {{Second Roll=\[1d20+0\]}} {{Damage=10}}}{&/eval} {&eval}ta - init - checks - saves{&/eval} first it makes a character sheet named whatever using an altered version of CharSheet. next with TokenMod the sheet is assigned to the currently selected token, and the token's hp bars are set according to the characters stats. next it uses ChatSetAttr to import the characters base stats and such. then it uses SetAbility to create a token action for each weapon the character has (the system has different attack/damage stats for weapons depending on what type of action is being used). finally it runs a version of TokenActionMaker that i have altered to work with our system to make buttons for initiative/armor checks/skill checks. right now, the code will work fully about 25% of the time. if i remove the TokenActionMaker command (ta) it works every time, but the goal is to have the players be able to click a button on our website to copy the code, and then just select a token and paste the code into chat to make their character
1634696125
timmaugh
Pro
API Scripter
You only need to register with Plugger if you're going to use your script as a plugin, which is *different* than just an outbound command. What I call a "plugin" is something that runs and then returns something to the command line in the place of everything between the {& eval} ... {&/eval} tags. For instance, I'm working with David on using his SpawnDefaultToken script as a plugin. Currently, you can issue an outbound command to Spawn to have it spawn a token: !The spawned token was {&eval}Spawn --options --options {&/eval}. {&simple} Plugger will issue the command, but nothing is returned. Once Plugger has issued the Spawn call, the EVAL block is removed, and what survives in the line is: !The spawned token was {&simple} Once Spawn is setup to work as a plugin, it will still work on its own, but if called from an EVAL block, it will return the ID of the spawned token, leaving something more like: !The spawned token was -M1234567890abcdef {&simple} You can see where that would be handy, especially if you wanted to apply a TokenMod alteration to the token you JUST spawned. The long and short of it is: your commands don't have to return anything to the line. You just need them to operate one after the other as if they were issued from the same macro (and the Roll20 drop-line bug wasn't interfering). So you only need to wrap the existing command lines in EVAL blocks, and you should be good. As for why TokenActionMaker might be a problem, I'd have to take a look at the script to know how it was built, whether it was trying to do anything asynchronously, or if anything it was trying to utilize would be relying on previous commands that hadn't resolved... but you might get more information on those questions posting over on the API board.