Files
healer-man/docs/STOCKADE_CHAIN_LIGHTNING_2026-10-05.md
2026-10-06 22:25:34 -04:00

5.8 KiB
Raw Permalink Blame History

Stockade Chain Lightning fan-out — 2026-10-05

Verified source contract

The Stockade attack is Hamhock (creature entry 1717), SmartAI row 0, spell 421. The imported row in src/game/generated/azerothCoreWorldAi.json casts spell 421 on target_type=2 (SMART_TARGET_VICTIM); the campaign import preserves it as target: "primary", range 30, nature school, and its existing 1.35 attack damage multiplier. Its cast timing remains the imported 1-second initial delay and 4–7-second repeat interval. No source row targets the whole party as the initial hit.

Both pinned Spell.dbc profiles were read directly and match their recorded SHA-256 values:

Profile SHA-256 Spell 421 effect 0 Total targets Chain damage multiplier
Ascension patch-D 2f77f18b91ffbae32a19568e4bc05ec78ee384b6ba8dd2a6e05f0e97abbb2dce SCHOOL_DAMAGE (effect 2), TARGET_UNIT_TARGET_ENEMY (target A 6), range index 4, nature school mask 8, magic damage class 1 EffectChainTarget[0] (field 104) = 3 EffectDamageMultiplier[0] (field 216) = 0.6
Epoch pinned client d5cce1a83550dcfa9eb2f0251dbb11fd24c272534b2b1a9b230924a44d817ab3 Same target, range index, school, and damage class; source base points differ EffectChainTarget[0] (field 104) = 3 EffectDamageMultiplier[0] (field 216) = 0.7

Field 216 is named EffectDamageMultiplier in the matching AzerothCore DBCStructure.h and is exposed as SpellEffectInfo::DamageMultiplier; the comment identifies the DBC field as m_effectChainAmplitude. AzerothCore's spell resolver applies the factor after each successive chain hit. The resulting damage factors are 1.0, 0.6, 0.36 for Ascension and 1.0, 0.7, 0.49 for Epoch. The currently imported Stockade record uses the Ascension profile. EffectChainTarget=3 means three total hits, including the explicit primary target: core requests two additional chain targets.

The source range index is 4; the existing compiler pin resolves it to 30 yards. Spell.dbc stores the range index, while this task's chain jump distance comes from the matching core behavior. Spell.cpp::SearchChainTargets uses a 10-yard jump radius for magic spells. It searches a candidate pool centered on the primary with radius jumpRange × total target count (30 yards here), then selects the nearest eligible target within 10 yards of the previous hit at each hop. The chain starts from the primary target because neither pinned profile has SPELL_ATTR2_CHAIN_FROM_CASTER (0x1000). It removes the primary from the candidate pool and removes every chosen candidate, so a target cannot be hit twice. Each bounce must have line of sight from the previous hit. In AzerothCore, the ordinary hostile-target cast path validates the primary's cast range and line of sight before chain selection; HealerMan integration must preserve that primary-target contract. A dead primary at resolution ends the attack instead of choosing a replacement.

These runtime rules were checked against the read-only matching core source at ../wow-pvt-server-backups-2/azerothcore-wotlk/src/server/game/Spells/Spell.cpp (SelectImplicitChainTargets, SearchChainTargets, and damage multiplier application), SpellInfo.cpp (ChainTarget and damage multiplier mapping), and src/server/shared/DataStores/DBCStructure.h (field names). The imported database snapshot is pinned to commit 4d9d1d4b5723e819c5c390f6ca1177283dbfb8e3 by azerothCoreWorldAi.json.

Helper and runtime integration

src/game/enemyChainTargeting.ts provides pure ordered target selection. It accepts a primary target, current living candidates with positions, target count, jump range, per-bounce damage multiplier, and a line-of-sight function. It returns the primary first and each reachable hop with its cumulative damage factor. The focused tests cover nearest-hop traversal, both source decay profiles, living filtering, LOS filtering, no repeats, search-pool range, and the primary-target contract.

For the compiler/runtime integration, keep these sourced values together on the imported attack as chain: { targetCount, jumpRange, damageMultiplier }. Parse EffectChainTarget[0] from field 104 and EffectDamageMultiplier[0] from field 216 (using the parser's localized-field shift helper when applicable); pin only spell 421's chain signature so unrelated source signatures do not change. Emit target count 3 and jump range 10 for the verified Ascension and Epoch signatures, with profile-specific multipliers 0.6 and 0.7. Keep the existing primary-target attack, 30-yard cast range, cooldowns, and attack scalar.

At resolution, validate the cast's primary target through the existing hostile-target range/LOS path, then pass that target and current living registered party actors to selectEnemyChainTargets. For each returned hit, multiply the existing attack damage by that hit's damageMultiplier and resolve the hit through the existing per-target damage, mitigation, resistance, and event path. This keeps each hit in normal combat accounting while the primary receives factor 1 and subsequent hits receive the source decay. Keep chain metadata absent on attacks without a verified chain signature. This subtask does not change the shared compiler, attack schema, combat runtime, generated catalogs, loot, ammo, level cap, or readiness policy; the integrating worker owns those reserved files.

The parent integration is complete in the shared compiler, attack schema and combat runtime. The three helper checks and five runtime cases pass, including actor-local player/NPC defenses in both stat modes, hop LOS/range, the original cast victim after a threat change and a secondary target outside the caster's home leash. Primary aggro eligibility remains unchanged. Final build and full Stormwind Stockade evidence are recorded in STOCKADE_ENEMY_MECHANICS_2026-10-05.md and its linked playtest report.