# 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\\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\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.
