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

Sheet Worker confusion

1619199166

Edited 1619234920
I have many sheet workers on my new character sheet for Castles and Crusades. Some work, and some, well, don't work as well. For example, this one. <script type="text/worker"> on("change:rangerclass change:smite change:level change:enemy", function() {          getAttrs(["RangerClass","Smite","Level","Enemy"], function(values) {     let rangerclass = parseInt(values.RangerClass)||0; let level = parseInt(values.Level)||0;     let modifier;     // the scale if (rangerclass == 0) modifier = 0;     setAttrs({Enemy : modifier});  }); }); </script> If you are not a ranger and you click the associated checkbox, it automatically clicks back off. If I add a (rangerclass == 1) modifier = 1 to the scale then it will automatically be checked if you are a ranger, and if you check it off, it will check back on. So that one is fine. However, this one isn't.  <script type="text/worker"> on("change:animosity change:dwarfrace change:gnomerace change:elfrace change:halfelfrace change:halforcrace change:humanrace change:halflingrace", function() {          getAttrs(["Animosity","DwarfRace","GnomeRace","HalfElfRace","HalfOrcRace","HumanRace","HalflingRace","ElfRace"], function(values) {     let dwarfrace = parseInt(values.DwarfRace)||0;     let gnomerace = parseInt(values.GnomeRace)||0;     let elfrace = parseInt(values.ElfRace)||0;     let halfelfrace = parseInt(values.HalfElfRace)||0;     let halforcrace = parseInt(values.HalfOrcRace)||0;     let halflingrace = parseInt(values.HalflingRace)||0;     let humanrace = parseInt(values.HumanRace)||0;     let modifier;     // the scale if (elfrace == 1) modifier = 0; if (halfelfrace == 1) modifier = 0; if (halforcrace == 1) modifier = 0; if (humanrace == 1) modifier = 0; if (halflingrace == 1) modifier = 0;     setAttrs({Animosity : modifier});  }); }); </script>  The intent is that if you are not a gnome or dwarf then your modifier will be set at 0 for animosity and if you check the box, it will automatically check off. But this one doesn't work. Nor does this one which is designed to set your hit die type based on class.  <script type="text/worker">     on("change:h.d.type change:assassinclass change:barbarianclass change:bardclass change:clericclass change:druidclass change:fighterclass change:illusionistclass change:knightclass change:monkclass change:paladinclass change:rangerclass change:rogueclass change:wizardclass", (eventInfo) => {                getAttrs(["H.D.Type","AssassinClass","BarbarianClass","BardClass","ClericClass","DruidClass","FighterClass","IllusionistClass","KnightClass","MonkClass","PaladinClass","RangerClass","RogueClass","WizardClass"], function(values) { let assassinclass = parseInt(values.AssassinClass) || 0; let barbarianclass = parseInt(values.BarbarianClass) || 0; let bardclass = parseInt(values.BardClass) || 0; let clericclass = parseInt(values.ClericClass) || 0; let druidclass = parseInt(values.DruidClass) || 0; let fighterclass = parseInt(values.FighterClass) || 0; let illusionistclass = parseInt(values.IllusionistClass) || 0; let knightclass = parseInt(values.KnightClass) || 0; let monkclass = parseInt(values.MonkClass) || 0; let paladinclass = parseInt(values.PaladinClass) || 0; let rangerclass = parseInt(values.RangerClass) || 0; let rogueclass = parseInt(values.RogueClass) || 0; let wizardclass = parseInt(values.WizardClass) || 0; let modifier = (assassinclass === 1) ? "d6" : (barbarianclass === 1) ? "d12" : (bardclass === 1) ? "d10" : (clericclass === 1) ? "d8" : (druidclass === 1) ? "d8" : (fighterclass === 1) ? "d10" : (illusionistclass === 1) ? "d4" : (knightclass === 1) ? "d10" : (monkclass === 1) ? "d12" : (paladinclass === 1) ? "d10" : (rangerclass === 1) ? "d10" : (rogueclass === 1) ? "d6" : (wizardclass === 1) ? "d4" :;             setAttrs({H.D.Type : modifier});          });     }); </script> Also, what if I just wanted to have the first one be conditional on level and class or available to two classes: so if (rangerclass == 0) or/and (assassinclass == 0) : modifier = 0 I know these probably look sloppy or unrefined, but I am just trying to get them to work. 
1619201962
Andreas J.
Forum Champion
Sheet Author
Translator
Please use the "code" formatting when posting code, it makes things infinity more readable and distinct from the rest. First place the code block in your post, then use ctrl+shift+V to paste the code without formatting(so it ends up in the codeblock. Original post, with code formatting I have many sheet workers on my new character sheet for Castles and Crusades. Some work, and some, well, don't work as well. For example, this one. <script type="text/worker"> on("change:rangerclass change:smite change:level change:enemy", function() { getAttrs(["RangerClass","Smite","Level","Enemy"], function(values) { let rangerclass = parseInt(values.RangerClass)||0; let level = parseInt(values.Level)||0; let modifier; // the scale if (rangerclass == 0) modifier = 0; setAttrs({Enemy : modifier}); }); }); </script> If you are not a ranger and you click the associated checkbox, it automatically clicks back off. If I ass if (rangerclass == 1) modifier = 1 to the scale then it will automatically be checked if you are a ranger, and if you check it off, it will check back on. So that one is fine. However, this one isn't.  <script type="text/worker"> on("change:animosity change:dwarfrace change:gnomerace change:elfrace change:halfelfrace change:halforcrace change:humanrace change:halflingrace", function() { getAttrs(["Animosity","DwarfRace","GnomeRace","HalfElfRace","HalfOrcRace","HumanRace","HalflingRace","ElfRace"], function(values) { let dwarfrace = parseInt(values.DwarfRace)||0; let gnomerace = parseInt(values.GnomeRace)||0; let elfrace = parseInt(values.ElfRace)||0; let halfelfrace = parseInt(values.HalfElfRace)||0; let halforcrace = parseInt(values.HalfOrcRace)||0; let halflingrace = parseInt(values.HalflingRace)||0; let humanrace = parseInt(values.HumanRace)||0; let modifier; // the scale if (elfrace == 1) modifier = 0; if (halfelfrace == 1) modifier = 0; if (halforcrace == 1) modifier = 0; if (humanrace == 1) modifier = 0; if (halflingrace == 1) modifier = 0; setAttrs({Animosity : modifier}); }); }); </script>  The intent is that if you are not a gnome or dwarf then your modifier will be set at 0 for animosity and if you check the box, it will automatically check off. But this one doesn't work. Nor does this one which is designed to set your hit die type based on class.  <script type="text/worker"> on("change:h.d.type change:assassinclass change:barbarianclass change:bardclass change:clericclass change:druidclass change:fighterclass change:illusionistclass change:knightclass change:monkclass change:paladinclass change:rangerclass change:rogueclass change:wizardclass", (eventInfo) => { getAttrs(["H.D.Type","AssassinClass","BarbarianClass","BardClass","ClericClass","DruidClass","FighterClass","IllusionistClass","KnightClass","MonkClass","PaladinClass","RangerClass","RogueClass","WizardClass"], function(values) { let assassinclass = parseInt(values.AssassinClass) || 0; let barbarianclass = parseInt(values.BarbarianClass) || 0; let bardclass = parseInt(values.BardClass) || 0; let clericclass = parseInt(values.ClericClass) || 0; let druidclass = parseInt(values.DruidClass) || 0; let fighterclass = parseInt(values.FighterClass) || 0; let illusionistclass = parseInt(values.IllusionistClass) || 0; let knightclass = parseInt(values.KnightClass) || 0; let monkclass = parseInt(values.MonkClass) || 0; let paladinclass = parseInt(values.PaladinClass) || 0; let rangerclass = parseInt(values.RangerClass) || 0; let rogueclass = parseInt(values.RogueClass) || 0; let wizardclass = parseInt(values.WizardClass) || 0; let modifier = (assassinclass === 1) ? "d6" : (barbarianclass === 1) ? "d12" : (bardclass === 1) ? "d10" : (clericclass === 1) ? "d8" : (druidclass === 1) ? "d8" : (fighterclass === 1) ? "d10" : (illusionistclass === 1) ? "d4" : (knightclass === 1) ? "d10" : (monkclass === 1) ? "d12" : (paladinclass === 1) ? "d10" : (rangerclass === 1) ? "d10" : (rogueclass === 1) ? "d6" : (wizardclass === 1) ? "d4" :; setAttrs({H.D.Type : modifier}); }); }); </script> Also, what if I just wanted to have the first one be conditional on level and class or available to two classes: so if (rangerclass == 0) or/and (assassinclass == 0) : modifier = 0 I know these probably look sloppy or unrefined, but I am just trying to get them to work.
Thank you for the advice and information. I will try to remember that in the future. Is there something I'm doing wrong in these codes?
1619235698

Edited 1619236598
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
So, I don't think all of these are the cause of your issue, but here's some best practice issues that I notice: 1. Use === instead of == (and !== instead of !=) for comparisons if (rangerclass == 0) modifier = 0; should be if (rangerclass === 0) modifier = 0; This is because of how the similarity is evaluated when you use == vs. ===. Long story short, == forces the object type to change to be the same. This seems like a preferred thing (e.g. you can do 0=="0" and get true back), but is not actually preferred because the forced type can return some very strange results in certain circumstances. 2. Using the Ternary operator I believe this is something that is actually causing your script failure. There are definite places where using the ternary operator can make your code more readable, but I think that this is a place where using if, else if, else would be much better. The part that I think is causing your script to fail here is that you never finish the ternary: let modifier = (assassinclass === 1) ? "d6" : (barbarianclass === 1) ? "d12" : (bardclass === 1) ? "d10" : (clericclass === 1) ? "d8" : (druidclass === 1) ? "d8" : (fighterclass === 1) ? "d10" : (illusionistclass === 1) ? "d4" : (knightclass === 1) ? "d10" : (monkclass === 1) ? "d12" : (paladinclass === 1) ? "d10" : (rangerclass === 1) ? "d10" : (rogueclass === 1) ? "d6" : (wizardclass === 1) ? "d4" :;//There needs to be something that happens on false here Compare to using if/else: let modifier; if(assassinclass === 1) modifier = "d6"; else if(barbarianclass === 1) modifier = "d12"; else if(bardclass === 1) modifier = "d10"; else if(clericclass === 1) modifier = "d8"; else if(druidclass === 1) modifier = "d8"; else if(fighterclass === 1) modifier = "d10"; else if(illusionistclass === 1) modifier = "d4"; else if(knightclass === 1) modifier = "d10"; else if(monkclass === 1) modifier = "d12"; else if(paladinclass === 1) modifier = "d10"; else if(rangerclass === 1) modifier = "d10"; else if(rogueclass === 1) modifier = "d6"; else if(wizardclass === 1) modifier = "d4" ; It's not that much more typing, and it's a lot easier to see where the logic ends. Your current code probably generated a syntaxError: unexpected token in the console log. 3. Use snake_case instead of camelCase for sheet attribute names This one probably isn't breaking your script, but it's something that is good to keep in mind for several reasons. With camelCase, you need to write your attributes in all lower case in the on, and then can use camelCase in the getAttrs. With snake_case, you can write your attribute names the same in both places and have them reflect the way you have them on the sheet. Also keep in mind that, except for the on, attribute names are case IN sensitive. This means that if you have halfelfrace and HalfElfRace on your sheet expecting them to be different, they are actually the same attribute as far as attribute calls and sheetworker getAttrs/setAttrs are concerned. And, finally, from an accessibility stand point; snake_cased attribute names are easier for a screen reader to read than camelCased attribute names which is an important point if you want your sheet to be usable by a wide audience. Note that I'd also recommend using this instead of H.D.Type 4. The value you are setting an attribute to has to be a valid value (e.g. a number or text). In your second problem script, it's extremely easy for modifier to never actually be set and then you are trying to do this: setAttrs({animosity:undefined}); Which will most likely spawn an error in your developer console. 5. And, finally, I'd highly recommend using the developer console (ctrl-shift-i on chrome PC, cmd-shift-i on chrome mac) and console.log() to troubleshoot your scripts. Trying to code without using these tools is like trying to carve a statue while blind; you can do it, but there's gonna be a lot of mistakes you don't even know are there. 6. This is actually #10 on the common mistakes list . Use a linter/syntax checker on your code when you run into odd errors. My preferred is the google closure compiler . This is especially important once you start using the developer console as the error reporting on syntaxErrors is useless for anything other than just know that you have the error. Running your code through a linter/syntax checker like the closure compiler will pinpoint where in your code your syntax error is. EDITED to add # 6 recommendation