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:
@@ -339,16 +339,24 @@ func currentRoomCleared(run *DungeonRun) bool {
|
||||
// handleHarvestCmd is the shared dispatcher for !forage/!mine/!scavenge/
|
||||
// !essence/!commune. Resolves a single attempt and DMs the outcome.
|
||||
func (p *AdventurePlugin) handleHarvestCmd(ctx MessageContext, action HarvestAction) error {
|
||||
char, err := LoadDnDCharacter(ctx.Sender)
|
||||
if err != nil || char == nil {
|
||||
return p.SendDM(ctx.Sender, "No D&D character found. Run `!setup` first.")
|
||||
}
|
||||
exp, err := getActiveExpedition(ctx.Sender)
|
||||
if err != nil {
|
||||
return p.SendDM(ctx.Sender, "Couldn't load expedition state.")
|
||||
}
|
||||
if exp == nil {
|
||||
return p.SendDM(ctx.Sender, "You're not on an expedition. Start one with `!expedition start <zone>`.")
|
||||
}
|
||||
char, err := LoadDnDCharacter(ctx.Sender)
|
||||
if err != nil || char == nil {
|
||||
return p.SendDM(ctx.Sender, "No D&D character found. Run `!setup` first.")
|
||||
// No expedition: fall through to single-session harvest if the
|
||||
// player has an active !zone enter run. Single-session harvest
|
||||
// lives in dnd_zone_harvest.go and stores nodes per-run rather
|
||||
// than per-region.
|
||||
run, _ := getActiveZoneRun(ctx.Sender)
|
||||
if run == nil {
|
||||
return p.SendDM(ctx.Sender, "You're not in a zone or expedition. Use `!zone enter <id>` or `!expedition start <zone>`.")
|
||||
}
|
||||
return p.handleStandaloneHarvest(ctx, char, action, run)
|
||||
}
|
||||
if action == HarvestFish && !isFishingZone(exp.ZoneID) {
|
||||
return p.SendDM(ctx.Sender, "There's no water to fish in here. `!fish` works only in Forest of Shadows, Sunken Temple, Underdark, or Feywild Crossing.")
|
||||
@@ -582,6 +590,9 @@ func grantHarvestYield(userID id.UserID, res ZoneResource, qty int) error {
|
||||
if qty <= 0 {
|
||||
return nil
|
||||
}
|
||||
if isHol, _ := isHolidayToday(); isHol {
|
||||
qty++
|
||||
}
|
||||
tier := zoneTierFromID(res.ZoneID)
|
||||
for i := 0; i < qty; i++ {
|
||||
item := AdvItem{
|
||||
|
||||
Reference in New Issue
Block a user