@motioneffector/stats

Documentation

Checks API

Functions for skill checks, saving throws, contests, and derived stats.


check()

Perform a skill check against a difficulty class.

Signature:

function check(
  statBlock: StatBlock,
  statName: string,
  options: CheckOptions
): CheckResult

Parameters:

Name Type Required Description
statBlock StatBlock Yes The stat block to check against
statName string Yes Name of the stat to use
options CheckOptions Yes Check configuration

Returns: CheckResult — The check result

Example:

import { createStatBlock, check } from '@motioneffector/stats'

const hero = createStatBlock({ strength: { base: 16 } })

const result = check(hero, 'strength', {
  difficulty: 15,
  advantage: true,
  bonus: 2
})

console.log(result.success) // true or false
console.log(result.total)   // roll + modifier + bonus

Throws:

  • TypeError — If stat doesn't exist

saveThrow()

Perform a simple saving throw (returns boolean).

Signature:

function saveThrow(
  statBlock: StatBlock,
  statName: string,
  difficulty: number
): boolean

Parameters:

Name Type Required Description
statBlock StatBlock Yes The stat block
statName string Yes Name of the stat
difficulty number Yes Target DC

Returns: booleantrue if successful

Example:

import { createStatBlock, saveThrow } from '@motioneffector/stats'

const hero = createStatBlock({ constitution: { base: 14 } })

if (saveThrow(hero, 'constitution', 12)) {
  console.log('Resisted!')
}

contest()

Run an opposed contest between two participants.

Signature:

// With stat blocks
function contest(
  statBlockA: StatBlock,
  statNameA: string,
  statBlockB: StatBlock,
  statNameB: string,
  options?: ContestOptions
): ContestResult

// With raw modifiers
function contest(
  modifierA: number,
  modifierB: number,
  options?: ContestOptions
): ContestResult

Parameters (stat blocks):

Name Type Required Description
statBlockA StatBlock Yes First participant's stat block
statNameA string Yes First participant's stat
statBlockB StatBlock Yes Second participant's stat block
statNameB string Yes Second participant's stat
options ContestOptions No Contest configuration

Parameters (raw modifiers):

Name Type Required Description
modifierA number Yes First participant's modifier
modifierB number Yes Second participant's modifier
options ContestOptions No Contest configuration

Returns: ContestResult — The contest result

Example:

import { createStatBlock, contest } from '@motioneffector/stats'

const hero = createStatBlock({ strength: { base: 16 } })
const orc = createStatBlock({ strength: { base: 14 } })

const result = contest(hero, 'strength', orc, 'strength')

console.log(result.winner) // 'a', 'b', or 'tie'
console.log(result.margin) // Difference between totals

Throws:

  • TypeError — If stats don't exist or arguments are invalid

createDerivedStat()

Create a stat that auto-calculates from other stats.

Signature:

function createDerivedStat(
  statBlock: StatBlock,
  name: string,
  formula: (statBlock: StatBlock) => number
): { getValue: () => number }

Parameters:

Name Type Required Description
statBlock StatBlock Yes The stat block to add to
name string Yes Name for the derived stat
formula (statBlock: StatBlock) => number Yes Calculation function

Returns: { getValue: () => number } — Accessor for the derived value

Example:

import { createStatBlock, createDerivedStat } from '@motioneffector/stats'

const hero = createStatBlock({ strength: { base: 16 } })

createDerivedStat(hero, 'carryCapacity', (stats) => {
  return stats.get('strength')! * 15
})

hero.get('carryCapacity') // 240

Throws:

  • CircularDependencyError — If formula creates a circular dependency

Types

CheckOptions

interface CheckOptions {
  difficulty: number
  dice?: string
  advantage?: boolean
  disadvantage?: boolean
  bonus?: number
  modifier?: number
}
Property Type Required Description
difficulty number Yes Target DC
dice string No Dice notation. Default: '1d20'
advantage boolean No Roll twice, take higher
disadvantage boolean No Roll twice, take lower
bonus number No Additional bonus to add
modifier number No Override calculated modifier

CheckResult

interface CheckResult {
  success: boolean
  roll: number
  rolls: number[]
  modifier: number
  bonus: number
  total: number
  difficulty: number
  margin: number
}
Property Type Description
success boolean Whether the check passed
roll number The selected die result
rolls number[] All dice rolled (for advantage/disadvantage)
modifier number Stat modifier applied
bonus number Additional bonus applied
total number Final total (roll + modifier + bonus)
difficulty number The DC that was checked against
margin number Total - difficulty (positive = success margin)

ContestOptions

interface ContestOptions {
  dice?: string
}
Property Type Description
dice string Dice notation. Default: '1d20'

ContestResult

interface ContestResult {
  winner: 'a' | 'b' | 'tie'
  rolls: { a: number; b: number }
  totals: { a: number; b: number }
  margin: number
}
Property Type Description
winner 'a' | 'b' | 'tie' Who won the contest
rolls { a: number; b: number } Raw die results
totals { a: number; b: number } Final totals
margin number Absolute difference between totals

Related