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

Custom sheet not updating hp/hp max correctly

Hi there folks, I've been using some code to run the hp value of the caracter in my custom game. I've recently tried to update the stuff, tinkering with the formula a bit and now, it seems that the numbers are not updating correctly. So, bit of context : Character have 4 stats which rang from 0 to 4 (mind, constitution, will and agility) and one other secondary stat refering to size (mass scale). The current formula to get max hp is (10*body) + (10*mass_scale) + (.mind) + (will) + (.agility). in the character sheet, I have this code : on('change:body change:mass_scale change:mind change:will change:agility',(event)=>{     getAttrs(['body','mass_scale','mind','will','agility','hp'],(attributes)=>{         let setObj = {                 hp_max:(10*attributes.body||10) + (10*attributes.mass_scale||10) + (attributes.mind*1||1) + (attributes.will*1||1) + (attributes.agility*1||1)             };         attributes.hp_max = setObj.hp_max;         figureWounds(attributes,setObj);         setAttrs(setObj,{silent:true});     }); }); on('change:hp change:hp_max',(event)=>{     getAttrs(['hp','hp_max'],(attributes)=>{         let setObj = {};         figureWounds(attributes,setObj);         setAttrs(setObj,{silent:true});     }); }); But it doesn't seem to work. Also, I really dont' understand this coding language. :S Could someone help me? Thanks, G
1589511366
GiGs
Pro
Sheet Author
API Scripter
You've made it a bit more complicated than it needs to be. Before we streamline it, in both functions, you have this line figureWounds(attributes,setObj); This calls a figureWounds function. Do you have such a function, and if so, can you post that code?
1589511464

