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

Creating a repeating section for spell effects and the like, to modify stats.

1589813300

Edited 1589813835
So, my friends and I play a table top role playing game that, for the purposes of this question, is functionally equivalent to any other table top role playing game.&nbsp; Each character has a set of stats, like ability scores, and defense scores, that are used by the game mechanics to determine the outcomes of actions.&nbsp; Lets call these ability scores.&nbsp; These scores can be set in the character sheet.&nbsp; However, there are spell effects, and also some character abilities, that can modify these scores, depending on whether they are active.&nbsp; Lets call them spell effects. Now, I already have a section where temporary modifiers can be added to adjust the character's ability scores.&nbsp; That's fine, but there are spell effects that are turned off and on so frequently, during the course of a combat, that updating these temporary modifiers becomes a drag on the game.&nbsp; What I'd like to do is create a repeating section of spell effect templates.&nbsp; So, whenever there's a spell effect that frequently affects your character, you handle this by adding an entry to this repeating section, which we'll call the repeating section of spell effects. Each instance of this repeating section has a field for each of your character's ability scores.&nbsp; Into those fields you can enter modifiers that will apply to your character's associated ability scores, adjusting them, depending on whether the spell effect is active.&nbsp; Each section will also have a toggle that you can use to indicate whether the spell effect is active. Now the toggle could be a checkbox, but I'd like to modify the button in the solution presented here: <a href="https://app.roll20.net/forum/post/8556606/collapsible-inside-repeating-section" rel="nofollow">https://app.roll20.net/forum/post/8556606/collapsible-inside-repeating-section</a> so that instead of making the button show or hide part of the UI, it would enable or disable the associated spell effect.&nbsp; As for how it would do that, my best idea so far is to tie a 0 to the off setting of the button, and a 1 to the on setting.&nbsp; That way I can just have a modifier = modifier * button_value.&nbsp; That way the modifier can always be in the final calculation of the ability score, but it will only affect the ability score if it is active. Toggle button aside, the real challenge is to sum up all of the modifiers of each type in the spell effects repeating section.&nbsp; So far I haven't managed to grasp the code to do this well enough to even attempt to code it.&nbsp; In case anyone does know how, let me give you a simple pseudo-code example interface to plug it into: // ability scores: attr_strength attr_armor_class attr_initiative_modifier // ability score sums (after spell effect have been applied): attr_final_strength attr_final_armor_class attr_final_initiative_modifier // spell effects repeating section: &lt;fieldset class="repeating_spelleffects"&gt; &lt;select id="cars"&gt; &lt;option value="0"&gt;Off&lt;/option&gt; &lt;option value="1"&gt;On&lt;/option&gt; &lt;/select&gt; &lt;input name="attr_strength_modifier" type="number"&gt; &lt;input name="attr_armor_class_modifier" type="number"&gt; &lt;input name="attr_initiative_modifier" type="number"&gt; &lt;/fieldset&gt;
1589817137
GiGs
Pro
Sheet Author
API Scripter
Summing up the modifiers of each type is easy enough. Though the code below may not look like it, since it has to take into account an unspecified number of attributes. You'd want to have a set of attributes outside the repeating section to hold the totals, like &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input name="attr_strength_modifier_total" type="number" value="0"&gt; &lt;input name="attr_armor_class_modifier_total" type="number" value="0&gt; &lt;input name="attr_initiative_modifier_total" type="number" value="0"&gt; These can be hidden if desired. Here's the total HTML I tested with: &lt;fieldset&nbsp;class="repeating_spelleffects"&gt;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;select&nbsp;name="attr_toggle_modifier"&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value="0"&gt;Off&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;option&nbsp;value="1"&gt;On&lt;/option&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/select&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;name="attr_strength_modifier"&nbsp;type="number"&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;name="attr_armor_class_modifier"&nbsp;type="number"&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;name="attr_initiative_modifier"&nbsp;type="number"&gt; &lt;/fieldset&gt; &lt;hr/&gt; &lt;input&nbsp;name="attr_strength_modifier_total"&nbsp;type="number"&nbsp;value="0"&gt; &lt;input&nbsp;name="attr_armor_class_modifier_total"&nbsp;type="number"&nbsp;value="0"&gt; &lt;input&nbsp;name="attr_initiative_modifier_total"&nbsp;type="number"&nbsp;value="0"&gt; Notice the change I made to the select: roll20 doesnt allow id tags, and you need to give it a name. Now you need a sheet worker to iterate through the section every time an attribute changes, and updates the totals. Here's the sheet worker and supporting functions: const&nbsp;int&nbsp;=&nbsp;(value,&nbsp;error&nbsp;=&nbsp;0)&nbsp;=&gt;&nbsp;parseInt(value)&nbsp;||&nbsp;error; const&nbsp;modifiers&nbsp;=&nbsp;['strength',&nbsp;'armor_class',&nbsp;'initiative']; const&nbsp;section_field&nbsp;=&nbsp;(section,&nbsp;field,&nbsp;id&nbsp;=&nbsp;':')&nbsp;=&gt;&nbsp;`repeating_${section}${id&nbsp;===&nbsp;':'&nbsp;?&nbsp;id&nbsp;:&nbsp;`_${id}_`}${field}`; const&nbsp;buildChanges&nbsp;=&nbsp;modifiers.reduce((total,item)&nbsp;=&gt;&nbsp;`${total}&nbsp;change:${section_field('spelleffects',&nbsp;item)}_modifier`,''); on(`${buildChanges}&nbsp;change:repeating_spelleffects:toggle_modifier&nbsp;remove:repeating_spelleffects&nbsp;sheet:opened`,&nbsp;()&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;getSectionIDs('repeating_spelleffects',&nbsp;idarray&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;fieldnames&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&nbsp;fieldnames.push(section_field('spelleffects',&nbsp;`${mod}_modifier`,&nbsp;id))); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fieldnames.push(section_field('spelleffects',&nbsp;'toggle_modifier',&nbsp;id)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getAttrs(fieldnames,&nbsp;v&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;output&nbsp;=&nbsp;{}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&nbsp;output[`${mod}_modifier_total`]&nbsp;=&nbsp;0); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toggle&nbsp;=&nbsp;int(v[section_field('spelleffects',&nbsp;'toggle_modifier',&nbsp;id)]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(toggle)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&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;output[`${mod}_modifier_total`]&nbsp;=&nbsp;output[`${mod}_modifier_total`]&nbsp;+&nbsp;int(v[section_field('spelleffects',&nbsp;`${mod}_modifier`,&nbsp;id)]); &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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs(output); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}); }); Make sure you define all your repeating fields with attributes like so value="attr_SOMETHING_modifier" and for each one have a matching input outside the section with an attribute name like so: value="attr_SOMETHING_modifier_total" Then in the sheet worker, there's one line you need to change: const&nbsp;modifiers&nbsp;=&nbsp;['strength',&nbsp;'armor_class',&nbsp;'initiative', 'SOMETHING']; So to add new attributes: add a new attribute to the const modifiers line&nbsp; add an input inside the repeating section with a matching name (just add _modifier ) add an input outside the section with an appropriate name for the total (add ( _modifier_total ) And thats it - this worker can handle any number of attributes just with these changes. Enjoy!
1589817269
GiGs
Pro
Sheet Author
API Scripter
The select could just as easily be a check box. Just swap the code for: &lt;input type="checkbox" name="attr_toggle_modifier" value="1"&gt;
1590012109

Edited 1590013195
Thank you GiGs.&nbsp; I very much appreciate your efforts to help me out.&nbsp; They've always been stepping stones to success for me in the past.&nbsp; Unfortunately, this time I think I've managed to confuse my description of what I'm working toward, but only just slightly.&nbsp; That is to say that in my code, the logic of the toggle button is handled outside of the sheet worker.&nbsp; You'll see in my code below how I managed that.&nbsp; I did this because doing so was simple enough, and because I thought it would simplify the sheet worker.&nbsp; Also, instead of&nbsp;repeating_spelleffects, I ended up just calling it&nbsp;repeating_effects. I've attempted several variations of your code, starting with plugging it in just as it is written, but so far I haven't gotten it to work.&nbsp; I've also spent some time analyzing your sheetworker.&nbsp; There are parts of it I'm afraid I still don't understand.&nbsp; I suppose that's obvious though, otherwise I'd have gotten it working.&nbsp; Anyway, if you'll take another pass at it, I'm hoping you'll see my error(s). I'll mention that in the code below, I've removed basically everything irrelevant, including all but three of the modifiers.&nbsp; The idea being to ask as little of you as possible. So here's my CSS.&nbsp; This is really just to make the checkbox look and work like a button, but I thought I'd include it anyway, as I'm quite pleased with it: input.sheet-effect { cursor: pointer; width: 54px; z-index: 1; height: 28px; opacity: 0; } input.sheet-effect + span::before { background-image: linear-gradient(to top left, #adbbff, #001a9c); /* blue */ color: white; width: 54px; content: attr(title); height: 28px; display: inline-block; margin-left: -56px; text-align: center; font-size: 14px; margin-top: 1px; font-weight: 600; padding-top: 8px; } input.sheet-effect:hover + span::before { background-image: linear-gradient(to top left, #ff69fa, #5c0959) !important; /* violet */ color: white !important; } input.sheet-effect:checked + span::before { color: black; background-image: linear-gradient(to top left, #fff65e, #948d13); /* yellow */ } input.sheet-effect:active + span::before { background-image: linear-gradient(to top left, #ffffff, #bfbfbf) !important; /* white */ color: black !important; } Here's the code where the values are stored, both in and out of the repeating section: &lt;input name="attr_physicalstrength_modifier_total" type="hidden" value="0"&gt; &lt;span class="field derived21" name="attr_physicalstrength_modifier_total"&gt;&lt;/span&gt; &lt;input name="attr_physicalendurance_modifier_total" type="hidden" value="0"&gt; &lt;span class="field derived21" name="attr_physicalendurance_modifier_total"&gt;&lt;/span&gt; &lt;input name="attr_agility_modifier_total" type="hidden" value="0"&gt; &lt;span class="field derived21" name="attr_agility_modifier_total"&gt;&lt;/span&gt; &lt;fieldset class="repeating_effects"&gt; &lt;input type="checkbox" name="attr_effect_checkbox" value="1" class="effect" title="@{effect_checkbox}"/&gt; &lt;span title="Toggle"&gt;&lt;/span&gt; &lt;input name="attr_physicalstrength_modifier" type="hidden" value="@{physicalstrength_on_value}*@{effect_checkbox}"&gt; &lt;input class="field right transparentBackground manual24" name="attr_physicalstrength_on_value" type="number" value='0'&gt; &lt;input name="attr_physicalendurance_modifier" type="hidden" value="@{physicalendurance_on_value}*@{effect_checkbox}"&gt; &lt;input class="field right transparentBackground manual24" name="attr_physicalendurance_on_value" type="number" value='0'&gt; &lt;input name="attr_agility_modifier" type="hidden" value="@{agility_on_value}*@{effect_checkbox}"&gt; &lt;input class="field right transparentBackground manual24" name="attr_agility_on_value" type="number" value='0'&gt; &lt;/fieldset&gt; And, here's the sheet worker.&nbsp; As you can see, I've messed with it quite a bit.&nbsp; I did try it as you wrote it though, before I messed with it.&nbsp; I only messed with it to try to get it to work.&nbsp; I also wanted to add some console.logging to it, so I'd be able to tell when it was called and what values it output.&nbsp; Unfortunately, I haven't made enough sense of it to do that yet.&nbsp; Also, and this might be telling as to the problem, I haven't been able to prove that it runs at all.&nbsp; Though, I'm sure that is an issue I introduced. const int = (value, error = 0) =&gt; parseInt(value) || error; const modifiers = ['physicalstrength', 'physicalendurance', 'agility']; const section_field = (section, field, id = ':') =&gt; `repeating_${section}${id === ':' ? id : `_${id}_`}${field}`; const buildChanges = modifiers.reduce((total,item) =&gt; `${total} change:${section_field('effects', item)}_modifier`,''); on(`${buildChanges} remove:repeating_effects sheet:opened`, () =&gt; { getSectionIDs('repeating_effects', idarray =&gt; { const fieldnames = []; idarray.forEach(id =&gt; { modifiers.forEach(mod =&gt; fieldnames.push(section_field('effects', `${mod}_modifier`, id))); fieldnames.push(section_field('effects', id)); }); getAttrs(fieldnames, v =&gt; { const output = {}; modifiers.forEach(mod =&gt; output[`${mod}_modifier_total`] = 0); idarray.forEach(id =&gt; { modifiers.forEach(mod =&gt; { output[`${mod}_modifier_total`] = output[`${mod}_modifier_total`] + int(v[section_field('spelleffects', `${mod}_modifier`, id)]); }); }); setAttrs(output); }); }); }); This may be obvious to you, but the way I see it, these are the things the sheet worker should handle. When it runs, it should add up all the values in each section, for each modifier (example: attr_physicalstrength_modifier), and store the sums for each modifier in the associated sum fields (example: attr_physicalstrength_modifier_total). It should run whenever: a section is added to repeating_effects actually this might not be necessary as the default values for each modifier field are all zero a section is deleted from repeating_effects any value in any section of repeating_effects is changed, including attr_effect_checkbox This includes changes to the modifiers as a result of the associated checkbox being turned on or off. Thanks again for taking the time to read my posts.
1590036516

Edited 1590036533
GiGs
Pro
Sheet Author
API Scripter
I think I follow the explanation, but there's one thing I dont understand: What do you mean by handling the logic of the toggle button outside the sheet worker? If you are having modifiers totalled within the sheet worker, the toggle logic has to be done in&nbsp; &nbsp;the sheet worker, or there's no way for the worker to know which modifiers to count. CSS can only hide or show sections of the sheet - but hiding them doesnt change whether they are counted or not.&nbsp; Is there something I'm missing?
1590038304
GiGs
Pro
Sheet Author
API Scripter
I see a couple of issues with the code: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id =&gt; { modifiers.forEach(mod =&gt; fieldnames.push(section_field('effects', `${mod}_modifier`, id))); fieldnames.push(section_field('effects', id)); }); The second line inside the forEach is faulty. section_field is a function that builds a repeating section attribute name, that must look like repeating_effects_ROWIDHERE_attrributename The function needs 3 parameters, the repetaing section name, the individual attribute name, and the row id. So this should be &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id =&gt; { modifiers.forEach(mod =&gt; fieldnames.push(section_field('effects', `${mod}_modifier`, id))); fieldnames.push(section_field('effects', 'effect_checkbox', id)); }); Then further down, you have this output[`${mod}_modifier_total`] = output[`${mod}_modifier_total`] + int(v[section_field('spelleffects', `${mod}_modifier`, id)]); in the section_field function, this is still using the old repeating section name, and so it should be output[`${mod}_modifier_total`] = output[`${mod}_modifier_total`] + int(v[section_field('effects', `${mod}_modifier`, id)]); The remaining problem is that the code as written, if it works, will always add up every modifier, whether the toggle is checked or not. So you need to insert a check for that.
1590038470

