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

Problem with Min value in a calc

Anyones help would be appreciated - Im stuck.   I am try to set a minimum value of 5% if a autocalc total is less than zero.  Normally the to hit value would be above zero however in rare instances a negative modifier can be applied which results in a negative to hit value, which cannot be used in a roll to hit. I read about using the following code <input type="hidden" disabled="true" name="attr_min_xy" value="(((@{x} + @{y}) - abs(@{x} - @{y})) / 2)" /> however I am recreation coder at best and I cannot seem to get it work. This is my autocalc to determine to hit % in my character sheet <input type="number" disabled name="attr_wpn_attk_totala" value="ceil(((@{wpn_attk_value}+@{manipulation_mod}+@{gift_attk_value}+@{magic_attk_value}+@{fatigue_mod}+@{gen_modn})*@{gen_modp})+@{negative_mod_value})" style="width:49px" /> I added the "min" below it <input type="hidden" disabled="true"name="attr_wpn_attk_total" value="(((@{wpn_attk_totala} + 5) - abs(@{wpn_attk_totala} - 5)) / 2)" /> The result i get is the negative value from  attr_wpn_attk_totala - not the 5% i am looking for. Thnks  
I'll bet you $5.00 Scott and GiGs recommend you use JavsScript, but I would too.  ;) I've not tested the code below, but perhaps something like this? const weaponAttackStats = [     'wpn_attk_value',     'manipulation_mod',     'gift_attk_value',     'magic_attk_value',     'fatigue_modgen_modn',     'gen_modp',     'negative_mod_value' ]; _.each(weaponAttackStats, was => {     const event = `change: ${was}`;     on(event, () => {      getAttrs(weaponAttackStats, v => {             const setObj = {};             const wpn_attk_totala = _.chain(weaponAttackStats)                 .map(w => { return v[w]; })                 .reduce((memo,stat) => { return memo + stat; })                 .value() || 0;             const wat = ((wpn_attk_totala + 5) - Math.abs(wpn_attk_totala - 5)) / 2;             const wpn_attk_total = wat < 0 ? Math.round(wpn_attk_totala * 0.05) : wat;             setObj.wpn_attk_totala = wpn_attk_totala;             setObj.wpn_attk_total = wpn_attk_total;             setAttrs(setObj,{silent:true});     });     }); });
1649747795

