NumberField draft buffer; surface massive-damage / death-at-0 rules in combat

- NumberField keeps a focus-time string draft so min-bounded fields (point-buy, HP,
  quantities) no longer snap to the minimum on every keystroke while retyping; the
  committed value is still always a clamped integer.
- Combat tracker now logs the 5e death rules when a downed PC takes damage: instant
  death from massive damage (leftover >= max HP), otherwise a reminder to mark a death
  save failure (two on a crit). Surfaced, not auto-applied — the player owns their
  character's death-save count (consistent with the no-auto-roll design). New tested
  isMassiveDamageDeath() engine helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 17:41:07 +02:00
parent f2e4259c84
commit bd78c87fb3
4 changed files with 68 additions and 8 deletions
+11
View File
@@ -7,6 +7,7 @@ import {
applyInitiatives,
currentCombatant,
endEncounter,
isMassiveDamageDeath,
moveCombatant,
nextTurn,
previousTurn,
@@ -216,3 +217,13 @@ describe('applyInitiatives', () => {
expect(currentCombatant(e)?.id).toBe('b');
});
});
describe('isMassiveDamageDeath', () => {
it('kills when leftover damage past 0 is >= max HP', () => {
// 12-max PC at 4 HP takes 17 → current -13; 13 >= 12 → instant death
expect(isMassiveDamageDeath(12, -13)).toBe(true);
expect(isMassiveDamageDeath(12, -12)).toBe(true); // exactly max → dead
expect(isMassiveDamageDeath(12, -11)).toBe(false); // one short → dying, not dead
expect(isMassiveDamageDeath(12, 0)).toBe(false); // dropped to 0, no overflow
});
});