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

DH2E Character Sheet help

I'm new to Character Sheet creation within Roll20, have a fair amount of coding knowledge, though nothing professional, and have been going through the tutorials and guides online for Roll20 sheetworkers.  I thought I had it figured out but am coming up empty. I got into sheet creation simply because I wanted to fix some issues with and existing sheet, Dark Heresy 2nd Edition Advanced, but have found myself wanting to add a bit more than intended. The first section shows the attr_Strength & attr_Toughness for those specific Attributes. In the second section I show where I'm trying to send the result of my code, attr_CarryMod & attr_CarryBase. The last section shows the code that I wrote based off my reading of Roll20 character sheet guides and my own personal knowledge. I'm attempting to use the Core Rulebook's set values for SB+TB and have the value automatically entered into CarryMod, then also have the value created and added for starting maximum weight into CarryBase.  I also am adding a section for maximum weight and available weight but those can be entered utilizing existing Attribute values without advanced calculations or statements. Can someone point out what I'm doing wrong here?  If you need more context please let me know what to add beyond what is already shown.  Thank you. <!-- Strength (S) --> <div class="sheet-2colrow">     <div class="sheet-col">         <button name="roll_S" type="roll" value="/em rolls Strength: [[1d100]] Target: [[@{Strength}+ ?{Modifier|0}]]."><span data-i18n="strength-(s)-u">Strength (S)</span></button>     </div>     <div class="sheet-col">         <div class="sheet-unnatural_box">             <input name="attr_Strength" class="sheet-unnaturaltext" type="text" value="0">             <input name="attr_UnS" Title="Unnatural Strength" class="sheet-unnatural" type="number" value="0" /> ...     <!-- Toughness (T) -->     <div class="sheet-2colrow">         <div class="sheet-col">             <button name="roll_T" type="roll" value="/em rolls Toughness: [[1d100]] Target: [[@{Toughness}+ ?{Modifier|0}]]."><span data-i18n="toughness-(t)-u">Toughness (T)</span></button>         </div>         <div class="sheet-col">             <div class="sheet-unnatural_box">                 <input name="attr_Toughness" class="sheet-unnaturaltext" type="text" value="0">                 <input name="attr_UnT" Title="Unnatural Toughness" class="sheet-unnatural" type="number" value="0" /> ...                                 <h3 data-i18n="gear-u">Gear</h3> <div class="sheet-quickborder"> <div class="sheet-row"> <div class="sheet-item" style="width:15%"> <span data-i18n="max-carry-wt-(sb+tb)-u">Carry Modifier: </span> </div> <div class="sheet-item" style="width:15%"> <input name="attr_CarryMod" type="number" disabled="disabled"/> <!-- value="floor(@{Strength}/10)+@{UnS}+floor(@{Toughness}/10)+@{UnT}"--> </div> <div class="sheet-item" style="width:15%"> <span style="width:15%" data-i18n="base-weight">Base Carry: </span> </div> <div class="sheet-item" style="width:15%"> <input name="attr_CarryBase" type="number" disabled="disabled"/> </div> <div class="sheet-item" style="width:15%"> <span style="width:15%" data-i18n="max-weight">Max Carry: </span> </div> <div class="sheet-item" style="width:15%"> <input name="attr_CarryMax" type="number" disabled="disabled"/> </div> </div> ... on('change:Strength change:Toughness',function() { getAttrs([Strength, Toughness], function(values) { let str = parseInt(values.Strength||0); let tgh = parseInt(values.Toughness||0); let cMod = str + tgh; let cBase = 0; switch(cBase) { case 0: cBase = 0.9; break; case 1: cBase = 2.25; break; case 2: cBase = 4.5; break; case 3: cBase = 9; break; case 4: cBase = 18; break; case 5: cBase = 27; break; case 6: cBase = 36; break; case 7: cBase = 45; break; case 8: cBase = 56; break; case 9: cBase = 67; break; case 10: cBase = 78; break; case 11: cBase = 90; break; case 12: cBase = 112; break; case 13: cBase = 225; break; case 14: cBase = 337; break; case 15: cBase = 450; break; case 16: cBase = 675; break; case 17: cBase = 900; break; case 18: cBase = 1350; break; case 19: cBase = 1800; break; case 20: cBase = 2250; break; } SetAttrs({ CarryMod: cMod CarryBase: cBase }); }); });
1632379718

Edited 1632380181
vÍnce
Pro
Sheet Author
A few things i see.  Make sure the HTML attributes you are wanting to update with setAttrs are not using "disabled".  Use readonly or type="hidden". Also, I didn't look, so it might not apply here... but make sure you don't try and mix and match HTML calculated attributes with sheetworker calculated attributes. It's probably best to just do all the calcs in the sheetworkers to prevent any conflicts. just something to look out for. Your getAttrs attributes should be in quotes. getAttrs(["Strength", "Toughness"] Use a comma between new lines in your setAttrs (which is also using the wrong case in your code.  js is case sensitive. Very import for these built-in functions) setAttrs({ CarryMod: cMod, CarryBase: cBase }); You also might want to add a final default case in your switch in case something in the computation doesn't match your cases. Hope this helps.
Thanks so much Vince, I was able to get the changes and fixes submitted thanks to you.
1632392075

