feat(01-03): add spell-slot overlay types with Wizard worked example
- Define SpellTradition type and SpellSlotOverlayEntry interface as the contract Plan 03b appends to - Wizard fully populated L1..L19 with ARCANE slot progression and L1 cantrip count (5) - Stub keys for the other 15 D-16 classes set to empty arrays for Plan 03b to populate - No 'any' types; type-clean against tsconfig.json
This commit is contained in:
83
server/prisma/data/spell-slot-overlays.ts
Normal file
83
server/prisma/data/spell-slot-overlays.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Hand-curated spell-slot / cantrip / repertoire progression overlay.
|
||||
*
|
||||
* WHY HAND-CURATED: Foundry pf2e encodes slot tables in description prose, not machine-
|
||||
* readable rules (Pitfall #6 / verified 2026-04-27 against `wizard-spellcasting.json`).
|
||||
* NLP-parsing prose is fragile; the canonical PF2e tables fit in ~300 lines and are stable
|
||||
* across reprints.
|
||||
*
|
||||
* SOURCE: Archives of Nethys — Pathfinder 2e Player Core + Advanced Player's Guide
|
||||
* (https://2e.aonprd.com). Per-class spell-slot tables, cantrip counts, and repertoire
|
||||
* sizes (spontaneous casters only).
|
||||
*
|
||||
* SCOPE: 16 D-16 classes (Core + APG). This file (Plan 03) ships the type definitions
|
||||
* and Wizard fully populated as the worked example. Plan 03b appends entries for the
|
||||
* remaining 6 caster classes (Cleric, Druid, Witch, Bard, Sorcerer, Oracle) and the
|
||||
* empty-array entries for non-casters.
|
||||
*
|
||||
* SPONTANEOUS vs PREPARED: Spontaneous casters (Bard, Sorcerer, Oracle) get
|
||||
* repertoireIncrement entries on level-up. Prepared casters (Cleric, Druid, Witch, Wizard)
|
||||
* get spellSlotIncrement only. Both get cantripIncrement at L1.
|
||||
*/
|
||||
|
||||
export type SpellTradition = 'ARCANE' | 'DIVINE' | 'OCCULT' | 'PRIMAL';
|
||||
|
||||
export interface SpellSlotOverlayEntry {
|
||||
level: number;
|
||||
spellSlotIncrement?: { tradition: SpellTradition; spellLevel: number; count: number };
|
||||
cantripIncrement?: number;
|
||||
repertoireIncrement?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each class maps to an array of overlay entries. Multiple entries per level are allowed
|
||||
* (e.g. L1 Wizard gets 5 cantrips AND 2 grade-1 slots — two separate entries).
|
||||
* Order within a level does not matter — the seed script merges them per (class, level).
|
||||
*/
|
||||
export const SPELL_SLOT_OVERLAY: Record<string, SpellSlotOverlayEntry[]> = {
|
||||
// === PREPARED CASTER — WIZARD (worked example, fully populated in Plan 03) ===
|
||||
Wizard: [
|
||||
{ level: 1, cantripIncrement: 5 },
|
||||
{ level: 1, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 1, count: 2 } },
|
||||
{ level: 2, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 1, count: 1 } },
|
||||
{ level: 3, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 2, count: 2 } },
|
||||
{ level: 4, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 2, count: 1 } },
|
||||
{ level: 5, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 3, count: 2 } },
|
||||
{ level: 6, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 3, count: 1 } },
|
||||
{ level: 7, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 4, count: 2 } },
|
||||
{ level: 8, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 4, count: 1 } },
|
||||
{ level: 9, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 5, count: 2 } },
|
||||
{ level: 10, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 5, count: 1 } },
|
||||
{ level: 11, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 6, count: 2 } },
|
||||
{ level: 12, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 6, count: 1 } },
|
||||
{ level: 13, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 7, count: 2 } },
|
||||
{ level: 14, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 7, count: 1 } },
|
||||
{ level: 15, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 8, count: 2 } },
|
||||
{ level: 16, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 8, count: 1 } },
|
||||
{ level: 17, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 9, count: 2 } },
|
||||
{ level: 18, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 9, count: 1 } },
|
||||
// L19 Magnum Opus = 1 grade-10 slot per day
|
||||
{ level: 19, spellSlotIncrement: { tradition: 'ARCANE', spellLevel: 10, count: 1 } },
|
||||
// L20: no slot increment (capstone is qualitative)
|
||||
],
|
||||
|
||||
// === STUBS — populated by Plan 03b ===
|
||||
// Caster stubs (Plan 03b will replace [] with full L1..L20 entries):
|
||||
Cleric: [],
|
||||
Druid: [],
|
||||
Witch: [],
|
||||
Bard: [],
|
||||
Sorcerer: [],
|
||||
Oracle: [],
|
||||
Champion: [], // focus-only; minimal entries
|
||||
|
||||
// Non-caster stubs (Plan 03b confirms these stay empty):
|
||||
Alchemist: [],
|
||||
Barbarian: [],
|
||||
Fighter: [],
|
||||
Investigator: [],
|
||||
Monk: [],
|
||||
Ranger: [],
|
||||
Rogue: [],
|
||||
Swashbuckler: [],
|
||||
};
|
||||
Reference in New Issue
Block a user