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

Problems with js on cutomized cWoD sheet

I am modifying a cWoD sheet for a wider tech mevel for a version of a game my brother runs. Basically, the group he was with in Korea took all the cWoD stuff and generalized it so they could use it in any genera then use the different WoD, Adventure!, etc. as sources for different characters. I am trying to get the Anduh cWoD sheet's armor to allow for multiple armors that can be enabled/disabled as needed. To do this I modified the HTML to this: &lt;div class="sheet-col"&gt; &lt;h3 class="sheet-center"&gt;Armor &amp; Soak&lt;/h3&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; Armor Type &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; Rating &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; DEX Penalty &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; In Use? &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor1-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor1-Rating"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor1-Dexterity_Penalty"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_1_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_1_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor2-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor2-Rating"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor2-Dexterity_Penalty"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_2_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_2_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor3-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor3-Rating"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor3-Dexterity_Penalty"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_3_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_3_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor4-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor4-Rating"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor4-Dexterity_Penalty"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_4_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_4_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;span&gt;Totals:&lt;/span&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" value="0" min="0" name="attr_armor-Rating" readonly="true" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" value="0" min="0" name="attr_armor-Dexterity_Penalty" readonly="true" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;/div&gt; &lt;/div&gt; And added this script: on("change:armor1-Rating change:armor2-Rating change:armor3-Rating change:armor4-Rating change:armor_1_use change:armor_2_use change:armor_3_use change:armor_4_use change:armor1-Dexterity_Penalty change:armor2-Dexterity_Penalty change:armor3-Dexterity_Penalty change:armor4-Dexterity_Penalty sheet:opened", function() { getAttrs(["armor1-Rating", "armor2-Rating", "armor3-Rating", "armor4-Rating", "armor_1_use", "armor_2_use", "armor_3_use", "armor_4_use", "armor1-Dexterity_Penalty", "armor2-Dexterity_Penalty", "armor3-Dexterity_Penalty", "armor4-Dexterity_Penalty"], function(values) { let aR1 = parseInt(values.armor1-Rating)||0; let aR2 = parseInt(values.armor2-Rating)||0; let aR3 = parseInt(values.armor3-Rating)||0; let aR4 = parseInt(values.armor4-Rating)||0; let aU1 = parseInt(values.armor_1_use)||0; let aU2 = parseInt(values.armor_2_use)||0; let aU3 = parseInt(values.armor_3_use)||0; let aU4 = parseInt(values.armor_4_use)||0; let aDP1 = parseInt(values.armor1-Dexterity_Penalty)||0; let aDP2 = parseInt(values.armor2-Dexterity_Penalty)||0; let aDP3 = parseInt(values.armor3-Dexterity_Penalty)||0; let aDP4 = parseInt(values.armor4-Dexterity_Penalty)||0; let aR = (aR1 * aU1) + (aR2 * aU2) + (aR3 * aU3) + (aR4 * aU4); let aDP = (aDP1 * aU1) + (aDP2 * aU2) + (aDP3 * aU3) + (aDP4 * aU4); setAttrs({ armor-Rating: aR, armor-Dexterity_Penalty: aDP }); }); }); When this script is active, all the scripts on the page die. Most of my scripting experience is in PHP where I have server side errors to work with. Here, trying to use the dev tools in the browser gets me loads of warning and errors from stiff some google, etc. but nothing I can find about this script. Obviously I have made some mistake because it kills all scripts, but I am not sure what I am doing wrong. The entire sheet can be found here: <a href="https://github.com/e-mccormick/cWoD-Unified-Roll20-sheet/" rel="nofollow">https://github.com/e-mccormick/cWoD-Unified-Roll20-sheet/</a>
1711742133

