문서 추가: 레거시 트리거 시스템 설명 및 관련 정보
This commit is contained in:
@@ -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`
|
||||
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user