Commit Graph

10 Commits

Author SHA1 Message Date
prosolis
8ee170bb9b UX S7: sheet + menu jargon sweep — outcome-first copy
Drops D&D-handbook syntax from the player-facing caster UX in favor of
verbs and feelings (per feedback_accessibility_over_dnd_crunch).

R12 — Drop "Spell DC: N / Spell Atk: +N" line from the spellbook view.
The numbers are pure handbook noise; the engine still computes them.

R13 — renderSlotLine swaps "L1 3/4 · L2 1/3" for "Level 1 ●●●○ · Level 2
●○○○". Filled bullets = energy left, hollow = spent.

R14 — Caster passive Description strings rewritten outcome-first: no
"+5%", no "scaled by your Charisma". Verbs and texture instead. All ten
class passives reworded; mechanics in applyClassPassives unchanged.

R18 — Class menu drops the "(d8, INT/WIS)" suffix → "**Mage** — INT &
WIS". The HP-die number was leaking implementation. !setup class confirm
line gets the same treatment.

P5 — Spellbook headers: "Cantrip" → "Cantrips", "L1" → "Level 1".

P6 — Cast queue line: "_(upcast to L2)_" → "_(empowered)_". Queued-line
in the spellbook view follows suit — drops "(L2 slot)" for "(empowered)"
when the slot is above the spell's base level.

P8 — Comment-convention marker added to dnd_passives.go and
dnd_subclass_combat.go file headers: `// internal note (not user-facing)`
flags Phase 2/3 tuning history so future codegen doesn't lift it into
Description / Flavor strings.

P9 — Spellbook line drops the duplicate "(can learn N more)" trailer —
the "%d / %d" already conveys remaining capacity.

