Sync parsers and game mechanics with vault changes (2026-08-18 to 08-23)

- talent-parser.ts, discipline-parser.ts, race-parser.ts: rebuilt to read
  from the vault's post-bab5a62 per-topic-file layout (rulebook monoliths
  were split into per-chapter subfolders; discipline/race writeups moved to
  their canonical disciplines/ and races/ folders). All three parsers were
  previously producing zero or broken output for their packs.
- constants.ts, actor-character.ts, actor-npc.ts, rest.ts: mana is now a
  daily pool (Poziom Mocy x3) restored via rest tiers, not a per-round
  budget; Zywotnosc is 2x(Cialo+Umysl+Dusza), not 3x; rest recovery amounts
  updated to match Odetchniecie/Krotki Odpoczynek/Dlugi Odpoczynek.
- combat.ts: removed the now-obsolete per-round mana reset hook.
- actor-npc.ts: Initiative now includes Refleks/Spostrzegawczosc skill
  bonuses (was missing entirely); Magia attribute constrained to valid
  1k10 character-creation values.
- fields.ts: added `choices` support to makeIntField for the above.
- spell-cast.ts: overcast test now uses the correct T-threshold tiers and
  triangular S = E*(E+1)/2 required-successes formula (Zasada
  Nadczarowywania Zaklec).

Not implemented (flagged as new features, out of scope for a sync fix):
mana-exhaustion/overcast-failure penalty tables, overcast bonus taper past
step 2, shield-breaking damage mechanic, elixir-weapon-coating system.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 01:15:38 +02:00
parent 0fe9dd02d6
commit 1fba0892b9
10 changed files with 345 additions and 396 deletions
+15 -13
View File
@@ -79,28 +79,30 @@ export const SKILL_KEYS = Object.freeze(Object.keys(SKILLS)) as readonly string[
/**
* Magic Power Level lookup table (level 0..10 → I..X).
* Drives dice pool size, max mana per single spell, and total mana per round.
* Drives dice pool size, max mana per single spell, and the daily mana pool
* ("Ilość Many" - there is no more per-round mana limit, see `rules/00.
* Podręcznik Gry/Rozdział II - Tworzenie Postaci/Atrybuty.md`).
*/
export interface MagicPowerEntry {
level: number; // 0..10
label: string; // '0' | 'I' | 'II' | ... | 'X'
dicePool: number; // dice added when casting
maxPerSpell: number; // max mana spent on one spell
manaPerRound: number; // mana budget per combat round
manaPerDay: number; // daily mana pool ("Ilość Many")
}
export const MAGIC_POWER_TABLE: readonly MagicPowerEntry[] = Object.freeze([
{ level: 0, label: '0', dicePool: 6, maxPerSpell: 10, manaPerRound: 20 },
{ level: 1, label: 'I', dicePool: 4, maxPerSpell: 6, manaPerRound: 12 },
{ level: 2, label: 'II', dicePool: 4, maxPerSpell: 5, manaPerRound: 10 },
{ level: 3, label: 'III', dicePool: 3, maxPerSpell: 5, manaPerRound: 7 },
{ level: 4, label: 'IV', dicePool: 3, maxPerSpell: 4, manaPerRound: 8 },
{ level: 5, label: 'V', dicePool: 3, maxPerSpell: 4, manaPerRound: 6 },
{ level: 6, label: 'VI', dicePool: 2, maxPerSpell: 3, manaPerRound: 6 },
{ level: 7, label: 'VII', dicePool: 2, maxPerSpell: 3, manaPerRound: 4 },
{ level: 8, label: 'VIII', dicePool: 1, maxPerSpell: 2, manaPerRound: 3 },
{ level: 9, label: 'IX', dicePool: 1, maxPerSpell: 1, manaPerRound: 2 },
{ level: 10, label: 'X', dicePool: 0, maxPerSpell: 1, manaPerRound: 1 },
{ level: 0, label: '0', dicePool: 6, maxPerSpell: 10, manaPerDay: 60 },
{ level: 1, label: 'I', dicePool: 4, maxPerSpell: 6, manaPerDay: 36 },
{ level: 2, label: 'II', dicePool: 4, maxPerSpell: 5, manaPerDay: 30 },
{ level: 3, label: 'III', dicePool: 3, maxPerSpell: 5, manaPerDay: 21 },
{ level: 4, label: 'IV', dicePool: 3, maxPerSpell: 4, manaPerDay: 24 },
{ level: 5, label: 'V', dicePool: 3, maxPerSpell: 4, manaPerDay: 18 },
{ level: 6, label: 'VI', dicePool: 2, maxPerSpell: 3, manaPerDay: 18 },
{ level: 7, label: 'VII', dicePool: 2, maxPerSpell: 3, manaPerDay: 12 },
{ level: 8, label: 'VIII', dicePool: 1, maxPerSpell: 2, manaPerDay: 9 },
{ level: 9, label: 'IX', dicePool: 1, maxPerSpell: 1, manaPerDay: 6 },
{ level: 10, label: 'X', dicePool: 0, maxPerSpell: 1, manaPerDay: 3 },
]);
export function getMagicPowerEntry(level: number): MagicPowerEntry {