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

Using sheet worker to convert input text to numbers

1557600163

Edited 1557600399
So I'm not sure how I would go about it, but I want to set up a sheet worker that will add 1 to an attribute every time a certain word is entered into a text input within a repeating section. Here's what I've borrowed from a couple threads that I've dug up but it just doesn't work and I really have no idea if it ever would for what I'm trying to do. on("change:wounds", (event)=>{ const woundtype={ Moderate:{ moderatewound: 1 }, Severe:{ severewound: 1 }, Grievous:{ grievouswound: 1 }, Extreme:{ extremewound: 1 }, Fatal:{ fatalwound: 1 }, }; let setObj = woundtype[event.newValue.toLowerCase()]; if(setObj){ setAttrs(setObj); } }); Obviously if it did work it would just set Xwound to 1 instead of adding 1 to it, but that's not the problem. Also I'm going to change it to a dropdown later. I'm using text input to test it out. The next takes the Xwound attributes and divides it by half, multiplied by a certain number. For some reason it doesn't work.  on("change:moderatewound change:severewound change:grievouswound change:extremewound change:fatalwound", function() { getAttrs(["moderatewound","severewound","grievouswound","extremewound","fatalwound"], function(v) { let moderatewound = parseInt(v.moderatewound,10)||0; let severewound = parseInt(v.severewound,10)||0; let grievouswound = parseInt(v.grievouswound,10)||0; let extremewound = parseInt(v.extremewound,10)||0; let fatalwound = parseInt(v.fatalwound,10)||0; let moderatewoundpenalty = math.floor(moderatewound / 2) * 1; let severewoundpenalty = math.floor(severewound / 2) * 2; let grievouswoundpenalty = math.floor(grievouswound / 2) * 3; let extremewoundpenalty = math.floor(extremewound / 2) * 4; let fatalwoundpenalty = math.floor(fatalwound / 2) * 5; setAttrs({ moderatewoundpenalty: moderatewoundpenalty, severewoundpenalty: severewoundpenalty, grievouswoundpenalty: grievouswoundpenalty, extremewoundpenalty: extremewoundpenalty, fatalwoundpenalty: fatalwoundpenalty }) }); }); I could probably simplify it too but that's just the way I know how to do that. The final portion actually works so that's not a problem, but here it is. on("change:moderatewoundpenalty change:severewoundpenalty change:grievouswoundpenalty change:extremewoundpenalty change:fatalwoundpenalty", function() { getAttrs(["moderatewoundpenalty","severewoundpenalty","grievouswoundpenalty","extremewoundpenalty","fatalwoundpenalty"], function(v) { let moderatewoundpenalty = parseInt(v.moderatewoundpenalty,10)||0; let severewoundpenalty = parseInt(v.severewoundpenalty,10)||0; let grievouswoundpenalty = parseInt(v.grievouswoundpenalty,10)||0; let extremewoundpenalty = parseInt(v.extremewoundpenalty,10)||0; let fatalwoundpenalty = parseInt(v.fatalwoundpenalty,10)||0; let woundpenalty = moderatewoundpenalty + severewoundpenalty + grievouswoundpenalty + extremewoundpenalty + fatalwoundpenalty; setAttrs({ woundpenalty: woundpenalty }) }); }); EDIT: Well that last one used to work...
Alright I guess math.floor was supposed to be Math.floor, because that's working now. And the third one had a spelling error somewhere I think because that's working again after some copy pasting.
1557610557

Edited 1557610612
GiGs
Pro
Sheet Author
API Scripter
For that first script, if its in a repeating section, the name should probably be  repeating_wounds. If you are adding to an existing attribute, you'll need a getAttrs in there to grab the original value. Can you explain more what it should do? Is it to keep track of the number of wounds of each severity? The more information you can provide 9and relevant attributes names needed), the easier it'll be to build a function that should work. By the way, regarding the second and third functions, do you actually need the different wound penalty attributes on the sheet? you could combine your second and third script, easily: on("change:moderatewound change:severewound change:grievouswound change:extremewound change:fatalwound", function() { getAttrs(["moderatewound","severewound","grievouswound","extremewound","fatalwound"], function(v) { let moderatewound = parseInt(v.moderatewound,10)||0; let severewound = parseInt(v.severewound,10)||0; let grievouswound = parseInt(v.grievouswound,10)||0; let extremewound = parseInt(v.extremewound,10)||0; let fatalwound = parseInt(v.fatalwound,10)||0; let moderatewoundpenalty = Math.floor(moderatewound / 2) * 1; let severewoundpenalty = Math.floor(severewound / 2) * 2; let grievouswoundpenalty = Math.floor(grievouswound / 2) * 3; let extremewoundpenalty = Math.floor(extremewound / 2) * 4; let fatalwoundpenalty = Math.floor(fatalwound / 2) * 5; let woundpenalty = moderatewoundpenalty + severewoundpenalty + grievouswoundpenalty + extremewoundpenalty + fatalwoundpenalty;         setAttrs({             woundpenalty: woundpenalty         }); }); }); That could be written a bit more elegantly, but it works fine.
I don't need them on the sheet, they're just going to be hidden to allow the math. But thanks for that one. I guess I just didn't think about putting them together. Maybe the best way to explain what I need is what I'm trying to do. I'm probably doing it in some kind of roundabout way. I need to calculate a penalty based on the number and severity of wounds a character has. So for every 2  instances of a certain wound, that severity's wound penalty would be applied. The best way I could think of doing it was to have the first sheet worker convert the text to a number, divided up by severities, the second sheet worker takes them and changes them to the actual penalty (moderate = 1, severe = 2, etc) and then the third just tallied all those together. I'm not sure the best way to do the first sheet worker. Would it be easier to use a dropdown instead of a text field?
1557612004

