
I struggled a bit with this, so I thought I might post my experience and solution.
In Hero System, there are two types of "hit points," if you will: STUN and BODY. The first keeps you aware and the second keeps you alive. The fact that attacks do both kinds of damage with one dice roll has been a real challenge to handle in Roll20 until the recent roll parsing feature. To make things more complicated there are two types of attacks: Killing and Normal. The first is relatively straightforward, you roll the dice for the BODY total and multiply that result by another number for the STUN total. The 'other' number isn't important here.
The second type of damage creates the challenge. For normal attacks, the STUN damage is the total of the dice rolled. To find the BODY damage you follow these rules:
- For each d6, a '1' is 0 BODY, a '2' to '5' is 1 BODY, and a '6' is 2 BODY.
- For each d3, a '1' is 0 BODY and a '3' is 1 BODY. A '2' can be 0 BODY or 1 BODY. This arises because in real life a '2' on a 1/2 d6 is either a '3' (0 BODY) or '4' (1 BODY).
So we need to separate the two types of dice and we don't know if the player will roll '5d6,' '5d6+1d3,' '1d3+5d6,' or maybe even '2d3.'
Say we call the our sheet worker with the dice roll {{STUN=[[@{weaponDamage}]]}} with weaponDamage equal to any combination of d6s or d3s. We need to break up the sets of d6 and d3 rolls. Fortunately, Roll20 automatically separates the two types of dice rolls, but here I think the help page on custom roll parsing could use a correction. It is missing the property name 'rolls.' Knowing this, if we create a variable with the assignment
const theDice = results.results.STUN.rolls; console.log(theDice);
we will find that theDice is an array of two objects each with properties
{ sides: dice: results: }
And now we can iterate over the dice sets selecting for sides of 3 or 6:
// Convert dice roll to equivalent BODY damage. let computed = 0; const theDice = results.results.STUN.rolls; // For each type of dice (d3 or d6) calculate BODY: for(let groupOfDice of theDice) { if (groupOfDice.sides == 3) { // calculate normal damage of d3 dice. for (let element of groupOfDice.results) { if (element === 3) { computed = computed+1; } else if (element === 2) { computed = computed + Math.floor(Math.random()*2); // Flip a coin. 0 or 1 BODY corresponding to a '3' or '4' on a d6. } else { computed = computed+0; // Do nothing. } } } else { // calculate normal damage of d6 dice for (let element of groupOfDice.results) { if (element === 1) { computed = computed+0; // Do nothing. } else if (element === 6) { computed = computed+2; } else { computed = computed+1; } } } }