mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Coop: lock combat actions for the full duration of an active run
Players in a co-op were getting their combat action back every midnight reset and offered the dungeon option in the morning DM. Per spec they should be "off in the Co-op" and unable to also solo-grind dungeons. Fix at the DB layer (so all CanDoCombat() paths agree): - New helper lockCoopCombatActions() sets combat_actions_used=99 for any user in an active coop run. Called immediately after every resetAllAdvDailyActions() — at startup and at midnight. - Render layer: morning DM now shows "combat locked (in Co-op #N, day X/Y)" and replaces the dungeon section with an explanatory line pointing them at !coop status. Combat returns to normal automatically once the run completes/wipes — the next midnight reset finds status != 'active' and skips the lock. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -128,6 +128,9 @@ func (p *AdventurePlugin) Init() error {
|
||||
if err := resetAllAdvDailyActions(); err != nil {
|
||||
slog.Error("adventure: startup daily reset failed", "err", err)
|
||||
}
|
||||
if err := lockCoopCombatActions(); err != nil {
|
||||
slog.Error("adventure: startup coop combat lock failed", "err", err)
|
||||
}
|
||||
// Revive any characters whose DeadUntil has expired
|
||||
p.catchUpRespawns(chars)
|
||||
|
||||
|
||||
@@ -283,11 +283,26 @@ func renderAdvMorningDM(char *AdventureCharacter, equip map[EquipmentSlot]*AdvEq
|
||||
harvestMax++
|
||||
}
|
||||
combatLeft := combatMax - char.CombatActionsUsed
|
||||
if combatLeft < 0 {
|
||||
combatLeft = 0
|
||||
}
|
||||
harvestLeft := harvestMax - char.HarvestActionsUsed
|
||||
sb.WriteString(fmt.Sprintf("📋 **Actions:** %d/%d combat · %d/%d harvest\n\n", combatLeft, combatMax, harvestLeft, harvestMax))
|
||||
|
||||
// Co-op participants have combat locked for the duration of the run.
|
||||
coopRun, _ := loadCoopRunForUser(char.UserID)
|
||||
inCoop := coopRun != nil && coopRun.Status == "active"
|
||||
|
||||
if inCoop {
|
||||
sb.WriteString(fmt.Sprintf("📋 **Actions:** combat locked (in Co-op #%d, day %d/%d) · %d/%d harvest\n\n",
|
||||
coopRun.ID, coopRun.CurrentDay, coopRun.TotalDays, harvestLeft, harvestMax))
|
||||
} else {
|
||||
sb.WriteString(fmt.Sprintf("📋 **Actions:** %d/%d combat · %d/%d harvest\n\n", combatLeft, combatMax, harvestLeft, harvestMax))
|
||||
}
|
||||
|
||||
// Location choices
|
||||
if char.CanDoCombat(isHol) {
|
||||
if inCoop {
|
||||
sb.WriteString(fmt.Sprintf("**1️⃣ Dungeon:** _(off in the Co-op, no solo combat — `!coop status` for run state)_\n"))
|
||||
} else if char.CanDoCombat(isHol) {
|
||||
sb.WriteString("**1️⃣ Dungeon:**\n")
|
||||
for _, el := range advEligibleLocations(char, equip, AdvActivityDungeon, bonuses) {
|
||||
warn := ""
|
||||
|
||||
@@ -422,6 +422,13 @@ func (p *AdventurePlugin) midnightReset() error {
|
||||
slog.Warn("adventure: daily action reset failed, retrying", "attempt", attempt+1, "err", resetErr)
|
||||
time.Sleep(time.Duration(attempt+1) * 2 * time.Second)
|
||||
}
|
||||
if resetErr == nil {
|
||||
// Re-lock combat for active co-op participants after the universal
|
||||
// reset would otherwise have given them a fresh combat action.
|
||||
if err := lockCoopCombatActions(); err != nil {
|
||||
slog.Error("adventure: post-reset coop combat lock failed", "err", err)
|
||||
}
|
||||
}
|
||||
if resetErr != nil {
|
||||
return fmt.Errorf("reset daily actions after 3 attempts: %w", resetErr)
|
||||
}
|
||||
|
||||
@@ -172,6 +172,23 @@ func completeCoopRun(runID int, status string, reward int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// lockCoopCombatActions sets combat_actions_used to a value that exceeds the
|
||||
// holiday cap on every active co-op participant. Called after the midnight
|
||||
// reset (which would otherwise zero them) and at bot startup. Combat stays
|
||||
// locked for the full duration of the run — players in a co-op cannot also
|
||||
// solo-grind dungeons or arena.
|
||||
func lockCoopCombatActions() error {
|
||||
d := db.Get()
|
||||
_, err := d.Exec(`UPDATE adventure_characters
|
||||
SET combat_actions_used = 99
|
||||
WHERE user_id IN (
|
||||
SELECT m.user_id FROM coop_dungeon_members m
|
||||
JOIN coop_dungeon_runs r ON r.id = m.run_id
|
||||
WHERE r.status = 'active'
|
||||
)`)
|
||||
return err
|
||||
}
|
||||
|
||||
func setCoopRunInvitePostID(runID int, postID id.EventID) error {
|
||||
d := db.Get()
|
||||
_, err := d.Exec(`UPDATE coop_dungeon_runs SET invite_post_id = ? WHERE id = ?`, string(postID), runID)
|
||||
|
||||
Reference in New Issue
Block a user