Files
healer-man/docs/ROM_NATIVE_ENEMY_DAMAGE_SOURCE_2026-10-03.md
T
2026-10-04 13:13:35 -04:00

35 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Native RuneWaker enemy direct damage — 2026-10-03
## Scope and runtime contract
`src/game/romNativeEnemyDamage.ts` resolves a direct enemy packet only from an exact imported `(NPC ID, source skill ID, component ID)` binding in `romNativeCombatData.generated.json`. `scripts/runewaker-pipeline/export-rom-native-combat-data.mjs` owns that generated binding data. The helper keeps the three source meanings independent: `MagicCollect.EffectType` selects the hit gate, `MagicObject.Attack.CalType` selects this formula, `MagicObject.EffectType` selects the CalType 8 absorber, and `MagicObject.MagicType` remains the native resistance channel. A formula packet reports `sourceHitEffectType`, `componentEffectType`, and `magicType` separately.
The helper implements negative direct-HP CalType 4 (fixed points) and CalType 8 (recipient MaxHP percentage) rows when all source inputs are present. It returns `unsupported` for positive/healing rows, unsupported component shapes, missing exact bindings, missing MaxHP, missing fixed-attribute values, unverified target absorption, or missing non-target AoE rates. It never guesses an NPC from a skill name. The source catalog has 440 NPC rows and currently contains 22 direct CalType 4 components, 11 direct CalType 8 components, and zero direct CalType 2 NPC-bound components. Day of Rain's CalType 2 skill 491183/component 501278 is catalogued, but this snapshot does not attach it to an imported NPC; the helper rejects that unbound pair.
For CalType 4, source power is `DmgPower * (1 + DmgPower_SkillLVArg * MagicLv / 100)`, plus `FixValue * GetValue(FixType) * (1 + MagicLv * FixDmg_SkillLVArg / 100)`. A nonzero fixed term with a nonzero FixType needs an explicit source attribute value. The known None FixType contributes 1. Negative power goes through target `CalMagicDMG` unless `IgnoreMagicAbsorb` is set. A non-target cast then applies source `AEMagicPowerRate * AEMagicDefRate`. The source share factor is multiplied into the absorbed/AoE-adjusted power before integer damage; unshared recipient ordinal attenuation modifies the base-power term before fixed power and target absorption.
For CalType 8, the target's current native MaxHP multiplies the source percentage before absorption. With absorption enabled, CalWeaponDMG or CalMagicDMG is evaluated against that HP-scaled value first and divided by 100 afterward, matching the source expression's order and truncation. Raw MagicObject `EffectType` 1 selects weapon absorption; 0 selects magic absorption. `IgnoreMagicAbsorb` and `FixDotPower` bypass that absorption. Non-target magical rows apply the AoE magic power/defense rates in the ordinary CalMagicDMG branch; `FixDotPower` takes the source's early raw-MaxHP branch and skips those rates. The share factor is applied after integer damage; unshared recipient ordinal attenuation modifies the source percentage before target MaxHP and absorption.
The supported direct point formulas set `resolverDamageChannel: "none"` and mark applicable source power stages as resolved or not applicable. The shared native resolver therefore retains only the independent collect hit gate and does not reapply level damage rate, typed power/resistance, generic DEF/MDEF, criticals, block, or parry. Ordinary damage auras and shields remain later simulator stages. Target source `AB/Abr/MAbr` is a separate formula input: `romNativeTrainingEnemyAbsorbInputs` supplies the verified canonical training profile's neutral values only when gear matches and the caller explicitly confirms no native absorb-channel aura is active. Custom gear or unverified auras fail closed.
The helper explicitly skips `nativeDamageBudgetScale` for exact source formulas because their source points or target-HP percentage already determine the native magnitude. Imported `mob.damageMultiplier` still applies after the formula. Authored encounter health and the simulator's health curve remain independent of native damage calculation.
CalType 2 Throw remains explicitly unsupported by the runtime helper. Its source path uses `Fin.Throw_DMG`, then `CalPhyDamage` applies NPC damage rate, `Global::DLvRate`, and typed resistance before the source combat table; target `CalWeaponDMG` and share damage happen after critical/block/parry. The current runtime has no completion hook at that exact post-table stage, so the helper returns `native-enemy-throw-post-table-absorption-runtime-unwired` instead of a partial amount. This source catalog has zero direct CalType 2 NPC-bound components; Day of Rain (491183/501278) has no exact imported NPC association and is never inferred.
## Source evidence
- `SourceCodeVS2019/Server/NetGameServer/MainProc/MagicProc/MagicProcess.cpp`, `Magic00_AddHP` around lines 2286–2980: direct `AtkCalType` dispatch, fixed/percentage formulas, recipient iteration, share/ordinal behavior, and final integer damage.
- `MagicProcess.cpp` around lines 2532–2610: CalType 4 `OrgPower`, `AddFixPower`, target CalMagicDMG, AoE rates, and share factor.
- `MagicProcess.cpp` around lines 2751–2840: CalType 8 recipient MaxHP calculation, raw component EffectType selection, FixDot/IgnoreMagicAbsorb bypass, AoE rates, and final integer damage.
- `MagicProcess.cpp` around lines 2477–2515: CalType 2 uses `Fin.Throw_DMG`; `CalPhyDamage` around lines 3366–3398 adds its fixed term, applies NPC damage rate, `Global::DLvRate`, and typed resistance. Its target weapon absorption occurs after block/parry/critical handling around lines 3478–3560.
- `SourceCodeVS2019/Libraries/Union/RoleData/RoleAttr.cpp` around lines 178–209: `Init_BaseEQValue` zeroes `Body` and initializes all `BodyRate` entries to 1. `CalWeaponDMG` and `CalMagicDMG` around lines 941–958 define the flat/rate absorption and minimum one-point damage behavior.
- `SourceCodeVS2019/Server/NetGameServer/MainProc/Global.cpp` around lines 8928–8964 defines the recursive source level-difference rate table, including its NPC lower-bound behavior.
- `src/game/generated/romNativeDamageTrainingProfiles.generated.json` is owned by the native training profile exporter. Its 999 selected training items and affixes have resolved source channels; no selected profile supplies AB/Abr/MAbr/AEMagicDefRate. NPC accepted WearEQ types are separately fail-closed when an unhandled nonzero ability appears, so the supported NPC subset has neutral `AEMagicPowerRate` from source BodyRate initialization plus its resolved equipment projection.
- `src/game/generated/enemyDamageTypeSources.generated.json` is owned by `scripts/dungeon-pipeline/export-enemy-damage-types.mjs`; the compact classifier now exports formula names and absorber policy independently of packet class, raw effect type, and MagicType.
## Verification and limits
`src/game/romNativeEnemyDamage.test.ts` covers exact Barren Axe Throw CalType 4 (NPC 101255, skill 492857/component 503019), Snow's Dance CalType 8 (NPC 101535, skill 492438/component 501098), target absorption, target order, AoE source rates, missing inputs, unbound Day of Rain, and canonical/custom training gear gates. Hall of Survivors NPC 102476/skill 493985/component 503044 is the only current non-target, magical-absorb CalType 4 direct NPC row, but its NPC equipment snapshot is unsupported; its AoE arithmetic is unit-tested with explicit source/target BodyRates, while live runtime correctly stays on the fallback. `src/game/mobDamageTypes.test.ts` verifies exported formula metadata and keeps hit-gate, absorber and resistance fields distinct. `src/game/romNativeEnemyDamage.integration.test.ts` covers the actual Treasure Trove packets against canonical active-five player/companion targets at levels 30 and 80.
CalType 2 target absorption remains pending after the shared combat table and is not integrated for current imported encounters because there are no exact NPC bindings. Non-target magical source packets require a verified source AoE-power multiplier; active source auras that may change that channel must remain fail-closed until represented. CalType 4 fixed types outside None require a caller-provided source attribute. The fixed and MaxHP branches intentionally do not claim support for buffs, healing, periodic damage, MP damage, extra PvP-only behavior, or source shapes beyond their direct HP branch.