@randsum/daggerheart
Version:
A flexible, type-safe dice roller for building Daggerheart-compatible applications
106 lines (98 loc) • 2.14 kB
text/typescript
import { type NumericRollOptions, roll } from '@randsum/dice'
import type {
AdvantageDisadvantageDH,
RollArgumentDH,
RollResultDH,
RollResultDHType
} from './types'
function rollArg({ modifier = 0, amplifyHope = false, amplifyFear = false }: RollArgumentDH): NumericRollOptions[] {
if (amplifyHope && amplifyFear) {
return [{
quantity: 2,
sides: 20,
modifiers: { plus: modifier }
}]
}
if (amplifyHope) {
return [{
quantity: 1,
sides: 20,
modifiers: { plus: modifier }
},
{
quantity: 1,
sides: 12,
modifiers: { plus: modifier }
}]
}
if (amplifyFear) {
return [{
quantity: 1,
sides: 12,
modifiers: { plus: modifier }
},
{
quantity: 1,
sides: 12,
modifiers: { plus: modifier }
}]
}
return [{
quantity: 2,
sides: 12,
modifiers: { plus: modifier }
}]
}
export function rollDH({
modifier = 0,
rollingWith,
amplifyHope = false,
amplifyFear = false
}: RollArgumentDH): RollResultDH {
const {
result: [hope, fear],
total
} = roll(...rollArg({ modifier, amplifyHope, amplifyFear }))
if (hope === undefined || fear === undefined) {
throw new Error('Failed to roll hope and fear')
}
const [totalWithAdvantage, advantage] = calculateTotal(total, rollingWith)
return {
type: calculateType(hope, fear),
total: totalWithAdvantage,
rolls: {
hope,
advantage,
fear,
modifier
}
}
}
function calculateType(hope: number, fear: number): RollResultDHType {
if (hope === fear) {
return 'critical hope'
}
if (hope > fear) {
return 'hope'
}
return 'fear'
}
function calculateTotal(
total: number,
rollingWith: AdvantageDisadvantageDH | undefined
): [number, number | undefined] {
if (rollingWith) {
const advantage = advantageDie()
if (rollingWith === 'Advantage') {
return [total + advantage, advantage]
}
return [total - advantage, -advantage]
}
return [total, undefined]
}
function advantageDie(): number {
return roll({
quantity: 1,
sides: 6
}).total
}