# Legacy Scenario System This document explains how scenarios are loaded and how they define the active rule set, commands, and effects. Core references include `legacy/hwe/sammo/Scenario.php`, `legacy/hwe/sammo/ResetHelper.php`, and `legacy/hwe/sammo/GameConstBase.php`. ## Scenario Loading Flow 1. Server reset/init calls `ResetHelper::buildScenario()`. 2. `Scenario` loads `scenario_{id}.json` and merges defaults (`default.json`). 3. `Scenario::buildConf()` generates runtime constants: - `d_setting/GameConst.php` from `GameConstBase + scenario.const/map/stat` - `d_setting/CityConst.php` from `scenario/map/{mapName}.php` - `d_setting/GameUnitConst.php` from `scenario/unit/{unitSet}.php` 4. `Scenario::build()` inserts nations, generals, and events into DB and runs `initialEvents` immediately. `Scenario::getAllScenarios()` is used for listing scenarios without fully building them (lazy init). ## Scenario JSON Structure (Observed) Common top-level keys (see `legacy/hwe/scenario/frame.json` and actual `scenario_*.json` files): - `title`, `startYear`, `history`, `iconPath` - `stat`: default stat totals and bounds - `map`: `mapName`, `unitSet`, `scenarioEffect` - `const`: overrides for `GameConst` (commands, items, limits, etc.) - `nation`, `diplomacy` - `general`, `general_ex`, `general_neutral` - `events`, `initialEvents` - `ignoreDefaultEvents` (skip `GameConst::$defaultInitialEvents/$defaultEvents`) Notes: - A few files still use `initialActions` or `defaultInitialEvents` keys. The engine currently reads `initialEvents` only. - `general` rows use the tuple format from `Scenario::generateGeneral()`: `affinity, name, picture, nationName, city, leadership, strength, intel, officerLevel, birth, death, ego, char, text`. ## General Icon Paths Scenario general rows store an explicit path relative to `/image/icons`. New shared portraits use `장수/.`; scenario-specific portraits keep their existing directory such as `걸그룹/` or `롤시나리오/`. This makes active and delayed generals persist the same path without requiring the legacy image service's runtime `list.json` lookup. `resources/general-icons.json` records the canonical general name, current path, retained numeric legacy aliases, and source image. The numeric files in the image repository remain compatibility aliases for deployed legacy versions. Run the following from a core2026 checkout whenever scenarios or portrait assets change: ```sh pnpm manage:general-icons --image-root /path/to/image --write pnpm manage:general-icons --image-root /path/to/image ``` The first command synchronizes canonical aliases and scenario paths. The second is a read-only drift and file-content check. Missing source images stay listed under the catalog's `unresolved` field and resolve to `default.jpg` when they were an explicit numeric reference. ## How Scenario Chooses Commands and Effects Scenario config influences runtime rules via `GameConst` and `ScenarioEffect`: - `const.availableGeneralCommand` / `const.availableChiefCommand` define the commands that appear in UI and can be executed. - `const.availableSpecialDomestic/War`, `const.availablePersonality`, `const.allItems`, `const.availableNationType` control selectable traits/items. - `map.scenarioEffect` or `const.scenarioEffect` sets `GameConst::$scenarioEffect`, which is injected into each `General` as an `iAction` (`General::getActionList()`). - `const.availableInstantAction` merges into `GameConst::$availableInstantAction`. Because `GameConst` is generated from scenario data, a scenario can swap available commands or replace the action pool entirely. ## Command Prefix Conventions Prefixes are used to separate rule packs and assets: - `che_`: default rule set (base commands, specials, items, nation types). - `cr_`: alternate rule set used by specific scenarios (e.g. `scenario_910`). - `event_`: scenario-specific extensions (research, extra unit sets, or special effects). Example: `scenario_910.json` uses `mapName=cr` and `unitSet=cr` and overrides `availableGeneralCommand/availableChiefCommand` to include `cr_건국`, `cr_맹훈련`, and `cr_인구이동` alongside `che_` commands. ## Scenario Environment Variants (Current Repo) These are the map/unit/effect variants referenced by existing scenario files. Defaults are `mapName=che` and `unitSet=che` when not specified. Map sets (`scenario/map/*.php`): - `che` (default) - `miniche`, `miniche_b`, `miniche_clean` - `cr` - `chess` - `pokemon_v1` - `ludo_rathowm` Unit sets (`scenario/unit/*.php`): - `che` (default) - `che_except_siege` - `cr` - `basic` - `siegetank` - `event_more_crewtype` - `ludo_rathowm` Scenario effects (`sammo/ActionScenarioEffect/*`): - `event_StrongAttacker` - `event_UnlimitedDefenceThresholdChange` - `event_MoreEffect` ## Event Targets Scenario events are stored in the `event` table and executed via `TurnExecutionHelper::runEventHandler()` using `EventTarget` values: `PRE_MONTH`, `MONTH`, `OCCUPY_CITY`, `DESTROY_NATION`, `UNITED`. Most scenario JSON uses lowercase targets (e.g. `"month"`). The DB enum uses uppercase values but is case-insensitive, so lowercase targets still match.