5.0 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
eventtable rows by target and priority, evaluates conditions, and runs actions.
- Loads
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 keytarget: enum ofPRE_MONTH,MONTH,OCCUPY_CITY,DESTROY_NATION,UNITEDpriority: 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:
- Query
eventrows withtarget = {PRE_MONTH|MONTH|OCCUPY_CITY|DESTROY_NATION|UNITED}(ordered bypriority DESC, id ASC). - Decode
conditionandactionJSON. - Build a
Event\EventHandlerwith condition + action lists. - Execute
tryRunEvent($env)where$envisgame_envKV storage pluscurrentEventID.
Events are used inside the monthly pipeline and in special moments like
city occupation (EventTarget::OCCUPY_CITY, called by some commands).
Rewrite runtime status
app/game-engine/src/turn/monthlyEventHandler.ts now dispatches persisted
event rows for pre_month and month. It preserves the legacy
priority DESC, id ASC order, evaluates Date, DateRelative, RemainNation,
and the boolean logic operators, and records DeleteEvent through the normal
turn dirty-state transaction.
The calendar calls pre_month before changing the world date and month
after changing it. Action names are resolved through an explicit registry.
An unported action stops the turn with its action name and event id instead of
being silently ignored. The runtime registry currently covers
ProcessIncome, NoticeToHistoryLog, NewYear, and ResetOfficerLock;
the remaining legacy action catalog must be migrated before full event-action
parity can be claimed.
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) viaEvent\Condition\Logic. - Built-in condition types include:
Date,DateRelative,IntervalRemainNationConstBool
- Conditions return
{ value, chain }for tracing.
- Supports logic combinators (
-
Action
- Actions are classes under
Event/Action/withrun(array $env). - The dispatcher instantiates them from
actionarrays like['ProcessIncome', 'gold'].
- Actions are classes under
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 fromGameConst::$staticEventHandlers[$eventType].- Handlers live under
legacy/hwe/sammo/StaticEvent/and implementBaseStaticEvent::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\\JoinTroop→event_부대탑승즉시이동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\Engineis 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.