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

Sheetworkers and Drop Menus

I am trying to set a weapon's damage based on how many hands hold it and a special notation for the weapon. So if the weapon has note 9 and is held 2 handed standard it is 1d12 damage, but if held 1 handed standard it is 1d10 damage. Here is the sheetworker I have so far: <script type="text/worker"> on("change:weaponspec_1 change:weaponhand_1 change:weapondmg_1 sheet:opened", function() {          getAttrs(["WeaponSpec_1","WeaponHand_1","WeaponDmg_1"], function(values) {     let weaponspec_1 = parseInt(values.WeaponSpec_1)||0;     let weaponhand_1 = parseInt(values.WeaponHand_1)||0;     let modifier;     // the scale if (weaponspec_1 == 9 && weaponhand_1 == 1) modifier = "1d12"; else if (weaponspec_1 == 9 && weaponhand_1 == 0) modifier = "1d10";     setAttrs({weapondmg_1 : modifier});  }); }); </script> Here is the standard weapon entry: <input type="hidden" name="attr_WeaponToggle_1" value="0" class="showStuff" /> <table class="hiddenTable">     <tr>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">EV</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Range</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Ammo</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Note</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Trait</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Type</td>     </tr>     <tr>         <td><input type="number" name="attr_WeaponEV_1" STYLE="width: 40px" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponRange_1" class="short alcenter" value="0" /></td>  <td>             <select name="attr_WeaponAmmo_1" STYLE="width: 60px;font-size: 10px" class="short alright">                 <option value="Melee" selected="selected">Melee</option>                 <option value="Thrown" >Thrown</option>                 <option value="Arrow" >Arrow</option>                 <option value="Bolt" >Bolt</option>                 <option value="Stone" >Stone</option>             </select>         </td>         <td>             <select name="attr_WeaponSpec_1" STYLE="width: 47px;font-size: 10px" class="short alright">                  <option value="0" selected="selected">NA</option>                 <option value="1" >1</option>                 <option value="2" >2</option>                 <option value="3" >3</option>                 <option value="4" >4</option>                 <option value="5" >5</option>                 <option value="6" >6</option>                 <option value="7" >7</option>                 <option value="8" >8</option>                 <option value="9" >9</option>                 <option value="10" >10</option>                 <option value="11" >11</option>             </select>         </td>         <td>             <select name="attr_WeaponTrait_1" STYLE="width: 47px;font-size: 10px" class="short alright">                 <option value="0" selected="selected">NA</option>                 <option value="*" >*</option>                 <option value="@" >@</option>                 <option value="*@" >*@</option>             </select>         </td>                 <td>             <select name="attr_WeaponType_1" STYLE="width: 63px;font-size: 10px" class="short alright">                  <option value="Blunt" selected="selected">Blunt</option>                 <option value="Slash" >Slash</option>                 <option value="Pierce" >Pierce</option>                 <option value="Fire" >Fire</option>                 <option value="Cold" >Cold</option>                 <option value="Acid" >Acid</option>                 <option value="Electric" >Electric</option>                 <option value="Poison" >Poison</option>             </select>         </td>     </tr> </table> <table class="hiddenTable">     <tr>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Attr</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">BtH +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Mod +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Misc +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Magic</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">= Total</td>     </tr>     <tr>         <td>             <select name="attr_WeaponHitAttr_1" STYLE="width: 75px;font-size: 10px" class="short alright">                 <option value="0" selected="selected">NA</option>                 <option value="1" >STR</option>                 <option value="2" >DEX</option>                 <option value="3" >CON</option>                 <option value="4" >INT</option>                 <option value="5" >WIS</option>                 <option value="6" >CHA</option>             </select>         </td>         <td><input type="number" name="attr_WeaponBth_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponHitMod_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponHitMisc_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponHitMagic_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponHitTotal_1" class="short alcenter" value="0" /></td>     </tr> </table> <table class="hiddenTable">     <tr>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Attr</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Dmg +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Mod +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Misc +</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Magic</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">= Total</td>     </tr>     <tr>         <td>             <select name="attr_WeaponDmgAttr_1" STYLE="width: 75px;font-size: 10px" class="short alright">                  <option value="0" selected="selected">NA</option>                 <option value="1" >STR</option>                 <option value="2" >DEX</option>                 <option value="3" >CON</option>                 <option value="4" >INT</option>                 <option value="5" >WIS</option>                 <option value="6" >CHA</option>             </select>         </td>         <td><input type="text" name="attr_WeaponDmg_1" class="short alcenter" value="1d0" /></td>         <td><input type="number" name="attr_WeaponDmgMod_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponDmgMisc_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponDmgMagic_1" class="short alcenter" value="0" /></td>         <td><input type="number" name="attr_WeaponDmgTotal_1" class="short alcenter" value="0" /></td>     </tr></table><table class="hiddenTable">         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Hand</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Magic</td>         <td class="bluehilite boldme alcenter" style="background-color:maroon;color:gold;text-shadow:2px 2px 2px #000000;">Slayer</td> </tr>         <tr>                   <td>             <select name="attr_WeaponHand_1" STYLE="width: 95px;font-size: 10px" class="short alright">                 <option value="0" selected="selected">1H Standard</option>                 <option value="1" >2H Standard</option>                 <option value="3" >1H Prime</option>                 <option value="6" >1H Off</option>             </select>         </td>       <td><select name="attr_WeaponMagical_1" STYLE="width: 55px;" class="short alright">  <option value="0"  selected="selected">No</option>  <option value="1" >Yes</option></select><td><input type="text" name="attr_WeaponSlayer_1" width="75" STYLE="width: 75px" size="0" class="short" value="None" /></td> </tr> </table> </div>
1622570785
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, what's the issue you are running into?
It doesn't set the damage.
1622573479
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, a couple things I notice. It is possible, actually very likely, to have modifier never set. This then results in modifier being undefined, and will cause setAttrs  to error out. You'll see this if you watch the developer console while working with your sheet. This is probably causing your problem because when setAttrs errors out in this way, it also corrupts the attribute that it was trying to set and makes it unchangeable by the sheetworker until a refresh. I'd recommend wrapping your setAttrs  in an if: if(modifier){     setAttrs({weapondmg_1:modifier}); }  And, just some general code critique. ==  is technically correct, but really ===  should be used instead. The full reasoning is admittedly a little beyond my code knowledge. The tldr though is that ==  (and != ) coerce the variable on the right side to match the type of the variable on the left side. While this seems like it is preferable, it has some odd effects where things you think would be equivalent aren't, and vice versa. Additionally, this behavior can depend on what type is on the left or right of the comparison. To ensure that you get consistent behavior, ===  (and !== ) are the preferred comparison methods as they compare the types rather than coercing them to be the same. This stack overflow thread has some good descriptions of the problems you can run into.
1622574212
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
One of my favorite the Aaron quotes: You'll always want to use "===" until you learn the difference between "==" and "===". And then you'll always want to use "===".
1622583801
GiGs
Pro
Sheet Author
API Scripter
Another thing you can do that is handy is (when setting values that are going to be used in setAttrs) is never do this: let modifier; But instead always set a default value that is valid, like let modifier = "1d6"; or something that will show the user there is a problem, like let modifier = "N/A"; When you letter set the modifier, you overwrite that default value, but having a default value that is invalid, you can see if something isn't being set properly. You can also combine it with CSS to change the HTML attribute's colour to read, or something, when it equals the default value. Again, so it makes it easy to spot there's an incorrect value somewhere. But as Scott points out, the main issue is here: if (weaponspec_1 == 9 && weaponhand_1 == 1) modifier = "1d12"; else if (weaponspec_1 == 9 && weaponhand_1 == 0) modifier = "1d10"; You don't handle what happens when weaponspec_1 is not 9.
If it's not 9 it's whatever value you make it. With the modifications given above I was able to get it to work. GiGs said: But as Scott points out, the main issue is here: if (weaponspec_1 == 9 && weaponhand_1 == 1) modifier = "1d12"; else if (weaponspec_1 == 9 && weaponhand_1 == 0) modifier = "1d10"; You don't handle what happens when weaponspec_1 is not 9.
Thank you Scott C. I got it to work.  Scott C. said: Ok, a couple things I notice. It is possible, actually very likely, to have modifier never set. This then results in modifier being undefined, and will cause setAttrs  to error out. You'll see this if you watch the developer console while working with your sheet. This is probably causing your problem because when setAttrs errors out in this way, it also corrupts the attribute that it was trying to set and makes it unchangeable by the sheetworker until a refresh. I'd recommend wrapping your setAttrs  in an if: if(modifier){     setAttrs({weapondmg_1:modifier}); }  And, just some general code critique. ==  is technically correct, but really ===  should be used instead. The full reasoning is admittedly a little beyond my code knowledge. The tldr though is that ==  (and != ) coerce the variable on the right side to match the type of the variable on the left side. While this seems like it is preferable, it has some odd effects where things you think would be equivalent aren't, and vice versa. Additionally, this behavior can depend on what type is on the left or right of the comparison. To ensure that you get consistent behavior, ===  (and !== ) are the preferred comparison methods as they compare the types rather than coercing them to be the same. This stack overflow thread has some good descriptions of the problems you can run into.
1622618368
GiGs
Pro
Sheet Author
API Scripter
I see a potential problem with this approach if you don't also make other changes to the code. To illustrate, lets say your player sets weaponspec_1 to 9 and weaponhand_1 to 1. The modifier will be set to d12. So far so good. Then the player changes weaponspec_1 to 7. The worker above runs, but since modifier is not set and still undefined, setAttrs does not run, and the modifier on the sheet is still d12. Changing weaponspec_1 to any value other than 9, and the modifier will remain d12. If this is not how it should behave, you need to either set a default value, or extend you if statement to account for the other possible weaponspec_1 values.
Why would they change weaponspec_1? The only reason would be that the weapon itself is being changed to a completely different weapon since weaponspec_1 is a trait of the weapon being used. The only thing a the player should be changing is whether they are using the weapon one handed or two handed. So they would have to change the damage code manually if the were changing the weapon anyway. This is for a custom Castles and Crusades sheet and this would only apply to a weapon with the 9 footnote. There is only one such weapon in the game. I know it seems like a lot of work for a bastard sword, but I'm trying to mimic the game as best as possible.
1622631131
GiGs
Pro
Sheet Author
API Scripter
I guarantee it will happen. A player might decide to reuse the row, and simply change the entries for the weapkn to change it to something else. I wouldn't hammer on about it, except it's such an easy fix. Just change this line let modifier; to let modifier = "1d0"; or let modifier = "0"; and that's it - your code works for the weaponspec_1 9 weapons, and it works for every other weapon too - and it handles players changing the weapon type should they do that.
So... <script type="text/worker"> on("change:weaponspec_1 change:weaponhand_1 change:weapondmg_1 sheet:opened", function() {          getAttrs(["WeaponSpec_1","WeaponHand_1","WeaponDmg_1"], function(values) {     let weaponspec_1 = parseInt(values.WeaponSpec_1)||0;     let weaponhand_1 = parseInt(values.WeaponHand_1)||0;     let modifier = "1d0";     // the scale if (weaponspec_1 === 9 && weaponhand_1 === 1) modifier = "1d12"; else if (weaponspec_1 === 9 && weaponhand_1 === 0) modifier = "1d10";     setAttrs({weapondmg_1 : modifier});  }); }); </script>
1622634822
GiGs
Pro
Sheet Author
API Scripter
That looks good to me! You could perform a minor optimisation - this isn't necessary. But if you read the modifier value from the sheet, you could take Scott's suggestion and only run setAttrs if the value actually changes. setAttrs is a slow operation, so it's handy to cut down on its use. That would look something like this: on("change:weaponspec_1 change:weaponhand_1 change:weapondmg_1 sheet:opened", function() {          getAttrs(["WeaponSpec_1","WeaponHand_1","WeaponDmg_1"], function(values) {     let weaponspec_1 = parseInt(values.WeaponSpec_1)||0;     let weaponhand_1 = parseInt(values.WeaponHand_1)||0; let oldmodifier = values.weaponDmg_1;     let modifier = "1d0";     // the scale if (weaponspec_1 === 9 && weaponhand_1 === 1) modifier = "1d12"; else if (weaponspec_1 === 9 && weaponhand_1 === 0) modifier = "1d10"; // check if modifier has changed, and only call setAttrs if it has     if(modifier !== oldmodifier) {         setAttrs({weaponDmg_1 : modifier});      } }); }); There's a possible extra optimisation. Can players manually change the weapondmg_1 rating? If they can, then leave the worker as is. If they cant, I suggest two changes: first change this line <td><input type="text" name="attr_WeaponDmg_1" class="short alcenter" value="1d0" /></td> to <td><input type="text" name="attr_WeaponDmg_1" class="short alcenter" value="1d0" readonly /></td> That protects the value from being altered by players. Only the worker can set it. The second change is to change the first line of the worker from on("change:weaponspec_1 change:weaponhand_1 change:weapondmg_1 sheet:opened", function() {  to on("change:weaponspec_1 change:weaponhand_1 sheet:opened", function() {  Since that value is being set by the worker, you don't need it in the event line (the line above), and having it there is causing the worker to run more often than is needed. Here's what happens:        The worker runs, and setAttrs sets weapondmg_1.    But weapondmg_1 is in the on(change) line, so a change triggers the worker to run again - but there is nothing to change.. So its best to remove it from that line if players cant manually change weapondmg_1