Active expeditions now tick on a 3-hour cadence between the 06:00
briefing and 21:00 recap. Each fire DMs the player a short TwinBee
moment — mostly pure flavor (dripping sounds, polite possums,
diplomatic moths) with a 50/50 chance of a small mechanical nudge
(±SU, +threat, 1d4 coins from a found purse, +1 HP if camped).
The dungeon is now louder while you're offline without being
balance-relevant. Multi-day expeditions feel populated by something
other than the player's calendar.
Mechanics:
- new last_ambient_at column with CAS idempotency (mirrors
briefing/recap pattern in dnd_expedition_cycle.go)
- ambientCooldown=3h, skipped if in turn-based combat session
- 60min politeness window around scheduled briefing/recap so we
don't pile DMs on the daily messages
- weighted event pool with per-event eligibility (camp_visitor
requires camped, pack_rat requires SU>=1, faction_whisper
requires threat>=30 and not siege)
- effects: applyThreatDelta, updateSupplies, euro.Credit +
coins_earned bump, SaveDnDCharacter HP nudge (clipped at max)
Files:
- internal/db/db.go: ALTER TABLE + CREATE TABLE update
- internal/flavor/twinbee_ambient_flavor.go: 7 humor-heavy pools
- internal/plugin/expedition_ambient.go: ticker + resolver
- internal/plugin/expedition_ambient_test.go: 8 pure-logic tests
- internal/plugin/adventure.go: wire goroutine in Start()