Edited 1589515415
GiGs
Pro
Sheet Author
API Scripter
Codeacula is wrong, don't do that. (sorry to be so blunt, Codeacula!) While youre function looks a bit weird, you can have multiple change statements as you have in the same function. This section is weird - the second line is unneeded      attributes.hp_max = setObj.hp_max;     figureWounds(attributes,setObj); The first line is unneccessary but doesnt break anything. We need to see what the figureWounds function looks like before we can sort this out.
The other figureWounds I have is this: let figureWounds = function(attributes,setObj){     let hpPercent = attributes.hp/attributes.hp_max,         woundsObj = {};     if(hpPercent > 0.5){         woundsObj.inconscient = 0;         woundsObj.blessure = 0;         woundsObj.blessure_grave = 0;     }else if(hpPercent > 0.25){         woundsObj.inconscient = 0;         woundsObj.blessure = 1;         woundsObj.blessure_grave = 0;     }else if(hpPercent > 0){         woundsObj.inconscient = 0;         woundsObj.blessure = 1;         woundsObj.blessure_grave = 1;     }else{         woundsObj.inconscient = 1;         woundsObj.blessure = 1;         woundsObj.blessure_grave = 1     }     Object.assign(setObj,woundsObj);// };
1589514185

Edited 1589515472
GiGs
Pro
Sheet Author
API Scripter
I see why you have written the workers the way you have now, that's helpful. One problem is that values from getAttrs(attributes) are always strings, and need to be coerced into numbers before you can do mathematics or logical tests on them reliably. Also your second worker is redundant. You should include hp in the change event of the first worker. Then you dont need a separate function to calculate the wound modifier (you can still use one, but its not necessary). Finally you are sending all the attributes to the figureWounds function, and then setAttrs. You dont need to send the body, mass, mind, etc in this way. They never change so shouldnt be sent to setAttrs. Here's one way to rewrite it. on('change:body change:mass_scale change:mind change:will change:agility change:hp',(event)=>{     getAttrs(['body','mass_scale','mind','will','agility','hp'],(attributes)=>{         let setObj = {};         setObj.hp_max = (10*attributes.body||10) + (10*attributes.mass_scale||10) + (attributes.mind*1||1) + (attributes.will*1||1) + (attributes.agility*1||1);         setObj.hp = +attributes.hp || 0;         let hpPercent = setObj.hp / setObj.hp_max;         setObj.blessure = (hpPercent <= 0.5) ? 1: 0;         setObj.blessure_grave = (hpPercent <= 0.25) ? 1: 0;         setObj.inconscient = (hpPercent <= 0) ? 1: 0;         setAttrs(setObj,{silent:true});     }); }); Note that you should create a separate object for the setAttrs command - dont use your original attributes. Get values out of it, convert them into the format you need (not strings), and create a new object that contains only the values you need saving. If you want to keep the external function, you could do this on('change:body change:mass_scale change:mind change:will change:agility change:hp',(event)=>{     getAttrs(['body','mass_scale','mind','will','agility','hp'],(attributes)=>{         let setObj = {};         setObj.hp_max = (10*attributes.body||10) + (10*attributes.mass_scale||10) + (attributes.mind*1||1) + (attributes.will*1||1) + (attributes.agility*1||1);         setObj.hp = +attributes.hp || 0;         setObj = figureWounds(setObj); // or you could use Object.assign within the function as you did, I'm just illustrating different methods.         setAttrs(setObj,{silent:true});     }); }); let figureWounds = function(obj){     let hpPercent = obj.hp / obj.hp_max;     obj.blessure = (hpPercent <= 0.5) ? 1: 0;     obj.blessure_grave = (hpPercent <= 0.25) ? 1: 0;     obj.inconscient = (hpPercent <= 0) ? 1: 0;     return obj; }; I think I got the blessure/grave/inconscient values correct, you might want to check those.
1589514410
GiGs
Pro
Sheet Author
API Scripter
I'm not really keen on adding hp to setObj, but it still needs converting to an integer or float. You have {silent:true}, so its not going to do any harm.
1589515667
GiGs
Pro
Sheet Author
API Scripter
I'd probably rewrite one line: setObj.hp_max = 10* (+attributes.body||10) + 10* (+attributes.mass_scale||10) + (+attributes.mind||1) + (+attributes.will||1) + (+attributes.agility||1); This way the default values are being applied properly, and the arithmetic is separated from the logical conversion from strings to numbers.
1589516950

Edited 1589517286
GiGs said: If you want to keep the external function, you could do this on('change:body change:mass_scale change:mind change:will change:agility change:hp',(event)=>{     getAttrs(['body','mass_scale','mind','will','agility','hp'],(attributes)=>{         let setObj = {};          setObj.hp_max = 10* (+attributes.body||10) + 10* (+attributes.mass_scale||10) + (+attributes.mind||1) + (+attributes.will||1) + (+attributes.agility||1);         setObj.hp = +attributes.hp || 0;         setObj = figureWounds(setObj); // or you could use Object.assign within the function as you did, I'm just illustrating different methods.         setAttrs(setObj,{silent:true});     }); }); let figureWounds = function(obj){     let hpPercent = obj.hp / obj.hp_max;     obj.blessure = (hpPercent <= 0.5) ? 1: 0;     obj.blessure_grave = (hpPercent <= 0.25) ? 1: 0;     obj.inconscient = (hpPercent <= 0) ? 1: 0;     return obj; }; I think I got the blessure/grave/inconscient values correct, you might want to check those. You did get them right. The checkboxe related to wound levels are still updating. I've copy-paste this an replace what I've put before but still, the formula doesn't return me the good HP value. I must say that all the coding is complete gibberish to me and I can't figure what's wrong. I can verify that the "mass scale" always impact the hp number but all the other stats are not changing anything when thinkered. 
1589517804
GiGs
Pro
Sheet Author
API Scripter
Can you post the html for the inputs of body, mass_scale, mind, will, agility, hp, and hp_max. There might be something in the way these stats are created in the html that is incorrect for roll20.
Look like this : <input align="right" type="number" name="attr_hp" value="0"> <input align="right" type="number" name="attr_hp_max" > All 4 charateristics are defined like this: <input type="number" name="attr_body" class='sheet-short' value="(@{base_body} + @{mod_body})" disabled="true"/> <h5>Base</h5> <input type="number" name="attr_base_body" value="1"> <h5>Mod</h5> <input type="number" name="attr_mod_body" value="0">  <input type="number" name="attr_agility" class='sheet-short' value="(@{base_agility} + @{mod_agility})" disabled="true"/> <input type="number" name='attr_mind' class="sheet-short" value="(@{base_mind} + @{mod_mind})" disabled="true"/> <input type="number" name='attr_will' class='sheet-short' value="(@{base_will} + @{mod_will})" disabled="true"/>  <input type="number" name="attr_mass_scale" value="0" />
1589518700

Edited 1589518742
GiGs
Pro
Sheet Author
API Scripter
The problem is your basic attributes are autocalc fields. Sheet workers are completely incompatible with sheet workers. Those attributes would need to be recreated as sheet workers. Change the disabled="true" in each of those to readonly , and add this sheet worker (sorry, its not going to be pretty): ['body', 'agility', 'mind', 'will'].forEach(stat => {     on(`change:base_${stat} change:${mod}`, () => {         getAttrs([`base_${stat}`, `change:${mod}`], attributes => {             setAttrs({                 [stat]: (+attributes[`base_${stat}`] ||1 ) + (+attributes[`change:${mod}`] ||0 )              });         });     }); }); This should calculate your attribute values in a format that other sheet workers can use.
GiGs said: (sorry, its not going to be pretty): The whole sheet is a complete mess to be honest. XD But, it look like it's got worse. I'm stuck with two things :     1 - the wound total does not reflect the formula and not it jumped in the 100 hit points. (normally around 10-40 wounds)     2 - With a "readonly" feature in my character sheet, I cannot update characteristics on the fly or show them to the players. Down the rabbit hole. I do need to take html + java class. 
1589519945
GiGs
Pro
Sheet Author
API Scripter
readonly is fine  -it updates when scripts update them, but players cant change them. Note: this is identical to disabled. Players also cannot change disabled attributes either. If the wounds are jumping too high, its likely there is some string concatenation going on. Don't get disheartened, this is fixable. Can you post your complete html to pastebin or a similar place?
Here : <a href="https://pastebin.com/j9YcbUbK" rel="nofollow">https://pastebin.com/j9YcbUbK</a>
1589525951
GiGs
Pro
Sheet Author
API Scripter
Thanks, I'll look over it tomorrow.
1589542439
GiGs
Pro
Sheet Author
API Scripter
The error was mine. The last code i gave had a couple of errors in it. Use this instead ['body',&nbsp;'agility',&nbsp;'mind',&nbsp;'will'].forEach(stat&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;on(`change:base_${stat}&nbsp;change:mod_${stat}&nbsp;sheet:opened`,&nbsp;()&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getAttrs([`base_${stat}`,&nbsp;`change:mod_${stat}`],&nbsp;attributes&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[stat]:&nbsp;(+attributes[`base_${stat}`]&nbsp;||10&nbsp;)&nbsp;+&nbsp;(+attributes[`change:mod_${stat}`]&nbsp;||0&nbsp;)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}); });
1589542935
GiGs
Pro
Sheet Author
API Scripter
The error with your hp_max value is in this line setObj.hp_max&nbsp;=&nbsp;10* (+attributes.body||10)&nbsp;+&nbsp;10* (+attributes.mass_scale||10)&nbsp;+&nbsp;(+attributes.mind||1)&nbsp;+&nbsp;(+attributes.will||1)&nbsp;+&nbsp;(+attributes.agility||1); specifically this bit 10* (+attributes.mass_scale||10)&nbsp; This part: || 0 says "when the bit before || is false, use a value of 10". the problem is, a value of 0 is considered equivalent to false . And since your character has default mass_scale of 0, it was being set to 10 in this calculation, and then being multiplied by 10. The fix is to set the ||10 to ||0. I'd recommend doing that for all the stats, so change that line to setObj.hp_max&nbsp;=&nbsp;10* (+attributes.body||0)&nbsp;+&nbsp;10* (+attributes.mass_scale||0)&nbsp;+&nbsp;(+attributes.mind||0)&nbsp;+&nbsp;(+attributes.will||0)&nbsp;+&nbsp;(+attributes.agility||0);
1589543208
GiGs
Pro
Sheet Author
API Scripter
One final comment. You have a bunch of sheet workers like this: on("change:repeating_weaponspistolet:weaponnamepistolet sheet:opened", function () { &nbsp;&nbsp;&nbsp;&nbsp;getAttrs(["repeating_weaponspistolet_weaponnamepistolet"],&nbsp;function&nbsp;(values)&nbsp;{ The problem is you are using the short repeating section syntax: "repeating_weaponspistolet_weaponnamepistolet" This isnt compatible with sheet:opened . If you view the browser console, you;ll see a lot of errors every time you open a character sheet. To avoid them, just remove sheet:opened &nbsp;from all these sheet workers that use this repeating section syntax: "repeating_weaponspistolet_weaponnamepistolet"
Great, everything seems fine now. I'll also check for the repeating attributes, thanks for the input. I've realized that when I put any stat (will, body, mind, agility) to "0", it gave me a 100+ hp value. With your precedent feedback, I've tweaked this : ['body',&nbsp;'agility',&nbsp;'mind',&nbsp;'will'].forEach(stat&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;on(`change:base_${stat}&nbsp;change:mod_${stat}&nbsp;sheet:opened`,&nbsp;()&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getAttrs([`base_${stat}`,&nbsp;`change:mod_${stat}`],&nbsp;attributes&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [stat]:&nbsp;(+attributes[`base_${stat}`]&nbsp;||10&nbsp;)&nbsp;+&nbsp;(+attributes[`change:mod_${stat}`]&nbsp;||0&nbsp;) to this : [stat]: (+attributes[`base_${stat}`] ||0 ) + (+attributes[`change:mod_${stat}`] ||0 )&nbsp; No more 100+ hp value this way. Thanks a lot!
1589549913
GiGs
Pro
Sheet Author
API Scripter
Oh yes, well spotted. I should have changed that when I noticed it happening with hit points.
GiGs said: Codeacula is wrong, don't do that. (sorry to be so blunt, Codeacula!) While youre function looks a bit weird, you can have multiple change statements as you have in the same function. This section is weird - the second line is unneeded &nbsp;&nbsp;&nbsp;&nbsp; attributes.hp_max = setObj.hp_max; &nbsp; &nbsp; figureWounds(attributes,setObj); The first line is unneccessary but doesnt break anything. We need to see what the figureWounds function looks like before we can sort this out. It's no problem, I don't want to give false help, and I'm still trying to learn Roll20's API quirks
I've encounter a new problem with the changes I've made. When I was calculating the body/mind/agility/will for a player, I used this code : &nbsp;&lt;input type="number" name="attr_body" class='sheet-short' value="@{base_body} + @{mod_body}"&nbsp;disabled="true"/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;h5&gt;Basic&lt;/h5&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="number" name="attr_base_body" value="1"&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;h5&gt;Modifier&lt;/h5&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="number" name="attr_mod_body" value="1"&gt;&nbsp; But now, the "modifier" doesn't have any effect one the total body score. The only thing Ive change is the disabled=true which is now readonly . Can the error come from this or it's elsewhere?
1589639663
GiGs
Pro
Sheet Author
API Scripter
The version of the code I shared had the modifiers working properly. So it's not working because of something you've changed since then and its impossible to say what's up without seeing the current code. Note that the value is now calculated by the sheet worker. This section value="@{base_body} + @{mod_body}" is completely ignored. You could change it to value="0", because the calculation there is no longer used.
GiGs said: Note that the value is now calculated by the sheet worker. This section value="@{base_body} + @{mod_body}" is completely ignored. You could change it to value="0", because the calculation there is no longer used. Noted. I've changed the value in the html section to reflect this and avoid confusion.I've taken a look and every "mod_" in the sheet worker and they seems to be right as rain. ['body', 'agility', 'mind', 'will'].forEach(stat =&gt; { &nbsp; &nbsp; on(`change:base_${stat} change:mod_${stat} sheet:opened`, () =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs([`base_${stat}`, `change:mod_${stat}`], attributes =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [stat]: (+attributes[`base_${stat}`] ||0 ) + (+attributes[`change:mod_${stat}`] ||0 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); });
1589677414
GiGs
Pro
Sheet Author
API Scripter
I'll need to see the full sheet. that worker is fine. If there's an error in the script block before it, it will stop that worker from working. There could be something in the html too.
Here goes : <a href="https://pastebin.com/4XE0McSa" rel="nofollow">https://pastebin.com/4XE0McSa</a> Note that I still didn't had the time to tweak the " sheet:opened" &nbsp;in the code as you suggested.
1589686678
GiGs
Pro
Sheet Author
API Scripter
You look at something so often, you just cant see it. The error is on the getAttrs line. This: getAttrs([`base_${stat}`, `change:mod_${stat}`], attributes =&gt; { should be getAttrs([`base_${stat}`, `mod_${stat}`], attributes =&gt; { I'm not sure how that got there, a little careless copy/paste. Sorry about that!
GiGs said: I'm not sure how that got there, a little careless copy/paste. Sorry about that! NP at all! Thanks for checking it. Made the change to it but it seems that the script part of the sheet might have an error. Nothing is updating anymore (stat, weapons, etc.) I'll try to find the error. (the error was there before I change the ( change:mod_$) &nbsp;part)
1589688240
GiGs
Pro
Sheet Author
API Scripter
Are the body, agility, etc attributes still working okay? I only glanced at the weapon workers, the language barrier makes it hard for me to understand what they are supposed to do.
1589688459

Edited 1589688575
GiGs said: Are the body, agility, etc attributes still working okay? I only glanced at the weapon workers, the language barrier makes it hard for me to understand what they are supposed to do. Everything's down atm. I've saved previous lines of code for weapons (line 933 to 1031) and C-Pasted them in place and re-run the sheet. Everything is still down, which mean that the problem is probably not in the weapons section. Also, I've deleted both change: in this code : ['body', 'agility', 'mind', 'will'].forEach(stat =&gt; { &nbsp; &nbsp; on(`change:base_${stat} change:mod_${stat} sheet:opened`, () =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs([`base_${stat}`, ` change: mod_${stat}`], attributes =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [stat]: (+attributes[`base_${stat}`] ||0 ) + (+attributes[` change :mod_${stat}`] ||0 )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); }); Which I think was the initial intention of your previous post.
1589688667

Edited 1589688740
GiGs
Pro
Sheet Author
API Scripter
You'll have to repost the sheet - because in the the version I've got, the stats are working. I dont know about the weapons because I dont have the CSS sheet so I cant tell from the basic layout what they are doing and whether its working. But you should completely remove eveyrthing from the script block, and just paste in the sheet worker above. Once you've confirmed that works, post in the big set of constants at the start of the script block, but no sheet workers, and see if the stats still work. Then start posting in the sheet workers in small groups, and see if they work. That will tell you what is breaking things.
I've been able to fix things. I've replaced readonly with disable=true and it was causing havoc. Now everything is fine and working. Thanks a million!&nbsp;
1589692128
GiGs
Pro
Sheet Author
API Scripter
Great!