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

8.0 KiB
Raw Permalink Blame History

Enemy shout speed and immunity audit — 2026-10-06

This follow-up pins the parent movement-speed effect and the immunity-related source scalars for Intimidating Shout 5246 -> 20511 and Frightening Shout 19134 -> 29544. The earlier ENEMY_TRIGGERED_SHOUTS_2026-10-06.md remains the targeting and timed-control reference. The runtime attaches the sourced speed modifier and tag to the existing parent control aura, and both player and party movement consume that target-local multiplier. Shout target selection also includes eligible owned summons, but the current summon action loop holds a controlled summon before its movement step. The +25% speed is therefore sourced on that recipient without changing its movement during the shared fear/control lifetime; no fear-flee behavior is claimed.

Client source rows

The Ascension input is ../LadiksMPQEditor/client-current/area-52/patch-D/DBFilesClient/Spell.dbc, SHA-256 2f77f18b91ffbae32a19568e4bc05ec78ee384b6ba8dd2a6e05f0e97abbb2dce. The Epoch input is ../HealerMan-Storage/pipeline-work/dungeons/epoch-client/DBFilesClient/Spell.dbc, SHA-256 d5cce1a83550dcfa9eb2f0251dbb11fd24c272534b2b1a9b230924a44d817ab3. Both use the shared patch-S SpellDuration.dbc and SpellRadius.dbc fallbacks recorded in enemySourceAuras.ts.

Raw Spell.dbc field 3 (Mechanic) is 5 on all four rows, which the selected core defines as MECHANIC_FEAR. Effect-level EffectMechanic is 0 on every effect. DamageClass is field 213; Dispel is field 2. The attribute tuple below lists raw fields 4 through 11 in order (Attributes0 through Attributes7):

Spell Profile Spell mechanic Damage class Dispel Attributes0–7
5246 parent Ascension 5 1 (Magic) 0 [0, 0, 0, 0, 0, 0, 0x02000000, 0]
20511 child Ascension 5 1 (Magic) 0 [0, 0, 0, 0x00090000, 0x00800000, 0, 0, 0]
19134 parent Ascension 5 1 (Magic) 0 [0x00050010, 0, 0, 0, 0, 0, 0, 0]
29544 child Ascension 5 0 (None) 0 [0, 0, 0, 0, 0, 0, 0, 0]
5246 parent Epoch 5 1 (Magic) 0 [0x00050010, 136, 0, 0, 0, 0, 0x00800000, 0]
20511 child Epoch 5 0 (None) 0 [0, 0, 0, 0, 0, 0, 0, 0]
19134 parent Epoch 5 1 (Magic) 0 [0x00050010, 0, 0, 0, 0, 0, 0, 0]
29544 child Epoch 5 0 (None) 0 [0, 0, 0, 0, 0, 0, 0, 0]

None of these rows sets ATTR0_NO_IMMUNITIES, ATTR2_NO_SCHOOL_IMMUNITIES, ATTR3_ALWAYS_HIT, ATTR4_NO_PARTIAL_IMMUNITY, or ATTR7_NO_ATTACK_MISS. The source does not mark a spell as always hitting or as bypassing immunity. Both parent casts are Magic-class rows. Child 20511 is Magic class only in Ascension; 20511 in Epoch and child 29544 in both profiles are DamageClass=None aura-only rows. The historical core routes Magic-class spells through its magic hit calculation and applies its ordinary aura-only handling to None-class rows. The HealerMan runtime does not implement the general hit, resist, or deflect calculation in this pass.

Parent speed effect

Both parents have effect 2 APPLY_AURA (effectType=6) with aura 31 MOD_INCREASE_SPEED, base points 25, target A 22 (TARGET_SRC_CASTER), target B 15 (TARGET_UNIT_SRC_AREA_ENEMY), and radius index 14 (8 yd). Thus the aura grants +25% movement speed to eligible hostile recipients in the same caster-centered 8-yard area as parent fear. Its duration follows the parent row:

Parent Ascension Epoch
5246 Intimidating Shout 5 s 8 s
19134 Frightening Shout 4 s 6 s