Edited 1711742165
vÍnce
Pro
Sheet Author
Not seeing anything that would break all your workers.... Maybe add some some console.log() statements to help see what is happening.&nbsp; eventInfo can be included with the event listener and can provide extra data to work with and/or log. Is this worker inside a single &lt;script type="text/worker"&gt;...&lt;/script&gt;?&nbsp; I would also recommend assigning default values to inputs in&nbsp; the html. Also, event listeners need to be lowercase. <a href="https://wiki.roll20.net/Sheet_Worker_Scripts" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Scripts</a> Note: All attribute names are lowercased in events. So even if you normally refer to an attribute as Strength, use change:strength in the event listener.
The script is in the script block. I linked the github so you can see the entire thing. The names, with caps, work on the original sheet. The change is to make numbered versions so that up to 4 different and potentially layered armors could be used. For example, a kinetic screen that only applies to physical attacks and not energy attacks can be enabled and disabled easily. It makes no sense to me that having one value works but having four that are calculated to become that one do not work. On this page:&nbsp; <a href="https://wiki.roll20.net/API:Debugging" rel="nofollow">https://wiki.roll20.net/API:Debugging</a> It says that major errors kills all scripts and make an auto log about, "Your scripts are disabled due to..." but I see nothing like that in the consol log. In fact, all I see are some css warnings about ids and google script errors. Since I am not the one trying to load the google scripts on the page, that is all just clutter.
1711746871
vÍnce
Pro
Sheet Author
Sheet development and API mod scripting are very different.&nbsp; You linked debugging for the API. but mods/scripts on roll20 will use the API console and have specific API-only functions and features.&nbsp; Sheets will use browser dev console and also require specefic sheet-only functions and features. You must follow the info for sheet development; <a href="https://wiki.roll20.net/Building_Character_Sheets" rel="nofollow">https://wiki.roll20.net/Building_Character_Sheets</a> and sheet workers:&nbsp; wiki:<a href="https://wiki.roll20.net/Sheet_Worker_Scripts" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Scripts</a> .&nbsp; Even though the event listeners are currently mixed, they should be lowercase according to the wiki, which has been written and updated based on countless sheet authors experiences. YMMV
1711748726

