Files
healer-man/docs/ROM_DRUID_SOURCE_FOLLOWUP_2026-10-02.md

9.8 KiB
Raw Permalink Blame History

RuneWaker Druid Source Follow-up

Updated 2026-10-02. This is a read-only continuation of the remaining-proc audit. It follows native collection conditions, callback dispatch, and the corresponding LearnMagic rows. It does not repeat the prior PlotName graph audit or substitute later CoA identities. No runtime files were changed and no tests were run.

Native dispatch findings

MagicCollectCondition stores a check function, component ID, and two arguments (../Runewaker/SourceCodeVS2019/Libraries/Union/RoleData/ObjectStruct.h:4389-4393). The source enum is Normal=0, FirstGroupHit=1, PrvGroupHit=2, Vampire=3, Vampire1=4 (ObjectStruct.h:4412-4418). In magiccollectobject.db, the mode int32 is at record +0x2C8: 499935 record 0x9C7304 has bytes 00 00 00 00; 499497 record 0x958D54 has 01 00 00 00; 499942 record 0x9C8F3C has 03 00 00 00. These offsets pin the mode independently of the condition rows. Check_Rand selects a surviving target when rand() % 100 < RandValue and skips deleted targets or targets already resolved in that group (../Runewaker/SourceCodeVS2019/Server/NetGameServer/MainProc/MagicProc/MagicProcess.cpp:4905-4918). The engine resets IsSpellOneMagic at each group, runs each condition in order, and dispatches its component after the check; group target transitions are handled in the same loop (MagicProcess.cpp:1390-1534). Therefore ordered 60/30 rows are not a combined-roll estimate.

MagicBase.CheckUseLua is called after the collection condition and before the component effect. The Lua guard only evaluates HIT targets; a false return removes that target from the pending effect list (MagicProcess.cpp:5496-5518). EndUseLua runs from effect handlers after the result is known. MagicCollect.CheckUseScript is a separate cast-use check (MagicProcess.cpp:187-212, 935-962). The targeted rows have no such collection script. The MagicCollect.LUAScript member is declared in ObjectStruct.h:4489-4497; no consumer for that field was found in the targeted NetGameServer source. The global Lua VM loader loads FDB or configured text scripts and calls Initialize; the split loader also loads C:\Runewaker\Resource\luascript (../Runewaker/SourceCodeVS2019/Server/NetGameServer/MainProc/Global.cpp:219-285, 301-325). Magic07_RunPlot dispatches a component's RunPlot.PlotName on HIT or CRITICAL (MagicProcess.cpp:4719-4743).

The raw event-trigger slots were checked on the linked Revival Slash components and the Inspiration child payloads. 623008 has OnAttack tuple [10,0,0] (rate with no trigger ID); its on-time, on-hit, timeout, rebound, and death IDs are zero. 623339 and 623340 likewise have no event IDs. The 499942 delay buffs are the exception: both carry OnBuffTimeOutMagicID=494344. Spring Flower's stack buffs carry a separate OnTimeMagicID expiry event, detailed below. BuffProc decrements the timer, applies periodic damage/healing ticks, then queues the timed magic at a matching remaining-time divisor before removing an expired buff (../Runewaker/SourceCodeVS2019/Libraries/Union/RoleData/RD_ValueCal.cxx:3456-3470, 3607-3622). Thus the numeric proc chances below come from collection Rand fields, not an inferred callback or plot-name convention.

Source-backed candidate rows

