Advertisement Create a free account

[Sheet Worker] Setting Roll Based on Variable in Repeating Section

1549896235
Shukin
Pro
Sheet Author
Continuing from this topic , I'm trying to set up a Repeating Section for weapons, where each section has a dropdown to set the weaponRange . weaponRange can only be 0 (melee) and 1 (ranged). When you change weaponRange , the value of another attribute ( atkOutput ) is supposed to be changed for the correct roll using a sheet worker, so I don't duplicate rolls like I was doing before. The thing is: I'm not being able to read the weaponRange being changed through the sheet worker, so I'm definitely doing it wrong. I tried the following code to read all values in the Repeating Section repeating_weapons and set each atkOutput , but again, it's not reading: on("sheet:opened change:repeating_weapons:weaponRange", function() { var tempOutput; getSectionIDs("repeating_weapons", function(idarray){         if (idarray.length>0) {                 _.each(idarray, function(currentID) {                 getAttrs(["repeating_weapons_"+currentID+"_weaponRange"], function(values) {                 rangeValue = Number(values["repeating_weapons_"+currentID+"_weaponRange"]);                     if (rangeValue == 1) {         tempOutput = "[[1d20cs+(@{rangedRoll})]]";         }         if (rangeValue == 0) {         tempOutput = "[[1d20cs+(@{meleeRoll})]]";         }         setAttrs({         ["repeating_weapons_"+currentID+"_atkOutput"]: tempOutput         });                 });             });         }        }); }); I'm not exactly sure what the problem might be, but I'm guessing the Repeating Section name's syntax usage, as I'm not exactly experienced with them.
1549900841