Bonus cleanup. The two Arcane-Trickster slot-ceiling errors ("Arcane
Trickster L5 only has up to L1 slots.") and the "No L1 slot available"
out-of-energy messages get the same jargon scrub: "At level 5, your
Arcane Trickster magic only reaches level-1 spells." / "You're out of
level-1 energy."

Tests. Full plugin suite green; no test pinned the old strings.
2026-05-14 22:17:03 -07:00
prosolis
6386161402 UX S6: race truth-up — wire Tiefling fire resist + best-fit hints
R22: replace race copy that promised mechanics the engine doesn't deliver.
- Tiefling: wire FireResist as a CombatModifier. Enemy main attack is
  halved when monster is FireAttacker-tagged; aoe_fire abilities are
  halved unconditionally; fire-tagged traps deal half damage to Tieflings.
  DnDMonsterTemplate carries FireAttacker; toCombatStats propagates it.
  Hand-authored fire entries tagged in dnd_bestiary.go (flameskull,
  magmin, azer, salamander, fire_elemental, emberlord_thyrak,
  young_red_dragon, infernax, belaxath).
- Open5e tuned generator derives FireAttacker from the highest-AvgDamage
  attack's DamageType (threshold AvgDamage>=5). 19 tuned monsters tag.
  Regenerated bestiary_tuned_data.go.
- Elf: drop "immune to sleep" (no sleep mechanic); reframe as keen
  senses + trance flavor.
- Half-Elf: drop "two bonus skill proficiencies" (no skill system);
  reframe as adaptable cross-cultural know-how.
- Tiefling copy: drop "bonus on CHA checks" (no checks); keep fire
  resistance with flavor framing.

R23: DnDRaceInfo grows a BestFit field; renderRaceMenu emits an
"_best with: …_" hint per race so spiky stat spreads (Orc -1/-1/-1)
read as specialist picks rather than a brick of penalties.

R24: dnd.go header comment for the caster classes now reflects the
shipped state (Playable=true, spell lists populated) instead of the
pre-Open5e scaffold language.

Tests: TestApplyRacePassives gains a FireResist column; new
TestTieflingFireResistance asserts ~0.5x ratio over a 300-trial sweep
against a FireAttacker enemy. Full suite green.
2026-05-14 22:06:31 -07:00
prosolis
e6e0009253 D&D: scaffold the five missing caster classes
Add Druid, Bard, Sorcerer, Warlock and Paladin as structural
scaffolding ahead of the Open5e spell-data import. They are wired
through the mechanical layer but gated out of !setup via the new
DnDClassInfo.Playable flag — they have no spell list yet.

- dnd.go: class constants, dndClasses rows, Playable gate, AC floors
- dnd_combat.go: classAttackStatMod, dndClassWeaponBonus,
  classStatPriority arrays for the five
- dnd_spells.go: mageSlots generalized to fullCasterSlots (shared by
  the full casters); Paladin shares rangerSlots; new warlockSlots
  simplified long-rest pool; spellcastingMod + classIsCaster extended
- dnd_setup.go: renderClassMenu and parseClass filter on Playable

Subclasses and spell lists are deferred to later sessions.
2026-05-14 14:43:05 -07:00
prosolis
4e412219f3 WIP: in-flight combat/expedition/flavor changes
Bundle of uncommitted working-tree edits across combat engine, expedition
cycle, flavor pools, and TwinBee/zone narration. Includes new files:
combat_debug.go, dnd_boss_consumables.go, dnd_dex_floor.go, plus
CHANGES_24H.md and REBALANCE_NOTES.md scratch notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:59:19 -07:00
prosolis
36e14c6084 Adv 2.0 L5 close-out: §7.4 reconciled + retire 3 CombatLevel readers
Reconcile the migration plan with what actually shipped, and clear the
three remaining CombatLevel reader sites so the §7 grep gates hold.

Plan reconciliation (gogobee_legacy_migration.md §7.4):
The original deletion list was wrong on two counts. (1) AdventureCharacter
struct survives as the loaded-view shape post-L5h overlay; only the
backing table drops at purge. (2) combat_engine.go / combat_bridge.go /
combat_stats.go are not legacy — they're the live combat engine the D&D
system layers on top of (applyDnDPlayerLayer/EquipmentLayer/etc. mutate
CombatStats before SimulateCombat). Verified via grep: 21+ files reference
these symbols across arena/dungeon/zone/expedition. §7.4 rewritten to
reflect this; no L6 combat-engine migration needed.

Reader fixes:
- babysitDailyCost reframed for D&D-level scale. Formula 100 + level*100
  preserves the curve at every old-CL boundary given the 5:1 compression
  in dndLevelFromCombatLevel (Level 4 ≈ old CL 20 = €500/day, Level 10 ≈
  old CL 50 = €1100/day). Caller switched to dndLevelForUser.
- dnd_sheet.go drops the vestigial "Combat (legacy) %d" stat-block line.
- D&D onboarding retired. Post-L5g the welcome DM never fires (every
  legacy player already has a D&D row), so dnd_onboarding.go +
  dnd_onboarding_test.go are deleted, the 3 production caller invocations
  (dnd_zone_combat, combat_bridge, dnd_combat::ensureCharForDnDCmd) and
  the dnd_setup.go stub-creation branch removed. OnboardingSent column
  kept for a separate cleanup pass. dnd_audit_fixes_test.go ported.

go vet ./... && go test ./... clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:25:23 -07:00
prosolis
dfa7beeb96 Adv 2.0 D&D polish: GM→DM rename, streamed zone combat, end-to-end scenario test
GM→DM rename across docs and code (GMNarrationType→DMNarrationType,
GMState→DMState, narration constants, comments) so the system reads as
"Dungeon Master" everywhere. Player-visible "GM mood" wording stays
where it appears in flavor.

Streamed zone/expedition combat: zone advance now stages patrol →
patrol play-by-play → patrol resolution → room intro → room play-by-play
→ final outcome through sendZoneCombatMessages with 2–3s pacing
(arena keeps its 5–8s window). Combat narrative lines pick up a compact
d20-vs-AC roll annotation for hit/crit/miss/block events.

Combat outcome polish: dndHPSnapshot lets narration show sheet HP
rather than legacy combat-engine HP, and markAdventureDead clears the
zombie state where hp_current was 0 but the legacy alive flag stayed
true after a D&D-layer KO.

Adv 2.0 announcement (ADVENTURE_2.0_ANNOUNCEMENT.md), README rewrite
covering the new layer, and adv2_scenario_test.go — a full
zone-run + expedition + harvest playthrough against a copy of the prod
DB asserting persisted state end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:25:22 -07:00
prosolis
45863bd5f3 Adv 2.0 D&D Phase R7: post-completion audit hardening
High-priority fixes from the multi-agent audit of Adventure 2.0:

- Phase 11 nil-deref cluster: zoneOrFallback() helper replaces 8 unsafe
  getZone(_) sites in dnd_zone_cmd.go. Corrupted zone IDs render a
  placeholder instead of panicking.
- Briefing/recap idempotency: deliverBriefing/deliverRecap now claim
  the rollover via a conditional UPDATE. Double-fires from clock skew
  or restart become no-ops; supply burn and day++ no longer reapply.
- Graceful ticker shutdown: AdventurePlugin gains stopCh + Stop(); all
  11 background tickers now select on stopCh in addition to ticker.C.
- Mood decay (§3.2): math.Round(elapsed*2) replaces int() truncation
  so sub-hour gaps decay correctly.
- 24h auto-abandon (§4.3): getActiveZoneRun returns clean slate and
  abandons stale runs whose LastActionAt is over 24h old.
- Respec / auto-migrate orphan cleanup: !respec and the auto-migrated
  draft wipe now abandon active zone runs and expeditions before
  deleting the dnd_character row.
- Phase R combat-link: applyBossDefeatThreat now wired from
  resolveBossRoom (-20 threat); applyRoomCombatThreatForUser adds
  +5/+8 from non-boss/elite kills (§8.1).
- Starvation → forced extraction: briefing-time check forces extract
  with §10.2 coin tax when supplies hit zero.
- GMNat20/Nat1 narration wired into resolveCombatRoom and
  resolveBossRoom (nat-20 takes precedence over nat-1).
- Treasure-undo race: LoadAndDelete on both timer-fire and `undo`
  paths so only one side wins.
- Battle Master: Disarming, Menacing, Parry maneuvers added (3 → 6
  of 10). Remaining 4 (Pushing, Goading, Riposte, Commander's Strike)
  documented inline as needing ally/reaction mechanics the engine
  doesn't model.
- Threat-70 warning: tracked in RegionState["siege_warning_fired"]
  so a drop-and-recross doesn't re-fire the beat.
- region_state JSON decode error now logged via slog.Warn instead
  of silently discarded.

Failing TestProdDB_DnDLayer fixed via option (a): track migrated
characters and only run round-trip / idempotency assertions on those,
skipping pre-existing prod-DB rows accumulated from live bot use.

New tests in dnd_audit_phase_R7_test.go cover: 24h auto-abandon,
briefing double-fire idempotency, threat-70 warning idempotency,
multi-region extract→resume state preservation, and starvation
forced-extraction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:25:22 -07:00
prosolis
437460c9b2 Adv 2.0 D&D Phase 10 SUB2a-i: Champion + Berserker + Thief L5/L7
First mechanical slice of the subclass system. Each subclass gets its L5
and L7 abilities wired through the existing combat engine + skill check
substrate; no new resource pools introduced.

Champion (L5/L7):
- Improved Critical: new Mods.CritThreshold lowers crit floor to nat 19+
  in resolvePlayerAttack. Default 20 preserved for non-Champions.
- Remarkable Athlete: +½ proficiency bonus to STR/DEX/CON skill checks
  via subclassSkillBonus, layered on raceSkillBonus.

Berserker (L5/L7):
- Rage: new !arm-able active ability gated to Berserker subclass via
  DnDAbility.Subclass field. Reuses the Fighter stamina pool (3/long-rest
  matches 5e's rage uses). On fire: +2 flat damage per hit, halve incoming
  weapon damage, +50% damage approximation for Frenzy's bonus-attack-per-
  turn (one-shot combat can't model that literally).
- Frenzy exhaustion: new exhaustion column on dnd_character; incremented
  by persistDnDPostCombatSubclass after any rage'd combat. Decremented by
  one per long rest.
- Mindless Rage: documented; charm/frighten conditions don't exist in the
  combat engine yet, so no functional effect until P11 zone bosses land.

Thief (L5/L7):
- Sleight of Hand added to dndSkillTable.
- Fast Hands: +5 to Sleight of Hand checks via subclassSkillBonus.
- Supreme Sneak: advantage on Stealth (best of two d20s) via new
  subclassSkillAdvantage hook in performSkillCheck. 5e's half-speed gate
  dropped — we don't track movement speed.

Plumbing:
- applySubclassPassives layered after applyClassPassives in both arena
  and dungeon combat bridges.
- DnDAbility.Subclass enables per-subclass gating; characterActiveAbilities
  filters !arm and !abilities lists by both class and subclass.
- Existing !respec full-wipe also clears Exhaustion.

Tests: Champion CritThreshold gating across L4/L5/no-subclass; rage Apply
flag-set; rage probabilistic win-rate lift vs tougher enemy; exhaustion
increment only on raged combats; long-rest decrement; Champion bonus on
STR/DEX/CON only and only at L7+; Thief Fast Hands SoH-only; Thief
Supreme Sneak L7+ Stealth-only; statistical advantage roll lifts Thief
stealth average by ≥2 vs plain Rogue; !arm rage subclass gating; schema
roundtrip; characterActiveAbilities visibility.
2026-05-09 14:25:21 -07:00
prosolis
1ee4276bcd Adv 2.0 D&D Phase 10 SUB1: subclass selection system
Implements the identity layer of gogobee_subclass_system.md: 15 subclasses
(3 per class) selectable at L5 via !subclass.

- Schema: new subclass + last_subclass_respec_at columns on dnd_character.
- Registry (dnd_subclass.go): 15 entries with class, display, tagline, and
  TwinBee flavor line; helpers for prompt rendering and input resolution
  (number, id, or display-name; case/space/hyphen-insensitive).
- !subclass command: bare form prints prompt or current; !subclass <name>
  selects (free first time) or changes (500 euros + 30-day cooldown via
  separate timestamp from the full !respec wipe). Save-then-debit ordering
  mirrors !respec audit fix B.
- Level-up DM at L5+ now embeds the real selection prompt instead of the
  Phase 9 placeholder; suppressed once a subclass is set.
- Sheet shows the subclass below the class line, or nudges !subclass when
  unchosen at L5+.
- Existing !respec full-wipe also clears subclass + cooldown timestamp.

Mechanical effects of L5/7/10/15 subclass abilities deferred to SUB2/SUB3.
2026-05-09 14:25:21 -07:00
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