Module fight

Source
Expand description

Deterministic, bounded fight simulation engine.

Combat owns its scheduling: delayed combat events and the FightProgress heartbeat live in the FightClock inside OverlordLogic, not in the System delayed/cron plugins. The live game loop drains the clock through OverlordLogic::collect_due_scheduled; this engine drains the same clock directly. Both paths therefore run identical combat machinery — the only difference is the driver.

Engine properties:

  • FightEngine::run executes at most max_game_ticks steps and always returns — there is no wall-clock timeout and no way to loop forever. A fight that doesn’t finish within the budget is FightResult::Undecided.
  • No DB, no async, no System, no PureEventHandler: callers are PvP precalculation, balance simulations, and tests.
  • EndFight is the fight boundary: the outcome is taken from the event and it is not processed, so progression side effects (rating, vassals, chapter advance) never run inside a simulation.

Structs§

BreakdownAccumulator
Per-fight totals, keyed by the fight INSTANCE so a delayed event that outlives its fight cannot land in the next one.
BreakdownActor
Who a recorded amount is credited to. Resolved at record time, because the entity may be dead and gone from active_fight.entities by fight end.
EntityMetrics
Per-entity summary line.
FightClock
FightEngine
Bounded, deterministic driver for fight simulations.
FightMetrics
The collector. One instance per FightSim.
FightMetricsSummary
Whole-fight structured summary. Serialize to JSON for the sim harness, or read the fields directly in tests.
FightOutcome
FightSim
A self-contained fight in progress. The scheduled work lives in the engine handler’s FightClock; the sim carries the simulated state and logical time.
TeamMetrics
Per-team aggregate.

Enums§

FightError
FightResult

Constants§

DEFAULT_CASCADE_MAX_DEPTH
Default cap on events processed within a single step’s cascade. The same wall the live System applies per root event — shared so the engine can never silently diverge from live combat on cascade depth.
DISPERSION_IDLE_SHARE_THRESHOLD_PCT
Dispersion criterion: no full 10 s window’s idle-in-contact share may exceed this percentage.
GAME_TICK_TICKS
Ticker units per fight step. The system ticker counts milliseconds (TICKER_UNIT_DURATION_MS = 1), and the live game loop advances the ticker by 100 units per 100ms game tick — one step equals one game tick.
STUN_UNTIL_TICK_ATTR
Absolute tick deadline stamped by the EntityStun handler. The single source of the name — the handler reads it from here, so the observer can never drift from the mechanic it observes.