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

roll template call inside roll template

1567201611

Edited 1567203695
admiralnlson
Sheet Author
I'd like to have a button inside a roll template, which calls the same roll template. This used to work: <div>[<span data-i18n="roll_again">Roll again</span>](!fs_critSuccessConfirm,{{characterName}},{{bonus_malus}},{{characteristicName}},{{skillName}})</div> !fs_critSuccessConfirm basically calls a API function which recomputes derived properties and issues a sendChat() for the same roll template. It's basically a recursive call from the roll template to the roll template that I'm doing, except the API function call is helping as an intermediate. But, following a comment by GiGs , I am trying not to rely on the API as much, so that the sheet is free-user friendly. So far, my attempt at calling the roll remplate directly, without going through the API, looks like this: <div>[<span data-i18n="roll_again">Roll again</span>](&{template:fs-GoalRoll} {{characterName={{characterName}}}} {{characteristicName={{characteristicName}}}} {{characteristicName-i18n={{characteristicName-i18n}}}} {{skillName={{skillName}}}} {{skillName-i18n={{skillName-i18n}}}} {{bonus_malus={{bonus_malus}}}} {{goal={{goal}}}} {{cappedgoal={{cappedgoal}}}} {{roll=[[1d20cs{{cappedgoal}}cf20]]}} {{critSuccessConfirm=1}})</div> The button/link generated by this code is borked though: there is no href attached to the <a>, so I assume this means roll20 internal code was not able to parse the above. I tried to escape all the &, { and } characters which do not belong to outer roll template parameters like so <div>[<span data-i18n="roll_again">Roll again</span>](&{template:fs-GoalRoll} {{characterName={{characterName}}}} {{characteristicName={{characteristicName}}}} {{characteristicName-i18n={{characteristicName-i18n}}}} {{skillName={{skillName}}}} {{skillName-i18n={{skillName-i18n}}}} {{bonus_malus={{bonus_malus}}}} {{goal={{goal}}}} {{cappedgoal={{cappedgoal}}}} {{roll=[[1d20cs{{cappedgoal}}cf20]]}} {{critSuccessConfirm=1}})</div> but same result. Can anyone help me make this work? Thanks.
1567220997

Edited 1567221334
GiGs
Pro
Sheet Author
API Scripter
I'm pretty sure that code will get parsed by the rolltemplate, and the html entities replaced, before it gets printed.  I think the easiest way include a button in a rolltemplate, is to create a second button in the character sheet, and make it hidden. Then you can put the call for it in the rolltemplate, using API Command Button syntax : [Label](~<character-name>|<button name>) The < > are not part of the address, For a character named Frodo, and a button named Ring, that would look like [Use Ring](~Frodo|Ring) Also, plenty of sheets (like the D&D 5e OGL one) have a damage roll button when printing out an attack, so you can look at their rolltemplate code to see how they do it (and the CSS for how they format the button).
1567244882

Edited 1567247037
admiralnlson
Sheet Author
What you are describing is a static call to another, standalone ability with no parameters, or in other words, a call to something which depends only on information which can be pulled (or pulled again) from the character sheet. What I need on the other hand is a contextual call, i.e. a call to something which can reuse the parameters of the my initial roll template, which for some of them I am unable to save to the character sheet. I've checked the D&D 5e OGL sheet, and there are only static calls in the form of [xxxx](~yyyy) in it, so still what I would call "easy stuff". For example, the {{bonus_malus}} parameter in my roll template is the result of a roll query triggered by what's inside a roll button value. After this bonus_malus value is passed as parameter to the roll template, if I don't use it inside the roll template code as a way to influence the href of the action button it displays, it's lost forever. Therefore I need to make the: [my-button](&{template:my-template-name} {{bonus_malus={{bonus_malus}}}}) syntax work somehow. Or I need to be able to save the result of the bonus_malus roll query into a character attribute before or along with the initial roll template call. But this seems impossible to me without the API because the translation from ?{...} to an actual value happens in chat, not in the sheet. I don't believe there is a way to trigger roll queries with sheet worker JS alone either.
1567254705
GiGs
Pro
Sheet Author
API Scripter
It is possible you are running up against the limits of what you can do without the API. Sheet workers have their own limits, rolltemplates have their own but different limits, and roll macros have their own limits. Sometimes the only way past these limits is the API, but that means free users can't use it. But it's also possible there is a way to do what you need. If you describe exactly what you are trying to do ( the way the roll works, if you were playing face-to-face, not in a VTT), we might be able to suggest an approach that works.
1567258410

