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

Maths in Templates

Hi there, I have a Pro account and am trying to write a character sheet. One thing that is giving me trouble is the ability / skill rolls. I need to be able to roll d100, compare it to the ability / skill and either show fail or the difference between them. That part is easy (ish). Where I fall down is that I want to be able to show the actual roll. So far I  have:- <label>  Strength </label>  <input type="number" name='attr_strength' class='sheet-short'>         <button class='old-roll' type='roll' name='roll_testattack' value='  &{template:mine} {{name=Strength Attribute Check}} {{character=@{charactername}}} {{theroll=[[@{strength}-1d100]]}} {{starget=@{strength}}}'> and the template <rolltemplate class="sheet-rolltemplate-mine">     <div class="sheet-wrapper">                 <div class="sheet-border">                 <table>                                 <tr>                                                 <td class="subheader">{{name}}</td>                                 </tr>                 </table>                                   <table>                                 <tr>                                                 <div class="big">Character: {{character}}</div>                                 </tr>                                 <tr>                                 <div class="small-win">Target: {{starget}}</div>                                 </tr>                                 <tr>                                 <div class="small-win">theroll: {{theroll}}</div>                                 </tr>                                 <tr>                                    {{#rollGreater() theroll-1}}                                                 <div class="small-win">Attack Margin: {{theroll}}</div>                                    {{/rollGreater() theroll-1}}                                 </tr>                                 <tr>                                    {{#rollLess() roll1 0}}                                                 <div class="small-fail">Result: FAIL </div>                                    {{/rollLess() roll1 0}}                                 </tr>                  </table>                  </div>                  </div> </rolltemplate> This works exactly as expected but, the players will want to know the actual dice roll (“how many did I fail by?” etc.) So, I changed the roll to be         <button class='old-roll' type='roll' name='roll_testattack' value='  &{template:chill} {{name=Strength Attribute Check}} {{character=@{charactername}}} {{roll1=[[@{strength}]]-[[1d100]]}} {{theroll=$[[1]]}} {{starget=@{strength}}}'> theroll is now what I need but now, roll1 gives text NOT a value. So, I tried using MathOps (and the associated Zeroframe) API scripts changing the button to         <button class='old-roll' type='roll' name='roll_testattack' value='!  &{template:chill} {{name=Strength Attribute Check}} {{character=@{charactername}}} {{roll1=[[@{strength}]]-[[1d100]]}} {{theroll=$[[1]]}} {{theresult={& math $[[0]]-$[[1]]}}} {{starget=@{strength}}} {&simple}'>   Which gives a blank “theresult” – I have tried moving the ! adding the \ “delayer” and moving the brackets around, all to no avail L - I either get text or nothing. I then tried !The result of 2+2 is {&math 2+2} in the chat window and got nothing at all! Is there something wrong with the API script or am I missing something? All this is occurring in the sandbox   P.S. Sorry for the long post :(      
1697724609
timmaugh
Forum Champion
API Scripter
Hey, Roger... This is definitely better solved on the character sheet side (rather than invoking a mod script) so that your sheet can be used by more people without requiring that they have that particular mod installed, too. I, unfortunately, do not have that skill, but I'll poke some people who do to see if they can take a look at your setup/example. One point about your MathOps line... remember that in order to see the output from a line that began by being aimed at the Script Moderator, you have to include a {&simple} in it somewhere. That's why you were getting no response from this line: !The result of 2+2 is {&math 2+2}   If you change that to include a {&simple} somewhere, it will work: !The result of 2+2 is {&math 2+2} {&simple} REQUIRED SCRIPTS: Fetch + ZeroFrame (or, simply, the MetaScriptToolbox)
1697724778

Edited 1697724823
!The result of 2+2 is {&math 2+2} {&simple} works in chat - thanks I was going (more) mad then :) Many thanks
1697740802
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Hi Roger, Seconding Timmaugh's recommendation to avoid using a mod script in this case. So if I understand your need correctly you want to: roll 1d100 and display the result of that roll Compare the result of the d100 to the value of the ability or skill that was rolled If the result doesn't meet the success threshold of your game: Output "Failure"   If the result does meet the success threshold: Output the difference between the roll and the ability/skill Most of this can be handled in your roll template code using the roll template helper functions . The rest will require a very simple sheetworker utilizing custom roll parsing (CRP) . Here's what the rolltemplate and button changes would look like: <label>  Strength </label>  <input type="number" name='attr_strength' class='sheet-short'> <button class='old-roll' type='action' name='act_testattack'></button> <rolltemplate class="sheet-rolltemplate-mine"> <div class="sheet-wrapper"> <div class="sheet-border"> <table> <tr> <td class="subheader">{{name}}</td> </tr> </table>  <!--I'd also getting rid of these. It's much better to handle spacing using css to customize paddings, margins, and borders--> <table> <tr> <div class="big">Character: {{character}}</div> </tr> <tr> <div class="small-win">Target: {{starget}}</div> </tr> <tr> <div class="small-win">theroll: {{theroll}}</div> </tr> <tr> {{#rollLess() theroll starget}} <div class="small-win">Attack Margin: {{computed::difference}}</div> {{/rollLess() theroll starget}} </tr> <tr> {{^#rollLess() theroll starget}} <div class="small-fail">Result: FAIL </div> {{/^rollLess() theroll starget}} </tr> </table> </div> </div> </rolltemplate> Then you add a short sheetworker section: <script type="text/javascript"> // This worker will assume that you don't need to make rolls from repeating sections. It will need some small additions if that is the case. const attackButtons = ['strength'];//Add additional abilities/skills here attackButtons.forEach(ability => { // create a listener for each attack button // note the async tag on the function in the listener. This will allow us to use async/await with startRoll on(`clicked:${ability}-attack`,async event => { const roll = await startRoll(`&{template:mine} {{name=${ability} Attribute Check}} {{character=@{charactername}}} {{theroll=[[1d100]]}} {{starget=[[@{${ability}}]]}} {{difference=[[0[computed value]]]}}`); const computeObj = {};//An empty object to accumulate our changes to the roll values in. In this case, we'll only be adding one value. const theRoll = roll.results.theroll; const sTarget = roll.results.starget if(theRoll.result <= sTarget.result){ computeObj.difference = sTarget.result - theRoll.result; } finishRoll(roll.rollId,computeObj);//This line tells Roll20 we're done modifying the roll and it can be released to chat. }); }); </script> That's all untested, but should be pretty close to what you need. Unrelated to your question, but I would highly  recommend not using tables on your sheet or roll template. Using tables for layout will generally make your sheet ineligible to be added to the roll20 repo for others to use Modern CSS technologies like CSS Grid, CSS Flexbox, and CSS multi column are designed to be used for layout and are much easier to use and make responsive.
Thanks for that Scott. I'm a VERY old programmer so tables where my first thought - I need to look at the "new" stuff :) If this works (and I'm sure it will) then, this will make my life SOOOOOO much easier! many, many thanks
1697757577