Edited 1549917755
GiGs
Pro
Sheet Author
you only need to use getSectionIDS when you are reading attributes from more than one "row" of the repeating section. Since wpnRange and atkOuput are on the same row, you treat them exactly the same as non-repeating sections. on("sheet:opened change:repeating_weapons:weaponRange", function () { getAttrs(["repeating_weapons_weaponRange"], function (values) { var rangeValue = Number(values["repeating_weapons_weaponRange"]); var tempOutput; if (rangeValue === 1) { // using triple equalities is better when you known the data type. tempOutput = "[[1d20cs+(@{rangedRoll})]]"; } else if (rangeValue === 0) {    // using 'else' is better, when you're repeatedly checking the same value tempOutput = "[[1d20cs+(@{meleeRoll})]]"; } setAttrs({ repeating_weapons_atkOutput: tempOutput }); }); }); One thing to be wary of, is can the rangeValue have a value that is not 0 or 1. Does it have a default value? In which case, you want to handle that before the setAttrs, to make sure that empty tempoutput values dont cause your roll button to fail. maybe set at the start,  var tempOutput = "[[1d20]]" to handle such situations.
1549901626

Edited 1549902054
GiGs
Pro
Sheet Author
Incidentally, one problem with your version was the fact you nested everything - including the setAttrs call - inside a loop, That's a bad idea. Since you'll likely need to do this again at some point, the proper way to handle that situation would be to do something like this: on("sheet:opened change:repeating_weapons:weaponRange", function () { getSectionIDs("repeating_weapons", function (idarray) { let fieldNames = []; idarray.forEach(function (id) { //forEach is an alternative to _each, native to javascript. fieldNames.push("repeating_weapons_" + id + "_weaponRange"); }); getAttrs(fieldNames, function (values) { let output = {}; // create an object literal, to hold the outputs key/value pairs. idarray.forEach(id => { // this is an alternative syntax, works the same as the previous forEach, but is simpler. let rangeValue = parseInt(values["repeating_weapons_" + id + "_weaponRange"]),10)||0; // I prefer parseInt to number let outputKey = "repeating_weapons_" + id + "_atkOutput"; if (rangeValue === 1) { output[outputKey] = "[[1d20cs+(@{rangedRoll})]]"; } else if (rangeValue === 0) { output[outputKey] = "[[1d20cs+(@{rangedRoll})]]"; } }); setAttrs(output); }); }); }); Inside getSectionIds, you loop through the repeating section rows, and build an array of the attribute names you need. Then run a single (not looped) getAttrs/setAttrs routine, giving getAttrs that array of attribute names. Inside getAttrs you loop through the idarray again to build a set of output values. In each loop, build the attribute name for this row of the section, get its value, and and build the output value you need, and store it in the object. Then once that loop is complete, you have an output object which contains all the attributes you plan to change. Simply pass that to setAttrs and you're done.
1549915494
Shukin
Pro
Sheet Author
Changing the variable names to their correct versions (I used simplified ones for the example), the first and second codes are currently with the same problem: I can't make it actually read the proper weaponRange . Testing its output with a console.log command to show the variable as it is captured, and omitting the rest of the process, it always assumes the default value set (in this case, 0) and, if removing the default value on the parseInt, it results in a NaN, so it's still not reading the variable. The rest of the code works out properly, comparing the value and setting the right roll. I'm not sure what's wrong with it, so I'm posting the code without placeholders to see if it was something I edited wrongly: on("sheet:opened change:repeating_armas:range_arma", function () { getAttrs(["range_arma"], function (v) { var rangeValue = v.range_arma; var tempOutput = "[[1d20]]"; if (rangeValue === 1) { tempOutput = "[[1d20cs>@{critrangearma}+(@{ADistancia})-(@{des_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } else if (rangeValue === 0) { tempOutput = "[[1d20cs>@{critrangearma}+(@{CorpoaCorpo})-(@{for_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } setAttrs({ repeating_armas_tipoataqueoutput: tempOutput }); }); }); Also, I'm using the simplest version of the code just to check if it'll read the variable at all, which is not working despite being the simplest one.
1549917605

Edited 1549917802
GiGs
Pro
Sheet Author
Oh! i forgot to include the repeating section in my first example, so you might need to change this var rangeValue = v.range_arma; should be var rangeValue = v.repeating_armas_range_arma; likewise getAttrs should be getAttrs(["repeating_armas_range_arma"], function (v) { Also, in your if statement, if you aren't using parseInt or number, you might need to change the statement to if (rangeValue === '1') { tempOutput = "[[1d20cs>@{critrangearma}+(@{ADistancia})-(@{des_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } else if (rangeValue === '0') { tempOutput = "[[1d20cs>@{critrangearma}+(@{CorpoaCorpo})-(@{for_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } since values from getAttrs are automatically strings unless coerced into another data type.
1549921281

Edited 1549921940
Shukin
Pro
Sheet Author
Adding the repeating_armas_ to the rangeValue made it work out the variable now, but using this method, the console gives out the following error: SHEET WORKER ERROR: You attempted to set an attribute beginning with 'repeating_' but did not include a Row ID or Attribute Name in repeating_armas_tipoataqueoutput Trying to get the row ID through eventInfo is not working as well, as the console lists this if I try to get eventInfo.sourceAttribute: ReferenceError: eventInfo is not defined I tried the eventInfo method because that's what is used on the official Roll20 D&D character sheet, so I was aiming to read it to see if I could cut the ID out with a substring. This is how the code is currently, with all the console.log that I'm using to try to understand what's happening. on("sheet:opened change:repeating_armas:range_arma", function () { var info = eventInfo.sourceAttribute; console.log(info); getAttrs(["repeating_armas_range_arma"], function (v) { var rangeValue = v.repeating_armas_range_arma; var tempOutput = "[[1d20]]"; if (rangeValue === '1') { tempOutput = "[[1d20cs>@{critrangearma}+(@{ADistancia})-(@{des_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } else if (rangeValue === '0') { tempOutput = "[[1d20cs>@{critrangearma}+(@{CorpoaCorpo})-(@{for_mod})+(@{atributochavearma})+(@{bonusarma})]]"; } console.log(rangeValue); console.log(tempOutput); setAttrs({ repeating_armas_tipoataqueoutput: tempOutput }); }); });
1549923128
GiGs
Pro
Sheet Author
any idea on which line the error is occurring? 
1549923556
Shukin
Pro
Sheet Author
This is the rest of the eventInfo error: @https://app.roll20.net/js/d20/sheetsandboxworker.js?1549921185513 line 698 > eval:211:9 self.trigger@https://app.roll20.net/js/d20/sheetsandboxworker.js?1549921185513:110:37 messageHandler@https://app.roll20.net/js/d20/sheetsandboxworker.js?1549921185513:702:6 So it quotes line 698 of the source JS for the error.
1549924125
GiGs
Pro
Sheet Author
my guess is its an error with the destination name, this section: setAttrs({ repeating_armas_tipoataqueoutput: tempOutput }); Is the attribute actually called:  tipoataqueoutput ? I created a new campaign, and put this as the only html (note: i added eventInfo in the function statement, your code above is missing that). <fieldset class="repeating_armas">     <input type="number" name="attr_range_arma" value="1"  />     <input type="text" name="attr_tipoataqueoutput" value="1"  /> </fieldset> <script type="text/worker"> on("sheet:opened change:repeating_armas:range_arma", function (eventInfo) {     var info = eventInfo.sourceAttribute;     console.log('=================' + info);     getAttrs(["repeating_armas_range_arma"], function (v) {         var rangeValue = v.repeating_armas_range_arma;         var tempOutput = "[[1d20]]";         if (rangeValue === '1') {              tempOutput = "[[1d20cs>@{critrangearma}+(@{ADistancia})-(@{des_mod})+(@{atributochavearma})+(@{bonusarma})]]";         } else if (rangeValue === '0') {                 tempOutput = "[[1d20cs>@{critrangearma}+(@{CorpoaCorpo})-(@{for_mod})+(@{atributochavearma})+(@{bonusarma})]]";         }         console.log('================= ' + rangeValue);         console.log('================= ' + tempOutput);         setAttrs({             repeating_armas_tipoataqueoutput: tempOutput         });     }); }); </script> The above code worked properly. I'm guessing this has the wrong attribute name: repeating_armas_tipoataqueoutput: tempOutput
1549928306
Shukin
Pro
Sheet Author
The lack of the eventInfo on the function statement corrected the problem I was having with the ID. Also, found out why the tempOutput wasn't being corrected by the if's, as I was testing against a single number, but I forgot (and it went completely over my head at every console log message until now) that I put them as conditional rolls for the roll template, which means they were [[0]] and [[1]] all this time. The resulting code is the one that worked properly, thank you for the help! on("sheet:opened change:repeating_armas:range_arma", function (eventInfo) {     var id = eventInfo.sourceAttribute.substring(17,36);     getAttrs(["repeating_armas_range_arma"], function (v) {         var rangeValue = v.repeating_armas_range_arma;         var tempOutput = "[[1d20]]";         if (rangeValue === "[[1]]") {             tempOutput = "[[1d20cs>@{critrangearma}+(@{ADistancia})-(@{des_mod})+(@{atributochavearma})+(@{bonusarma})]]";         } else if (rangeValue === "[[0]]") {                tempOutput = "[[1d20cs>@{critrangearma}+(@{CorpoaCorpo})-(@{for_mod})+(@{atributochavearma})+(@{bonusarma})]]";         }         console.log('================= ' + rangeValue);         console.log('================= ' + tempOutput);         setAttrs({             ["repeating_armas_" + id + "_tipoataqueoutput"]: tempOutput         });     }); });
1549928548
GiGs
Pro
Sheet Author
You're welcome! It's still weird to me that your setAttrs is in the format it is. It shouldn't need to use the id. But if it works, it works.
1549963409
Finderski
Pro
Sheet Author
GiGs said: You're welcome! It's still weird to me that your setAttrs is in the format it is. It shouldn't need to use the id. But if it works, it works. Perhaps it's because of the underscore in the name? I wonder if it would be necessary if the field were simply  rangearma?
1549989840
GiGs
Pro
Sheet Author
I tested it as mentioned in a post above with  repeating_armas_tipoataqueoutput: tempOutput and it worked fine. I'm pretty sure I've used names like  repeating_skills_Skill_Athletics , though I may need to check that. I think roll20 is smart enough to recognise the underscore placement in compound names like this. But when I tested it where there was a name mismatch (using  repeating_armas_tipoataqueoutput but the attribute named in the input was actually  tipoataque , and there was no actual  tipoataqueoutput attribute) I saw the error described earlier. That's why i sugegsted earlier I thought it was a name mismatch.