Pets: fire 25% morning event from expedition briefing + fix defense-buff leak

Recovers the genuinely-missing half of ade0335 (orphaned on the unmerged
phase-H-harvest-charges branch). 3ed2e1d redid pet *arrival* via the
emergence seam and explicitly deferred the morning event; this closes
that gap.

- deliverBriefing now rolls the 25% morning pet event (petMorningEvent,
  already present but only wired into the overworld DM that underground
  players never see) and prepends it to the briefing body, granting the
  one-day PetMorningDefense buff.
- Add resetAllPetMorningDefense + wire it into midnightReset. The buff was
  leaking permanently even on HEAD's existing overworld path — it was set
  on the 25% roll but never cleared. Resets the pet_flags_json key in place.

Deliberately omits ade0335's ArrivalPending machinery: arrival is now the
emergence seam's job (3ed2e1d + 978dc5e + 513cf32), so queuing arrival
from the briefing would double-roll it.
This commit is contained in:
prosolis
2026-05-21 23:45:57 -07:00
parent 513cf32e42
commit f6a457ae84
3 changed files with 35 additions and 0 deletions

View File

@@ -495,6 +495,12 @@ func (p *AdventurePlugin) midnightReset() error {
return fmt.Errorf("reset daily actions after 3 attempts: %w", resetErr)
}
// Clear the one-day pet morning-defense buff so it re-rolls fresh each
// morning (briefing or overworld DM) instead of leaking permanently.
if err := resetAllPetMorningDefense(); err != nil {
slog.Error("adventure: failed to reset pet morning defense", "err", err)
}
// Prune expired buffs
if err := pruneAdvExpiredBuffs(); err != nil {
slog.Error("adventure: failed to prune expired buffs", "err", err)

View File

@@ -300,6 +300,22 @@ func (p *AdventurePlugin) deliverBriefing(e *Expedition, now time.Time) error {
}
if uid := id.UserID(e.UserID); uid != "" {
// The legacy overworld morning DM is skipped while underground, so
// its 25% morning pet event fires here instead, granting the one-day
// defense buff (reset at midnight via resetAllPetMorningDefense).
// Pet *arrival* is handled separately on the emergence seam below —
// not queued here — so we only roll the morning event.
if pet, perr := loadPetState(uid); perr == nil {
if petEvent := petMorningEvent(pet); petEvent != "" {
if char, cerr := loadAdvCharacter(uid); cerr == nil {
char.PetMorningDefense = true
if serr := saveAdvCharacter(char); serr != nil {
slog.Warn("expedition: save pet morning defense", "user", uid, "err", serr)
}
}
body = fmt.Sprintf("🐾 *%s*\n\n%s", petEvent, body)
}
}
if err := p.SendDM(uid, body); err != nil {
slog.Warn("expedition: send briefing DM", "user", uid, "err", err)
}

View File

@@ -909,6 +909,19 @@ func resetAllPlayerMetaDailyActions() error {
return err
}
// resetAllPetMorningDefense clears the one-day pet morning-defense buff for
// every player. The buff is a fresh morning grant (25% roll in the briefing /
// overworld DM), so it must not survive past the midnight rollover. The flag
// lives inside pet_flags_json (see petFlagsJSON), so patch that key in place;
// only rows where it's currently set are touched.
func resetAllPetMorningDefense() error {
_, err := db.Get().Exec(`
UPDATE player_meta
SET pet_flags_json = json_set(pet_flags_json, '$.morning_defense', json('false'))
WHERE json_extract(pet_flags_json, '$.morning_defense') = 1`)
return err
}
// DeathState mirrors player_meta's death-state columns. Phase L5e ports
// these fields off AdvCharacter (gogobee_legacy_migration.md §7.3 L5e).
// Mutation surface is large (~50 saveAdvCharacter sites touch death