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

8.1 KiB
Raw Blame History

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.