Edited 1557612217
GiGs
Pro
Sheet Author
API Scripter
a dropdown would be easier, definitely. The sheet worker doesn't care which you use, but getting players to enter the right spelling every time is much easier if you use a dropdown. If I'm understanding you correctly, when a character gets hit, they check a box for the size of wound suffered. If that's the case, I can think of two ways to do it: First, you can use a repeating_wounds section, which has a single field: a drop down to chose the wound severity. Each time the player takes a wound, they add a new wound and choose its severity. The sheet worker counts up how many boxes of each type and updates the damage penalty. When PCs get healed, they remove the wound, and damage updates again. This is the best approach if you have any other information you need to track with each wound (like location). A second method is probably better: have a list of number inputs, labelled Moderate, Severe, Fatal, etc. When players take a hit, they add 1 to the appropriate wound box. The sheet worker counts how many of each type you have and updates the penalties as appropriate. This is the best approach if you only care about the wound size and dont need to record any other information with each wound. Have I understood what you need?
The first example is preferable but I need a second field since there is also HP damage tied to each wound, though that doesn't affect the penalty calculation. But yes, how do I get the sheet worker to tally up each different type within a repeating section?
1557616947

Edited 1557618399
GiGs
Pro
Sheet Author
API Scripter
Assuming you have a repeating_wounds section something like this:     <fieldset class="repeating_wounds"> <select name="attr_damagetype" > <option value="moderate">Moderate</option> <option value="severe">Severe</option> <option value="grievous">Grievous</option> <option value="extreme">Extreme</option> <option value="fatal">Fatal</option> </select> <input type="number" name="attr_damagevalue" value="0" >         <br/> </fieldset> You can use this sheet worker to count the number of each type (I'll add some description below). If I've misunderstood what you need, let me know and we can tweak it. on('change:repeating_wounds:damagetype change:repeating_wounds:damagevalue remove:repeating_wounds', () => { "use strict"; getSectionIDs('repeating_wounds', idArray => { let fieldNames = []; idArray.forEach(id => fieldNames.push(`repeating_wounds_${id}_damagetype`,`repeating_wounds_${id}_damagevalue`)); getAttrs(fieldNames, v => { const woundtypes = ['moderate', 'severe', 'grievous', 'extreme', 'fatal']; let wounds = {}; let penaltyTotal = 0; idArray.forEach(id => { const type = v[`repeating_wounds_${id}_damagetype`]; const value = parseInt(v[`repeating_wounds_${id}_damagevalue`],10)||0; if(value > 0) { wounds[type] = _.has(wounds,type) ? wounds[type] + 1 : 1 ; } }); woundtypes.forEach(type => { if(_.has(wounds,type)) { const mult = woundtypes.indexOf(type) + 1; const number = wounds[type]; const penalty = Math.floor(number / 2) * mult; penaltyTotal += penalty; } }); setAttrs({ woundpenalty: penaltyTotal }); }); }); }); So some description: on('change:repeating_wounds:damagetype change:repeating_wounds:damagevalue remove:repeating_wounds', () => { This checks both fields for changes, and also when you remove a wound, makes sure it gets updated. getSectionIDs('repeating_wounds', idArray => {         let fieldNames = [];         idArray.forEach(id => fieldNames.push(`repeating_wounds_${id}_damagetype`,`repeating_wounds_${id}_damagevalue`));     When using repeating sections, they have very complex attribute names, but each row has its own id. getSectionIds gives you an array of the rowids, and you use that to build a list of the attribute names you plan to use. getAttrs(fieldNames, v => { Here is how I'm using the set of attribute names build in the previous step. In the next section we use idArray again. This is an array of each row id in the repeating section, which also tells us how many rows there are in the section. so using forEach we can loop through each row, get the type of wound, and get the value of that wound. If the value is greater than 0 (so its actually a wound!), we record it.         idArray.forEach(id => {                 const type = v[`repeating_wounds_${id}_damagetype`];                 const value = parseInt(v[`repeating_wounds_${id}_damagevalue`],10)||0;                 if(value > 0) {                     wounds[type] = _.has(wounds,type) ? wounds[type] + 1 : 1 ;                 }             });             After the above loop runs, we'll have a wounds object which will look something like: {"grievous":2,"moderate":4}  We can then use the following routine to calculate the penalty based on the number of each wound type woundtypes.forEach(type => { if(_.has(wounds,type)) { const mult = woundtypes.indexOf(type) + 1; const number = wounds[type]; const penalty = Math.floor(number / 2) * mult; penaltyTotal += penalty; } }); mult is a way to get the multiplier for the wound type (1-5), by checking its order in this array defined earlier: const woundtypes = ['moderate', 'severe', 'grievous', 'extreme', 'fatal']; The rest hsould be self-explanatory. Doing stuff with repeating sections can be pretty complicated!
1557620621

Edited 1557620830
Ok I had no clue how to use getSectionIDs, though I knew I had to use it. The descriptions are super helpful and it looks like it does exactly what I need it to do all in one. Thanks so much! The only problem I'm having is, it only results in zero, but the console is telling me "no attr name" every time I select a wound type, so I'm thinking it's something on my end? EDIT: Yup, definitely on my end. I just straight copy pasted your code exactly, including the html and it works now.
1557621789
GiGs
Pro
Sheet Author
API Scripter
Glad to hear it :)