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

[Custom Roll Parsing] Separating groups of dice by type

1629068354

Edited 1629068803
Villain in Glasses
Pro
Sheet Author
API Scripter
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; } } } }
1629119218
GiGs
Pro
Sheet Author
API Scripter
It's good to share your problem and solution. That helps others. This bit seems weird to me: } 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. Why not roll a d6, not a d3, and then convert its value to stun by halving the die, and convert to body by dividing by 3 (is that how its done?) You would need to identify the "d3s" and calculate them accordingly, but that seems a better way to do it. And you can then show the d6's that become d3s in the output.
1629134939
Villain in Glasses
Pro
Sheet Author
API Scripter
I admit, it does seem weird, but it is the best solution I could think of for a problem that arises with the roll20 simulation. We start with a roll as entered by a player. In the physical world a d3 is a d6/2, but in roll20 it is a true d3.  We also need the player's roll as-is. The STUN value is the straight up roll of the player's entered dice, which is displayed in the chat via the roll template. The calculated value (also delivered to chat) produced by the startRoll() finishRoll() sheet worker is the BODY value. The weird random call is needed to reproduce the lost information when converting a real half-d6 to a d3. Most of the time the difference between a '3' or '4' doesn't matter, but this is a case where it does. 
1629136155
GiGs
Pro
Sheet Author
API Scripter
Villain in Glasses said: in roll20 it is a true d3.  It doesnt have to be though. You can process the expression to turn the d3s into d6s, and then handle them appropriately - or have d3s listed in the roll maybe like {{d3=[[2d6]]}} so you have the raw d6 to work with. I don't want to hijack the thread and wont belabour the point, it just occurred to me that you could handle it as actual d6s just the way you would at the table.
1629163681
Villain in Glasses
Pro
Sheet Author
API Scripter
That does sound interesting. It sounds like you would need to do that before the startRoll(), because by that time the roll has already occurred?
1629170424

Edited 1629170449
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
You should be able to do something like: {{d3=[[ceil(1d6/2)]]}} And then extract the "d3" result and the d6 result from the results object. Something like this would work to extract it: on('clicked:button',async (event)=>{ let rolls = await startRoll('&{template:default} {{d3=[[ceil(1d6/2)]]}}'); console.log({rolls}); let d3Roll = rolls.results.d3.dice; console.log({d3Roll}); finishRoll(rolls.rollId); });
1629235649

Edited 1629236419
Villain in Glasses
Pro
Sheet Author
API Scripter
I'm not entirely sure this method works. If a user types '3d6+1d3' into a text input field for damage dice, can the 1d3 be converted to an identifiable d6 in the roll?
1629238707
GiGs
Pro
Sheet Author
API Scripter
In HERO, I think there's no need to have a text important for damage, and it's bad practice in programming anyway. (So many ways users can enter the wrong values.) You should have a number input for damage class, or active points (depending on situation), and a selector for killing damage/normal damage/stun only, and a sheet worker should calculate the actual text string for damage, used for display purposes.
1629248810
Villain in Glasses
Pro
Sheet Author
API Scripter
Ideally, yes, but weapons in Hero system only loosely follow damage class rules. A DC 2 can be 1/2 d6 or 1d6-1. A DC 5 can be 1d6+2 or  1 1/2d6. Then you add in strength bonuses, which depend on the weapon's strength minimum and how much strength over that minimum (but less than the character's strength) they might want to use. Then you add in combat skill levels, which can change for every attack, depending on the player's mood. And combat maneuvers can add damage, which can vary depending on the relative velocities of the attacker and defender. It's a nightmare.
1629270084
GiGs
Pro
Sheet Author
API Scripter
Yes, thats a good point, weapons are a pain in that respect. I'd probably have a hidden attribute to contain the damage code used for the button, with a sheet worker to process the text entry players use to create a valid input for the button roll sheet worker. So you can separate the d3s into separate inputs (d6/2) for the button, and then on the output that the players see, show it however you like.