RuneWaker mechanic Exact local evidence Status for runtime work
Warrior/Druid Revival Slash 499496 / hidden child 499497 learnmagic.db has Warrior primary entry 128: 499496, level 60, key 546742, prerequisite 493528; general entry 28 is hidden 499497 with prerequisite 499496. Child 499497 is FirstGroupHit mode (raw record 0x958D54, mode field +0x2C8 = 1). Group 0 requires the original hostile target's hit to survive; misses/zero-value failures delete that target. Groups 1 and 2 retain the original target, with later hit types forced to HIT (MagicProcess.cpp:1425-1459, 1544-1558, 2932-2954). Group 2 is one Rand 25 -> 623008 check. Its plot calls Cl_JOB1_8_Heal_Decapitate, which self-casts 499883 at secondary-job Magic Power level; the separate CheckUseLua only guards against active 623340 or Recover 503797 (../Runewaker/Resource/luascript/02707.lua:43-58). Chance resolved: 25%, once on the surviving original target per cast. The hidden heal is not yet a complete runtime formula. Components 623339/623340 use HolyHeal base 30 and periodic base 15 (skill arguments 20/18); normal Recover 503796/503797 uses 40/20. Native HolyHeal also uses MND, MDMG, MPow, HealPowerRate, and HealPoint (MagicProcess.cpp:2636-2655). Do not scale ordinary Recover by 0.75. The current runtime has no targeted 499496/499497/499883 handler.
Druid/Scout Spring Flower Eulogy 494932 / active 499935 learnmagic.db Druid entry 71 is 499935, level 50, key 543156, prerequisite 494932; 02248.lua:164-166 maps Druid/Scout level 50 to key 543156. Its Normal group mode is 0 (raw record 0x9C7304, mode field +0x2C8). Group 0 is an ordered target-buff ladder: 623115 if target has 623115, otherwise 623115 if it has 623111, otherwise 623111 if it has 623109, otherwise 623109. Group 1 is Rand 30 -> 505742; 505742 binds lua_star_Skill_NatureBase(0, 1) in 01465.lua:145, granting one Nature Power. The similarly named Lua_Skill499935_main function in 02708.lua:125-143 is not bound to the inspected component. Proc chance and expiration effect resolved: 30% for +1 Nature Power on learned/cast 499935, plus a bound 1/3/5% maximum-HP end heal. The stack buffs have six-second duration (EffectTime_SkillLVArg=0) and one-second Dot cadence, with bases 15/25/35 and DotSkillLVArg 16; native tick scaling depends on MDMG, MND, HealPowerRate, HealPoint, MPow, and target healing absorption (RD_Normal.cxx:2423-2501). Each tier's OnTimeMagic is scheduled at interval six: 623109 -> collection 494952 -> component 505706 (FixPer HP 1); 623111 -> 494953 -> 505740 (FixPer HP 3); 623115 -> 494954 -> 505741 (FixPer HP 5). The final DoT tick and end heal occur when the six-second buff reaches zero. The below-50% Lua helper remains unbound. This is a source-backed candidate tied by LearnMagic prerequisite to 494932. The current generated player catalog has no 499935 row, so HealerMan has no invocation or runtime approximation for it yet.
Druid/Mage Inspiration Display 499941 / hidden 499942 learnmagic.db Druid entry 91 is 499942, level 70, key 546840, prerequisite 499941. Its Vampire group mode is 3 (raw record 0x9C8F3C, mode field +0x2C8); the later group target redirects to the owner after an earlier target survives. Group 2 is ordered Rand 60 -> 623123, then Rand 30 -> 504890. A successful first assist marks the target resolved and suppresses the fallback. 623123 is gated by lua_bico_dru_mag_es_70 checking Spiritual Gush buff 505163 (02708.lua:154-161); if that guard rejects the first effect, the second check can still run. Both one-second special buffs time out to collection 494344 (../Runewaker/SourceCodeVS2019/Libraries/Union/RoleData/RD_ValueCal.cxx:3042-3070), whose effect is component 504863: 10 seconds, modifier type 51 (SpellSpeed_AllMagic) at -1000 (ObjectStruct.h:1427-1478). The hidden row and its learned prerequisite are source-backed. This establishes the child’s ordered 60% gated effect / 30% fallback and timeout payload. It does not establish an automatic cast from public Inspiration 494322 or an automatic trigger from Spiritual Gush 494370; 505163 is only the 623123 gate. Model it, if selected, as the 499942 variant with this exact order and payload. The current generated player catalog has no 499942 row.

Remaining unresolved mechanics

  • Quick Light Protection 494924: its passive row has no component conditions; active Blind Spot 490311 has ordered SelfEqType checks but no Rand chance. The proc probability, heal amount, and recipient tie-break remain unknown.
  • Boiling Rock 494565: its passive has no component conditions; active Magma Blade 494564 has no Rand condition. The MP-restoration chance and amount remain unknown.
  • Avalanche 494029: its passive has no component conditions; Rockslide 493543 has no Rand condition. The local extra-damage and Nature Power proc payloads remain unbound.
  • Extended Recovery 494200: neither its passive row nor Recover 493528 exposes a Rand condition. The existing runtime approximation at src/game/romDruidOverrides.ts:162-163 adds six seconds; the separate Nature Power chance remains unknown.
  • Spring Flower Eulogy 494932: its passive row has no group condition. The sourced 499935 Rand30 clause above is usable as the learned child mechanic; other passive clauses still have no bound numeric chance in the inspected rows.

These checks cover the named parents, active rows, learned hidden children, and linked effect objects only. RuneWaker remains separate from the later CoA reworks recorded in the original audit.

Healing-input boundary

The RuneWaker stat enum identifies MND as stat type 5 (ObjectStruct.h:1427-1434), and the HealerMan exporter maps source stat type 5 to wisdom (scripts/runewaker-pipeline/export-rom-heirloom-reference.mjs:23-27); src/game/romStats.ts:17-37 exposes that base value. This is a verified base-stat alias, but the targeted RoM combat path does not provide the final effective MND value consumed by the heal formulas. The direct HolyHeal formula also needs native MDMG, the cast's Magic Power level, MPow, HealPowerRate, HealPoint, and target HealAbsorbRate/HealAbsorb (MagicProcess.cpp:2640-2674). Periodic heal scaling uses the analogous caster values and target heal absorption through CalAddDotMagicLv (../Runewaker/SourceCodeVS2019/Libraries/Union/RoleData/RD_Normal.cxx:2423-2501). No verified RoM-runtime aliases were established here for those final values. Keep the Revival Slash heal and Spring Flower periodic tick amounts blocked until those mappings exist; the Spring Flower expiry percentages are separately source-defined.