Edited 1697814727
GiGs
Pro
Sheet Author
API Scripter
To underline the suggestion to avoid tables: using CSS Grid is easier than tables, once you know a few basics. You don't have to type all those <tr> and <td> - just decide how wide you want each column to be and do this. div.my-style { display: grid; grid-template-columns: 50px 70px; /* enter the width of each column * column-gap: 5px; /* a width of whitespace - a margin - between each column */ }   And that's it. Every html element (span, heading, p, etc), will be sorted into the listed columns. You don't have to do anything in the HTML - that's all the code you need to set up a "table".
Hi GiGs, many thanks for that - it does look A LOT simpler :) Roger
Hi Scott, I seem to have hit a snag - probably something I'm doing. I have modified everything as you suggested (with one or two modifications). So now I have <label>  Strength </label>  <input type="number" name='attr_strength' class='sheet-short'> <button class='old-roll' type='action' name='act_testattack'></button> and <script type="text/javascript">    const attackButtons = ["strength"];//Add additional abilities/skills here    attackButtons.forEach(ability => {       // create a listener for each attack button       // note the async tag on the function in the listener. This will allow us to use async/await with startRoll       on("clicked:${ability}-attack",async event => {          const roll = await startRoll(&{template:mine} {{name=${ability} Attribute Check}} {{character=@{charactername}}} {{theroll=[[1d100]]}} {{starget=[[@{${ability}}]]}} {{difference=[[0[computed value]]]}});          const computeObj = {};//An empty object to accumulate our changes to the roll values in. In this case, we'll only be adding one value.          const theRoll = roll.results.theroll;          const sTarget = roll.results.starget          if(theRoll.result <= sTarget.result){             computeObj.difference = sTarget.result - theRoll.result;          }          finishRoll(roll.rollId,computeObj);//This line tells Roll20 we're done modifying the roll and it can be released to chat.       });    }); </script> (Changing single quotes to double and removing them from startRoll) the template is as you suggested except I have changed  {{^#rollLess() theroll starget}} to  {{#^rollLess() theroll starget}} (changed the position of the carat) Now, I get nothing in chat at all :(. I put the quotes back - still nothing The button, of course has (cosmetically) changed but, I can work around that. Any ideas as to what I have done wrong? Roger
1697815231