Edited 1590038753
GiGs
Pro
Sheet Author
API Scripter
So, the working code should be: const&nbsp;int&nbsp;=&nbsp;(value,&nbsp;error&nbsp;=&nbsp;0)&nbsp;=&gt;&nbsp;parseInt(value)&nbsp;||&nbsp;error; const&nbsp;modifiers&nbsp;=&nbsp;['physicalstrength',&nbsp;'physicalendurance',&nbsp;'agility']; const&nbsp;section_field&nbsp;=&nbsp;(section,&nbsp;field,&nbsp;id&nbsp;=&nbsp;':')&nbsp;=&gt;&nbsp;`repeating_${section}${id&nbsp;===&nbsp;':'&nbsp;?&nbsp;id&nbsp;:&nbsp;`_${id}_`}${field}`; const&nbsp;buildChanges&nbsp;=&nbsp;modifiers.reduce((total,item)&nbsp;=&gt;&nbsp;`${total}&nbsp;change:${section_field('effects',&nbsp;item)}_modifier`,''); on(`${buildChanges}&nbsp;change:repeating_effects:effect_checkbox&nbsp;remove:repeating_effects&nbsp;sheet:opened`,&nbsp;()&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;getSectionIDs('repeating_effects',&nbsp;idarray&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;fieldnames&nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&nbsp;fieldnames.push(section_field('effects',&nbsp;`${mod}_modifier`,&nbsp;id))); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fieldnames.push(section_field('effects',&nbsp;'effect_checkbox',&nbsp;id)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getAttrs(fieldnames,&nbsp;v&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;output&nbsp;=&nbsp;{}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&nbsp;output[`${mod}_modifier_total`]&nbsp;=&nbsp;0); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idarray.forEach(id&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const toggle = int(section_field('effects',&nbsp;'effect_checkbox',&nbsp;id)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(toggle)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modifiers.forEach(mod&nbsp;=&gt;&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;output[`${mod}_modifier_total`]&nbsp;=&nbsp;output[`${mod}_modifier_total`]&nbsp;+&nbsp;int(v[section_field('effects',&nbsp;`${mod}_modifier`,&nbsp;id)]); &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;&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; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs(output); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}); }); I added this if statement: if(int(section_field('effects',&nbsp;'effect_checkbox',&nbsp;id)))&nbsp;{ inside the idarray.foreach: so it will run once each row, check if the toggle is one or off, and add them if its on. I also added a reference for the efect_checkbox to the on(change) line at the start of the worker, so that clicking the checkbox triggers the sheet worker.
1590038666

Edited 1590038685
GiGs
Pro
Sheet Author
API Scripter
I do notice this reverts the script to exactly the one I posted 2 days ago, with just the repeating_spelleffects and toggle_modifier attributes changed to repeating_effects and effect_checkbox wherever they appear, and the names in modifier changed. I know &nbsp;the original worker works, because i tested it. You just have to make sure the attribute name references are correct.
1590038815
GiGs
Pro
Sheet Author
API Scripter
If there are any parts of the sheet worker you need explaining, feel free to ask - this sheet worker is a lot trickier to understand than the ones I usually post.
1590072420

Edited 1590073481
Thanks again for replying GiGs.&nbsp; I've tested your code again, exactly as it is written, and there has been an improvement.&nbsp; I added several log statements and I am seeing them show up in the log.&nbsp; So, I can now prove that the code is running.&nbsp; However, I am seeing these issues: This statement &lt;&nbsp;if(toggle) &gt; is always returning false because the value &lt; toggle &gt; is always zero. The total values, like &lt; attr_physicalendurance_modifier_total &gt; just stay zeroes, regardless of the sheet worker running. Commenting out &lt;if(toggle) &gt;, and thus forcing the entire sheetworker to run, does not result in the total values changing.&nbsp; They stay zeroes. The code is run whenever I press the toggle button, but it does not run when I adjust the modifier values. I'll give you more information on that later.&nbsp; This is going to take several posts, and I'm only posting in my breaks from work, so it may be several hours before I finish giving you all the information you need.&nbsp; I do appreciate your patience. For this post though, I wanted to answer your first question."What do you mean by handling the logic of the toggle button outside the sheet worker?" Sorry for not explaining this more clearly.&nbsp; You said that the names of the repeating fields had to be attr_SOMETHING_modifier.&nbsp; So that's what I've done.&nbsp; Let's take this one for example, attr_physicalstrength_modifier.&nbsp; Here, SOMETHING is replaced with physicalstrength.&nbsp; However, look at the code below. &lt;fieldset class="repeating_effects"&gt; &lt;input type="checkbox" name="attr_effect_checkbox" value="1" class="effect" title="@{effect_checkbox}"/&gt; &lt;span title="Toggle"&gt;&lt;/span&gt; &lt;input name="attr_physicalstrength_modifier" type="hidden" value="@{physicalstrength_on_value}*@{effect_checkbox}"&gt; &lt;input class="field right transparentBackground manual24" name="attr_physicalstrength_on_value" type="number" value='0'&gt; attr_physicalstrength_modifier is not the name of the input field where you enter the value of the modifier.&nbsp; That input field is named attr_physicalstrength_on_value.&nbsp; Instead, the value of attr_physicalstrength_modifier is calculated by multiplying the value of attr_physicalstrength_on_value, by the value of the checkbox included in that instance of repeating_effects.&nbsp; You see, the value of that checkbox is 0, when the checkbox is unchecked and 1 when the checkbox is checked.&nbsp; That way, when the checkbox is checked, the value being added up by the sheet worker is the modifier value multiplied by the value of the checkbox, 1, resulting in the original modifier value.&nbsp; However, when the checkbox is unchecked, the value being added up by the sheet worker is the modifier value multiplied by the value of the checkbox, now 0, resulting in 0. If the sheetworker is rerun whenever the value of attr_physicalstrength_modifier is changed, then checking and unchecking the checkbox included in that instance of repeating_effects, will result in the value of attr_physicalstrength_modifier being changed to zero and back again, and with each change, the sheetworker would recalculate the total.&nbsp; I suppose that means that having the sheetworker run whenever the checkbox is checked or unchecked would be redundant, because changing the value of the checkbox would also change the value of the modifiers in that instance of repeating_effects, and both of these occurrences would trigger the sheetworker to be rerun.&nbsp; That could be an issue.
1590077109

Edited 1590077171
GiGs
Pro
Sheet Author
API Scripter
I see what you mean. The way you have implemented it is faulty though: &lt;input name="attr_physicalendurance_modifier" type="hidden" value="@{physicalendurance_on_value}*@{effect_checkbox}"&gt; This will never produce a value, because it lacks&nbsp; disabled="true" . It's an autocalc field without the part that makes it work. There's another reason not to use this: if the sheet worker runs properly, it will overwrite the value of anything there, because the worker changes the&nbsp; physicalendurance _modifier &nbsp;value. I did find the error though:&nbsp; const&nbsp;toggle&nbsp;=&nbsp;int(section_field('effects',&nbsp;'effect_checkbox',&nbsp;id)); should be const&nbsp;toggle&nbsp;=&nbsp;int(v[section_field('effects',&nbsp;'effect_checkbox',&nbsp;id)]); Oops. Make that change and you'll see the totals being calculated. Note that this error is not in the original sheet worker I posted back here:&nbsp; <a href="https://app.roll20.net/forum/permalink/8688091/" rel="nofollow">https://app.roll20.net/forum/permalink/8688091/</a> We should have just gone straight back to that and updated the attribute names! Regarding your discovered issues: This statement &lt;&nbsp;if(toggle) &gt; is always returning false because the value &lt; toggle &gt; is always zero. The total values, like &lt; attr_physicalendurance_modifier_total &gt; just stay zeroes, regardless of the sheet worker running. Commenting out &lt;if(toggle) &gt;, and thus forcing the entire sheetworker to run, does not result in the total values changing.&nbsp; They stay zeroes. The code is run whenever I press the toggle button, but it does not run when I adjust the modifier values. They are all caused by that toggle error.&nbsp; With this fix, you dont need the _on_value attributes: just delete them, and set the _modifier versions to type-"number" instead of hidden.
OK.&nbsp; So I've made the changes that you suggested, and it is functioning as intended now.&nbsp; So thank you for that.&nbsp; I'm really quite pleased that it's working.&nbsp; I think I understand what it's doing, but I don't understand how it does it.&nbsp; I've added comments below to explain it as best I can.&nbsp; You offered to answer questions on how it works, so I thought this would be a good way to do that. There are a few reasons why I wanted to understand how it works.&nbsp; First, I'm always interested in how things work.&nbsp; Beyond that though, on all my sheet workers I include logging statements that show when a function is run, and output the values it comes up with.&nbsp; I don't really understand this one well enough to do that. The most important reason though, is that I have two other repeating sections that I'd like to add up values from.&nbsp; One is a repeating section of inventory items, where I'd like to add up their weight. That one's actually very similar because whether an item is carried, stored at home, or stored in extra-dimensional space would determine whether its weight counts toward encumbrance.&nbsp; The toggle button could be used for this.&nbsp; The other repeating section is journal entries, each with a field for experience earned.&nbsp; So adding up that experience would be good.&nbsp; That's a simpler example though. I'm not asking for help with those though, not yet at least, because I haven't tried to get them working myself yet.&nbsp; Understanding how this sheetworker works though would help with that. Here is where I was going to include the sheet worker with my comments explaining how I think it works, thus giving you an opportunity to correct me.&nbsp; However, after taking the time to run through it line by line and make my best guess, it turns out I understand it a lot better than I did before.&nbsp; So I'm not going to ask you questions about it, or at least not until I've failed to adapt it for the other uses I've mentioned.&nbsp; And, It may just work for me, so I may not need to do that. Thanks again = ).
1590122689
GiGs
Pro
Sheet Author
API Scripter
If you do have any questions, I am very happy to answer them. I know how useful it us to be able to understand the code, if you want to reuse it. For the encumbrance and experience, it will work - those are a little simpler, so there's a function I posted on the wiki that is perfect for that kind of thing (it was specifically written for encumbrance and experience, as it happens):&nbsp; <a href="https://wiki.roll20.net/RepeatingSum" rel="nofollow">https://wiki.roll20.net/RepeatingSum</a> You just need to copy the repeatingSum function into your script block (do not edit it, just copy it directly, with no changes), then create two very short sheet workers, one for the encumbrance section, and the other for the experience section. It supports toggles. For example, this would total up the contents of the xp_gained attribute in a repeating_journal section, and put that total in an experience_total attribute on ( 'change:repeating_journal:xp_gained remove:repeating_journal' , function () { repeatingSum ( "experience_total" ,"journal","xp_gained"); }); This would check each row of an repeating_encumbrance section, and if a item_carried toggle is checked, it would multiply item_weight by item_number , and then save the total in an attribute called encumbrance_total on ( 'change:repeating_inventory remove:repeating_inventory' , function () { repeatingSum ( "encumbrance_total" ,"inventory",[ "item_weight" ,"item_number","item_carried"]); }); If you plan to use multiple encumbrance sections (like, you want to total the amount carried, the amount on horse, and the amount at home) you are best off using the worker from this thread and adapting it for that purpose. But if you just want a single total, sumRepeating is great.