rollDetailed()
Roll dice and get the individual results back. Never writes to chat.
Part of the Action API · Function reference
Signature
rollDetailed(expression: string): {
total: number;
rolls: number[];
expression: string;
breakdown: string;
}
Synchronous. Returns an object, not a promise.
Parameters
| Parameter | Type | Description |
|---|---|---|
expression |
string |
A dice expression, with the same grammar and property substitution as roll(). |
Returns
An object with four fields:
| Field | Type | Description |
|---|---|---|
total |
number |
The sum, with every modifier applied. 0 if the expression could not be parsed. |
rolls |
number[] |
Every individual die face, in order, across all dice groups. Flat modifiers do not appear here. Empty for a diceless expression. |
expression |
string |
The expression exactly as you passed it, before property substitution. |
breakdown |
string |
A human-readable trace, e.g. 2d6(4, 2) + 3. On failure this is Error: ... and total is 0. |
rolls is a flat list. rollDetailed('1d8+1d6') returns two entries with no
indication of which die was which — if you need them apart, roll them apart.
When to use it instead of roll()
Reach for rollDetailed() when the individual dice matter:
- counting successes, hits, or sixes
- rerolling ones
- showing the dice in a layout of your own
- deciding something before anything reaches chat
Reach for roll() when you just want a total and the standard dice
row.
Examples
Show your own breakdown
const r = rollDetailed('3d8+2');
sendMessage(`<b>${token.name}</b> channels ${r.breakdown} = <b>${r.total}</b>.`);
Count successes in a dice pool
const pool = rollDetailed(`${token.getProperty('rank')}d6`);
const hits = pool.rolls.filter((d) => d >= 5).length;
sendMessage(`${pool.rolls.join(', ')} → <b>${hits}</b> hit${hits === 1 ? '' : 's'}.`);
Great Weapon Fighting: reroll 1s and 2s once
const first = rollDetailed('2d6');
const kept = first.rolls.map((d) => (d <= 2 ? rollDetailed('1d6').total : d));
const total = kept.reduce((a, b) => a + b, 0) + 3;
sendMessage(`Damage: ${kept.join(' + ')} + 3 = <b>${total}</b>`);
Detect a natural 20
const attack = rollDetailed('1d20+attackBonus');
if (attack.rolls[0] === 20) {
sendMessage('<b>Critical hit!</b>');
}
Notes and gotchas
- No chat, no 3D dice, ever. Nothing about this call is visible to anyone
until you call
sendMessage()yourself. - Beware echoing
expressioninto chat. It is the raw string you passed, sosendMessage(r.expression)handssendMessage()a live dice expression and it rolls it again. Sendr.breakdownorr.totalinstead. - Failures are silent. A malformed expression does not throw; you get
total: 0and abreakdownstarting withError:. Check for that if the expression came from user input. roll(expression, false)is the same maths with only the total returned — use it when you do not needrollsorbreakdown.
See also
roll()— the total, plus the standard chat row and 3D dicesendMessage()— how to display what you rolled- Dice