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

140 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`](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.