Edited 1697822823
GiGs
Pro
Sheet Author
API Scripter
Roger said: Hi GiGs, many thanks for that - it does look A LOT simpler :) Roger You're welcome. There's a lot more you can do with grids - setting height or width of the grid item, nesting grids within each other, have column width use different units or be flexible, position were exactly an item will be within the grid, have grid cells be wider or taller than a single cell, and more, but that's for further explaration. Two things that are handy: align: start; A grid will spread out vertically to fill the area its in. Often you want rows to congregate in order at the start, with no spreading, and this command usually does that. And on roll20, inputs (maybe other items, but its mostly inputs) have specific sizes assigned to them. You night want to reassign their size to match a column width like this: .ui-dialog .charsheet .sheet-container input[type="number"].item-class { width: 50px; } If you have multiple inputs with the same width, it's a good idea give them the same class you you only need to create the class once. Those are the two main gotchas to watch out for.
Excellent! - It does look very good :) R
1697821961
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Roger said: Hi Scott, I seem to have hit a snag - probably something I'm doing. I have modified everything as you suggested (with one or two modifications). So now I have <label>  Strength </label>  <input type="number" name='attr_strength' class='sheet-short'> <button class='old-roll' type='action' name='act_testattack'></button> and <script type="text/javascript">    const attackButtons = ["strength"];//Add additional abilities/skills here    attackButtons.forEach(ability => {       // create a listener for each attack button       // note the async tag on the function in the listener. This will allow us to use async/await with startRoll       on("clicked:${ability}-attack",async event => {          const roll = await startRoll(&{template:mine} {{name=${ability} Attribute Check}} {{character=@{charactername}}} {{theroll=[[1d100]]}} {{starget=[[@{${ability}}]]}} {{difference=[[0[computed value]]]}});          const computeObj = {};//An empty object to accumulate our changes to the roll values in. In this case, we'll only be adding one value.          const theRoll = roll.results.theroll;          const sTarget = roll.results.starget          if(theRoll.result <= sTarget.result){             computeObj.difference = sTarget.result - theRoll.result;          }          finishRoll(roll.rollId,computeObj);//This line tells Roll20 we're done modifying the roll and it can be released to chat.       });    }); </script> (Changing single quotes to double and removing them from startRoll) the template is as you suggested except I have changed  {{^#rollLess() theroll starget}} to  {{#^rollLess() theroll starget}} (changed the position of the carat) Now, I get nothing in chat at all :(. I put the quotes back - still nothing The button, of course has (cosmetically) changed but, I can work around that. Any ideas as to what I have done wrong? Roger Ah, I forgot to change the button name, it should be strength-attack instead of test attack.
1697822386

Edited 1697822401
GiGs
Pro
Sheet Author
API Scripter
I haven't studied the code,  was too busy on my soapbox about CSS grid vs tables, but this leaps out at me: "clicked:${ability}-attack", That should be `clicked:${ability}-attack`,
regrettably, still nothing in chat :( <script type="text/javascript">    // This worker will assume that you don't need to make rolls from repeating sections. It will need some small additions if that is the case.    const attackButtons = ['strength'];//Add additional abilities/skills here    attackButtons.forEach(ability => {       // create a listener for each attack button       // note the async tag on the function in the listener. This will allow us to use async/await with startRoll       on('clicked:${ability}-attack',async event => {          const roll = await startRoll(&{template:mine} {{name=${ability} Attribute Check}} {{character=@{charactername}}} {{theroll=[[1d100]]}} {{starget=[[@{${ability}}]]}} {{difference=[[0[computed value]]]}});          const computeObj = {};//An empty object to accumulate our changes to the roll values in. In this case, we'll only be adding one value.          const theRoll = roll.results.theroll;          const sTarget = roll.results.starget          if(theRoll.result <= sTarget.result) {             computeObj.difference = sTarget.result - theRoll.result;          }          finishRoll(roll.rollId,computeObj);//This line tells Roll20 we're done modifying the roll and it can be released to chat.       });    }); </script> and <button class='old-roll' type='action' name='act_strength-attack'></button> :(
1697824600

Edited 1697824657
With the same template, the other buttons with my old code still give something though (don't know if this helps) <label>  Dexterity </label>  <input type="number" name='attr_dexterity' class='sheet-short'>         <button class='old-roll' type='roll' name='roll_testattack' value=' &{template:mine} {{name=Dexterity Attribute Check}} {{character=@{charactername}}} {{roll1=[[@{strength}]]-[[1d100]]}} {{theroll=$[[1]]}} {{starget=@{strength}}}'> </button>
Unfortunately, I will require this on a repeating section (skills) I'm not making this easy, am I? sorry
After much messing around, I believe I have it working I trimmed out the comments I changed the class of the button (as it was showing as just a thin button instead of a 22 * 22)) I changed the button name to remove the hyphen (act_strength-attack => act_strengthattack) Not sure which (if any) of these did the trick (   or others I have forgotten ) but, I'm too tired to work it out now (I suspect number 3) Just need to get the Action button to look like the standard Roll button and work out how to do the repeating sections (in the game you either have the skill or don't - it's not like others that have default values) oh - and move away from tables ;) Thanks guys