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

Calculated rolls with repeatable rows

1628348722
.Hell
Sheet Author
Hey everyone, it seems like I cannot get calculated rolls to work with repeatable rows. Is there a trick to it? Thanks
1628352020
GiGs
Pro
Sheet Author
API Scripter
It should work just like other sections. It's hard to guess what the issue might be. Can you post the code you're trying?
1628355372

Edited 1628355384
.Hell
Sheet Author
Thanks for taking a look at it. on('clicked:roll', (event) => { startRoll(event.htmlAttributes.value + "{{fumble=[[1d10!]]}} {{fumble2=[[1d10!]]}}", (results) => { var rollComputed = results.results.roll.result; var roll2Computed = 0; if(results.results.roll.dice[0] == 1) // We check if the first die is a fumble. { rollComputed = results.results.roll.result - 1 - results.results.fumble.result; } if(results.results.roll2 != null) { roll2Computed = results.results.roll2.result; if( results.results.roll2.dice[0] == 1) // We check if the first die is a fumble. { roll2Computed = results.results.roll2.result - 1 - results.results.fumble2.result; } } finishRoll( results.rollId, { roll: rollComputed, roll2: roll2Computed } ); }); });
1628355392

Edited 1628355480
.Hell
Sheet Author
<fieldset style ='margin-bottom: 10px;' class ="repeating_npcskill" > <span class ='repeating_npcskill_container' > <input class ='repeating_npcskill_name' name ='attr_npcskill_name' type ='text' value ='Name Here...' > <select class ='repeating_npcskill_stat' name ='attr_npcskill_stat' > <option value ='@{int_npc}' data-i18n ="int-u" > INT </option> <option value ='@{ref_npc}' data-i18n ="ref-u" > REF </option> <option value ='@{dex_npc}' data-i18n ="dex-u" > DEX </option> <option value ='@{body_npc}' data-i18n ="body-u" > BODY </option> <option value ='@{spd_npc}' data-i18n ="spd-u" > SPD </option> <option value ='@{emp_npc}' data-i18n ="emp-u" > EMP </option> <option value ='@{cra_npc}' data-i18n ="cra-u" > CRA </option> <option value ='@{will_npc}' data-i18n ="will-u" > WILL </option> </select> <input class ='repeating_npcskill_score' name ='attr_npcskill_score' type ='text' value ='0' > --> <button type ='action' name ='act_roll' style ='margin-top: -4px;' class ='repeating_npc_skill_roll' value ='@{whisper}&{template:statistics2} {{title=@{npcskill_name}}} {{name=@{character_name}}} {{roll=[[1d10!+@{npcskill_stat}[STAT]+@{npcskill_score}[SKILL]+?{ADDITIONAL MODS? (Bright Light, No Vision, Terrain etc)|0}[MOD]]]}}' ></button> </span> </fieldset> I added the arrow to show where it is called :)
1628401168
GiGs
Pro
Sheet Author
API Scripter
Can you say what happens or doesnt happen? Have you tried logging in the sheet worker to see if the sheet worker is firing? Can you post the rolltemplate code for testing, too? Does this code work if you remove the HTML from the repeating section, and just treat it as a non-repeating roll? also action buttons can be finicky about being called properly - try changing the sheet worker first line to on('clicked:repeating_npcskill:roll', (event) => {
1628410209
.Hell
Sheet Author
Everywhere where I use it and it is not a repeating section the sheet worker and button interaction work as expected. In the repeating action it is not fired. I tried to get some output with console.logs but nothing happened
1628411661
GiGs
Pro
Sheet Author
API Scripter
That answers two of the four questions I asked: GiGs said: Can you post the rolltemplate code for testing, too? also action buttons can be finicky about being called properly - try changing the sheet worker first line to on('clicked:repeating_npcskill:roll', (event) => {
1628415506
.Hell
Sheet Author
Thanks for your input I changed the sheet worker to: on('clicked:roll clicked:repeating_finearts:roll clicked:repeating_npcskill:roll', (event) => { startRoll(event.htmlAttributes.value + "{{fumble=[[1d10!]]}} {{fumble2=[[1d10!]]}}", (results) => { var rollComputed = results.results.roll.result; var roll2Computed = 0; if(results.results.roll.dice[0] == 1) // We check if the first die is a fumble. { rollComputed = results.results.roll.result - 1 - results.results.fumble.result; } if(results.results.roll2 != null) { roll2Computed = results.results.roll2.result; if( results.results.roll2.dice[0] == 1) // We check if the first die is a fumble. { roll2Computed = results.results.roll2.result - 1 - results.results.fumble2.result; } } finishRoll( results.rollId, { roll: rollComputed, roll2: roll2Computed } ); }); }); <rolltemplate class ="sheet-rolltemplate-statistics2" > <table> <tr><th style ='text-transform: uppercase;' > {{title}} </th></tr> <tr><td><strong class ="template-title" > NAME: </strong> {{name}} </td></tr> <tr><td><strong class ="template-title" > SKILL ROLL: </strong> {{computed::roll}} </td></tr> {{#rollWasCrit() roll}} <tr style ='text-align: justify; font-size: 12px;' ><td><strong class ="template-title" style ='color: #66c600; text-shadow: 1px 1px #000;' > CRITICAL: </strong> Criticals are already calculated into the roll </td></tr> {{/rollWasCrit() roll}} {{#rollWasFumble() roll}} {{#^rollWasCrit() roll}} <tr style ='text-align: justify; font-size: 12px;' > <td> <strong class ="template-title" style ='color: #c60000; text-shadow: 1px 1px #000;' > FUMBLE: </strong> Fumbles are already calculated into the roll. Your fumble roll was {{fumble}}. </td> </tr> {{/^rollWasCrit() roll}} {{/rollWasFumble() roll}} </table> </rolltemplate>
1628415636
.Hell
Sheet Author
Now it has an output where it says that it cannot find the other attibutes in the fieldset like npcskill_stat and npcskillname. The charactername is displayed
1628415743
.Hell
Sheet Author
The same happens for finearts <fieldset class ="repeating_finearts" > <button type ='action' name ='act_roll' data-i18n ="fine-art-u" class ='repeating_skill_roller_emp' value ='@{whisper}&{template:statistics2} {{title=FINE ARTS: @{fa_name2}}} {{name=@{character_name}}} {{roll=[[1d10!+@{emp}[STAT]+@{fine_arts2}[SKILL]+?{ADDITIONAL MODS? (Bright Light, No Vision, Terrain etc)|0}[MOD]]]}}' > FINE ARTS: </button> <input name ='attr_fa_name2' type ='text' class ='repeating_extraskill' placeholder ='Type...' > <input name ='attr_fine_arts2' class ='repeating_skillbox' type ='number' value ='0' ><br> </fieldset>
1628421062

Edited 1628427915
GiGs
Pro
Sheet Author
API Scripter
I think this might be a bug with the new action button roll system. For some reason, attributes inside a repeating section are not being resolved properly. It's not a problem with your code. Note: this isnt the first problem specific to action buttons and repeating sections. I think in this case, they just forgot to test the code with repeating sections, and in the thread where the feature was announced, none of us thought to test repeating sections either.
1628569555

Edited 1628569827
Oosh
Sheet Author
API Scripter
From the custom roll parsing page: Note that when starting a roll via the startRoll sheet worker, the system will not be able to automatically add the correct repeating section id, and you will need to fully resolve the attribute name [Click Here](~repeating_test_-MckIineUhDw8UwVpy-z_test1) . You'll need to grab the rowID & section from your event click, and fully construct your attribute names. A helper function like this run on event.sourceAttribute should do it: const getRowId = (input) => typeof(input) === 'string' ? (input.match(/_(-[A-Za-z0-9-]{19})_/)||[])[1] : undefined; If there are multiple repeating sections and non-repeating sections in the same listener, you'll obviously need the section name & another check to see if it's even a repeating section at all.
1628570635
GiGs
Pro
Sheet Author
API Scripter
Oosh said: From the custom roll parsing page: Note that when starting a roll via the startRoll sheet worker, the system will not be able to automatically add the correct repeating section id, and you will need to fully resolve the attribute name [Click Here](~repeating_test_-MckIineUhDw8UwVpy-z_test1) . Aha, well spotted. I had forgotten that.
1628578339
GiGs
Pro
Sheet Author
API Scripter
Here's a function to get the valid start of a name: const getPrefix = trigger => trigger.startsWith('repeating_') ? trigger.split('_').slice(0,3).join('_') + '_' : ''; and you pass triggerName to that, and for repeating sections it will return repeating_section_-fd7ghhr_ (the repeating section name and id), and for non-repeating sections, it will return '' (empty string). You can then simply add that to the start of your attribute names, and whether they are repeating section attributes or not it will work (as long as the attributes you are calling are all in the same repeating section, when a repeating section is used). You do have the problem of extracting the attributes though - your earlier method of value ='@{whisper}&{template:statistics2} {{title=@{npcskill_name}}} {{name=@{character_name}}} {{roll=[[1d10!+@{npcskill_stat}[STAT]+@{npcskill_score}[SKILL]+?{ADDITIONAL MODS? (Bright Light, No Vision, Terrain etc)|0}[MOD]]]}} makes that tricky. A better method would be the one Scott C posted a while back, where you define an object variable at the start of your sheet worker, that lists all relevant attributes of a roll, keyed by the action button name. Though you should have unique names for each action button - you are using the name 'roll' for all of them, and your finearts one should be called name='act_finearts' for example.
1628581322
GiGs
Pro
Sheet Author
API Scripter
Here;s a method for you to try. First change the value in your action buttons to only include the {{title= }} and {{roll=}} parts -those parts that when it is a repeating section, are attributes that are only from that repeating section. Example: <button type='action' name='act_roll' data-i18n="fine-art-u" class='repeating_skill_roller_emp' value='{{title=FINE ARTS: @{fa_name2}}} {{roll=[[1d10!+@{emp}[STAT]+@{fine_arts2}[SKILL]+?{ADDITIONAL MODS? (Bright Light, No Vision, Terrain etc)|0}[MOD]]]}}'> FINE ARTS: </button> Then in your sheet worker, do this: const   buttons  = [ 'roll' ,  'repeating_finearts:roll' , 'repeating_npcskill:roll' ]; buttons . forEach (( b ) => {      on ( `clicked: ${ b } ` ,( event ) => {          const   trigger  =  event . triggername . splice ( 8 );  // this always starts with 'clicked:'          // prefix gets an empty string for normal attributes, and repeating_section_ID_ for repeating attributes           const   prefix  =  trigger . startsWith ( 'repeating_' ) ?  trigger . split ( '_' ). slice ( 0 , 3 ). join ( '_' ) +  '_'  :  ''                   let   rollBegins  =  '@{whisper}&{template:statistics2} {{name=@{character_name}}}' ;          // rollPart should be constructed to include NO global attributes, only repeating sections          let   rollPart  =  event . htmlAttributes . value . replaceAll ( '@{' ,  `@{ ${ prefix } ` );          let   rollEnds  =  '{{fumble=[[1d10!]]}} {{fumble2=[[1d10!]]}}' ;          startRoll ( rollBegins  +  rollPart  +  rollEnds , ( results )  =>  {              var   rollComputed  =  results . results . roll . result ;              var   roll2Computed  =  0 ;                     if ( results . results . roll . dice [ 0 ] ==  1 )  // We check if the first die is a fumble.              {                  rollComputed  =  results . results . roll . result  -  1  -  results . results . fumble . result ;              }                   if ( results . results . roll2  !=  null ) {                roll2Computed  =  results . results . roll2 . result ;                if (  results . results . roll2 . dice [ 0 ] ==  1 )  // We check if the first die is a fumble.                 {                     roll2Computed  =  results . results . roll2 . result  -  1  -  results . results . fumble2 . result ;                 }             }                     finishRoll (                   results . rollId ,                  {                       roll :   rollComputed ,                       roll2 :   roll2Computed                        }              );          });     }); }); This uses a standard roll beginning and roll ending, and extracts the bit that changes in each roll from the button value. It also identifies whether this is a repeating section or not, and if so inserts an appropriate prefix inside all the @{} references, in the button value. I haven't tested this, but it should help you make progress. For your buttons outside of the repeating section, you might need to give them unique names for it to work properly, I don't know, but that's always a good idea because it allows people to use the buttons in chat menus and call them from scripts. If they don't have unique names, players can't do these things and the sheet is missing out of the full functionality of roll20. If they do have unique names, you'll have to add each name to the buttons array at the start.
1628620586

Edited 1628620667
.Hell
Sheet Author
I solved it a little bit different then you suggested. I made one action for all non-repeating sections and one for all repeating section. In the prepeating sections I made the changes as follows: <fieldset style ='margin-bottom: 10px;' class ="repeating_npcskill" > <span class ='repeating_npcskill_container' > <input class ='repeating_npcskill_name' name ='attr_npcskill_name' type ='text' value ='Name Here...' > <select class ='repeating_npcskill_stat' name ='attr_npcskill_stat' > <option value ='@{int_npc}' data-i18n ="int-u" > INT </option> <option value ='@{ref_npc}' data-i18n ="ref-u" > REF </option> <option value ='@{dex_npc}' data-i18n ="dex-u" > DEX </option> <option value ='@{body_npc}' data-i18n ="body-u" > BODY </option> <option value ='@{spd_npc}' data-i18n ="spd-u" > SPD </option> <option value ='@{emp_npc}' data-i18n ="emp-u" > EMP </option> <option value ='@{cra_npc}' data-i18n ="cra-u" > CRA </option> <option value ='@{will_npc}' data-i18n ="will-u" > WILL </option> </select> <input class ='repeating_npcskill_score' name ='attr_npcskill_score' type ='text' value ='0' > <button type ='action' name ='act_roll' style ='margin-top: -4px;' class ='repeating_npc_skill_roll' value ='@{whisper}&{template:statistics2} {{title=@{prefix-npcskill_name}}} {{name=@{character_name}}} {{roll=[[1d10!+@{prefix-npcskill_stat}[STAT]+@{prefix-npcskill_score}[SKILL]+?{ADDITIONAL MODS? (Bright Light, No Vision, Terrain etc)|0}[MOD]]]}}' ></button> </span> </fieldset> The repeating-attributes got a "prefix-" added. This allows to still see the normal stat and makes it obvious that a prefix is added. The sheet worker looks like this: on('clicked:repeating_finearts:roll clicked:repeating_npcskill:roll', (event) => { // prefix gets an empty string for normal attributes, and repeating_section_ID_ for repeating attributes var trigger = event.triggerName.slice(8); // this always starts with 'clicked:' var prefix = trigger.split('_').slice(0,3).join('_') + '_'; let rollPart = event.htmlAttributes.value.replaceAll('prefix-', `${prefix}`); startRoll(rollPart + "{{fumble=[[1d10!]]}}", (results) => { var rollComputed = results.results.roll.result; if(results.results.roll.dice[0] == 1) // We check if the first die is a fumble. { rollComputed = results.results.roll.result - 1 - results.results.fumble.result; } finishRoll( results.rollId, { roll: rollComputed, } ); }); }); Due to the knowledge that only the "prefix-" has to be replaced we can do it quite targeted. Due to only having repeated-section we dont need to be careful when analyzing what kind of action we want to do. I think this way it looks more forward and also allows other contributors who are not as firm in javascript to have a fast understanding :) Thanks for your help
1628620919
GiGs
Pro
Sheet Author
API Scripter
You're welcome. Adding "prefix-" to the attributes is a neat solution for the replacements.