Edited 1711749143
vÍnce
Pro
Sheet Author
My guess is that some of your attribute names will cause issues with the variable assignments because of the dashes in their names. Try using template literals instead.&nbsp; example; (untested) on( 'change:armor1-rating change:armor2-rating change:armor3-rating change:armor4-rating change:armor_1_use change:armor_2_use change:armor_3_use change:armor_4_use change:armor1-dexterity_penalty change:armor2-dexterity_penalty change:armor3-dexterity_penalty change:armor4-dexterity_penalty sheet:opened', function () { getAttrs(['armor1-Rating', 'armor2-Rating', 'armor3-Rating', 'armor4-Rating', 'armor_1_use', 'armor_2_use', 'armor_3_use', 'armor_4_use', 'armor1-Dexterity_Penalty', 'armor2-Dexterity_Penalty', 'armor3-Dexterity_Penalty', 'armor4-Dexterity_Penalty'], function (values) { const aR1 = parseInt(`${values['armor1-Rating']}`) || 0; const aR2 = parseInt(`${values['armor2-Rating']}`) || 0; const aR3 = parseInt(`${values['armor3-Rating']}`) || 0; const aR4 = parseInt(`${values['armor4-Rating']}`) || 0; const aU1 = parseInt(`${values.armor_1_use}`) || 0; const aU2 = parseInt(`${values.armor_2_use}`) || 0; const aU3 = parseInt(`${values.armor_3_use}`) || 0; const aU4 = parseInt(`${values['armor4-use']}`) || 0; const aDP1 = parseInt(`${values['armor1-Dexterity_Penalty']}`) || 0; const aDP2 = parseInt(`${values['armor2-Dexterity_Penalty']}`) || 0; const aDP3 = parseInt(`${values['armor3-Dexterity_Penalty']}`) || 0; const aDP4 = parseInt(`${values['armor4-Dexterity_Penalty']}`) || 0; const aR = aR1 * aU1 + aR2 * aU2 + aR3 * aU3 + aR4 * aU4; const aDP = aDP1 * aU1 + aDP2 * aU2 + aDP3 * aU3 + aDP4 * aU4; setAttrs({ 'armor-Rating': aR, 'armor-Dexterity_Penalty': aDP, }); } ); } );
I did change it all to lower case, which made no change in function. I did note that even though I have a default value of 0 now, the&nbsp; armor-rating and&nbsp; armor-dexterity_penalty do not show up in the&nbsp; Attributes &amp; Abilities tab on the sheet, but injury does. Injusry is set the same way as these are, so... but it also has a script assoiated with it that uses other form values that don't show. Perhaos that is making it show up. I mention the injury only because undefined variables tend to be a common issue that kill scripts, I have tried a few ways of forcing creation that I saw, but none seem to work. They might be API rather than SheetWorker. No clue as the posts did not say. What does not help is that neiter of the sheetworker pages lits any info on debugging and searching for Roll20 and debugging only links me the API debugging, which you have pointed out is the wrong script so the info there may not apply... My script consol is loaded with errors and any acctive debugging stops the page and I consantly have to sep through things. All of these hits are on scripts relating to Roll20, google, etc. and not the one I uploaded, which also makes it interesting. Can't even move a window on the screen because it pauses and drops me out of the mouse activity. Going to try the FF dsebugger rather than Chrome to see if that makes a difference. If I can at least get an error message it will give me something to work towards.
parseInt(`${values['armor1-Rating']}`) &lt;- That works. So kill the dashes for a better practices.
For referenc, the fixed and working sections (removing - and upper case) is: &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; Armor Type &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; Rating &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; DEX Penalty &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; In Use? &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor1-name" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor1_rating" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor1_dexterity_penalty" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_1_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_1_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor2-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor2_rating" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor2_dexterity_penalty" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_2_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_2_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor3-name"/&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor3_rating" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor3_dexterity_penalty" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_3_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_3_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;input type="text" name="attr_armor4-name" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor4_rating" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" name="attr_armor4_dexterity_penalty" value="0" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;div class="sheet-Query"&gt; &lt;input type="radio" class="sheet-Query sheet-no" name="attr_armor_4_use" value="0" checked="checked" /&gt; &lt;input type="radio" class="sheet-Query sheet-yes" name="attr_armor_4_use" value="1" /&gt; &lt;span class="sheet-Query sheet-yes"&gt;Yes&lt;/span&gt; &lt;span class="sheet-Query sheet-no"&gt;No&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-row"&gt; &lt;div class="sheet-item sheet-90"&gt; &lt;span&gt;Totals:&lt;/span&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" value="0" name="attr_armor_rating" readonly="true" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-50"&gt; &lt;input type="number" value="0" name="attr_armor_dexterity_penalty" readonly="true" /&gt; &lt;/div&gt; &lt;div class="sheet-item sheet-40"&gt; &lt;/div&gt; &lt;/div&gt; And: on("change:armor1_rating change:armor2_rating change:armor3_rating change:armor4_rating change:armor_1_use change:armor_2_use change:armor_3_use change:armor_4_use change:armor1_dexterity_penalty change:armor2_dexterity_penalty change:armor3_dexterity_penalty change:armor4_dexterity_penalty sheet:opened", function(eventInfo) { getAttrs(["armor1_rating", "armor2_rating", "armor3_rating", "armor4_rating", "armor_1_use", "armor_2_use", "armor_3_use", "armor_4_use", "armor1_dexterity_penalty", "armor2_dexterity_penalty", "armor3_dexterity_penalty", "armor4_dexterity_penalty"], function(values) { let aR1 = parseInt(values.armor1_rating)||0; let aR2 = parseInt(values.armor2_rating)||0; let aR3 = parseInt(values.armor3_rating)||0; let aR4 = parseInt(values.armor4_rating)||0; let aU1 = parseInt(values.armor_1_use)||0; let aU2 = parseInt(values.armor_2_use)||0; let aU3 = parseInt(values.armor_3_use)||0; let aU4 = parseInt(values.armor_4_use)||0; let aDP1 = parseInt(values.armor1_dexterity_penalty)||0; let aDP2 = parseInt(values.armor2_dexterity_penalty)||0; let aDP3 = parseInt(values.armor3_dexterity_penalty)||0; let aDP4 = parseInt(values.armor4_dexterity_penalty)||0; let aR = (aR1 * aU1) + (aR2 * aU2) + (aR3 * aU3) + (aR4 * aU4); let aDP = (aDP1 * aU1) + (aDP2 * aU2) + (aDP3 * aU3) + (aDP4 * aU4); setAttrs({ armor_rating: aR, armor_dexterity_penalty: aDP }); }); }); The use of&nbsp; parseInt(`${values['durn-dash-errors']}`) did work, but I would rather just not have the errors or as much code work. Great help vÍnce ! Much thanks!
1711750203

