import type { SystemId } from '@/lib/rules'; export type Degree = 'critical-success' | 'success' | 'failure' | 'critical-failure'; export const DEGREE_LABEL: Record = { 'critical-success': 'Critical Success', success: 'Success', failure: 'Failure', 'critical-failure': 'Critical Failure', }; export const DEGREE_COLOR: Record = { 'critical-success': 'text-success', success: 'text-success', failure: 'text-warning', 'critical-failure': 'text-danger', }; /** * Evaluate a d20 result against a DC. * - PF2e: ≥DC+10 crit success, ≥DC success, ≤DC-10 crit failure; a natural 20 * improves the degree one step and a natural 1 worsens it one step. * - 5e: success/failure vs DC, with natural 20/1 mapped to critical results. */ export function degreeOfSuccess(input: { total: number; dc: number; system: SystemId; /** the natural face of the d20, if known */ natural?: number | undefined; }): Degree { const { total, dc, system, natural } = input; if (system === 'pf2e') { let step = total >= dc + 10 ? 2 : total >= dc ? 1 : total <= dc - 10 ? -1 : 0; if (natural === 20) step += 1; else if (natural === 1) step -= 1; step = Math.max(-1, Math.min(2, step)); return step === 2 ? 'critical-success' : step === 1 ? 'success' : step === 0 ? 'failure' : 'critical-failure'; } // 5e if (natural === 20) return 'critical-success'; if (natural === 1) return 'critical-failure'; return total >= dc ? 'success' : 'failure'; }