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

An evolution of repeating sections and sheet workers

This is the user-story of what I'm trying to achieve with this new section. User enters a value into any of the Op row. Farsense, Create, Redact, PK, Coerce or Dream. (green boxes) The user creates a new Operant Skill. The previously entered values (green boxes) appears in the coresponding readonly number cells in each (all) repeating sections in the Operant Skills section. (red boxes) The user enters the name and description of the skill in the grey boxes on the left side of the repeating skill. The user defines the Title of the Operant Skill (this is the skill level). The user selects one or more of the checkboxes in the repeating section. The highest of the values in the selected checkboxes is added to the value derived from the Title dropdown list. This value is then updated into the readonly Rating box in the repeating section. (blue box) I have some broken code on how I've tried to do this, but it's not working. What I was doing was using a sheet worker to monitor the green boxes. On change, the values were supposed to appear in the red boxes. on("change:Farsense", function(){ getAttrs(["Farsense"], function(values){ let skillfarsense = values.Farsense||0; setAttrs({ SkillFarsense: skillfarsense }); }); }); But it's not working. After that, I have no idea how to use the largest of the selected values from the red boxes. Also I don't know why the checkboxes are so small.
1588056762

Edited 1588060508
GiGs
Pro
Sheet Author
API Scripter
Can you show the HTML of the section of the sheet in the screenshot? If you want to copy a value outside of a repeating section to all relevant matching places inside a repeating section ,you have to understand how repeating section names work. I explained them in a recent post here:&nbsp; <a href="https://app.roll20.net/forum/permalink/8560775/" rel="nofollow">https://app.roll20.net/forum/permalink/8560775/</a> Assuming you've read the post linked above, we cannot use the short code for ids in sheet workers, we have to use the long code. Luckily we have a function to get that for us, getSectionIDs. And we have to loop through the entire repeating section to get all the names - each row is differently. Here's a post where I have an annotated sheet worker using getSectionIDs:&nbsp; <a href="https://app.roll20.net/forum/permalink/8560996/" rel="nofollow">https://app.roll20.net/forum/permalink/8560996/</a> Here's a first pass at a sheet worker that might handle all 6 of your attributes: This assumes your attributes are named:&nbsp; Farsense, Create, Redact, PK, Coerce or Dream and they have a corresponding attribute in the repeating section named SkillFarsense, SkillCreate, and so on. Finally, i dont know what your repeating section is called, so replace repeating_WHATEVER in the code below with the name of your repeating section. //&nbsp;on&nbsp;the&nbsp;change&nbsp;line,&nbsp;attributes&nbsp;must&nbsp;always&nbsp;be&nbsp;lower&nbsp;case on("change:farsense&nbsp;change:create&nbsp;change:redact&nbsp;change:pk&nbsp;change:coerce&nbsp;change:dream",&nbsp;(event)&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;event&nbsp;gives&nbsp;the&nbsp;attribute&nbsp;that&nbsp;just&nbsp;changed.&nbsp;we&nbsp;store&nbsp;its&nbsp;name&nbsp;in&nbsp;a&nbsp;variable&nbsp;to&nbsp;make&nbsp;it&nbsp;easier&nbsp;to&nbsp;use. &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;changing&nbsp;=&nbsp;event.sourceAttribute; &nbsp;&nbsp;&nbsp;&nbsp;getSectionIDs("repeating_operantskills",&nbsp;idarray&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;loop&nbsp;through&nbsp;the&nbsp;repeating&nbsp;section&nbsp;to&nbsp;get&nbsp;the&nbsp;row&nbsp;ides&nbsp;and&nbsp;full&nbsp;names&nbsp;of&nbsp;the&nbsp;relevant&nbsp;repeating&nbsp;sections &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;fieldnames.push(`repeating_operantskills_${id}_Skill${changing}`)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getAttrs([changing],&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;//&nbsp;get&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;attribute&nbsp;that&nbsp;just&nbsp;changed. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;newvalue&nbsp;=&nbsp;parseInt(v[changing])&nbsp;||&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//loop&nbsp;through&nbsp;the&nbsp;attribute&nbsp;names&nbsp;found&nbsp;earlier,&nbsp;and&nbsp;store&nbsp;the&nbsp;new&nbsp;value&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fieldnames.forEach(name&nbsp;=&gt;&nbsp;output[name]&nbsp;=&nbsp;newvalue); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;save&nbsp;the&nbsp;values&nbsp;to&nbsp;the&nbsp;sheet &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;}); });
1588056890
GiGs
Pro
Sheet Author
API Scripter
The previous worker should handle steps 1-3. We cant do the rest without knowing your attribute names, and they will need at least one more sheet worker anyway.&nbsp;
Hi GiGs. This is the code for the section above. &lt;div class="sheet-meta"&gt; &lt;h1 class="sheet-section"&gt;Metabilities&lt;/h1&gt; &lt;table width="100%"&gt; &lt;/table&gt; &lt;table&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td width="100%"&gt; &lt;table width="100%"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th&gt;Lat&lt;/th&gt; &lt;th&gt;Farsense:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_FarsenseLatency" min="0"&gt; &lt;/td&gt; &lt;th&gt;Create:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_CreativityLatency" min="0"&gt; &lt;/td&gt; &lt;th&gt;Redact:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_RedactionLatency" min="0"&gt; &lt;/td&gt; &lt;th&gt;PK:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_PKLatency" min="0"&gt; &lt;/td&gt; &lt;th&gt;Coerce:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_CoercionLatency" min="0"&gt; &lt;/td&gt; &lt;th&gt;Dream:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_DreamLatency" min="0"&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;th&gt;Op&lt;/th&gt; &lt;th&gt;Farsense:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Farsense" min="0"&gt; &lt;button type="roll" title="Roll against Farsense" value="!continuum Farsense|@{Farsense}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Create:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Creativity" min="0"&gt; &lt;button type="roll" title="Roll against Creativity" value="!continuum Creativity|@{Creativity}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Redact:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Redaction" min="0"&gt; &lt;button type="roll" title="Roll against Redaction" value="!continuum Redaction|@{Redaction}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;PK:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_PK" min="0"&gt; &lt;button type="roll" title="Roll against PK" value="!continuum PK|@PK}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Coerce:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Coercion" min="0"&gt; &lt;button type="roll" title="Roll against Coercion" value="!continuum Coercion|@Coercion}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Dream:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Dream" min="0"&gt; &lt;button type="roll" title="Roll against Dream" value="!continuum Dream|@Dream}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;th&gt;Prog:&lt;/th&gt; &lt;td&gt;Farsense:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_FarsenseProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;td&gt;Create:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_CreativityProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;td&gt;Redact:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RedactionProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;td&gt;PK:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_PKProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;td&gt;Coerce:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_CoercionProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;td&gt;Dream:&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_DreamProgress" value="0" min="0" max="100"&gt; /100&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;h2 class="sheet-subsection"&gt;Operant Skills&lt;/h2&gt; &lt;fieldset class="repeating_oerantskills"&gt; &lt;table width="100%"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th width="28%"&gt;Name&lt;/th&gt; &lt;th width="21%" colspan="4"&gt;Title&lt;/th&gt; &lt;th width="10%" colspan="2"&gt;Rating&lt;/th&gt; &lt;th width="10%" colspan="2"&gt;Roll&lt;/th&gt; &lt;th width="20%" colspan="4"&gt;Progress&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td width="20%"&gt;&lt;input type="text" STYLE="color: #1C2833; font-family: Verdana; font-weight: bold; font-size: 12px; background-color: #D0D3D4;" name="attr_OperantSkillName"&gt; &lt;/td&gt; &lt;td colspan="4"&gt; &lt;select name="attr_OperantSkillTitle"&gt; &lt;option selected disabled&gt;&lt;/option&gt; &lt;option value="-2"&gt;Untrained&lt;/option&gt; &lt;option value="0"&gt;Novice&lt;/option&gt; &lt;option value="1"&gt;Apprentice&lt;/option&gt; &lt;option value="2"&gt;Journeyman&lt;/option&gt; &lt;option value="3"&gt;Master&lt;/option&gt; &lt;option value="4"&gt;Grandmaster&lt;/option&gt; &lt;option value="5"&gt;Grandmaster + 1&lt;/option&gt; &lt;option value="6"&gt;Grandmaster + 2&lt;/option&gt; &lt;option value="7"&gt;Grandmaster + 3&lt;/option&gt; &lt;option value="8"&gt;Grandmaster + 4&lt;/option&gt; &lt;/select&gt; &lt;/td&gt; &lt;td colspan="2"&gt;&lt;input type="number" name="attr_OperantSkillRating" readonly&gt;&lt;/td&gt; &lt;td colspan="2"&gt;&lt;button type="roll" title="Roll your Metability" value="!continuum @{OperantSkillRating}|@{OperantSkillRating}|[[ ?{Modifiers not including IP|0} - @{IPTOTal}]]"&gt;&lt;/button&gt;&lt;/td&gt; &lt;td width="25%" colspan="4"&gt; &lt;input type="number" name="attr_OperantSkillProgress" value="0" min="0"&gt; / &lt;input type="number" name="attr_OperantSkillProgressMax" value="(@{OperantSkillTitle} + 1) * 10" disabled&gt; &lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;td&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;input type="textarea" STYLE="color: #1C2833; font-family: Verdana; font-weight: bold; font-size: 12px; background-color: #D0D3D4;" name="attr_OperantSkillDescription1"&gt; &lt;/td&gt; &lt;th colspan="2"&gt;Farsense&lt;/th&gt; &lt;th colspan="2"&gt;Create&lt;/th&gt; &lt;th colspan="2"&gt;Redact&lt;/th&gt; &lt;th colspan="2"&gt;PK&lt;/th&gt; &lt;th colspan="2"&gt;Coerce&lt;/th&gt; &lt;th colspan="2"&gt;Dream&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;input type="text" STYLE="color: #1C2833; font-family: Verdana; font-weight: bold; font-size: 12px; background-color: #D0D3D4;" name="attr_OperantSkillDescription2"&gt; &lt;/td&gt; &lt;input type="hidden" value="10" name="attr_str_mod" value="0" /&gt; &lt;td&gt;&lt;input type="number" name="attr_SkillFarsense" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesFarsense"&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RangedDamageD" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesCreate"&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RangedDamageD" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesRedact"&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RangedDamageD" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesPK"&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RangedDamageD" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesCoerce"&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="number" name="attr_RangedDamageD" readonly&gt;&lt;/td&gt; &lt;td&gt;&lt;input type="checkbox" name="attr_OperantSkillUsesDream"&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/fieldset&gt; &lt;/div&gt;
1588060722
GiGs
Pro
Sheet Author
API Scripter
I think your repeating skill name has a typo, it is listed as&nbsp;"repeating_oerantskills"; shouldnt it be "repeating_operantskills" ? I added this to previous code. You have a lot of these towards the end: &lt;input type="number" name="attr_RangedDamageD" readonly&gt; Should they be the various SkillCreate, SkillPK, etc.? If so, change them and the sheet worker should work (if you correct the typo in the repeating section name).
Got that to work. Thanks. The repeaters update with the values from the main Metabilities section. The last thing is that bit where it takes the highest of all selected Metabilities and uses that value to add to the value in the OperantSkillTitle dropdown, and then display that in the OperantSkillRating box.
1588119285
GiGs
Pro
Sheet Author
API Scripter
Can you be specific about how this works, and which attributes (use their roll20 names) are being watched, and how they change?
It's all in that first post I made to this topic. The player gets to chose one or more of the values in the Red boxes. Those are now all working, thanks. :) The highest of the values in the Red boxes appears in the Blue box. This is then used for the dice roll.&nbsp; I have the dice roll working. I just need to find the highest of the arbitrarily selected Rex values and squirt that into the Blue box.
It seems something like this can be used to compare two values and decide which is higher- ((@{A} + @{B} + abs(@{A} - @{B})) / 2) Is this like what we would do in this case?
1588136991
GiGs
Pro
Sheet Author
API Scripter
No, the best way is to use Math.max() and inside the max, just have a comma separated list of attributes, like Math.max(attr1, attr2, attr3). I'd do the code but you havent answered me in enough detail so i dont know how to.
Understood. Here's what I'm looking to do: Psychic powers come in Latent (can't use them) and Operant (can use them). A power has Latent Potential, but that's not a mechanic we need to care about. All powers have an Operant level, from 0 to 5. 0 means it doesn't work, 5 is pretty godlike. The player enters the level of Operancy in each of the 6 powers. Then there's Skills. A Metability Skill is an application of the base powers. PK (Psycho Kinesis) has a Skill called "Fly". You can use your PK to throw yourself through the air. It's silly and dangerous, but fun. So the Skill for that would look like this- The Rating slot would have the sum of the value in PK (4) plus the value linked to the Apprentice title in the dropdown (+1), for a total of 5. Another skill might be a combo that uses Farsense and Coercion- In this one, since the Farsense and Coercion checkboxes are ticked, the code would decide which of those two values is the highest, and apply that to the math like so: The highest of 3 and 4 is 4, so then it's 4 plus Apprentice (+1) for a total of 5. That 5 would appear in the Rating box. Does that make it clear?
1588142500
GiGs
Pro
Sheet Author
API Scripter
It's clearer. I'm going to bed now and will have a proper look tomorrow. But you also need to tell us what the relevant attributes are - the roll20 attributes, not the rpg attributes. In the big html code above, there are names like FarsenseProgress, OperantSkillProgress, and so on. Which of those attributes are involved here?
Thanks. I'll do that here. The following code contains the relevant attributes: &lt;tr&gt; &lt;th&gt;Op&lt;/th&gt; &lt;th&gt;Farsense:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Farsense" min="0"&gt; &lt;button type="roll" title="Roll against Farsense" value="!continuum Farsense|@{Farsense}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Create:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Creativity" min="0"&gt; &lt;button type="roll" title="Roll against Creativity" value="!continuum Creativity|@{Creativity}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Redact:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Redaction" min="0"&gt; &lt;button type="roll" title="Roll against Redaction" value="!continuum Redaction|@{Redaction}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;PK:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_PK" min="0"&gt; &lt;button type="roll" title="Roll against PK" value="!continuum PK|@PK}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Coerce:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Coercion" min="0"&gt; &lt;button type="roll" title="Roll against Coercion" value="!continuum Coercion|@Coercion}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;th&gt;Dream:&lt;/th&gt; &lt;td&gt; &lt;input type="number" name="attr_Dream" min="0"&gt; &lt;button type="roll" title="Roll against Dream" value="!continuum Dream|@Dream}|[[ ?{Modifiers not including IP|0} - @{IPTOTal} -@{Shadow}]]"&gt;&lt;/button&gt; &lt;/td&gt; &lt;/tr&gt; attr_Farnsense, attr_Creativity, attr_Redaction, attr_PK, attr_Coercion, attr_Dream These are the attributes which the player assigned to a given Skill, in singles or multiples. A Skill can have up to all 6 involved. The highest value from the selected attributes above is then added as described in the previous post.
Keep in mind I'm super tired right now so I'm not 100% sure I understand this, or that this is the best way to accomplish it, but I think this could work: You have your 6 scores, each with a check box inside the repeating section Give the check boxes an attribute (like, Creativity, CreativityChecked, Redaction, Redaction Checked) etc. Then set up a formula using math.max((CreativityCheckedx10)+Creativity, (RedactionCheckedx10)+Rexaction, (...etc...))-10 If the check-mark is checked, it'll add 10 to whatever scores are checked, then find the highest score, then subtract the 10 back out - leaving you with the highest score. Since a score can't go any higher than 5, any without the check will never be higher than any with the check. The only downside to this method is that your roll template won't be able to tell you which score is being used - only the actual number. If you need to know which score is being used in your output, then you'll need to use a sheet worker.
No, we don't need to know which score is being used. That's made clear by the checkbox.
1588187353
GiGs
Pro
Sheet Author
API Scripter
Tuck S. said: These are the attributes which the player assigned to a given Skill, in singles or multiples. A Skill can have up to all 6 involved. The highest value from the selected attributes above is then added as described in the previous post. The bit I'm not grasping is - which attribute is it saved to? I think I'm using the word attribute differentlly to you. You're talking about game statistics, I'm talking about the specific names of things on the character sheet, things like this: &lt;input type="checkbox" name="attr_OperantSkillUsesFarsense"&gt;&lt;/td&gt; That is the attribute OperantSkillIUsesfarSense. I get that you read the 6 attributes and use the largest, but I dont know which attribute that gets saved to, on the sheet. There's a bunch of stuff in there that I'm not sure how it's involved in this caclulation.
1588189124

Edited 1588189316
arg, sorry. Please forgive my lack of comprehension. The attribute it's being saved to in the repeating sections is called&nbsp;"attr_OperantSkillRating"
also, would it be easier if the source values were taken from attributes within the repeating section? If so, then the source attributes are attr_SkillFarsense attr_SkillCreativity attr_SkillRedaction attr_SkillPK attr_SkillCoercion attr_SkillDream
1588200931

Edited 1588200969
GiGs
Pro
Sheet Author
API Scripter
I think I understand it now, mostly. Here's a revised description, with things that aren't relevant to the worker removed - let me know if it's in error. The user creates a new Operant Skill (OperantSkillName), and chooses a level from the Title checkbox (OperantSkillTitle).&nbsp; &nbsp;The SkillFarsense, skillCreativity, etc attributes get their values from the corresponding attributes outside the repeating section. &nbsp;A max skill is chosen from those attributes which are checked: OperantSkillUsesFarsense, OperantSkillUsesCreate, etc &nbsp;The OperantSkillRating is calculated based on this max rating, and the bonus from OperantSkillTitle Is that accurate? If the above summary is correct, I can create the sheet worker. Two html changes you should make for the sheet worker: &nbsp; &nbsp; &nbsp; &nbsp; for each of the operant skill checkboxes, add value="1", like so &nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="checkbox" name="attr_OperantSkillUsesFarsense" value="1" &gt; &nbsp; &nbsp; &nbsp; &nbsp; For the OperantSkillTitle select: get rid of the first option, and set Untrained as the default &nbsp; &nbsp; &nbsp; &nbsp; &lt;option value="-2" selected&gt;Untrained&lt;/option&gt; &nbsp; &nbsp; &nbsp; &nbsp; Having a null value there as selected complicates the sheet worker and calculation of skill value. And of course make sure the repeating_o p erantskills typo is fixed (the missing p)
1588201191

Edited 1588203497
A few corrections: The user creates a new Operant Skill (OperantSkillName), and chooses a level from the Title dropdown (OperantSkillTitle). [yes] &nbsp;The SkillFarsense, skillCreativity, etc attributes get their values from the corresponding attributes outside the repeating section. [yes] &nbsp;A max Stat is chosen from those attributes which are checked: OperantSkillUsesFarsense, OperantSkillUsesCreate, etc [yes] &nbsp;The OperantSkillRating is calculated based on this max rating, and the bonus from OperantSkillTitle [yes] I say "Stat" because I consider the Farsense, Creation etc to be stats, and the "Fly" or "Remote Coercion" to be "skills" which are built by adding a Title to a Stat. But yes, I think you're correct. I'll make those fixes and changes.
1588204337

Edited 1588219051
GiGs
Pro
Sheet Author
API Scripter
Here's a sheet worker to test. It's very complex, and workers as complex as this might need some revisions to get working properly. //&nbsp;a&nbsp;function&nbsp;to&nbsp;construct&nbsp;a&nbsp;string&nbsp;on&nbsp;the&nbsp;on(change)&nbsp;line const&nbsp;buildChanges&nbsp;=&nbsp;(list,&nbsp;prefix&nbsp;=&nbsp;'',&nbsp;section&nbsp;=&nbsp;'')&nbsp;=&gt;&nbsp;list.map(item&nbsp;=&gt;&nbsp;`change:${(section&nbsp;?&nbsp;`repeating_${section.toLowerCase()}:`:&nbsp;'')}${prefix.toLowerCase()}${item.toLowerCase()}`).join('&nbsp;'); const&nbsp;clog&nbsp;=&nbsp;(message)&nbsp;=&gt;&nbsp;console.log(`%c&nbsp;${message}`,&nbsp;`color:green;&nbsp;font-weight:bold`); const&nbsp;stats&nbsp;=&nbsp;['Farsense',&nbsp;'Creativity',&nbsp;'Redaction',&nbsp;'PK',&nbsp;'Coercion',&nbsp;'Dream']; on(`${buildChanges(stats)}&nbsp;${buildChanges(stats,&nbsp;'OperantSkillUses',&nbsp;'operantskills')}&nbsp;change:repeating_operantskills:operantskilltitle&nbsp;change:repeating_operantskills:operantskillname`,&nbsp;(event)&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;event&nbsp;tells&nbsp;us&nbsp;which&nbsp;attribute&nbsp;changed,&nbsp;and&nbsp;that&nbsp;tells&nbsp;us&nbsp;what&nbsp;we&nbsp;need&nbsp;to&nbsp;do&nbsp;in&nbsp;the&nbsp;worker. &nbsp;&nbsp;&nbsp;&nbsp;getSectionIDs("repeating_operantskills",&nbsp;idarray&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;loop&nbsp;through&nbsp;the&nbsp;repeating&nbsp;section&nbsp;to&nbsp;get&nbsp;the&nbsp;row&nbsp;ides&nbsp;and&nbsp;full&nbsp;names&nbsp;of&nbsp;the&nbsp;relevant&nbsp;repeating&nbsp;attributes &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;fieldnames.push(`repeating_operantskills_${id}_OperantSkillTitle`); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fieldnames.push(`repeating_operantskills_${id}_OperantSkillRating`); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stats.forEach(stat&nbsp;=&gt;&nbsp;fieldnames.push( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`repeating_operantskills_${id}_OperantSkillUses${stat}`, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`repeating_operantskills_${id}_Skill${stat}` &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;getAttrs([...stats,&nbsp;...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;//&nbsp;get&nbsp;the&nbsp;values&nbsp;of&nbsp;the&nbsp;six&nbsp;core&nbsp;stats. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;statValues&nbsp;=&nbsp;{}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stats.forEach(stat&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statValues[stat]&nbsp;=&nbsp;parseInt(v[stat])&nbsp;||&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;check&nbsp;the&nbsp;stat&nbsp;values&nbsp;in&nbsp;the&nbsp;section&nbsp;are&nbsp;correct &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;stats.forEach(stat&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;statvalue&nbsp;=&nbsp;parseInt(v[`repeating_operantskills_${id}_Skill${stat}`])&nbsp;||&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(statvalue&nbsp;!==&nbsp;statValues[stat])&nbsp;output[`repeating_operantskills_${id}_Skill${stat}`]&nbsp;=&nbsp;statValues[stat]; &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;now&nbsp;calculate&nbsp;the&nbsp;OperantSkillRating&nbsp;for&nbsp;each&nbsp;row &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&nbsp;oldvalue&nbsp;=&nbsp;parseInt(v[`repeating_operantskills_${id}_OperantSkillRating`])&nbsp;||&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;title&nbsp;=&nbsp;parseInt(v[`repeating_operantskills_${id}_OperantSkillTitle`])&nbsp;||&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;maxValue&nbsp;=&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;loop&nbsp;through&nbsp;stats,&nbsp;see&nbsp;if&nbsp;they&nbsp;are&nbsp;checked,&nbsp;and&nbsp;if&nbsp;so&nbsp;add&nbsp;their&nbsp;value&nbsp;to&nbsp;statValues &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stats.forEach(stat&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(parseInt(v[`repeating_operantskills_${id}_OperantSkillUses${stat}`])&nbsp;&amp;&amp;&nbsp;statValues[stat]&nbsp;&gt;&nbsp;maxValue)&nbsp;maxValue&nbsp;=&nbsp;statValues[stat]; &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;now&nbsp;add&nbsp;the&nbsp;highest&nbsp;stat&nbsp;to&nbsp;the&nbsp;title/level &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;newvalue&nbsp;=&nbsp;maxValue&nbsp;+&nbsp;title; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(newvalue&nbsp;!=&nbsp;oldvalue)&nbsp;output[`repeating_operantskills_${id}_OperantSkillRating`]&nbsp;=&nbsp;newvalue; &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;}); });
Wow, that's big. I'll try that. Thanks.
ok, first impression is that it didn't work. I pasted that in to the bottom of the sheet, just above the &lt;/script&gt; I didn't see any change in the behaviour of the repeater. All I'm qualified to do is check for spelling errors, and I'm not seeing any.
1588216011
GiGs
Pro
Sheet Author
API Scripter
Did you remove the previous worker? I'll probably have to install it myself to do proper testing. can you post your html and css on pastebin.com and link them here?
<a href="https://hastebin.com/hinuyaroza.cs" rel="nofollow">https://hastebin.com/hinuyaroza.cs</a> <a href="https://hastebin.com/ehuyaseyaq.css" rel="nofollow">https://hastebin.com/ehuyaseyaq.css</a>
1588218992
GiGs
Pro
Sheet Author
API Scripter
You havent made those changes to the html. Also make sure to remove the sheet worker I posted earlier in this thread that acts on the same repeating section. They werent the reason it wasnt working, but it wont work properly till you make those fixes. I've updated the earlier post with the fixed code. There were a couple of issues, but its working now.&nbsp;
Thanks very much. Trying it.
Ok, the OperantSkillTitle dropdown is updating the OperantSkillRating box, but it's only updating it with the value in the OperantSkillTitle dropdown. -2, 0, 1, 2, 3, 4 etc. It's not adding that value to the maxValue you have in your line 1643. Also, does it update when a checkbox is ticked? If I wanted that to happen, would I add "change:repeating_operantskills_OperantSkillUsesFarsense" to line 1601?
1588226560
GiGs
Pro
Sheet Author
API Scripter
It works perfectly for me, have you removed the previous worker and updated the html?
1588226821

Edited 1588226841
GiGs
Pro
Sheet Author
API Scripter
Tuck S. said: Ok, the OperantSkillTitle dropdown is updating the OperantSkillRating box, but it's only updating it with the value in the OperantSkillTitle dropdown. -2, 0, 1, 2, 3, 4 etc. It's not adding that value to the maxValue you have in your line 1643. Also, does it update when a checkbox is ticked? If I wanted that to happen, would I add "change:repeating_operantskills_OperantSkillUsesFarsense" to line 1601? On my version of the campaign, the maxValue is being added properly. And it is updating when the checkbox is ticked. Dont add the change line - this section of the on(change) line handles that &nbsp;${buildChanges(stats,&nbsp;'OperantSkillUses',&nbsp;'operantskills')} Can you post the html you are using (dont need the css this time) to another pastebin/hastebin?
<a href="https://hastebin.com/doyufogumu.cs" rel="nofollow">https://hastebin.com/doyufogumu.cs</a>
1588227040
GiGs
Pro
Sheet Author
API Scripter
Thanks. By the way, here's a screenshot of it working
1588227261

Edited 1588227387
GiGs
Pro
Sheet Author
API Scripter
You still havent made the change to the html. Thats causing your issue. add value="1" to each of your checkboxes. so &lt;td width= "5%" &gt;&lt;input type= "checkbox" name= "attr_OperantSkillUsesFarsense" &gt;&lt;/td&gt; becomes &lt;td width= "5%" &gt;&lt;input type= "checkbox" name= "attr_OperantSkillUsesFarsense" value="1" &gt;&lt;/td&gt; Less important but also change this in your title select &lt;option selected disabled&gt;&lt;/option&gt; &lt;option value = "-2" &gt;Untrained&lt;/option&gt; to this &lt;option value = "-2" selected &gt;Untrained&lt;/option&gt; That empty selected box will mess up the calculations. I don't think disabled works there either.
poop. I must have borked your code somehow. I would not be surprised.
That did it. Thanks very much. It's just working. You're amazing.
1588228498
GiGs
Pro
Sheet Author
API Scripter
Thank you! :)