From faa0fd3df3562e23213228fe2c834352bb578702 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Fri, 26 Dec 2025 19:28:01 +0000 Subject: [PATCH] =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80:=20?= =?UTF-8?q?=EB=A0=88=EA=B1=B0=EC=8B=9C=20=ED=8A=B8=EB=A6=AC=EA=B1=B0=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=84=A4=EB=AA=85=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=A0=95=EB=B3=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/architecture/legacy-engine-triggers.md | 210 ++++++++++++++++++++ docs/architecture/legacy-engine.md | 1 + 2 files changed, 211 insertions(+) create mode 100644 docs/architecture/legacy-engine-triggers.md diff --git a/docs/architecture/legacy-engine-triggers.md b/docs/architecture/legacy-engine-triggers.md new file mode 100644 index 0000000..2674029 --- /dev/null +++ b/docs/architecture/legacy-engine-triggers.md @@ -0,0 +1,210 @@ +# Legacy Trigger System (iAction + Trigger Callers) + +This document explains how the legacy Trigger system is built on `iAction` +and `TriggerCaller`, and how it affects both command outcomes and battle flow. +Primary references include `legacy/hwe/sammo/iAction.php`, +`legacy/hwe/sammo/TriggerCaller.php`, `legacy/hwe/sammo/General.php`, +`legacy/hwe/process_war.php`, and `legacy/hwe/sammo/WarUnit.php`. + +## Core Concepts + +### `iAction`: modifier hooks + trigger provider + +`iAction` is the unified interface for traits, specials, crew types, items, +scenario effects, and hidden buffs. It provides: + +- Modifier hooks (`onCalcDomestic`, `onCalcStat`, `onCalcOpposeStat`, + `onCalcStrategic`, `onCalcNationalIncome`, `getWarPowerMultiplier`). +- Trigger hooks (`getPreTurnExecuteTriggerList`, + `getBattleInitSkillTriggerList`, `getBattlePhaseSkillTriggerList`). +- Ad-hoc hooks (`onArbitraryAction`) for non-turn side effects. + +Action sources are merged into a single list in `General::getActionList()`: + +1. Nation type +2. Officer level +3. Domestic special +4. War special +5. Personality +6. Crew type (`GameUnitDetail`) +7. Inheritance buff (`TriggerInheritBuff`) +8. Scenario effect +9. Items + +The order above is the execution order for modifier hooks, and also the merge +order for trigger lists (later actions override duplicates with the same +unique trigger ID). + +Crew types (`GameUnitDetail`) are special: + +- They implement `iAction`. +- They expose `initSkillTrigger` and `phaseSkillTrigger` arrays defined in + scenario data (`buildWarUnitTriggerClass`). +- They can include an `iActionList` (crew-type-specific actions) which + themselves implement `iAction`. + +### `ObjectTrigger` and `TriggerCaller` + +Triggers are small, prioritized actions: + +- `ObjectTrigger` defines priorities and a single `action()` method. +- `TriggerCaller` groups triggers by priority, merges lists, and `fire()`s + them in priority order. + +Priority constants (lower runs earlier): + +- `PRIORITY_BEGIN` = 10000 +- `PRIORITY_PRE` = 20000 +- `PRIORITY_BODY` = 30000 +- `PRIORITY_POST` = 40000 +- `PRIORITY_FINAL` = 50000 + +`TriggerCaller` uses a unique ID (`priority + class + object id`) for dedup. +`BaseWarUnitTrigger` extends this with `raiseType` to separate item-based +triggers from trait-based ones. + +Specialized callers enforce type safety: + +- `GeneralTriggerCaller` accepts `BaseGeneralTrigger`. +- `WarUnitTriggerCaller` accepts `BaseWarUnitTrigger`. + +## Modifier Hooks (Command + Stat + War) + +### `onCalcDomestic` + +Used by general commands to adjust cost, success, failure, and score. Inputs: + +- `turnType`: command key (`징병`, `조달`, `주민선정`, `정착장려`, 등). +- `varType`: `cost`, `rice`, `train`, `atmos`, `success`, `fail`, `score`. +- `aux`: extra context (ex: `armType` in `che_징병`). + +Examples: + +- `Command/General/che_징병.php` uses `cost`, `rice`, `train`, `atmos`. +- `Command/General/che_주민선정.php` uses `score`, `success`, `fail`. +- `GeneralTrigger/che_병력군량소모.php` uses `징집인구:score`. + +### `onCalcStrategic` + +Used by nation commands to adjust delays/limits: + +- `varType` often `delay`, `globalDelay`, `strategic_cmd_limit`. +- Examples: `Command/Nation/che_급습.php`, `che_백성동원.php`, `che_수몰.php`. + +### `onCalcNationalIncome` + +Used by `Event/Action/ProcessSemiAnnual.php` to adjust population growth and +income ratios at the nation level. Nation types (e.g., 유가/법가/병가 계열)이 +여기에서 보정을 걸어준다. + +### `onCalcStat` / `onCalcOpposeStat` + +Used for base stats and battle-derived parameters. Common `statName` keys: + +- Base stats: `leadership`, `strength`, `intel` (General stat calc). +- Progression: `addDex`, `experience`, `dedication`. +- Battle timing: `initWarPhase` (phase count from `WarUnitGeneral`). +- Battle accuracy: `dex{armType}` (e.g., `dex2`). +- Train/atmos: `bonusTrain`, `bonusAtmos`. +- Combat odds: `warCriticalRatio`, `warAvoidRatio`. +- War magic: `warMagicTrialProb`, `warMagicSuccessProb`, + `warMagicSuccessDamage`, `warMagicFailDamage`. +- Damage range: `criticalDamageRange` (in `WarUnit::criticalDamage()`). +- Supply cost: `killRice` (war rice consumption). +- Battle order: `cityBattleOrder` (opponent modifies city order). + +`aux` carries context such as `isAttacker`, `opposeType`, or magic name +(`반목`, `화계`, etc.). + +## Pre-Turn General Triggers + +`TurnExecutionHelper::preprocessCommand()` runs pre-turn triggers: + +1. `General::getPreTurnExecuteTriggerList()` merges triggers from all actions. +2. Base triggers are appended: + - `GeneralTrigger/che_부상경감` (priority 10000 / BEGIN) + - `GeneralTrigger/che_병력군량소모` (priority 50000 / FINAL) +3. `TriggerCaller::fire()` executes them before the command runs. + +General triggers use `General::activateSkill()` for logging and gating. +`TurnExecutionHelper::processCommand()` clears activated skills after the +command completes. + +## Battle Triggers + +Battle triggers are fired in two stages inside `process_war.php`: + +### Battle-init triggers + +- Fired once per engagement when a defender is first set (`phase == 0`). +- Constructed via `General::getBattleInitSkillTriggerList()`. +- Used for start-of-battle setup (ex: `che_부상무효` from `견고`). + +### Phase triggers + +Every phase: + +1. `WarUnit::beginPhase()` clears activated skills and recomputes war power. +2. `General::getBattlePhaseSkillTriggerList()` builds the trigger list. + - Base triggers (always included): + - `che_필살시도`, `che_필살발동` + - `che_회피시도`, `che_회피발동` + - `che_계략시도`, `che_계략발동`, `che_계략실패` +3. Attacker/defender trigger lists are merged and fired. +4. Damage is calculated using `getWarPower()` (after trigger multipliers). + +### Attempt → Execute pattern (PRE/POST) + +Most battle skills split into two triggers: + +- **Attempt (PRE)**: check conditions, set flags or env payload. +- **Execute (POST)**: read env/flags and apply damage or status. + +Examples: + +- `WarUnitTrigger/che_저격시도.php` (PRE) sets `저격발동자`, wound ranges, + then `che_저격발동.php` (POST) applies wounds and logs. +- `WarUnitTrigger/che_계략시도.php` (PRE) sets `magic` and success/failure, + then `che_계략발동.php` / `che_계략실패.php` (POST) applies multipliers. +- `WarUnitTrigger/che_필살시도.php` → `che_필살발동.php` adjusts war power. + +### Battle env and stop flags + +`BaseWarUnitTrigger::action()` supplies a mutable env: + +- `e_attacker` / `e_defender`: per-side state map. +- `stopNextAction`: if true, later triggers are skipped. + +Triggers can return `false` from `actionWar()` to set `stopNextAction`. + +### Item-based triggers and consumption + +`BaseWarUnitTrigger` uses a `raiseType` bitmask to tag item-based triggers: + +- `TYPE_ITEM`: item-triggered, with `아이템사용` skill gating. +- `TYPE_CONSUMABLE_ITEM`: consumes and deletes the item. +- `TYPE_DEDUP_TYPE_BASE`: offset for dedup grouping. + +`processConsumableItem()` handles the consumption flow and logging. Item +triggers typically pass `raiseType` so the same skill can coexist with +non-item versions (see `ActionItem/che_저격_매화수전.php`). + +## Interaction Notes for Porting + +- Preserve `General::getActionList()` order; modifier hooks stack in sequence. +- Apply `onCalcOpposeStat` using the opponent's action list after the + general's own `onCalcStat` adjustments. +- Keep priority-based execution (`PRIORITY_*`) and the PRE/POST split. +- Replicate trigger dedup semantics (`getUniqueID` + `raiseType`). +- Maintain `beginPhase()` clearing of activated skills; battle triggers assume + per-phase activation. +- Ensure RNG usage stays deterministic (`RandUtil` everywhere in triggers). + +## Related Files + +- `legacy/hwe/sammo/iAction.php` +- `legacy/hwe/sammo/TriggerCaller.php` +- `legacy/hwe/sammo/ObjectTrigger.php` +- `legacy/hwe/sammo/General.php` +- `legacy/hwe/sammo/WarUnit.php` +- `legacy/hwe/process_war.php` diff --git a/docs/architecture/legacy-engine.md b/docs/architecture/legacy-engine.md index 0f60b44..6e2529e 100644 --- a/docs/architecture/legacy-engine.md +++ b/docs/architecture/legacy-engine.md @@ -39,6 +39,7 @@ organization rather than endpoint-first routing. - Turn execution pipeline: `docs/architecture/legacy-engine-execution.md` - General model and action stack: `docs/architecture/legacy-engine-general.md` +- Trigger system (iAction + trigger callers): `docs/architecture/legacy-engine-triggers.md` - Battle and war resolution: `docs/architecture/legacy-engine-war.md` - Command catalog: `docs/architecture/legacy-commands.md` - Scenario system and rule sets: `docs/architecture/legacy-scenarios.md`