J3 D8-f #1: route prod autopilot boss/elite through the turn engine

Prod autopilot resolved boss/elite fights inline via SimulateCombat, which
swings the enemy once per round (Combatant has no ID to look up the SRD
multiattack profile). Manual !fight uses the turn engine, which loops the
full profile — so autopilot players faced strictly weaker bosses than
manual. D8-e confirmed this is the gap, not a turn-engine artifact.

- Promote the sim's autoResolveCombat/simPickCombatAction to shared plugin
  methods autoDriveCombat/pickAutoCombatAction (single source of truth; the
  sim now calls the same code prod does).
- Add MessageContext.Silent + a replyDM helper; the turn-engine combat
  handlers route their DMs through it so the background autopilot can drive
  the real !fight/!attack engine without spamming a DM per round (the EoD
  digest summarizes the outcome).
- tryAutoRun now calls runAutopilotWalkDriven (inlineBossCombat flipped
  true->false): walk->fight->walk loop so one tick still covers ~autoRunRoomCap
  rooms, but boss AND elite now face the player's full kit against the
  enemy's full multiattack. Loss surfaces as stopEnded (run already
  force-extracted by finishCombatSession).

Trash mobs stay on the fast inline path. GOGOBEE_SIM_INLINE_BOSS=1 A/B
toggle preserved. Build + plugin tests green; sim smoke-run unchanged.
This commit is contained in:
prosolis
2026-05-28 15:30:48 -07:00
parent b80de43db1
commit a46b773750
5 changed files with 192 additions and 81 deletions

View File

@@ -41,6 +41,13 @@ type MessageContext struct {
// routes DM commands to the player's game room). When set, sender-private
// replies should go here instead of the rewritten RoomID.
OriginRoomID id.RoomID
// Silent suppresses player-facing replies for handlers that honor it
// (currently the turn-engine combat commands via replyDM). Set by the
// background autopilot when it drives a boss/elite fight through the
// real !fight/!attack engine for manual parity (long-expedition D8-f) —
// the day digest summarizes the outcome, so the per-round narration is
// dropped rather than DM'd round-by-round.
Silent bool
}
// ReactionContext holds the context for a reaction event.