Files
gogobee/internal/plugin/dnd_spells_data.go
prosolis 9e1a1f606c Adv 2.0 D&D layer: Phases 1-8 + Phase 9 SP1+SP2
Combines all uncommitted D&D work into one checkpoint:

Phases 1-8 (per gogobee_dnd_session_summary.md):
- Race/class/stats system, !setup flow, !sheet, !respec
- d20-vs-AC combat with race/class passives, auto-migration
- XP/level-up, skill checks, NPC refund hooks
- Equipment slot mapping, rarity, !rest short/long
- Pre-arm active abilities, resource pools
- Bestiary, !roll/!stats/!level, onboarding DM
- Audit fixes A-I, flavor wiring under internal/flavor/
- Phase 8 weapon dice + armor AC tables (gogobee_equipment_appendix)

Phase 9 SP1 — spell system foundations:
- 79 SpellDefinitions (76 in-scope + 3 reaction-deferred)
- dnd_known_spells, dnd_spell_slots tables
- pending_cast / concentration_* columns on dnd_character
- Slot tables for Mage/Cleric/Ranger, DC + attack-bonus math
- Long-rest refreshes slots; respec wipes spell state
- Auto-grant default known list on !setup confirm and auto-migration

Phase 9 SP2 — !cast / !spells / !prepare commands:
- Out-of-combat HEAL and UTILITY resolve immediately
- Damage/control/buff queue as pending_cast for next combat
- Audit-style save-then-debit, slot refund on save failure
- !cast --drop, concentration supersession, prep-cap enforcement
- Reaction spells refused with Phase 11 note

SP3 (combat-time resolution of pending_cast) and SP4 (full prep/learn
tests) are next. Build clean, full test suite green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:25:21 -07:00

