D&D: wire the Open5e magic-item registry into live gameplay

Magic items now reach players through three surfaces: zone loot drops,
Luigi's "Curios" shelf, and combat effects. Effects are formulaic
(Rarity scalar x Kind), mirroring the bestiary tuning pass, with an
empty magicItemEffectOverlay as the hand-authored refinement path.

- magic_items_gameplay.go: rarity index, magic_item_equipped persistence
  (new table, DnDSlot-keyed), codified effect formula, applyMagicItemEffects
  combat hook, potion/scroll -> ConsumableDef bridge, !adventure equip-magic
- dropZoneLoot: 15% magic-item substitution roll by tier rarity
- Luigi's Curios category: daily UTC-seeded 8-item rotation
- combat_bridge / combat_session_build: applyMagicItemEffects after passives
- consumableDefByName falls through so loot/shop potions auto-resolve
- renderDnDSheet: new Magic Items section

Equippable items live entirely in the DnDSlot scheme, separate from the
legacy tier-gear. Attunement items equip inert until attuned (3-slot cap).
This commit is contained in:
prosolis
2026-05-14 18:38:57 -07:00
parent 297ce3d786
commit 0d666beea3
12 changed files with 996 additions and 10 deletions

View File

@@ -1268,6 +1268,19 @@ CREATE TABLE IF NOT EXISTS adventure_treasures (
);
CREATE INDEX IF NOT EXISTS idx_adv_treasure_user ON adventure_treasures(user_id);
-- Magic items equipped into the D&D 10-slot scheme (Open5e SRD registry).
-- One row per (user, DnDSlot). item_id references magicItemRegistry. Effects
-- are applied in combat from a codified Rarity+Kind formula; attunement gates
-- whether the item's effect counts (see magic_items_gameplay.go).
CREATE TABLE IF NOT EXISTS magic_item_equipped (
user_id TEXT NOT NULL,
slot TEXT NOT NULL,
item_id TEXT NOT NULL,
attuned INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (user_id, slot)
);
CREATE INDEX IF NOT EXISTS idx_magic_item_equipped_user ON magic_item_equipped(user_id);
CREATE TABLE IF NOT EXISTS adventure_buffs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,