feat: dedicated BRP dice pack; Day One uses it instead of coc-d100
Add brp-d100 rule-pack (Basic Roleplaying roll-under): fumble on 100, critical <= skill/20, special <= skill/5, success <= skill — bands transcribed from the Continuum Day One console's verdict() logic. Register it and switch day-one meta.system from coc-d100 to brp-d100. tests/dice/brp-d100.test.js covers the ladder, low-skill rounding, and the fumble-only-on-100 edge. 147 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9d0e6c7ec4
commit
49e9dcda46
@@ -0,0 +1,23 @@
|
||||
// Basic Roleplaying (BRP) roll-under d100 ladder vs a skill %.
|
||||
// Bands match the Continuum "Day One" console: fumble on 100, critical ≤ skill/20,
|
||||
// special ≤ skill/5, success ≤ skill (the fractions rounded up).
|
||||
export const brpD100 = {
|
||||
id: 'brp-d100',
|
||||
label: 'd100 (Basic Roleplaying)',
|
||||
params: [{ key: 'target', label: 'Skill %', default: 50 }],
|
||||
interpret(results, params = {}) {
|
||||
const value = results[0]?.value ?? 0;
|
||||
const target = params.target ?? 50;
|
||||
let level;
|
||||
if (value === 100) level = 'fumble';
|
||||
else if (value <= Math.ceil(target / 20)) level = 'critical';
|
||||
else if (value <= Math.ceil(target / 5)) level = 'special';
|
||||
else if (value <= target) level = 'success';
|
||||
else level = 'failure';
|
||||
const success = ['critical', 'special', 'success'].includes(level);
|
||||
return { value, target, level, success };
|
||||
},
|
||||
summary(v) {
|
||||
return `${v.value} vs ${v.target}% → ${v.level.toUpperCase()}`;
|
||||
},
|
||||
};
|
||||
@@ -1,10 +1,11 @@
|
||||
import { yearZero } from './year-zero.js';
|
||||
import { cocD100 } from './coc-d100.js';
|
||||
import { brpD100 } from './brp-d100.js';
|
||||
import { vanityD6 } from './vanity-d6.js';
|
||||
import { panicGlory } from './panic-glory.js';
|
||||
import { deeSanction } from './dee-sanction.js';
|
||||
|
||||
const packs = new Map([[yearZero.id, yearZero], [cocD100.id, cocD100], [vanityD6.id, vanityD6], [panicGlory.id, panicGlory], [deeSanction.id, deeSanction]]);
|
||||
const packs = new Map([[yearZero.id, yearZero], [cocD100.id, cocD100], [brpD100.id, brpD100], [vanityD6.id, vanityD6], [panicGlory.id, panicGlory], [deeSanction.id, deeSanction]]);
|
||||
|
||||
export function getRulePack(id) { return packs.get(id) || null; }
|
||||
export function registerRulePack(pack) { packs.set(pack.id, pack); }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// DAY ONE — "London Falls" · Continuum 2026 · Fri Slot 1.
|
||||
// Timeline transcribed from gm-utility/day-one-console.html (SCHED array).
|
||||
// System is BRP; mapped to the d100 roller pack (no dedicated BRP pack yet).
|
||||
// System is BRP (Basic Roleplaying) — uses the dedicated brp-d100 rule-pack.
|
||||
export default {
|
||||
meta: { id: 'day-one', title: 'DAY ONE — London Falls', system: 'coc-d100', players: 6, playMinutes: 210, slot: 'Fri · Slot 1' },
|
||||
meta: { id: 'day-one', title: 'DAY ONE — London Falls', system: 'brp-d100', players: 6, playMinutes: 210, slot: 'Fri · Slot 1' },
|
||||
timeline: [
|
||||
{ id: 'intro', label: 'Intro done — six placed, alert fired, players converging', targetMin: 15 },
|
||||
{ id: 'market', label: 'MARKET BREAKS — vendor bitten in full view, stampede (force it now if not yet)', targetMin: 60, hardTrigger: true },
|
||||
|
||||
Reference in New Issue
Block a user