Using Logic In a Rolltemplate

In programming, the term logic usually means analysis. Thats what we are doing ehre – analysing the result of a roll, then showing something based on that result.

A common request on the Roll20 forums is to make a roll and print out text based on that result, like on a 1 you might say “fumble”, 2-3 might say “failed”, 4-5 gives “success” and 6 = “critical”. It’s reasonable to want something like this, but that’s just not possible (exception: see rollable tables, which have their own issues, some of which have been covered here).

But if you could check the roll value, and print something different based on that value, then you could do that. Thats where the logic helpers of rolltemplates come in. You can examine a roll’s value and then show different HTML based on that value.

The Logic Helpers

The Roll20 Wiki gives this list of rolltemplate Helper Functions. (Don’t worry, we’ll look at how they are used below.) They can easily be split into two categories. First, for roll type:

  • {{#rollWasCrit() <rollname>}}
  • {{#rollWasFumble() <rollname>}}

Then for Roll Value:

  • {{#rollTotal() <rollname> <value>}} – check if a roll equals a value.
  • {{#rollGreater() <rollname> <value>}} – check if a roll exceeds a value.
  • {{#rollLess() <rollname> <value>}} – check if a roll is less than a value.
  • {{#rollBetween() <rollname> <lower> <upper>}} – check if a roll is between a lower and upper value, including those values. so 7 9 would be checking if a roll equals 7, 8, or 9.

Their name tells you what they look for. You must end the block the same way, using / instead of #.

So if you wanted to check if a roll exactly equalled 6, you could use:

{{#rollTotal() roll 6}}
   <!-- some html goes here -->
{{/rollTotal() roll 6}}Code language: HTML, XML (xml)

Simple Example

Lets say you have a template that wants to show the textual results in the paragraph above, you could do this:

&{template:d6} {{name=?{Name of Roll} }} {{roll=[[?{How many D6?|1}d6kh1]]}}Code language: Markdown (markdown)

Then use a rolltemplate like this:

<rolltemplate class="sheet-rolltemplate-d6">
      {{#rollTotal() roll 6}}Critical{{/rollTotal() roll 6}}
      {{#rollBetween() roll 4 5}}Success{{/rollBetween() roll 4 5}}
      {{#rollBetween() roll 2 3}}Failure{{/rollBetween() roll 2 3}}
      {{#rollTotal() roll 1}}Fumble{{/rollTotal() roll 1}}
</rolltemplate>Code language: HTML, XML (xml)

Note that rolltemplates ignore linebreaks and spaces – so you can break your code over multiple lines like these.

You might use the first two logic helpers instead, like this:

<rolltemplate class="sheet-rolltemplate-d6">
      {{#rollWasCrit() roll}}Critical{{/rollWasCrit() roll}}
      {{#rollBetween() roll 4 5}}Success{{/rollBetween() roll 4 5}}
      {{#rollBetween() roll 2 3}}Failure{{/rollBetween() roll 2 3}}
      {{#rollWasFumble() roll}}Fumble{{/rollWasFumble() roll}}
</rolltemplate>Code language: HTML, XML (xml)

This uses the fact that any max roll on the dice is treated as a critical (that’s a 6), and any minimum result is treated as a fumble. Tou can set the critical and fmble ranges, but we don’t have to here.

This will show the roll value and the textual label for that roll. It’s tedious to create that, but you’re working in HTML – there’s a lot of things that you think should be easy that aren’t!

Logic Helpers only work with numeric inline rolls: values enclosed in [[ ]] brackets. They don’t have to be calculations – they can be fixed numbers, like [[1]] or [[73]] – but they must be numeric inline rolls.
A value might contain a text value, like {{roll=this is some text and a roll [[17]], and also [[1d6]] }}. The Logic Helper will find the first (and only the first) inline roll in the text and use that.

Feeding Variables to A Rolltemplate

Let’s say you have a skill roll that is d20 + an attack value. You need to know if it equals or exceeds an AC target which is set by the GM. You could do this in a macro like this:

&{template:default} {{attack=[[ { 1d20+@{attack} }>?{target AC|10} ]]}}Code language: JavaScript (javascript)

This uses the group roll (see Dice Reference) to compare on roll vs another. The problem is the result will always be either 0 or 1, for failure or success. What if you want to show something more meaningful in chat?

You can pass the roll value and the target, both, to a rolltemplate of your creation and then compare them using the logic helpers.

&{template:target} {{attack=[[1d20+@{attack}]] }} {{target=[[?{target AC|10} ]]}}Code language: Markdown (markdown)

The result (with the same styling as before) would look like this:

Here we have a template that shows the attack roll, the taregt being aimed for, and a text description of the result.

This is very handy. But there is a problem. Look at the HTML and see if you spot it.

Here’s the HTML for that template.

<rolltemplate class="sheet-rolltemplate-attack">
    <div class="key">Attack Roll:</div>
    <div class="value">{{roll}}</div>
    <div class="key">Target:</div>
    <div class="value">{{target}}</div>
    <div class="key">Result:</div>
    <div class="value">
        {{#rollGreater() roll target}}Success{{/rollGreater() roll target}}
        {{#rollLess() roll target}}Failure{{/rollLess() roll target}}
</rolltemplate>Code language: HTML, XML (xml)

And here’s the matching CSS

.sheet-rolltemplate-attack {
    background-color: white;
    line-height: 1.9em;
.sheet-rolltemplate-attack {
    display: grid;
    grid-template-columns: 45% 45%;
    column-gap: 10%;
.sheet-rolltemplate-attack div:nth-child(odd)  {
    text-align: right; 
.sheet-rolltemplate-attack div:nth-child(even)  {
    text-align: left; 
}Code language: CSS (css)

Using Not

One of the oddities of rolltemplates is that they act differently from rolls. In a roll if you use >, it means equal or larger, whereas the Logic Helper rollGreater really means greater, not greater than or equal.

Either way, we’d have a problem in the template above, we tested for greater than and less than. But what if the roll exactly equals the target?

The clunky way to fix this would be using rollTotal.

{{#rollGreater() roll target}}Success{{/rollGreater() roll target}}
{{#rollTotal() roll target}}Success{{/rollTotal() roll target}}
{{#rollLess() roll target}}Failure{{/rollLess() roll target}}Code language: HTML, XML (xml)

The addition of a third logic helper, to check against the exact value of the target will do the job. But that’s unneccessary repetition that gets worse with more complex rolltemplates. You can do it with just two rules and no repetition.

{{#rollLess() roll target}}Failure{{/rollLess() roll target}}
{{#^rollLess() roll target}}Success{{/^rollLess() roll target}}Code language: HTML, XML (xml)

That ^ operator is the Not operator. It is when something is NOT true. In the above code, we first test if you get less than the target, in which case it’s a failure.

Then we tests if your roll is NOT less than the target. If its not less than, then it must be equal or greater.

The NOT operator is very useful, if a bit mind-bending. You must use it as shown, with the ^ operator written after the # at the start and the / at the end of a logic helper expression.

The Not operator only works with the numeric Logic Helpers above. You cannot use it with Optional keys (see last post). Something like {{#^name}}{{name}}{{^name}} will fail.

Nesting Helpers

Take the above roll and imagine the roll also gives a critical and fumble, and you want to report those. You could try this:

{{#rollWasFumble() roll}}Fumble{{/rollWasFumble() roll}}
{{#rollLess() roll target}}Failure{{/rollLess() roll target}}
{{#^rollLess() roll target}}Success{{/^rollLess() roll target}}
{{#rollWasCrit() roll}}Critical{{/rollWasCrit() roll}}Code language: HTML, XML (xml)

But wait. Imagine you rolled a fumble and failed (very likely): both the twop two rules would be true, and both would be printed out. That is probably what you want.

That’s where nesting comes in, often used in combination with NOT.

{{#rollWasFumble() roll}}Fumble{{/rollWasFumble() roll}}
{{#^rollWasFumble() roll}} <!-- roll is not a fumble -->
   {{#rollWasCrit() roll}}Critical{{/rollWasCrit() roll}}
   {{#^rollWasCrit() roll}} <!-- roll is not a critical -->
      {{#rollLess() roll target}}Failure{{/rollLess() roll target}}
      {{#^rollLess() roll target}}Success{{/^rollLess() roll target}}
   {{/^rollWasCrit() roll}}
{{/^rollWasFumble() roll}}Code language: HTML, XML (xml)

Here we check as follows:

  • Is the roll a fumble?
  • If it’s not a fumble, is it a critical?
  • If it’s not a critical, it is also not a fumble, because of the above ordering. Now we can check if it was an ordinary success or failure.

The indentation here is just to make the code easier to read – it’s not needed for the code to work.

Each helper can only check on thing at a time. Every time you are checking two or more conditions, you need to use nested logic helpers. Code can get very complex and cumbersome. One day you’ll be able to make these structures easier with Custom Roll Parsing. But rolltemplates are easier to understand.

Inline Rolls and Text

The Logic Helps above assume your tolltemlate value is an inline roll. For instance:

&{template:default} {{attack=[[1d20+5]]}} {{target=[[15]]}}Code language: JavaScript (javascript)

But a value might include text and an inline roll, like

&{template:default} {{attack=My attack roll is [[1d20+5]]}} {{target=The AC is [[15]]}}Code language: JavaScript (javascript)

Logic helpers ignore text, but will extract the first inline roll in the value and use that. If there are multiple inline rolls, it only uses the first.

What Did We Learn Here?

Since this is a long post, here’ a quick revision of the main points.

  • Logic Helpers must be numeric inline rolls.
  • You can use the NOT operator ^
  • You can pass a value as a variable, and use it anywhere in a Logic Helper.
  • Logic helpers can be nested (and it’s often necessary).
  • This is HTML so you can include comments.
  • A value can include inline rolls and text, but logic helpers use only the first inline roll.
Series Navigation<< rollTemplate Keys and ValuesWhat to Show in rollTemplates >>

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.