Edited 1567260409
admiralnlson
Sheet Author
OK let's take a step back. Basically, Fading Suns is a "roll under" system. You have to: - reroll the d20 for as long as you get a crit success (i.e. which is when you roll the "goal", or 19 whichever is lower), summing the scores until failure - reroll the d20 once when get you a natural 20, to know if it's going to be an auto failure (if your 2nd roll is under or equal to the goal) or a critical failure (if it is above) Note this is relative to FS v2.75, the latest official version. The new version coming up by Ulysses Spiele later this year on Kickstarter uses a different system. I have this roll template which works and implements this and more (e.g. includes special case when the goal is > 20): <rolltemplate class="sheet-rolltemplate-fs-GoalRoll"> <div class="fs-container"> {{#rollGreater() bonus_malus -1}} {{#skillName}} <div class="fs-header"><h1>{{characteristicName-i18n}} + {{skillName-i18n}} +{{bonus_malus}}</h1></div> {{/skillName}} {{^skillName}} <div class="fs-header"><h1>{{characteristicName-i18n}} +{{bonus_malus}}</h1></div> {{/skillName}} {{/rollGreater() bonus_malus -1}} {{#^rollGreater() bonus_malus -1}} {{#skillName}} <div class="fs-header"><h1>{{characteristicName-i18n}} + {{skillName-i18n}} {{bonus_malus}}</h1></div> {{/skillName}} {{^skillName}} <div class="fs-header"><h1>{{characteristicName-i18n}} {{bonus_malus}}</h1></div> {{/skillName}} {{/^rollGreater() bonus_malus -1}} <div class="arrow-container"><div class="arrow-right"></div></div> {{#^rollGreater() roll cappedgoal}} {{#critFailureConfirm}} <span class="success actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="success" data-i18n="noncritical_failure">Non-critical failure.</span> {{/critFailureConfirm}} {{^critFailureConfirm}} {{#rollWasCrit() roll}} <span class="critsuccess actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="critsuccess" data-i18n="critical_success">Critical Success!</span> {{/rollWasCrit() roll}} {{#^rollWasCrit() roll}} <span class="success actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="success" data-i18n="success">Success!</span> {{/^rollWasCrit() roll}} {{#rollTotal() roll 1}} <span class="success">0</span> {{/rollTotal() roll 1}} {{#rollBetween() roll 2 3}} <span class="success">1</span> {{/rollBetween() roll 2 3}} {{#rollBetween() roll 4 5}} <span class="success">2</span> {{/rollBetween() roll 4 5}} {{#rollBetween() roll 6 7}} <span class="success">3</span> {{/rollBetween() roll 6 7}} {{#rollBetween() roll 8 9}} <span class="success">4</span> {{/rollBetween() roll 8 9}} {{#rollBetween() roll 10 11}} <span class="success">5</span> {{/rollBetween() roll 10 11}} {{#rollBetween() roll 12 13}} <span class="success">6</span> {{/rollBetween() roll 12 13}} {{#rollBetween() roll 14 15}} <span class="success">7</span> {{/rollBetween() roll 14 15}} {{#rollBetween() roll 16 17}} <span class="success">8</span> {{/rollBetween() roll 16 17}} {{#rollBetween() roll 18 19}} <span class="success">9</span> {{/rollBetween() roll 18 19}} {{#above20pv}} <span class="success"> + {{above20pv}}</span> {{/above20pv}} <span class="success"> <span data-i18n="victory_points">VP</span></span> {{#rollWasCrit() roll}} {{#skillName}} <div>[<span data-i18n="roll_again">Roll again</span>](!fs_critSuccessConfirm,{{characterName}},{{bonus_malus}},{{characteristicName}},{{skillName}})</div> {{/skillName}} {{^skillName}} <div>[<span data-i18n="roll_again">Roll again</span>](!fs_critSuccessConfirm,{{characterName}},{{bonus_malus}},{{characteristicName}},null)</div> {{/skillName}} {{/rollWasCrit() roll}} {{/critFailureConfirm}} {{/^rollGreater() roll cappedgoal}} {{#rollGreater() roll cappedgoal}} {{#critSuccessConfirm}} <span class="failure actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="failure" data-i18n="failure">Fin.</span> {{/critSuccessConfirm}} {{^critSuccessConfirm}} {{#critFailureConfirm}} <span class="critfailure actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="critfailure" data-i18n="critical_failure">Critical failure.</span> {{/critFailureConfirm}} {{^critFailureConfirm}} {{#rollWasFumble() roll}} <span class="critfailure actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="critfailure" data-i18n="critical_failure_q">Critical failure?</span> {{#skillName}} <div>[<span data-i18n="confirm">Confirm</span>](!fs_critFailureConfirm,{{characterName}},{{bonus_malus}},{{characteristicName}},{{skillName}})</div> {{/skillName}} {{^skillName}} <div>[<span data-i18n="confirm">Confirm</span>](!fs_critFailureConfirm,{{characterName}},{{bonus_malus}},{{characteristicName}},null)</div> {{/skillName}} {{/rollWasFumble() roll}} {{#^rollWasFumble() roll}} <span class="failure actualroll">{{roll}}</span><span> | {{goal}}. </span><span class="failure" data-i18n="failure">Failure!</span> {{/^rollWasFumble() roll}} {{/critFailureConfirm}} {{/critSuccessConfirm}} {{/rollGreater() roll cappedgoal}} </div> </rolltemplate> Roll buttons next to character characteristics call this template like this (example here is: strength): &{template:fs-GoalRoll} {{characterName=@{character_name}}} {{characteristicName=strength}} {{characteristicName-i18n=^{strength}}} {{bonus_malus=[[?{Bonus/Malus|0}]]}} {{goal=[[@{strength}+[[?{Bonus/Malus|0}]]]]}} {{cappedgoal=[[{@{strength}+[[?{Bonus/Malus|0}]],19}kl1]]}} {{above20pv=[[@{strength}+?{Bonus/Malus|0}-20]]}} {{roll=[[1d20cs[[{@{strength}+[[?{Bonus/Malus|0}]],19}kl1]]cf20]]}} Roll buttons next to character skills call it like this (example here is: survival): &{template:fs-GoalRoll} {{characterName=@{character_name}}} {{characteristicName=@{selected_characteristic}}} {{characteristicName-i18n=^{@{selected_characteristic}}}} {{skillName=survival}} {{skillName-i18n=^{survival}}} {{bonus_malus=[[?{Bonus/Malus|0}]]}} {{goal=[[@{selected_characteristic_value}+@{survival}+[[?{Bonus/Malus|0}]]]]}} {{cappedgoal=[[{@{selected_characteristic_value}+@{survival}+[[?{Bonus/Malus|0}]],19}kl1]]}} {{above20pv=[[@{selected_characteristic_value}+@{survival}+?{Bonus/Malus|0}-20]]}} {{roll=[[1d20cs[[{@{selected_characteristic_value}+@{survival}+[[?{Bonus/Malus|0}]],19}kl1]]cf20]]}} As you can see there are 4 API button commands (starting with !fs_) in the rolltemplate, they are there as a shortcut to call the same rolltemplate, with exact same list of parameter key/values, except for: - {{roll}} which is going to be a new roll (with same 'cappedgoal') - an additional {{critSuccessConfirm=[[1]]}} or {{critFailureConfirm=[[1]]}} parameter It's these 4 calls I am trying to replace to make the sheet non-Pro friendly. My only alternative, if not possible, is going to be to show these 4 buttons in Pro-creator games only, thus degrading the experience in non-Pro games (via a sheet config parameter (sheet.json), I imagine ; not entirely sure how to do this yet, but I'm sure I can find examples).
1567261853
GiGs
Pro
Sheet Author
API Scripter
If I'm understanding the roll system, there's no way to do what you want without the API. whether using rolltemplate or not, you cant have rerolls separate from the previous roll. The roll20 dice parser does include a reroll, and reroll once operator, so you could do this: /roll 1d20ro=20r<10 This will reroll the dice once if its a 20, and roll as many times as needed if you roll under 10. But you need to interpret the results separately. You can use exploding dice in a similar way: /roll 1d20!<10ro=20 The two problems with both are the same. the first is that it doesnt distinguish between the 20 and other results, so if you get 20 in a chain of rerolls, it isn't going to be right. The second is you have to interpret the results separately. it'll show you the dice, but you have to figure out what to do with them. A third problem is you cant use /roll in a rolltemplate - you have to use an inline roll, which will hide the individual dice rolls and only show you the last (for rerolls) or the sum (for the exploding dice version). I think the only way to get what you want is through the API. But you should include a fallback for non-Pro users. I'd suggest printing out the basic result, and two buttons: one for the critical die, and one for the fumble die. So players can roll them manually and do what needs to be done with them.
I'm not sure that I can print-out crit-related rerolls in a way that is going to be usable. I think I will merely indicate to non-Pro users that a second roll needs to happen in these 4 special cases. And they will have to click the same button again in the sheet (or use the up arrow + enter), enter the same bonus/malus, and be smart about what shows up in the chat. For example, they would have to understand that: a 20 after a initial critical success, despite the "Critical failure?" message, is nothing special and just means they need to stop rolling. Non-beginner Fading Suns GM and players would know this though, that's the base of the rule-system and something you have to do in your head when rolling physical dice. Alright, thanks for the help. We reach similar conclusions.
1567266200
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
A couple questions, Is the goal player intrinsic (based on their skill), situation specific (like a dc in pathfinder/D&D), or a mixture of the two? If the second, how are you getting the goal value for the roll? Is it a roll query? or entered on the sheet? From what you've mentioned, I'm guessing it's not the latter.
1567277555

Edited 1567279283
admiralnlson
Sheet Author
1. Mixture of the two. The goal is a characteristic value + a skill value + a bonus/malus representing the difficulty of the task + situational modifiers. Although it is capped to 19 because 20 is either an auto failure or a crit fail, depending on another roll result. 2. The goal is described in the roll button value (see example below). And yes it does contain a roll query for the bonus/malus. Extract from above: [...] {{goal=[[@{selected_characteristic_value}+@{survival}+[[?{Bonus/Malus|0}]]]]}} [...] {{cappedgoal=[[{@{selected_characteristic_value}+@{survival}+[[?{Bonus/Malus|0}]],19}kl1]]}}
1567289791

Edited 1567290303
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Ok, there is a solution, but it has limits. You'll need to change your roll template code You'll need to change your sheet roll button's macro It will be a very complex, and large roll template definition The roll template won't really be compatible with 3d dice using this solution (there will likely be lots of extraneous rolls) The solution is to display subsequent rolls depending on whether it passes the goal, critically succeeds, or is a 20. If you want to use it, here's a simplified example: Example of the technique (small section of the code): <rolltemplate class="sheet-rolltemplate-rollunder"> roll1 Template start <div> {{#rollGreater() roll1 target}} {{#rollTotal() roll1 20}} <div class='greater'>{{roll1}}</div> {{#^rollGreater() roll2 target}} <div class='less'>{{roll2}}</div> {{/^rollGreater() roll2 target}} {{#rollGreater() roll2 target}} <div class='greater'>{{roll2}}</div> {{/rollGreater() roll2 target}} {{/rollTotal() roll1 20}} {{#^rollTotal() roll1 20}} <div class='greater'>{{roll1}}</div> {{/^rollTotal() roll1 20}} {{/rollGreater() roll1 target}} {{#^rollGreater() roll1 target}} {{#rollTotal() roll1 target}} <div class='crit'>{{roll1}}</div> {{#rollGreater() roll2 target}} <div class='greater'>{{roll2}}</div> {{/rollGreater() roll2 target}} {{#^rollGreater() roll2 target}} {{#rollTotal() roll2 target}} <div class='crit'>{{roll2}}</div> {{#rollGreater() roll3 target}} <div class='greater'>{{roll3}}</div> {{/rollGreater() roll3 target}} {{#^rollGreater() roll3 target}} {{#rollTotal() roll3 target}} <div class='crit'>{{roll3}}</div> {{/rollTotal() roll3 target}} {{#^rollTotal() roll3 target}} <div class='less'>{{roll3}}</div> {{/^rollTotal() roll3 target}} {{/^rollGreater() roll3 target}} {{/rollTotal() roll2 target}} {{#^rollTotal() roll2 target}} <div class='less'>{{roll2}}</div> {{/^rollTotal() roll2 target}} {{/^rollGreater() roll2 target}} {{/rollTotal() roll1 target}} {{#^rollTotal() roll1 target}} <div class='less'>{{roll1}}</div> {{/^rollTotal() roll1 target}} {{/^rollGreater() roll1 target}} roll1 Template end </rolltemplate> example CSS: .sheet-rolltemplate-rollunder .sheet-less span.inlinerollresult{ border:none; background-color:transparent; color:black; } .sheet-rolltemplate-rollunder .sheet-crit span.inlinerollresult{ border:none; background-color:transparent; color:green; } .sheet-rolltemplate-rollunder .sheet-greater span.inlinerollresult{ border:none; background-color:transparent; color:red; } Essentially you would set up the template to handle n+1  number of rolls (3 in my example code). This should be a number of rolls that are unlikely to be needed. Since you only have 1 critical point this doesn't need to be a huge number of rolls, maybe 4 or 5. Then, you just nest the checks within the critical detection (when the field is equal to the target) like I have above. If they're a crit as well, it keeps adding rolls to the list. The code above uses the following macro: &{template:rollunder} {{roll1=[[1d20]]}} {{roll2=[[1d20]]}} {{roll3=[[1d20]]}} {{target=[[11]]}} and gives the following results: It's not pretty code, but it gets the job done and doesn't require the user to click a button multiple times.
1567292380

Edited 1567292804
admiralnlson
Sheet Author
I was initially doing something like this, with recursive API calls, to have all rolls made after a single click by the player. This was without limitations on the number of consecutive crits and also much simpler in terms of code. But because our group has grown fond of 3d rolls (and tends to contemplate the side the dice land on), i then moved back to a "one roll / click to continue rolling" approach. I may be willing to go back to a multi-roll approach / follow your suggestion, if there's at least a roll sound (even if its a mess) generated by this (which I think there will) because no roll sound is a showstopper. Your example, while verbose already, is a simplified version of what I need to have in terms of rolltemplate code ultimately. It however seems like I just need to take my own template as a base, add a few roll# as parameters, and replace internal API calls inside it, with nested versions of my template (minus the header part) using roll#N+1 for each  new recursivity level. And I repeat this until I'm satisfied with the statistical probability of consecutive crit successes not being realistic anymore. That's simple enough so long as I'm not distracted while I do it. This could end up being the non-pro experience, while I keep my current solution for Pro users, who like looking at 3d rolls too. Thanks for the time you allocated to this.
1567294427
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
No worries, and good luck.