/** * Evaluate a spell/miracle damage formula with per-die explosion, then post to chat. * Explosion dice are shown manually via showForRoll; the main roll is shown automatically * by toMessage() (which triggers Dice So Nice via its createChatMessage hook). * Append "NE" to the formula to disable explosion. * * @param {string} formula Dice formula, e.g. "1d8", "2d6", "1d8NE" * @param {Object} rollOpts Options for LethalFantasyRoll (rollType, actorId, defenderId, etc.) * @returns {Promise} */ export async function rollSpellDamageToMessage(formula, rollOpts) { const roll = new this(formula, {}, rollOpts) await roll.evaluate() const shouldExplode = !/NE$/i.test(formula) const diceResults = [] let diceSum = 0 for (const term of roll.dice) { const singleDice = `1D${term.faces}` const termResults = Array.from(term.results) for (const r of termResults) { let diceResult = r.result diceResults.push({ dice: singleDice.toUpperCase(), value: diceResult }) diceSum += diceResult if (shouldExplode && term.faces > 0) { while (diceResult === term.faces) { const xr = await new Roll(singleDice).evaluate() // Optional chaining guards against unexpected roll structure diceResult = xr.dice?.[0]?.results?.[0]?.result ?? (term.faces - 1) diceResults.push({ dice: `${singleDice.toUpperCase()}-1`, value: diceResult - 1 }) diceSum += (diceResult - 1) term.results.push({ result: diceResult, active: true }) } } } } roll.options.diceResults = diceResults roll.options.rollTotal = diceSum return roll.toMessage() }