mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
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>
This commit is contained in:
@@ -487,3 +487,36 @@ func persistDnDHPAfterCombat(userID id.UserID, legacyStartHP, legacyEndHP int) {
|
||||
slog.Error("dnd: persist hp after combat", "user", userID, "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// dndHPSnapshot returns the user's D&D-scale (current, max) HP. Caller
|
||||
// captures pre-combat values via this helper, runs combat (which calls
|
||||
// persistDnDHPAfterCombat internally), then re-snapshots for the post
|
||||
// values. Used so combat outcome narration shows sheet HP rather than
|
||||
// the legacy combat-engine HP scale.
|
||||
func dndHPSnapshot(userID id.UserID) (cur, max int) {
|
||||
c, err := LoadDnDCharacter(userID)
|
||||
if err != nil || c == nil {
|
||||
return 0, 0
|
||||
}
|
||||
return c.HPCurrent, c.HPMax
|
||||
}
|
||||
|
||||
// markAdventureDead flips the legacy adventure_characters.alive flag and
|
||||
// starts the 6h respawn timer for a player who went down in a D&D-layer
|
||||
// combat. Without this, hp_current persists as 0 but the legacy alive
|
||||
// flag stays true — the "zombie" state where !hospital says "you're
|
||||
// alive!" while the sheet shows 0/33. Idempotent: bails if already dead.
|
||||
//
|
||||
// source is "zone" / "expedition" / "patrol"; location is human-readable
|
||||
// (e.g. "Forest of Shadows") and surfaces in the daily report and
|
||||
// standout-loss flavor.
|
||||
func markAdventureDead(userID id.UserID, source, location string) {
|
||||
char, err := loadAdvCharacter(userID)
|
||||
if err != nil || char == nil || !char.Alive {
|
||||
return
|
||||
}
|
||||
char.Kill(source, location)
|
||||
if err := saveAdvCharacter(char); err != nil {
|
||||
slog.Error("dnd: kill on combat loss", "user", userID, "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user