Custom Roll Parsing for Character Sheets

The functions startRoll and finishRoll will allow sheet authors to access dice rolls and compute their own results for those rolls

Custom_Roll_Parsing.gif

Sheetworker Functions

startRoll( roll, callback? ) (asynchronous) 

This function accepts a roll as a string (generally a roll template string). The function will initiate a roll to the roll server, the results for which will be returned to the callback. The roll will wait for a corresponding “finishRoll” function call before posting the results to chat, however if the finishRoll call is not made within 5 seconds, the roll will be posted automatically. The results from the roll server will be an object containing the following properties


rollId: (string)

A unique identifier for this roll, required to finish the roll


results: (object)

An object containing the roll information from the roll server, where the keys are roll names and the values are an object containing the roll information, for example:

results: {
  roll1: {
      // The result of the roll, as calculated by the roll server
      result: 48,
      // An ordered array of the results of all dice in this roll
      dice: [9,9,20,4,4,1],
      // The original expression for this roll
      expression: ‘4d20+2d4’,
      // A breakdown of each “sub-roll” (each part of an expression is rolled separately)
      [
          {
              // The ‘4’ in ‘4d20’
              dice: 4,
              // The ‘20’ in ‘4d20’
              sides: 20,
              // Array of the results of each die
              results: [9,9,20,4]
          },
          …
      ]
  },
  …
}

finishRoll( rollId, computedResults? )

This function will finish a roll initiated with the startRoll function, and allow for adding computed results to each roll. The function requires the rollId from the startRoll function, and can accept an object, where the keys are roll names and the values are the computed results for that roll, as a string or an integer.

 


Roll Template Changes

To use the custom computed results in your roll templates, replace the roll names in the template with ‘computed::<rollname>’:

<rolltemplate class="sheet-rolltemplate-test">
    <div class="sheet-template-container">
        <h1>{{name}}</h1>
        <div class="sheet-results">
            <h4>Result = {{roll1}}</h4>
            <h4>Custom Result = {{computed::roll1}}</h4>
        </div>
    </div>
</rolltemplate>

When the roll is output to the chat, hovering the mouse over a custom result will display the quantum roll symbol and the original results of each die.

In addition, the roll template functions rollTotal, rollGreater, rollLess, and rollBetween can use the computed result of a roll:

<rolltemplate class="sheet-rolltemplate-test2">
    <div class="sheet-template-container">
        <h1>{{name}}</h1>
        <div class="sheet-results">
            <h4>Result = {{roll1}}</h4>
            <h4>Custom Result = {{computed::roll1}}</h4>
            {{#rollTotal() computed::roll1 0}}
                <h5>Total 0!</h5>
            {{/rollTotal() computed::roll1 0}}
            {{#rollGreater() computed::roll1 1}}
                <h5>Greater Than 1!</h5>
            {{/rollGreater() computed::roll1 1}}
            {{#rollLess() computed::roll1 2}}
                <h5>Less Than 2</h5>
            {{/rollLess() computed::roll1 2}}
            {{#rollBetween() computed::roll1 1 3}}
                <h5>Between 1 and 3</h5>
            {{/rollBetween() computed::roll1 1 3}}
        </div>
    </div>
</rolltemplate>

Note that these roll template functions generally expect an integer value to compare, and attempting to use them to compare string values may not not work as expected.

Bringing all of these new elements together, here is an example of implementing this feature:

<button type="action" name="act_test">Click me</button>

<rolltemplate class="sheet-rolltemplate-test">
    <div class="sheet-template-container">
        <h1>{{name}}</h1>
        <div class="sheet-results">
            <h4>Result = {{roll1}}</h4>
            <h4>Custom Result = {{computed::roll1}}</h4>
        </div>
    </div>
</rolltemplate>

<script type="text/worker">
    on('clicked:test', (info) => {
        startRoll("&{template:test} {{name=Test}} {{roll1=[[1d20]]}}", (results) => {
            const total = results.results.roll1.result
            const computed = total % 4;

            finishRoll(
                results.rollId,
                {
                    roll1: computed,
                }
            );
        });
    });
</script>

Also, you can now include a clickable action button directly in a roll (or in a macro) in the same way that roll buttons can be included: [Click Here](~[character id]|[action button name]). If including this in a roll made from the character sheet, the character id can be omitted (same as roll buttons): [Click Here](~[action button name]).

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).

However, if you go through the trouble of initiating a roll via the startRoll function, and include a reference to an action button, when a user clicks that button in the roll in the chat, the event info object in your clicked event listener will contain an additional property, originalRollId, which will match the results.rollId returned from the original roll’s startRoll call. In this way, you’d be able to match a roll made by clicking on a button in another roll to its original roll, and perhaps modify the second roll based on the results of the first.

And last, but certainly not least, some of you may have noticed and are wondering why the callback in startRoll is marked as optional. This will be our first sheetworker function to implement the option to use promises in your sheet code. Simply omit the callback in the function call and the function will return a promise. So, the sheetworker for the above code could be written like this instead:

<script type="text/worker">
    on('clicked:test', async (info) => {
        const results = await startRoll("&{template:test} {{name=Test}} {{roll1=[[1d20]]}}");
        const total = results.results.roll1.result
        const computed = total % 4;
        finishRoll(
            results.rollId,
            {
                roll1: computed,
            }
        );
    });
</script>

A note on best practices: This workflow allows you to use basically anything as the computed result of a roll, but generally you’ll want to make sure that a user can hover over the result and see all of the dice rolls that went into calculating it. It’s recommended that you have someone check the calculation and make sure the sheet got it right.

Was this article helpful?
3 out of 4 found this helpful