3 Commits

Author SHA1 Message Date
prosolis
adcc62112b N2/B1+B4+C4: tempering, the expedition achievement wing, arena seasons
B1 — tempering. `!adventure temper` pushes an owned magic item one rung up
the rarity ladder at the blacksmith, capped at Legendary. Rarity lives on
the registry definition, so an upgraded instance records its progress as a
`temper` step count on its own row (adventure_inventory, magic_item_equipped)
and effective rarity is derived on read. The stored base rarity is never
written back, so an item cannot double-bump across a load/save round-trip.
Effects flow through the existing rarity scalars — no new combat math, and
the Legendary cap means this accelerates reaching the current ceiling rather
than raising it.

Costs mirror the crafting ladder (10k/25k/60k/150k, Foraging 15/20/25/30).
Only the Legendary rung consumes a T5 material; gating the lower rungs on
one would make tempering unreachable until a player already clears T5.

Two plan anchors were wrong: thyraks_core and portal_fragment are not
loot-note strings needing promotion — they are UniqueAlways slate entries
that already materialize as inventory rows on every T5 clear.

B4 — expedition achievement wing: first-clear and all-zones-cleared per tier
(10), a quiet-clear for keeping peak threat under 50, and temper_legendary.
The quiet-clear requires max_threat_seen to be *present*, not merely low:
recordMaxThreat samples only on day rollover and never stores a zero, so an
absent key means no threat history, not low threat. The plan's no-death-T4
achievement is not shipped — no per-expedition death counter exists — and
pet-saved-my-life already ships as combat_pet_save.

C4 — arena seasons. Standings are derived from arena_history.created_at per
calendar quarter rather than wiping arena_stats: same visible reset, but
lifetime totals survive for `!arena stats` and no destructive job can fire
twice. Crowns archive to arena_season_titles rather than player_meta.title,
which already carries the Survivalist milestone. Rollover rides the existing
midnight ticker and self-dedups on the season key, so a bot that was down on
the boundary catches up on its next wake.
2026-07-09 19:22:10 -07:00
prosolis
c2fdc63b51 UX S4: magic-item polish — slot fixes, swap-back, shop & sheet truth-up
B4: Slot classifier no longer treats "Springing" / "Snaring" / "Devouring"
as ring matches; tokenises by word boundary instead of raw substring.
Adds DnDSlotCloak so cloaks/capes/mantles/wings stop evicting body armor
from the chest slot. Regenerated magic_items_srd_data.go: boots_of_*,
gloves_of_missile_snaring, bag_of_devouring, talismans, and 6 cloaks all
land in the right slot.

R4: equipMagicItem swap-back returns the prior occupant at full Value
instead of half — swapping a curio shouldn't tax it.

R5: Attunement count is recomputed *after* the swap-back so freeing the
prior occupant's bond opens the slot for the incoming item.

R1: Inventory tags magic_item rows with 🔮 + rarity label and prints a
single equip-magic footer when any are present.

R6: Sheet's Magic Items block marks unbonded items as **(inactive)**
with the reason (cap full vs unbonded), so over-cap items aren't silent.

R7: New activeMagicItemsLine surfaces a one-shot "your curios stir: …"
at combat-start in both the dungeon path and !fight, mirroring the way
class passives are surfaced.

R8/R9: dropMagicItemLoot pretty-prints rarity, drops "wondrous", calls
attunement "needs bonding", appends "auto-uses in combat" for
potions/scrolls, and routes persistence errors to slog instead of
leaking %v into chat.

R2/R3: Curios shelf now shows "Very Rare" not "very_rare", drops the
bare "wondrous" word (the effect line carries it), renders the codified
magicItemEffectSummary above the SRD desc, and ends with a one-line
plain-language "what is bonding" footnote.

R10: Curios stock day flips at 06:00 UTC instead of midnight so EU
players don't see a fresh shelf at 1 a.m. mid-session.

R11: Curios buy resolver disambiguates fuzzy matches — typing "ring"
when several rings are on the shelf lists candidates instead of
silently selling the first.

P1: Greeting grid pairs Curios with an Exit chip so the 2-column
emoji layout doesn't dangle.

P2: Equip-magic empty state trimmed to one line.

P4 (back-from-curios reprompt) deferred — the existing back-flow is
correct, just verbose; not worth the surface-area expansion this
session.

Tests: word-boundary classifier, cloak/chest coexistence, full-value
swap-back. go test ./... + go vet clean.
2026-05-14 22:37:47 -07:00
prosolis
0d666beea3 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).
2026-05-14 18:38:57 -07:00