Edited 1632392399
GiGs
Pro
Sheet Author
API Scripter
To add to Vinces comments: The event line (the first line of each worker) must be entirely in lower case. This line: on('change:strength change:toughness',function() It doesnt matter how they are defined in the html, or what case they have in the lines after this, on this line they must always be in lower case. Now, you'll probably point out that this worker is working fine. But you'll find that workers sometimes fail if you don't do this, and it's completely unpredictable when this happens, so it's best to write everything in lower-case on this line. This is also what you are told to do in the official documentation. This doesnt contradict Vince's comment that JS is case-sensitive. You have to be careful about getting case correct with variable names - but in this one place, you always have to use lower case regardless of the original case. For this reason, it's a good idea to define all attribute names in lower case in your html - just so you never have to worry about it. For your attributes in html, when you know they are numbers, it's best to define them as numbers, like so: <input name="attr_Strength" class="sheet-unnaturaltext" type="number" value="0"> That stops people being able to accidentall enter the wrong values. Also two more of your sheet workers have errors: let str = parseInt(values.Strength||0); let tgh = parseInt(values.Toughness||0); Should be let str = parseInt(values.Strength) || 0; let tgh = parseInt(values.Toughness) || 0; The ||0 should be outside the parseInt brackets. If its inside, players can enter text values and that error wouldnt be detected, then the sheet worker would crash as the praseInt operation fails. The second version properly catches that error. Though technically speaking, you don't need the ||0 at all if you set the values as type="number" in the html. I was going to suggest an alternative and more compact way of dealing with your switch, but then I noticed this:                 let cBase = 0; switch(cBase) It looks like your switch will always return the 0 value. Are you supposed to be using cBase to choose which switch item to choose?
Thanks Gigs!  I'll get those changes put in right away! I was "in the zone" I guess last night so didn't realize what time it was when I was learning about/working on this so I must have overlooked those details, also I swear I saw this in the guide: let str = parseInt(values.Strength||0); Upon another inspection this morning with eyes that are rested I do see the error, lol. In regards to the Attribute type, I am editing an existing character sheet so many of those things were already put in as "text", as I notice them I will be correcting them.  Had fun working on this sheet last night so will likely be working on further changes, including removal of what seems like a bloated method that I copy pasta'd from the normal DH2E sheet. Thanks so much! I actually found that last error myself after beating my head against my keyboard for about an hour and changed it to the correct variable: switch(cMod)
1632423192
GiGs
Pro
Sheet Author
API Scripter
Changing an attribute type from text to number will erase any values that arent valid as numbers, so since its a live sheet you'd want to be absolutely sure that no one is going to lose data from changing it. Since the sheet is working, in this case I'd leave it alone. It's not likely to caiuse issues if you changed those two attributes, but you never know how people are using the sheets... Here's the more concise version of the sheet worker, replacing the switch with an array. Explanation is after the code. on ( 'change:strength change:toughness' , function () {      getAttrs ([ 'Strength' ,  'Toughness' ],  function ( values )     {          let   str  =  parseInt ( values . Strength ) ||  0 ;          let   tgh  =  parseInt ( values . Toughness ) ||  0 ;          let   cMod  =  str  +  tgh ;          const   cBaseValues  = [ 0.9 ,  2.25 ,  4.5 ,  9 ,  18 ,  27 ,  36 ,  45 ,  56 ,  67 ,  78 ,               90 ,  112 ,  225 ,  337 ,  450 ,  675 ,  900 ,  1350 ,  1800 ,  2250 ];          let   cBase  =  0 ;          if ( cMod  >=  0  &&  cMod  < cBaseValues .length  ) {              cBase  =  cBaseValues [ cMod ];         }                   SetAttrs ({              CarryMod :   cMod ,              CarryBase :   cBase         });     }); }); In case you don't know, an array is a variable that holds many values, each separated by a comma, and each value in the array has a numbered index, starting at 0, and going up by 1 each. So in the above array, index 0 is 0.9, index 1 is 2.25, index 2 is 4.5, etc. Since you switch uses the same progression (0, 1, 2, etc), the cMod value is the index, and you can just use that to grab the value. You do need to check the value is within the range of indexes in the array, or it'll crash - thats what the if statement is for. Here's an even more compact way to write that:          const   cBaseValues  = [ 0.9 ,  2.25 ,  4.5 ,  9 ,  18 ,  27 ,  36 ,  45 ,  56 ,  67 ,  78 ,               90 ,  112 ,  225 ,  337 ,  450 ,  675 ,  900 ,  1350 ,  1800 ,  2250 ];          const   cBase  = ( cmod  >=  0  &&  cmod  <  cBaseValues . length ) ?  cBaseValues [ cMod ] :  0 ;          Here the let cBase = 0 and the if statement are combined into one line, in a ternary operator. I'll leave that for googling or further questioning, I'm just including it for completeness. But generally where you have an if statement to set a value between exactly 2 options, ternary operators are great.
Nice Gigs!  Yea, I went to school for programming, but that was years ago and I ended up in a completely different field.  I didn't even consider using an array and just referring to the index, would have condensed my work significantly lol. I'm dusting off the cobwebs in that part of my brain to start exercising it once again.  Thanks for the pointers!
Lol you kept my bad code:          SetAttrs ({              CarryMod :   cMod ,              CarryBase :   cBase         }); It took me a minute to find why it wasn't working.
1632427674
GiGs
Pro
Sheet Author
API Scripter
hehe, that's always a danger when copying code rather than writing from scratch :)