112 lines
5.9 KiB
Markdown
112 lines
5.9 KiB
Markdown
# RoM native Priest healing source adapter
|
|
|
|
This is a local RuneWaker source implementation for native RoM healing. It is
|
|
not a Chronicles of Arcadia formula, and it does not infer a spell rank from a
|
|
source catalog value. `MagicProc.MagicLv` is a required runtime input. The
|
|
simulator may explicitly map its trained skill level to
|
|
`clamp(characterLevel, 1, 80)`; that is simulator policy, not a claim about the
|
|
source database's configured `MagicLV` field.
|
|
|
|
## Direct HolyHeal
|
|
|
|
`romNativeHealing.ts` resolves the `MagicProcess.cpp` `AtkCalType::HolyHeal`
|
|
branch. The source equation is:
|
|
|
|
```text
|
|
OrgPower = DmgPower + DmgPower * DmgPower_SkillLVArg * MagicLv / 100
|
|
SpellTime = MagicCol.SpellTime; use 1 when below 1 or IsFixDmgEffect is true
|
|
MNDPart = MND * 0.3 * SpellTime
|
|
Power = OrgPower * 6 when OrgPower * 5 < MNDPart; otherwise OrgPower + MNDPart
|
|
unless IsIgnoreDmgEffect:
|
|
add MDMG * FIX.Dmg_HealArg, once when fixed or multiplied by SpellTime otherwise
|
|
Power = Power * MPow * HealPowerRate + HealPoint * SpellTime
|
|
per target, apply Atk.Rand variation
|
|
unless MagicBase.SettingEx.IgnoreMagicAbsorb:
|
|
Power = Power * (1 + HealAbsorbRate / 100) + HealAbsorb
|
|
clamp Power below zero; reverse sign for undead; suppress negative undead output out of combat
|
|
```
|
|
|
|
The generated source map binds ability and rank identity to raw `MagicCollect`
|
|
rows and direct HP `MagicObject` components. It preserves source component IDs,
|
|
`AtkCalType`, signed `DmgPower`, its skill-level argument, fixed fields,
|
|
random range, critical rate, `SpellTime`, range/sharing data, and the distinct
|
|
`MagicCollect` timing flags and mode flags. `holyHealBindings` is the 18-row
|
|
subset with `AtkCalType == 5`; `attackBindings` retains all 225 direct HP
|
|
ability rows for shared combat integrations.
|
|
|
|
The Priest bindings include Heal (`490261`, `DmgPower 90`, argument `30`,
|
|
`SpellTime 2`), Group Heal (`490281`, `DmgPower 65`, argument `20`,
|
|
`SpellTime 3`), and Urgent Heal (`491147`, `DmgPower 35`, argument `20`,
|
|
`SpellTime 1`). Their exact component and rank records are in the generated
|
|
metadata. The helper expects already-effective native caster and recipient
|
|
channels; callers must not run generic healing modifiers a second time when
|
|
those modifiers were included in the effective inputs.
|
|
|
|
## Periodic HP healing
|
|
|
|
Runewaker has a separate native HoT path. It is not a HolyHeal cast repeated
|
|
each tick. `MagicProcess.cpp` computes the applied buff duration and invokes
|
|
`CalAddDotMagicLv`; `RD_Normal.cxx` calculates the buff's source rank
|
|
correction; `RD_ValueCal.cxx::BuffProc` uses the frozen `Buff.Power` at each
|
|
tick. The helper supports active positive magical `DotMagic` with HP type 0,
|
|
including Priest's Regenerate (`490269`). It deliberately returns no result
|
|
for unsupported `DotMagic` types, including percentage HP type 5.
|
|
|
|
At application, the source first derives actual buff duration from
|
|
`EffectTime`, `EffectTime_SkillLVArg`, `DLV_EffectTime`, and owner/target
|
|
levels, then uses `DotTimes = max(1, int(EffectTime / Dot.Time))`. For a
|
|
positive magic HP dot, the source calculates:
|
|
|
|
```text
|
|
DotBase = Dot.Base * (1 + MagicLv * DotSkillLVArg / 100)
|
|
ExRate = 0.6 + abs(DotBase) / 600 for an IsPlayer owner; otherwise 1
|
|
Power = DotBase + ExRate * MDMG * int(SpellTime) * FIX.Dmg_HealDotArg / DotTimes
|
|
MNDPart = MND * 0.3 * int(SpellTime) / DotTimes
|
|
Power = Power * 6 when Power * 5 < MNDPart; otherwise Power + MNDPart
|
|
Power = Power * HealPowerRate + HealPoint * int(SpellTime) / DotTimes
|
|
unless IgnoreMagicAbsorb:
|
|
Power = Power * (1 + HealAbsorbRate / 100) + HealAbsorb / DotTimes
|
|
clamp Power below zero; Power *= MagicPow(MagicType)
|
|
MagicLvAdjustment = int((Power - Dot.Base) / (Dot.Base * DotSkillLVArg / 100) - MagicLv)
|
|
Buff.Power = MagicLvAdjustment + MagicLv
|
|
```
|
|
|
|
`FixDotPower` or a zero `DotSkillLVArg` bypasses the rank correction, leaving
|
|
`Buff.Power = MagicLv`. The source tick then computes
|
|
`Damage = int(-Dot.Base * (100 + DotSkillLVArg * Buff.Power) / 100)` and applies
|
|
`AddHP(-Damage)`. C++ integer conversion truncates toward zero. Recipient
|
|
absorb and caster channels are captured through the buff-rank correction at
|
|
application; the source does not reapply them on each tick. The helper returns
|
|
the resulting integer tick amount and the `DotTimes` interval count so the
|
|
runtime can preserve that application snapshot.
|
|
|
|
The live helper requires an explicit effective
|
|
`MagicPow(MagicType)` value. The existing native stat sidecar has an all-magic
|
|
neutral MPow channel but does not expose all six element-specific MPow
|
|
`BodyRate` channels. The caller must supply an effective source value when
|
|
element-specific modifiers are modeled. For this simulator's active
|
|
player-build identities, `sourceIsPlayer=true` is an explicit policy applied
|
|
to both the active player and party companions; the original `IsPlayer()` test
|
|
itself distinguishes actual server player roles.
|
|
|
|
The current Priest Regenerate source row contains positive HP DotMagic
|
|
components `500469` (argument 18), `621318` (argument 18), and `621548`
|
|
(argument 25). They share `Dot.Time 2`, `Dot.Base 20`, and duration 20 seconds.
|
|
The generated map retains each component ID so the runtime can use the
|
|
component selected by its own source semantics instead of guessing which raw
|
|
component is active.
|
|
|
|
## Source snapshot and limits
|
|
|
|
The generated artifact is
|
|
`src/game/generated/romNativeHolyHealBindings.generated.json`; regenerate it
|
|
with `scripts/runewaker-pipeline/export-rom-native-healing.mjs`. It is tied to
|
|
the current hashes of `magiccollectobject.db`, `magicobject.db`, the local
|
|
server formula files, the player catalog, and generated native stat rules.
|
|
The output includes 225 direct-attack ability rows, 18 HolyHeal ability rows,
|
|
and 8 positive magical HP DotMagic ability rows across the catalog.
|
|
|
|
The data and formula boundary is the local RuneWaker source version hashed in
|
|
that artifact. This work does not add CoA rank data, model percentage HP
|
|
periodics, or infer unavailable source skill levels from `configuredCollectMagicLevel`.
|