forked from phenom/healer-man
140 lines
8.0 KiB
Markdown
140 lines
8.0 KiB
Markdown
# 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.
|