392 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package plugin
// Phase 9 spell registry data. All 76 in-scope spells from
// gogobee_spell_system.md. Reaction spells (Shield, Counterspell,
// Absorb Elements) are included with EffectReaction so the registry is
// complete; SP2's !cast refuses them with a "Phase 11" note.
func buildSpellList() []SpellDefinition {
mage := []DnDClass{ClassMage}
cleric := []DnDClass{ClassCleric}
ranger := []DnDClass{ClassRanger}
mageCleric := []DnDClass{ClassMage, ClassCleric}
clericRanger := []DnDClass{ClassCleric, ClassRanger}
rangerCleric := []DnDClass{ClassRanger, ClassCleric}
allCasters := []DnDClass{ClassMage, ClassCleric, ClassRanger}
return []SpellDefinition{
// ── Cantrips (level 0) ────────────────────────────────────────────────
{ID: "fire_bolt", Name: "Fire Bolt", Level: 0, School: "evocation",
Classes: mage, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "1d10", DamageType: "fire",
Description: "Hurl a mote of fire at a target.",
Upcast: "2d10 at L5, 3d10 at L11"},
{ID: "toll_the_dead", Name: "Toll the Dead", Level: 0, School: "necromancy",
Classes: mageCleric, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "WIS", DamageDice: "1d8", DamageType: "necrotic",
Description: "1d8 necrotic; 1d12 if target is missing HP."},
{ID: "chill_touch", Name: "Chill Touch", Level: 0, School: "necromancy",
Classes: mageCleric, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "1d8", DamageType: "necrotic",
Description: "Spectral hand — target can't heal until next turn."},
{ID: "poison_spray", Name: "Poison Spray", Level: 0, School: "conjuration",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "CON", DamageDice: "1d12", DamageType: "poison",
Description: "Puff of noxious gas; CON save or full damage."},
{ID: "shocking_grasp", Name: "Shocking Grasp", Level: 0, School: "evocation",
Classes: mage, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "1d8", DamageType: "lightning",
Description: "Lightning leaps from your touch; target loses Reaction."},
{ID: "sacred_flame", Name: "Sacred Flame", Level: 0, School: "evocation",
Classes: cleric, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "1d8", DamageType: "radiant",
Description: "Flame-like radiance descends; ignores cover."},
{ID: "guidance", Name: "Guidance", Level: 0, School: "divination",
Classes: clericRanger, Effect: EffectUtility, CastTime: CastAction,
Concentration: true,
Description: "+1d4 to one ability check (self or ally)."},
{ID: "shillelagh", Name: "Shillelagh", Level: 0, School: "transmutation",
Classes: rangerCleric, Effect: EffectBuffSelf, CastTime: CastBonusAction,
Concentration: true,
Description: "Club/staff uses WIS for attack+damage; 1d8."},
{ID: "thorn_whip", Name: "Thorn Whip", Level: 0, School: "transmutation",
Classes: ranger, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "1d6", DamageType: "piercing",
Description: "Vine of thorns; pull target 10 ft."},
{ID: "mending", Name: "Mending", Level: 0, School: "transmutation",
Classes: allCasters, Effect: EffectUtility, CastTime: CastAction,
Description: "Repair one non-magical item. Out of combat only."},
{ID: "message", Name: "Message", Level: 0, School: "transmutation",
Classes: mage, Effect: EffectUtility, CastTime: CastAction,
Description: "Whisper to target up to 120 ft."},
{ID: "minor_illusion", Name: "Minor Illusion", Level: 0, School: "illusion",
Classes: mage, Effect: EffectUtility, CastTime: CastAction,
Description: "Create a sound or image."},
// ── 1st level — Mage ──────────────────────────────────────────────────
{ID: "magic_missile", Name: "Magic Missile", Level: 1, School: "evocation",
Classes: mage, Effect: EffectDamageAuto, CastTime: CastAction,
DamageDice: "3d4+3", DamageType: "force",
Description: "Three darts × 1d4+1 force; auto-hit.",
Upcast: "+1 dart per slot above 1st"},
{ID: "thunderwave", Name: "Thunderwave", Level: 1, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "CON", DamageDice: "2d8", DamageType: "thunder", AOE: true,
Description: "Wave of force in 15 ft cube; push 10 ft.",
Upcast: "+1d8 per slot above 1st"},
{ID: "mage_armor", Name: "Mage Armor", Level: 1, School: "abjuration",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastAction,
Description: "AC = 13 + DEX mod (no armor required) for 8 hours."},
{ID: "burning_hands", Name: "Burning Hands", Level: 1, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "3d6", DamageType: "fire", AOE: true,
Description: "Cone of fire; DEX save half.",
Upcast: "+1d6 per slot above 1st"},
{ID: "detect_magic", Name: "Detect Magic", Level: 1, School: "divination",
Classes: mage, Effect: EffectUtility, CastTime: CastRitual,
Concentration: true,
Description: "Sense magic within 30 ft. Ritual castable (no slot)."},
{ID: "fog_cloud", Name: "Fog Cloud", Level: 1, School: "conjuration",
Classes: []DnDClass{ClassMage, ClassRanger}, Effect: EffectBuffSelf, CastTime: CastAction,
Concentration: true,
Description: "20 ft heavily obscured radius. Attacks inside have disadvantage."},
{ID: "grease", Name: "Grease", Level: 1, School: "conjuration",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
SaveStat: "DEX", AOE: true,
Description: "10 ft square; DEX save or Prone. Difficult terrain."},
{ID: "shield", Name: "Shield", Level: 1, School: "abjuration",
Classes: mage, Effect: EffectReaction, CastTime: CastReaction,
Description: "+5 AC as Reaction until next turn. (Phase 11)"},
{ID: "sleep", Name: "Sleep", Level: 1, School: "enchantment",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
AOE: true,
Description: "Incapacitate creatures totaling 5d8 HP (weakest first).",
Upcast: "+2d8 per slot above 1st"},
{ID: "chromatic_orb", Name: "Chromatic Orb", Level: 1, School: "evocation",
Classes: mage, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "3d8", DamageType: "varies",
Description: "3d8 of chosen damage type.",
Upcast: "+1d8 per slot above 1st"},
// ── 1st level — Cleric ────────────────────────────────────────────────
{ID: "cure_wounds", Name: "Cure Wounds", Level: 1, School: "evocation",
Classes: clericRanger, Effect: EffectSpellHeal, CastTime: CastAction,
DamageDice: "1d8",
Description: "Heal 1d8 + WIS mod HP. Touch.",
Upcast: "+1d8 per slot above 1st"},
{ID: "bless", Name: "Bless", Level: 1, School: "enchantment",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastAction,
Concentration: true,
Description: "Up to 3 targets: +1d4 to attack rolls and saves. 1 min."},
{ID: "inflict_wounds", Name: "Inflict Wounds", Level: 1, School: "necromancy",
Classes: cleric, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "3d10", DamageType: "necrotic",
Description: "3d10 necrotic. Melee spell attack.",
Upcast: "+1d10 per slot above 1st"},
{ID: "guiding_bolt", Name: "Guiding Bolt", Level: 1, School: "evocation",
Classes: cleric, Effect: EffectDamageAttack, CastTime: CastAction,
AttackRoll: true, DamageDice: "4d6", DamageType: "radiant",
Description: "Next attack on target has advantage.",
Upcast: "+1d6 per slot above 1st"},
{ID: "shield_of_faith", Name: "Shield of Faith", Level: 1, School: "abjuration",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastBonusAction,
Concentration: true,
Description: "+2 AC to one target. 10 min."},
{ID: "healing_word_spell", Name: "Healing Word", Level: 1, School: "evocation",
Classes: cleric, Effect: EffectSpellHeal, CastTime: CastBonusAction,
DamageDice: "1d4",
Description: "1d4 + WIS mod HP. Range 60 ft.",
Upcast: "+1d4 per slot above 1st"},
{ID: "command", Name: "Command", Level: 1, School: "enchantment",
Classes: cleric, Effect: EffectControl, CastTime: CastAction,
SaveStat: "WIS",
Description: "One-word command (Flee/Grovel/Halt). 1 turn.",
Upcast: "+1 target per slot above 1st"},
{ID: "protection_from_evil", Name: "Protection from Evil and Good", Level: 1, School: "abjuration",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastAction,
Concentration: true,
Description: "Aberrations/fiends/undead have disadvantage vs. target."},
// ── 1st level — Ranger ────────────────────────────────────────────────
{ID: "hunters_mark", Name: "Hunter's Mark", Level: 1, School: "divination",
Classes: ranger, Effect: EffectBuffSelf, CastTime: CastBonusAction,
Concentration: true,
Description: "+1d6 damage to marked target; track as bonus action. 1 hr."},
{ID: "ensnaring_strike", Name: "Ensnaring Strike", Level: 1, School: "conjuration",
Classes: ranger, Effect: EffectControl, CastTime: CastBonusAction,
Concentration: true, SaveStat: "STR",
Description: "On hit: STR save or Restrained; 1d6/turn."},
{ID: "speak_with_animals", Name: "Speak with Animals", Level: 1, School: "divination",
Classes: ranger, Effect: EffectUtility, CastTime: CastRitual,
Description: "Communicate with beasts. 10 min."},
{ID: "absorb_elements", Name: "Absorb Elements", Level: 1, School: "abjuration",
Classes: ranger, Effect: EffectReaction, CastTime: CastReaction,
Description: "Reaction: resistance to incoming elemental damage. (Phase 11)"},
// ── 2nd level — Mage ──────────────────────────────────────────────────
{ID: "scorching_ray", Name: "Scorching Ray", Level: 2, School: "evocation",
Classes: mage, Effect: EffectDamageAuto, CastTime: CastAction,
DamageDice: "6d6", DamageType: "fire",
Description: "3 rays × 2d6 fire; each is a separate auto-hit.",
Upcast: "+1 ray per slot above 2nd"},
{ID: "mirror_image", Name: "Mirror Image", Level: 2, School: "illusion",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastAction,
Description: "3 duplicates absorb hits."},
{ID: "misty_step", Name: "Misty Step", Level: 2, School: "conjuration",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastBonusAction,
Description: "Bonus-action teleport up to 30 ft."},
{ID: "hold_person", Name: "Hold Person", Level: 2, School: "enchantment",
Classes: mageCleric, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "WIS",
Description: "Paralyzed; auto-crit melee while held.",
Upcast: "+1 target per slot above 2nd"},
{ID: "shatter", Name: "Shatter", Level: 2, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "CON", DamageDice: "3d8", DamageType: "thunder", AOE: true,
Description: "3d8 thunder in 10 ft sphere.",
Upcast: "+1d8 per slot above 2nd"},
{ID: "blur", Name: "Blur", Level: 2, School: "illusion",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastAction,
Concentration: true,
Description: "All attacks vs. you have disadvantage."},
{ID: "web", Name: "Web", Level: 2, School: "conjuration",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "STR", AOE: true,
Description: "20 ft cube; Restrained (STR DC to escape)."},
{ID: "levitate", Name: "Levitate", Level: 2, School: "transmutation",
Classes: mage, Effect: EffectUtility, CastTime: CastAction,
Concentration: true, SaveStat: "CON",
Description: "Float up to 20 ft; immune to ground-based effects."},
{ID: "knock", Name: "Knock", Level: 2, School: "transmutation",
Classes: mage, Effect: EffectUtility, CastTime: CastAction,
Description: "Open any mundane lock or magically sealed door."},
// ── 2nd level — Cleric ────────────────────────────────────────────────
{ID: "spiritual_weapon", Name: "Spiritual Weapon", Level: 2, School: "evocation",
Classes: cleric, Effect: EffectBuffSelf, CastTime: CastBonusAction,
DamageDice: "1d8",
Description: "Bonus-action spectral weapon attacks 1d8+WIS each turn. 1 min.",
Upcast: "+1d8 per 2 slots above 2nd"},
{ID: "lesser_restoration", Name: "Lesser Restoration", Level: 2, School: "abjuration",
Classes: clericRanger, Effect: EffectUtility, CastTime: CastAction,
Description: "Remove one condition (Blinded/Deafened/Paralyzed/Poisoned)."},
{ID: "prayer_of_healing", Name: "Prayer of Healing", Level: 2, School: "evocation",
Classes: cleric, Effect: EffectSpellHeal, CastTime: CastAction,
DamageDice: "2d8",
Description: "Up to 6 targets: 2d8 + WIS mod HP. Out of combat only."},
{ID: "silence", Name: "Silence", Level: 2, School: "illusion",
Classes: clericRanger, Effect: EffectUtility, CastTime: CastAction,
Concentration: true,
Description: "No sound in 20 ft sphere; no verbal spells."},
{ID: "aid", Name: "Aid", Level: 2, School: "abjuration",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastAction,
Description: "3 targets: +5 max HP and current HP. 8 hr.",
Upcast: "+5 HP per slot above 2nd"},
{ID: "augury", Name: "Augury", Level: 2, School: "divination",
Classes: cleric, Effect: EffectUtility, CastTime: CastRitual,
Description: "Omen about action in next 30 min. TwinBee delivers."},
// ── 2nd level — Ranger ────────────────────────────────────────────────
{ID: "pass_without_trace", Name: "Pass Without Trace", Level: 2, School: "abjuration",
Classes: ranger, Effect: EffectBuffSelf, CastTime: CastAction,
Concentration: true,
Description: "+10 to Stealth; can't be tracked magically."},
{ID: "spike_growth", Name: "Spike Growth", Level: 2, School: "transmutation",
Classes: ranger, Effect: EffectDamageAuto, CastTime: CastAction,
Concentration: true, DamageDice: "2d4", DamageType: "piercing", AOE: true,
Description: "20 ft radius; 2d4 per 5 ft moved through. Difficult terrain."},
{ID: "beast_sense", Name: "Beast Sense", Level: 2, School: "divination",
Classes: ranger, Effect: EffectUtility, CastTime: CastRitual,
Concentration: true,
Description: "See/hear through a beast's senses."},
{ID: "cordon_of_arrows", Name: "Cordon of Arrows", Level: 2, School: "transmutation",
Classes: ranger, Effect: EffectBuffSelf, CastTime: CastAction,
Description: "4 arrows guard area; fire on intruders (1d6+DEX). 8 hr."},
{ID: "find_traps", Name: "Find Traps", Level: 2, School: "divination",
Classes: ranger, Effect: EffectUtility, CastTime: CastAction,
Description: "Detect presence of traps within 120 ft."},
// ── 3rd level — Mage ──────────────────────────────────────────────────
{ID: "fireball", Name: "Fireball", Level: 3, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "8d6", DamageType: "fire", AOE: true,
Description: "8d6 fire in 20 ft radius. DEX save half.",
Upcast: "+1d6 per slot above 3rd"},
{ID: "lightning_bolt", Name: "Lightning Bolt", Level: 3, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "8d6", DamageType: "lightning", AOE: true,
Description: "8d6 lightning in 100 ft line. DEX save half.",
Upcast: "+1d6 per slot above 3rd"},
{ID: "counterspell", Name: "Counterspell", Level: 3, School: "abjuration",
Classes: mage, Effect: EffectReaction, CastTime: CastReaction,
Description: "Reaction: cancel a spell of 3rd level or lower. (Phase 11)"},
{ID: "fly", Name: "Fly", Level: 3, School: "transmutation",
Classes: mage, Effect: EffectBuffAlly, CastTime: CastAction,
Concentration: true,
Description: "Target gains 60 ft fly speed. 10 min."},
{ID: "hypnotic_pattern", Name: "Hypnotic Pattern", Level: 3, School: "illusion",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "WIS", AOE: true,
Description: "Creatures in 30 ft cube: Incapacitated, speed 0."},
{ID: "dispel_magic", Name: "Dispel Magic", Level: 3, School: "abjuration",
Classes: mageCleric, Effect: EffectUtility, CastTime: CastAction,
Description: "End one magical effect on target."},
{ID: "slow", Name: "Slow", Level: 3, School: "transmutation",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "WIS", AOE: true,
Description: "Up to 6 targets: halve speed, -2 AC, no reactions."},
{ID: "animate_dead", Name: "Animate Dead", Level: 3, School: "necromancy",
Classes: mageCleric, Effect: EffectUtility, CastTime: CastAction,
Description: "Animate up to 3 corpses as skeletons/zombies. 24 hr."},
// ── 3rd level — Cleric ────────────────────────────────────────────────
{ID: "spirit_guardians", Name: "Spirit Guardians", Level: 3, School: "conjuration",
Classes: cleric, Effect: EffectDamageSave, CastTime: CastAction,
Concentration: true, SaveStat: "WIS", DamageDice: "3d8",
DamageType: "radiant", AOE: true,
Description: "15 ft aura: 3d8/turn to enemies. WIS save half.",
Upcast: "+1d8 per slot above 3rd"},
{ID: "revivify", Name: "Revivify", Level: 3, School: "necromancy",
Classes: cleric, Effect: EffectUtility, CastTime: CastAction,
MaterialCost: 300,
Description: "Restore a creature dead <1 min to 1 HP. 300-coin diamond."},
{ID: "mass_healing_word", Name: "Mass Healing Word", Level: 3, School: "evocation",
Classes: cleric, Effect: EffectSpellHeal, CastTime: CastBonusAction,
DamageDice: "1d4",
Description: "Up to 6 targets: 1d4 + WIS mod HP."},
{ID: "beacon_of_hope", Name: "Beacon of Hope", Level: 3, School: "abjuration",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastAction,
Concentration: true,
Description: "Targets have advantage on WIS saves and death saves; max healing."},
{ID: "remove_curse", Name: "Remove Curse", Level: 3, School: "abjuration",
Classes: cleric, Effect: EffectUtility, CastTime: CastAction,
Description: "End one curse on target or object."},
// ── 3rd level — Ranger ────────────────────────────────────────────────
{ID: "lightning_arrow", Name: "Lightning Arrow", Level: 3, School: "transmutation",
Classes: ranger, Effect: EffectDamageSave, CastTime: CastBonusAction,
SaveStat: "DEX", DamageDice: "4d8", DamageType: "lightning", AOE: true,
Description: "Ranged: 4d8 lightning on hit; 2d8 to creatures within 10 ft."},
{ID: "conjure_barrage", Name: "Conjure Barrage", Level: 3, School: "conjuration",
Classes: ranger, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "3d8", DamageType: "varies", AOE: true,
Description: "3d8 of weapon type in 60 ft cone. DEX save half."},
{ID: "water_walk", Name: "Water Walk", Level: 3, School: "transmutation",
Classes: ranger, Effect: EffectUtility, CastTime: CastRitual,
Description: "Up to 10 targets walk on liquid surfaces. 1 hr."},
{ID: "plant_growth", Name: "Plant Growth", Level: 3, School: "transmutation",
Classes: ranger, Effect: EffectUtility, CastTime: CastAction,
Description: "100 ft difficult terrain; or enhance crops."},
{ID: "nondetection", Name: "Nondetection", Level: 3, School: "abjuration",
Classes: ranger, Effect: EffectUtility, CastTime: CastAction,
Description: "Target undetectable by divination magic. 8 hr."},
// ── 4th level (Mage / Cleric) ─────────────────────────────────────────
{ID: "banishment", Name: "Banishment", Level: 4, School: "abjuration",
Classes: cleric, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "CHA",
Description: "Send extraplanar creature to home plane temporarily."},
{ID: "polymorph", Name: "Polymorph", Level: 4, School: "transmutation",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "WIS",
Description: "Transform target into beast. Max CR = target's level."},
{ID: "ice_storm", Name: "Ice Storm", Level: 4, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "6d6", DamageType: "cold", AOE: true,
Description: "2d8 bludgeoning + 4d6 cold in 20 ft cylinder."},
{ID: "wall_of_fire", Name: "Wall of Fire", Level: 4, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
Concentration: true, SaveStat: "DEX", DamageDice: "5d8",
DamageType: "fire", AOE: true,
Description: "60 ft wall; 5d8 fire to those passing through."},
{ID: "greater_invisibility", Name: "Greater Invisibility", Level: 4, School: "illusion",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastAction,
Concentration: true,
Description: "Target invisible; attacks have advantage; can't be targeted. 1 min."},
{ID: "guardian_of_faith", Name: "Guardian of Faith", Level: 4, School: "conjuration",
Classes: cleric, Effect: EffectBuffSelf, CastTime: CastAction,
Description: "Spectral guardian deals 20 radiant to approaching enemies."},
{ID: "death_ward", Name: "Death Ward", Level: 4, School: "abjuration",
Classes: cleric, Effect: EffectBuffAlly, CastTime: CastAction,
Description: "Next time target would drop to 0 HP: drops to 1 instead. 8 hr."},
{ID: "freedom_of_movement", Name: "Freedom of Movement", Level: 4, School: "abjuration",
Classes: clericRanger, Effect: EffectBuffAlly, CastTime: CastAction,
Description: "Target ignores Difficult terrain, paralysis, restraint. 1 hr."},
// ── 5th level (Mage / Cleric) ─────────────────────────────────────────
{ID: "cone_of_cold", Name: "Cone of Cold", Level: 5, School: "evocation",
Classes: mage, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "CON", DamageDice: "8d8", DamageType: "cold", AOE: true,
Description: "8d8 cold in 60 ft cone. CON save half.",
Upcast: "+1d8 per slot above 5th"},
{ID: "hold_monster", Name: "Hold Monster", Level: 5, School: "enchantment",
Classes: mage, Effect: EffectControl, CastTime: CastAction,
Concentration: true, SaveStat: "WIS",
Description: "Paralyze any creature type."},
{ID: "wall_of_force", Name: "Wall of Force", Level: 5, School: "evocation",
Classes: mage, Effect: EffectBuffSelf, CastTime: CastAction,
Concentration: true,
Description: "Invisible impenetrable wall."},
{ID: "scrying", Name: "Scrying", Level: 5, School: "divination",
Classes: mageCleric, Effect: EffectUtility, CastTime: CastAction,
Concentration: true, SaveStat: "WIS",
Description: "Observe target at any distance."},
{ID: "mass_cure_wounds", Name: "Mass Cure Wounds", Level: 5, School: "evocation",
Classes: cleric, Effect: EffectSpellHeal, CastTime: CastAction,
DamageDice: "3d8",
Description: "Up to 6 targets: 3d8 + WIS mod HP."},
{ID: "flame_strike", Name: "Flame Strike", Level: 5, School: "evocation",
Classes: cleric, Effect: EffectDamageSave, CastTime: CastAction,
SaveStat: "DEX", DamageDice: "8d6", DamageType: "fire", AOE: true,
Description: "4d6 fire + 4d6 radiant in 10 ft cylinder."},
{ID: "divine_word", Name: "Divine Word", Level: 5, School: "evocation",
Classes: cleric, Effect: EffectControl, CastTime: CastBonusAction,
SaveStat: "WIS",
Description: "Targets suffer effects based on HP. Kills below 20 HP."},
{ID: "raise_dead", Name: "Raise Dead", Level: 5, School: "necromancy",
Classes: cleric, Effect: EffectUtility, CastTime: CastAction,
MaterialCost: 500,
Description: "Restore a creature dead up to 10 days. 500-coin diamond."},
}
}