mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Camp: auto-break when party moves to a different room
Camp was a stationary "rest here until the next briefing" intent, but
nothing struck it when the autopilot / !zone advance / fork picks walked
the party into a new room. The stale CampState then blocked !camp <type>
with "already camped" even though the player was several rooms away.
autoBreakCampOnMove clears the camp (no rest bonuses — those only land
at briefing time via processOvernightCamp) whenever Camp.RoomIndex no
longer matches run.CurrentRoom. Wired into advanceOnceWithOpts (covers
advance/autopilot, complete/fork/next-room branches all surface a
"⛺ Camp struck" banner) and zoneCmdGo (fork commit).
This commit is contained in:
@@ -384,6 +384,41 @@ func campLocationCheck(exp *Expedition) (cleared bool, problem string) {
|
|||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// autoBreakCampOnMove strikes an active camp when the player has moved
|
||||||
|
// to a different room than the one camp was pitched in. Camp is a
|
||||||
|
// stationary intent (long-rest at this spot until the next briefing);
|
||||||
|
// once the party walks on — whether by autopilot, manual !advance, or
|
||||||
|
// fork pick — the tent stops mattering. Overnight rest effects are not
|
||||||
|
// applied here (those only land at briefing time via
|
||||||
|
// processOvernightCamp). Returns the camp type that was struck, or ""
|
||||||
|
// if no break happened. Safe to call when there's no expedition.
|
||||||
|
func autoBreakCampOnMove(userID id.UserID) string {
|
||||||
|
exp, err := getActiveExpedition(userID)
|
||||||
|
if err != nil || exp == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if exp.Camp == nil || !exp.Camp.Active {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if exp.RunID == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
run, err := getZoneRun(exp.RunID)
|
||||||
|
if err != nil || run == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if run.CurrentRoom == exp.Camp.RoomIndex {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
kind := exp.Camp.Type
|
||||||
|
if err := updateCamp(exp.ID, nil); err != nil {
|
||||||
|
slog.Warn("camp: auto-break on move failed", "expedition", exp.ID, "err", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
_ = appendExpeditionLog(exp.ID, exp.CurrentDay, "narrative", "camp struck (party moved on)", "")
|
||||||
|
return kind
|
||||||
|
}
|
||||||
|
|
||||||
// campCurrentRoomIndex returns 0 (entry) when no room context exists.
|
// campCurrentRoomIndex returns 0 (entry) when no room context exists.
|
||||||
func campCurrentRoomIndex(exp *Expedition) int {
|
func campCurrentRoomIndex(exp *Expedition) int {
|
||||||
if exp.RunID == "" {
|
if exp.RunID == "" {
|
||||||
|
|||||||
@@ -606,6 +606,10 @@ func (p *AdventurePlugin) advanceOnceWithOpts(ctx MessageContext, compact bool)
|
|||||||
if gerr != nil {
|
if gerr != nil {
|
||||||
return advanceResult{}, fmt.Errorf("Couldn't advance: %s", gerr.Error())
|
return advanceResult{}, fmt.Errorf("Couldn't advance: %s", gerr.Error())
|
||||||
}
|
}
|
||||||
|
var campStruck string
|
||||||
|
if kind := autoBreakCampOnMove(ctx.Sender); kind != "" {
|
||||||
|
campStruck = fmt.Sprintf("⛺ Camp struck (**%s**) — the party moved on.\n\n", kind)
|
||||||
|
}
|
||||||
if complete {
|
if complete {
|
||||||
_, _ = applyMoodEvent(run.RunID, MoodEventZoneComplete)
|
_, _ = applyMoodEvent(run.RunID, MoodEventZoneComplete)
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
@@ -613,6 +617,9 @@ func (p *AdventurePlugin) advanceOnceWithOpts(ctx MessageContext, compact bool)
|
|||||||
b.WriteString(outcome)
|
b.WriteString(outcome)
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
}
|
}
|
||||||
|
if campStruck != "" {
|
||||||
|
b.WriteString(campStruck)
|
||||||
|
}
|
||||||
// A "complete" run is only a full zone clear when it isn't a mid-zone
|
// A "complete" run is only a full zone clear when it isn't a mid-zone
|
||||||
// region clear of a multi-region zone. For the latter, name the region
|
// region clear of a multi-region zone. For the latter, name the region
|
||||||
// and point at the next one — "Cleared {zone}. Run complete." reads
|
// and point at the next one — "Cleared {zone}. Run complete." reads
|
||||||
@@ -658,6 +665,9 @@ func (p *AdventurePlugin) advanceOnceWithOpts(ctx MessageContext, compact bool)
|
|||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
}
|
}
|
||||||
b.WriteString(fmt.Sprintf("✓ Cleared room %d (%s).\n\n", prevIdx+1, prettyRoomType(prev)))
|
b.WriteString(fmt.Sprintf("✓ Cleared room %d (%s).\n\n", prevIdx+1, prettyRoomType(prev)))
|
||||||
|
if campStruck != "" {
|
||||||
|
b.WriteString(campStruck)
|
||||||
|
}
|
||||||
b.WriteString(forkMsg)
|
b.WriteString(forkMsg)
|
||||||
return advanceResult{
|
return advanceResult{
|
||||||
preStream: preStream,
|
preStream: preStream,
|
||||||
@@ -668,6 +678,9 @@ func (p *AdventurePlugin) advanceOnceWithOpts(ctx MessageContext, compact bool)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
finalMsg := p.formatNextRoomMessage(run, zone, prev, prevIdx, outcome, next)
|
finalMsg := p.formatNextRoomMessage(run, zone, prev, prevIdx, outcome, next)
|
||||||
|
if campStruck != "" {
|
||||||
|
finalMsg = campStruck + finalMsg
|
||||||
|
}
|
||||||
|
|
||||||
// H2 — auto-harvest the room the player just walked into. Only fires
|
// H2 — auto-harvest the room the player just walked into. Only fires
|
||||||
// for Exploration rooms (Entry/Trap/Elite/Boss self-skip via
|
// for Exploration rooms (Entry/Trap/Elite/Boss self-skip via
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ func (p *AdventurePlugin) zoneCmdGo(ctx MessageContext, rest string) error {
|
|||||||
nextRoom := nodeKindToRoomType(nextNode.Kind)
|
nextRoom := nodeKindToRoomType(nextNode.Kind)
|
||||||
nextIdx := run.CurrentRoom + 1
|
nextIdx := run.CurrentRoom + 1
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
|
if kind := autoBreakCampOnMove(ctx.Sender); kind != "" {
|
||||||
|
b.WriteString(fmt.Sprintf("⛺ Camp struck (**%s**) — the party moved on.\n\n", kind))
|
||||||
|
}
|
||||||
b.WriteString(fmt.Sprintf("➡ You take the path: **%s**.\n\n", chosen.Label))
|
b.WriteString(fmt.Sprintf("➡ You take the path: **%s**.\n\n", chosen.Label))
|
||||||
if nextRoom == RoomBoss {
|
if nextRoom == RoomBoss {
|
||||||
if line := composeBossEntry(zone.ID, run.RunID, nextIdx); line != "" {
|
if line := composeBossEntry(zone.ID, run.RunID, nextIdx); line != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user