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

Help using Sheetworker if statments to select choices from a dropdown

Ok, first time using sheetworker and I'm struggling finding the right place to start. I'm trying to get the D&D3.5 sheet to auto detect encumbrance load. It currently has the user manually use a dropdown box to select between light medium and heavy. My goal is to use sheetworker to scan current load ranges than use IF statements to find the correct range 'totalcarriedweight' sits in using >=/<= then set the correct dropdown option. Dropdown code:                                 <td><select style="height: 24px; width: 75px; padding: 0px;" name="attr_encumbrload" title="encumbrload (choose the category from above)"> <option value="0.1" data-i18n="light" selected>Light</option> <option value="-3" data-i18n="medium">Medium</option> <option value="-6" data-i18n="heavy">Heavy</option> </select></td> light/medium/heavy load code: <tr> <td><input type="hidden" name="attr_encumbrstr" title="encumbrstr" value="0"> <input class="inputbox" type="text" name="attr_lightloadmax" title="lightloadmax" style="height: 24px; width: 53px; text-align: right;" disabled value="floor(@{encumbrsize}*(floor(@{encumbrstr}/3))*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span> <span data-i18n="or-less">or less</span>.</td> <td><input class="inputbox" type="text" name="attr_medloadmin" title="medloadmin" style="height: 24px; width: 53px; text-align: right;" disabled value="floor(@{encumbrsize}*(floor(@{encumbrstr}/3)*(@{weightscale}))+1)"/>-<input class="inputbox" type="text" name="attr_medloadmax" title="medloadmax" style="height: 24px; width: 53px; text-align: left;" disabled value="floor(@{encumbrsize}*(floor(2*@{encumbrstr}/3))*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span>.</td> <td><input class="inputbox" type="text" name="attr_heavyloadmin" title="heavyloadmin" style="height: 24px; width: 53px; text-align: right;" disabled value="floor(@{encumbrsize}*(floor(2*@{encumbrstr}/3)*(@{weightscale}))+1)"/>-<input class="inputbox" type="text" name="attr_heavyloadmax" title="heavyloadmax" style="height: 24px; width: 53px; text-align: left;" disabled value="floor(@{encumbrsize}*(@{encumbrstr})*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span>.</td> <td><input class="inputbox" type="text" name="attr_liftovermax" title="liftovermax" style="height: 24px; width: 53px; text-align: right;" disabled value="floor(@{encumbrsize}*(@{encumbrstr})*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span> <span data-i18n="or-less">or less</span>.</td> <td><input class="inputbox" type="text" name="attr_liftoffmax" title="liftoffmax" style="height: 24px; width: 53px; text-align: right;" disabled value="floor(@{encumbrsize}*(2*(@{encumbrstr}))*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span> <span data-i18n="or-less">or less</span>.</td> <td><input class="inputbox" type="text" name="attr_pushdragmax" title="pushdragmax" style="height: 24px; width: 58px; text-align: right;" disabled value="floor(@{encumbrsize}*(5*(@{encumbrstr}))*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span> <span data-i18n="or-less">or less</span>.</td> </tr> my first go at the code that I tired copying and changing what I found in this forum. ignore the extra attrs I've been playing around to see if i can get anything to work (it breaks the character sheet) <script type="text/worker"> on("change:totalcarriedweight", function() { getAttrs(["encumbrload","lightloadmax","medloadmin","medloadmax","heavyloadmin","heavyloadmax","totalcarriedweight"], function(values) { const lightloadmax = parseInt(values.lightloadmax) const heavyloadmin = parseInt(values.heavyloadmin) const totalcarriedweight = parseInt(values.totalcarriedweight) const encumbrload = parseInt(values.encumbrload) ///I know I'm messing up here but I don't know the correct way to do it if (totalcarriedweight < lightloadmax) { encumbrload='light'; } else if (totalcarriedweight >= heavyloadmin) { encumbrload='heavy'; } else { encumbrload='medium'; } setAttrs({ attribute: encumbrload }); }); }); </script> I feel like I'm not using the if/else statement correctly. I really have no idea where to start with this thing, particularly with changing the dropdown (light,medium,heavy). Once I can get the basic thing working I know I can run with it, any direction would be appreciated!
1723002311

Edited 1723002476
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
your code looks very close to me. There are a few issues I see: The first is that you have defined your encumbrload  variable as a constant, so it can never be changed from whatever it is first set to. Second, encumbrload is a number on the sheet (all the values of the options in the select are numbers), but you are setting it to the text of the select. Set it to the number corresponding to the option that it needs to be. Third is how you are using the setAttrs . The first argument for setAttrs is an object with the keys being the attribute names and the values being what to set those attributes to. Your setAttrs is setting an attribute named attribute  to be whatever your variable encumbrload winds up being set to. With all of that taken into account, your code should look like: <script type="text/worker"> on("change:totalcarriedweight", function() { //you don't need to actually get the value of encumbrload in the getAttrs since we are just setting it, not using it. getAttrs(["lightloadmax","medloadmin","medloadmax","heavyloadmin","heavyloadmax","totalcarriedweight"], function(values) { const lightloadmax = parseInt(values.lightloadmax) const heavyloadmin = parseInt(values.heavyloadmin) const totalcarriedweight = parseInt(values.totalcarriedweight)     // use let to define encumbrload, and we leave it with a value of undefined initially let encumbrload; // There's some fancier ways to do this, but they don't have any performance enhancement over if/else and // can be less easy to read.     // Changed your logic a little so that it sets at increasing levels of load just to make it a little more readable.     // Also I think you actually wanted the light load check to be a less than or equal, not just less than. if (totalcarriedweight <= lightloadmax) { encumbrload=0.1; } else if (totalcarriedweight < heavyloadmin) { encumbrload=-3; } else { encumbrload=-6; }     // Because our variable name is the same as the attribute name, we can shorthand the object we pass to setAttrs     // This is equivalent to setAttrs({ encumbrload: encumbrload }); setAttrs({ encumbrload }); }); }); </script>
That almost does it scott! I have ran into the issue that the lightloadmax and other fields are all marked as disabled and cannot be read, causing the if statement to always set encumbrload to -6. When I moved them to a regular value or readonly their equation ( Ex. value="floor(@{encumbrsize}*(floor(@{encumbrstr}/3))*(@{weightscale}))" ) does not calc in the sheet, it instead prints its contents.  I believe its a macro, the deeper I look into this sheet it seems to do this a lot.  Do you happen to know workarounds because right now I think I have to re write that whole section using TAS function or something similar...
1723011424
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
ah, I missed that those were autocalcs. Yes, autocalcs and sheetworkers do not mix. You'll need to convert those to sheetworker calculated fields in order for this to work. You can use the readonly html property to make them uneditable by the user.
1723014705

Edited 1723014997
OK! got it. I added 2 'hidden' functions and by using this on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenlightloadmax"], function(values) { setAttrs({ "hiddenlightloadmax": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(parseInt(values.encumbrstr)/3)) * parseInt(values.weightscale) }); }); }); on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenheavyloadmin"], function(values) { setAttrs({ "hiddenheavyloadmin": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(2*(parseInt(values.encumbrstr)/3))) * parseInt(values.weightscale) + 1 }); }); }); I was able to get it working! ill just add the hidden tag and it'll be like nothing is there! Thanks for the help Scott! code I ended up using Added hidden attr <td><input class="inputbox" type="text" name="attr_pushdragmax" title="pushdragmax" style="height: 24px; width: 58px; text-align: right;" disabled value="floor(@{encumbrsize}*(5*(@{encumbrstr}))*(@{weightscale}))"/><span name="attr_weightunit" title="weightunit"></span> <span data-i18n="or-less">or less</span>.</td> //this one <td><input class="inputbox" type="hidden" name="attr_hiddenlightloadmax" title="hiddenlightloadmax" style="height: 24px; width: 53px; text-align: right;" value="0"/></td> //this one <td><input class="inputbox" type="hidden" name="attr_hiddenheavyloadmin" title="hiddenheavyloadmin" style="height: 24px; width: 53px; text-align: right;" value="0"/></td> The function for each new attr on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenlightloadmax"], function(values) { setAttrs({ "hiddenlightloadmax": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(parseInt(values.encumbrstr)/3)) * parseInt(values.weightscale) }); }); }); on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenheavyloadmin"], function(values) { setAttrs({ "hiddenheavyloadmin": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(2*(parseInt(values.encumbrstr)/3))) * parseInt(values.weightscale) + 1 }); }); }); The script Scott made <script type="text/worker"> on("change:totalcarriedweight", function() { //you don't need to actually get the value of encumbrload in the getAttrs since we are just setting it, not using it. getAttrs(["hiddenlightloadmax","medloadmin","medloadmax","hiddenheavyloadmin","heavyloadmax","totalcarriedweight"], function(values) { const hiddenlightloadmax = parseInt(values.hiddenlightloadmax) const hiddenheavyloadmin = parseInt(values.hiddenheavyloadmin) const totalcarriedweight = parseInt(values.totalcarriedweight) // use let to define encumbrload, and we leave it with a value of undefined initially let encumbrload; // There's some fancier ways to do this, but they don't have any performance enhancement over if/else and // can be less easy to read. // Changed your logic a little so that it sets at increasing levels of load just to make it a little more readable. // Also I think you actually wanted the light load check to be a less than or equal, not just less than. if (totalcarriedweight <= hiddenlightloadmax) { encumbrload=0.1; } else if (totalcarriedweight < hiddenheavyloadmin) { encumbrload=-3; } else { encumbrload=-6; } // Because our variable name is the same as the attribute name, we can shorthand the object we pass to setAttrs // This is equivalent to setAttrs({ encumbrload: encumbrload }); setAttrs({ encumbrload }); }); }); </script> THIS TOOK ME WAY TOO LONG TO FIGURE OUT!
1723241159
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Note that I'd recommend just replacing the auto calc visible fields with the sheetworker calculated fields.
1723242453

Edited 1723289436
GiGs
Pro
Sheet Author
API Scripter
I second Scott's recommendation. You can leep the autocalcs, but once you start using sheet workers, you might as well replace them for overall better sheet efficiency, and make it possible to use those attributes on sheet workers directly. Also, you have two sheet workers that could be combined into one. You have this: on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenlightloadmax"], function(values) { setAttrs({ "hiddenlightloadmax": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(parseInt(values.encumbrstr)/3)) * parseInt(values.weightscale) }); }); }); on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale","hiddenheavyloadmin"], function(values) { setAttrs({ "hiddenheavyloadmin": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(2*(parseInt(values.encumbrstr)/3))) * parseInt(values.weightscale) + 1 }); }); }); Since they both trigger off the same change event, you should combine those. Here's one way to do that. on("change:totalcarriedweight", function() { getAttrs(["encumbrsize", "encumbrstr", "weightscale"], function(values) { setAttrs({ "hiddenlightloadmax": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(parseInt(values.encumbrstr)/3)) * parseInt(values.weightscale), "hiddenheavyloadmin": (Math.floor(parseInt(values.encumbrsize))) * (Math.floor(2*(parseInt(values.encumbrstr)/3))) * parseInt(values.weightscale) + 1 }); }); }); Also if totalcarriedweight is dependent on any of those attributes in getAttrs, you might want to add them to the change: line.
Thank you!!