Edited 1649765119
GiGs
Pro
Sheet Author
API Scripter
John is right :) But John, you have seperate sheet workers for each attribute - it would be more efficient to use a single sheet worker with change events for each attribute built in. It looks like your formula is correct, so maybe there's something wrong with one of your initial attributes. Try putting each @{wpn_attk_totala} inside inline roll brackets [[ @{wpn_attk_totala} ]] and see if there's a change. Are any of the inital attributes themselves autocalcs? If any of these stats     'wpn_attk_value',     'manipulation_mod',     'gift_attk_value',     'magic_attk_value',     'fatigue_modgen_modn',     'gen_modp',     'negative_mod_value' are also autocalcs, try putting inline roll brackets around them to see if the behaviour changes. For a sheet worker, you can get rid of the first attribute, and just have a single attribute that takes the minimum of 5 into account: input type="hidden" name="attr_wpn_attk_total" value="5"> If you have never used sheet workers before, you need to create a space in your html for them. That's simple: just create these two lines at the very bottom of your HTML: < script type = "text/worker" >     </ script > All your sheet workers go between those two script lines. Here's an introductory version of your sheet worker would look something like: // with a sheet worker, you have to first list which attributes will be watched for changes. on ( 'change:wpn_attk_value change:manipulation_mod change:gift_attk_value change:magic_attk_value change:fatigue_modgen_modn change:gen_modp change:negative_mod_value sheet:opened' , () => {         // then when a change happens on any of them, you have to tell roll20 which attributes to grab     getAttrs ([ 'wpn_attk_value' , 'manipulation_mod' , 'gift_attk_value' , 'magic_attk_value' , 'fatigue_modgen_modn' , 'gen_modp' , 'negative_mod_value' ], values => {                 // then convert each attribute to a variable, so you can use it in arithmetic.         const wpn_attk_value = parseInt ( values . wpn_attk_value ) || 0 ;         const manipulation_mod = parseInt ( values . manipulation_mod ) || 0 ;         const gift_attk_value = parseInt ( values . gift_attk_value ) || 0 ;         const magic_attk_value = parseInt ( values . magic_attk_value ) || 0 ;         const fatigue_modgen_modn = parseInt ( values . fatigue_modgen_modn ) || 0 ;         const gen_modp = parseInt ( values . gen_modp ) || 0 ;         const negative_mod_value = parseInt ( values . negative_mod_value ) || 0 ;                 // then add all the attributes together         const total = wpn_attk_value + manipulation_mod + gift_attk_value + magic_attk_value + fatigue_modgen_modn + gen_modp + negative_mod_value ;                 //now that you have a sum, you want to make sure it isnt below 5.         const final_total = Math . max ( 5 , total );                 // finally you save the calculated value to the character sheet attribute.         setAttrs ({             wpn_attk_total: final_total         });     }); }); The green lines are comments describing what is happening in the next bit. They can be deleted. As you can see Sheet Workers are much more complex initially than using autocalcs, but there are advantages to using them - they are more efficient, and the attributes you create with them can be used for token bubble values, among other things. If you want anything explained in that sheet worker, ask away. It's handy to understand how these work so you can make your own. Though it looks complicated, almost all of your sheet workers will use the same structure so it's very easy to create more once you know how one works. The big drawback is they cant be combined with autocalc attributes - if you have any autocalc attributes, they need to be changed to sheet worker calculations before those stats can be used. For John, since you know how to use reduce, here's another version of that sheet worker, taking advantage of functions and automation. I wouldnt recommend this to novices - there's way too much to explain here. The above worker has exactly the same result! const int = ( score , fallback = 0 ) => parseInt ( score ) || fallback ; const sum = scores => scores . reduce (( a , b ) => a + int ( b ), 0 ); const changes = ( stats , sheet_open = false ) => stats . reduce (( all , stat ) =>      ` ${ all } change: ${ stat . toLowerCase () } ` , sheet_open ? 'sheet:opened' : '' ); const weapon_attack_stats = [   'wpn_attk_value' ,   'manipulation_mod' ,   'gift_attk_value' ,   'magic_attk_value' ,   'fatigue_modgen_modn' ,   'gen_modp' ,   'negative_mod_value' ]; on ( changes ( weapon_attack_stats , true ), () => {   getAttrs ( weapon_attack_stats , values => {     const output = {};     const total = sum ( Object . values ( values ));     output . wpn_attk_total = Math . max ( 5 , total );     setAttrs ( output );   }); });
1649816469

Edited 1649817252
Thank you both for the assistance - trying to get it to work with the sheetworker - I  think I have a few autocalc for the atributes I need to figure out
1649826209

Edited 1649827891
John D.
Sheet Author
Thanks for another great lesson, GiGs!  You and Scott never cease to amaze me and bend my mind in uncomfortable ways (but that's good!)  You've used reduce like I had no idea it could do that...and I'll be picking it apart for a while as I unravel this new black magic. As for my code above...that's what happens when I try to problem solve after my bed time.  *facepalm*  I see what you mean.  :P Happy to help, Duncman!  Even when I'm not that helpful, and I'll apologize later for leading you astray.  But if it is of help, when I first started on Roll20 I also went with autocalcs.  Seemed easier than learning JavaScript, but it leads you down a deep, dark rabbit hole ending in misery and despair.  I use them sparingly for very simple calculations when I'm too lazy to write JS.  Probably still not a good practice on my part, though. UPDATE *foaming at the mouth and green ooze dripping from ears* I get it!  Gigs, I...get it.  Only had to read your comments and the documentation for reduce about 20 times or more...but I get it.  Originally thought reduce could only be used for mathematical purposes, so seeing you use it on strings was forcing me to rethink my very existence...and how it built the listener string.  Freaking awesome dude!  Thank you for that!  Not gonna lie, but I think I'll be plagiarizing your code.  :D
1649838547

Edited 1649838665
GiGs
Pro
Sheet Author
API Scripter
Duncman, if you post the other autocalcs, we can show you how to convert them into sheet workers. Also, the sheet worker above operates on the assumption that the minimum value is a flat 5; if you need it to be 5% of the total attack value, it needs a slight tweak (it's not hard). John - hehe, it's great to get feedback like that. For the record, I had the same attitude to autocalcs, that they were okay in moderation. It took a long time for me to stop using them altogether. Also, the realisation I could create that changes function has changed the way I write sheet workers - I use that method almost everytime there's more than one attribute to call in a sheet worker now.