Files
core2026/docs/architecture/legacy-engine-events.md
T

4.2 KiB

Legacy Event System

This document summarizes how the legacy event system executes scenario- and turn-based events, and how static event hooks are wired into commands. Primary references include legacy/hwe/sammo/TurnExecutionHelper.php, legacy/hwe/sammo/Event/*, and legacy/hwe/sammo/StaticEventHandler.php.

Entry Points

  • TurnExecutionHelper::runEventHandler(EventTarget $eventTarget)
    • Loads event table rows by target and priority, evaluates conditions, and runs actions.
  • StaticEventHandler::handleEvent(...)
    • Invoked by many commands and API handlers to run per-action static hooks.

Event Table Schema

event rows are stored in the legacy DB schema (legacy/hwe/sql/schema.sql):

  • id: auto-increment primary key
  • target: enum of PRE_MONTH, MONTH, OCCUPY_CITY, DESTROY_NATION, UNITED
  • priority: higher first (default 1000)
  • condition: JSON array (condition DSL)
  • action: JSON array (action DSL)

Indexes: (target, priority, id) for dispatch ordering. Both condition and action are JSON-validated by DB constraints.

Event Table Dispatch

runEventHandler() drives the dynamic event pipeline:

  1. Query event rows with target = {PRE_MONTH|MONTH|OCCUPY_CITY|DESTROY_NATION|UNITED} (ordered by priority DESC, id ASC).
  2. Decode condition and action JSON.
  3. Build a Event\EventHandler with condition + action lists.
  4. Execute tryRunEvent($env) where $env is game_env KV storage plus currentEventID.

Events are used inside the monthly pipeline and in special moments like city occupation (EventTarget::OCCUPY_CITY, called by some commands).

Condition and Action DSL

Event\Condition::build() and Event\Action::build() decode JSON arrays into class instances:

  • Condition

    • Supports logic combinators (and, or, xor, not) via Event\Condition\Logic.
    • Built-in condition types include:
      • Date, DateRelative, Interval
      • RemainNation
      • ConstBool
    • Conditions return { value, chain } for tracing.
  • Action

    • Actions are classes under Event/Action/ with run(array $env).
    • The dispatcher instantiates them from action arrays like ['ProcessIncome', 'gold'].

Common Event Actions (Examples)

These are the action modules observed in the legacy tree:

  • Economy & upkeep: ProcessIncome, ProcessSemiAnnual, ProcessWarIncome
  • World state: UpdateCitySupply, UpdateNationLevel, RandomizeCityTradeRate
  • NPC/Invader flow: RaiseInvader, RaiseNPCNation, ProvideNPCTroopLeader
  • Betting & unique items: OpenNationBetting, FinishNationBetting, LostUniqueItem, MergeInheritPointRank
  • Event lifecycle: DeleteEvent, NoticeToHistoryLog

All action execution uses the event environment (year, month, startyear, turnterm, etc.) coming from game_env.

Static Events (Command Hooks)

Static events are hooks triggered directly by commands/APIs:

  • StaticEventHandler::handleEvent() looks up handler names from GameConst::$staticEventHandlers[$eventType].
  • Handlers live under legacy/hwe/sammo/StaticEvent/ and implement BaseStaticEvent::run().
  • These hooks are used to extend command behavior without modifying the command code itself (e.g., troop join/exit side effects).

Static Handler Map Sources

GameConst::$staticEventHandlers defaults to an empty array in legacy/hwe/sammo/GameConstBase.php. Scenario JSON can override it:

  • legacy/hwe/scenario/scenario_911.json (only observed override in repo)
    • sammo\\API\\Troop\\JoinTroopevent_부대탑승즉시이동
    • sammo\\Command\\Nation\\che_발령event_부대발령즉시집합

Static handler names should map to classes in legacy/hwe/sammo/StaticEvent/ (class name matches handler key).

RNG Notes

Dynamic event actions can use deterministic RNG by constructing LiteHashDRBG with UniqueConst::$hiddenSeed and an event-specific tag. Examples include RandomizeCityTradeRate and UpdateNationLevel.

Open Questions / Follow-ups

  • Event\Engine is a stub with a TODO; it is not currently used in the main turn pipeline.
  • Verify whether any runtime code injects additional static handlers beyond scenario JSON overrides.