enemyTriggeredShoutMovementSpeedEffect exposes this only when effect 2 still matches the source aura, amount, target pair, radius, and area contract. Its modifier uses the ActiveAura fraction (0.25) and the tag enemy-triggered-shout:parent-movement-speed. The target-local multiplier helper ignores expired, permanent, differently targeted, and untagged auras; if multiple shout speed effects are active it returns the strongest positive bonus, matching the historical core's GetMaxPositiveAuraModifier handling for SPELL_AURA_MOD_INCREASE_SPEED.

The runtime stores the speed modifier on the existing per-target parent enemy-control:source-spell-5246 or enemy-control:source-spell-19134 aura. This keeps same-caster refresh, different-caster preserve-existing behavior, and caster-removal persistence with the parent control record. PlayerRig and PartyPopulation movement consume the target-local multiplier. The summon loop currently returns for the parent's active control before moving, so this pass does not introduce summon movement or fear-flee AI. The control and speed effects share one duration. The table gives the DBC duration baseline; historical core Spell::DoSpellHitOnUnit computes one duration for the shared aura, then Unit::ModSpellDuration derives mechanic duration modifiers from the complete spell, including its spell-level fear mechanic. A fear-duration modifier can therefore shorten the combined fear and speed aura together.

The runtime attaches the speed modifier only when it accepts the parent spell application. This is important for fear immunity: the source rows have spell-level Mechanic=5, and the historical core checks that mechanic in Unit::IsImmunedToSpell before resolving the per-effect aura immunities. Unit::SpellHitResult calls that whole-spell check. Under the runtime's whole-spell fear-immunity policy, a fear-immune recipient does not receive the parent's fear or +25% speed effect. While fear is active, the existing player and party locomotion policy blocks movement; the speed multiplier is tracked on the shared aura but does not override that fear movement policy.

Child control and immunity behavior

Child 20511 has aura 12 (MOD_STUN) for 5 seconds in Ascension and 8 seconds in Epoch. Ascension also has a separate aura 87 effect that increases physical damage taken by 15% for 5 seconds; Epoch has no such rider. Child 29544 has only fear aura 7, for 3 seconds in Ascension and 6 seconds in Epoch.

The whole-spell fear mechanic applies to all four rows. A fear mechanic immunity therefore rejects the parent or triggered child as a whole in the selected core. A stun-state immunity is narrower: it filters child 20511's aura-12 effect. In Ascension the separate aura-87 physical damage-taken rider can remain; Epoch's 20511 row has no remaining child effect. The source children have Dispel=0, so neither is dispellable by category. The same source-caster refresh and different-caster preserve-existing policy remains in applyEnemySourceAura; the shared parent control aura IDs already survive caster removal. Recipient removal removes the combined fear and speed aura.

Targeting and implementation boundary

The parent effect-0 trigger remains a separate cast on its explicit victim; the child is not selected from the area list. Effects 1 and 2 remain the independent caster-centered area pair at 8 yards, with the existing cap of 5 for 5246 and unlimited (MaxAffectedTargets=0) for 19134. A qualifying explicit victim may also receive the area effects. The prior targeting report documents the separate LOS rules, overlap, and random-ordering boundary.

Historical AzerothCore sources were read-only under ../wow-pvt-server-backups-2/azerothcore-wotlk/src/server/game/Spells/ and ../wow-pvt-server-backups-2/azerothcore-wotlk/src/server/game/Entities/Unit/. The relevant paths are Spell::EffectTriggerSpell, Spell::AddUnitTarget, Unit::IsImmunedToSpell, Unit::IsImmunedToSpellEffect, Unit::SpellHitResult, Unit::MagicSpellHitResult, and Unit::UpdateSpeed. The current simulation still does not model general magic hit/resist/deflect rolls or creature-specific exceptions. The level-80 cap, loot, readiness, and publication scope are unchanged.

Focused verification passed: npx vitest run src/game/enemyTriggeredShouts.test.ts src/game/enemySourceAuras.test.ts (2 files, 12 tests). The root-owned shout integration suite also passed during integration; the owner runs final repository checks after shared changes settle.