Edited 1711750244
vÍnce
Pro
Sheet Author
I normally use Chrome for developing sheets.&nbsp; I also turn off most of the console log levels and filter the log to only show "info" and "warnings".&nbsp; Using eventInfo liberally when devloping helps immensely IME. Cheers
Like I mentioned, I do more php stuff... My brother has more js under his belt, but I have more time, so I am getting to work on the character sheet. Wheee! Working layers of armor is going to be so much more useful. I have the sheet about 95% of the way he wants and this was one of the last, real PITA things. With me copying what the original had with dashes and not knowing js, it just was not happening!
1711751651
vÍnce
Pro
Sheet Author
I cannot reccomend GiGs site ( roll20 sheet author, mod author and Guru ) enough&nbsp; <a href="https://cybersphere.me/roll20-sheet-author-master-list/" rel="nofollow">https://cybersphere.me/roll20-sheet-author-master-list/</a> For helping better understand how to develop a character sheet on roll20.&nbsp; There are just so many nuances with roll20's environment that require special attention. Goodluck.
1711752115

Edited 1711804540
GiGs
Pro
Sheet Author
API Scripter
I'm late to the thread, is it all working now? As pointed out earlier, this will not work: let aR1 = parseInt(values.armor1-Rating)||0; I see you have changed them to a working version: let aR1 = parseInt(values.armor1_rating)||0; So I thought I'd explain why&nbsp; the second works but the first doesn't. The thing is, values expects a valid variable name. In javascript variable names must start with a letter, and can only include letters, numbers, and underscores. Dashes are not valid in variable names. This would also work by the way: let aR1 = parseInt(values['armor1-Rating'])||0; This is because there is a second syntax for values you can use. If you dont use periods, but enclose the name in [ ] square brackets, you can include a variable or a string inside the square brackets. This is useful for dynamic names here - ones you don't know ahead of time and can supply as needed. So the values. syntax requires a valid variable name, and values[ ] can accept any string (which must be in quotes) or variable (which doesn't need quoting). I generally recommend that attributes be always lowercase and only include underscores for two issues: this is one of them, and the other is the on('change') event which must always be lower case. Following the lowercase and special characters can only be underscores rules makes writing javascript easier.
1711754381

Edited 1711804323
GiGs
Pro
Sheet Author
API Scripter
Vince earlier made a suggestion, and I'm pointing this out as much for Vince because I know he likes to learn. He suggested this: const aR1 = parseInt(`${values['armor1-Rating']}`) || 0; That's an overly complicated structure. The structure is valid, but you can simplify it by removing the outer quotes and brackets, so it becomes this: const aR1 = parseInt(values['armor1-Rating']) || 0; That won't work any more because you have replaced dashes with underscores (a good move IMO), but let's explain what was going on here. There's a special kind of quote used in the first example above: ` ` - the backtick. It encloses a special kind of string called a template literal. One benefit of this kind of string is you can include code inside a ${ } structure. Vince put the code values['armor1-Rating'] inside that structure. But you can write that code directly here - you don't need the template literal and its ${ } structure to include it. So can simplify it to the second example above.
1711756873
vÍnce
Pro
Sheet Author
+1
GiGs said: I'm late to the thread, is it all working now?&nbsp; Yes, it was all working by that point. However, I do appreciate the other things you pointed out. I had copy/pasted things on the page that one of the eariler authors had a - in. Likely because there was no affiliated script. I did a bulk replace to remove the - and replace it with _ to be more in line with js.&nbsp;