7.7 KiB
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():
- Nation type
- Officer level
- Domestic special
- War special
- Personality
- Crew type (
GameUnitDetail) - Inheritance buff (
TriggerInheritBuff) - Scenario effect
- 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
initSkillTriggerandphaseSkillTriggerarrays defined in scenario data (buildWarUnitTriggerClass). - They can include an
iActionList(crew-type-specific actions) which themselves implementiAction.
ObjectTrigger and TriggerCaller
Triggers are small, prioritized actions:
ObjectTriggerdefines priorities and a singleaction()method.TriggerCallergroups triggers by priority, merges lists, andfire()s them in priority order.
Priority constants (lower runs earlier):
PRIORITY_BEGIN= 10000PRIORITY_PRE= 20000PRIORITY_BODY= 30000PRIORITY_POST= 40000PRIORITY_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:
GeneralTriggerCalleracceptsBaseGeneralTrigger.WarUnitTriggerCalleracceptsBaseWarUnitTrigger.
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:armTypeinche_징병).
Examples:
Command/General/che_징병.phpusescost,rice,train,atmos.Command/General/che_주민선정.phpusesscore,success,fail.GeneralTrigger/che_병력군량소모.phpuses징집인구:score.
onCalcStrategic
Used by nation commands to adjust delays/limits:
varTypeoftendelay,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 fromWarUnitGeneral). - Battle accuracy:
dex{armType}(e.g.,dex2). - Train/atmos:
bonusTrain,bonusAtmos. - Combat odds:
warCriticalRatio,warAvoidRatio. - War magic:
warMagicTrialProb,warMagicSuccessProb,warMagicSuccessDamage,warMagicFailDamage. - Damage range:
criticalDamageRange(inWarUnit::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:
General::getPreTurnExecuteTriggerList()merges triggers from all actions.- Base triggers are appended:
GeneralTrigger/che_부상경감(priority 10000 / BEGIN)GeneralTrigger/che_병력군량소모(priority 50000 / FINAL)
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:
WarUnit::beginPhase()clears activated skills and recomputes war power.General::getBattlePhaseSkillTriggerList()builds the trigger list.- Base triggers (always included):
che_필살시도,che_필살발동che_회피시도,che_회피발동che_계략시도,che_계략발동,che_계략실패
- Base triggers (always included):
- Attacker/defender trigger lists are merged and fired.
- 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, thenche_저격발동.php(POST) applies wounds and logs.WarUnitTrigger/che_계략시도.php(PRE) setsmagicand success/failure, thenche_계략발동.php/che_계략실패.php(POST) applies multipliers.WarUnitTrigger/che_필살시도.php→che_필살발동.phpadjusts 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
onCalcOpposeStatusing the opponent's action list after the general's ownonCalcStatadjustments. - 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 (
RandUtileverywhere in triggers).
Related Files
legacy/hwe/sammo/iAction.phplegacy/hwe/sammo/TriggerCaller.phplegacy/hwe/sammo/ObjectTrigger.phplegacy/hwe/sammo/General.phplegacy/hwe/sammo/WarUnit.phplegacy/hwe/process_war.php