Here's one fairly straightforward way to do it:
function: ROLL:n add BONUS:d to TARGET:s {
if ROLL = TARGET { result: ROLL + BONUS }
result: ROLL
}
function: explode DIE:d as BONUS:d {
result: [DIE add BONUS to [maximum of DIE]]
}
output
[explode d12 as
[explode d10 as
[explode d8 as
[explode d6 as
[explode d4 as d2]
]
]
]
]
A nice feature of this approach is that it's easy to specify any sequence of dice to roll on successive explosions. Want a d10 that explodes first as a d4 and then as a d20? Just use [explode d10 as [explode d4 as d20]]
.
The long nested expression at the end can be written a bit more compactly using a helper variable:
X: d2
X: [explode d4 as X]
X: [explode d6 as X]
X: [explode d8 as X]
X: [explode d10 as X]
X: [explode d12 as X]
output X
…or even more compactly using a loop:
X: 0
loop SIZE over {2, 4, 6, 8, 10, 12} {
X: [explode dSIZE as X]
}
output X
Of course we can also output all the intermediate results if we want:
X: 0
loop SIZE over {2, 4, 6, 8, 10, 12} {
X: [explode dSIZE as X]
output X named "decaying exploding d[SIZE]"
}
Ps. The [ROLL add BONUS to TARGET]
helper function is a bit more flexible that the examples above show. In particular, it can take a sequence of multiple target values to add the bonus to.
For example, if you wanted to modify your mechanic to let the two highest rolls of each die (e.g. 5 and 6 on a d6) explode, you could modify the [explode DIE as BONUS]
function into:
function: explode DIE:d as BONUS:d {
MAX: [maximum of DIE]
result: [DIE add BONUS to {MAX-1 .. MAX}]
}
This should be significantly more efficient than modifying HighDiceRoller's recursive solution to explode on multiple values per roll, since it will still only calculate each intermediate result once, whereas a recursive solution would calculate the d10 result twice, the d8 result for times, the d6 result eight times and so on. (For a normal explosion on the highest roll only, the two solutions should be approximately equally fast.)