mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 00:32:40 +00:00
A player who stops tending their adventurer doesn't stop having one. After 24h with no action against Adventure, the character gets restless and leaves on an expedition by itself: the easiest zone its level band allows, the cheapest supplies it can afford, and whatever gear was already on the rack. Everything downstream of the start was already autonomous — the autopilot walks rooms, drives elite and boss fights on the turn engine, camps, harvests and picks forks. The only thing that ever needed a human was `!expedition start`, so that's all this adds: a 30m ticker plus a clock. It never buys or equips anything, and that is the whole mechanic: a neglected adventurer grinds half-starved runs on rusting gear and comes home taxed. The prodexercise killed an L4 mage four rooms in on its first run. The clock is a new column. Every existing timestamp is unusable: last_active_at is auto-bumped by saveAdvCharacter (the autopilot would refresh a bored character's own idle clock), loadAdvDailyActivity counts the autopilot's own expedition logs, and user_stats.updated_at is chat presence, not a game action. last_player_action_at is written only by markPlayerAction, from a real player action against Adventure — any interface, not just Matrix. Raid zones (raidContentWarning: the party-tuned T5 bosses with a 0% solo clear) are avoided while anything else is in band. At L13+ they're all that's left, and the adventurer goes in anyway and loses. That's intended. dnd_expedition.boredom + isBoredomDriven stop a run nobody asked for from shielding an absent player from the idle reaper or holding their streak. A manually-started expedition still holds it while the autopilot walks it. Robbie visits and pays silently for idle players — he was going to file a daily public bulletin about people who stopped playing weeks ago. Note for anyone touching the time-scanning queries here: modernc.org/sqlite rebuilds a time.Time from the column's declared type, and COALESCE()/MAX() erase it. playerIsIdle fails open, so a broken scan there declares the whole server idle. Both it and lastExpeditionByZone select declared columns and fold in Go, and the tests seed real rows so the scan actually executes.