Files
healer-man/docs/UTILITY_HIT_EXTENSION_AUDIT_2026-10-06.md
T
2026-10-07 13:05:04 -04:00

86 lines
4.7 KiB
Markdown

# Utility hit extension audit — 2026-10-06
## Result
The exact WoW 3.3.5a single-rank Shield Bash (72), Kick (1766), and Pummel
(6552) can share the existing ordinary-creature **full-block** result. The
binding is intentionally exact to the selected playable row, source profile,
class, rank, source effects, and projected effect list. It does not add miss,
dodge, parry, or mechanic-resist rolls. Those outcomes remain on the current
effect path until the runtime carries the source inputs needed to calculate
them faithfully.
Kick's playable identity is `rogue-kick`; `wow335-rogue-kick` is its raw
generated source-chain identity. The catalog merge must retain the source
Kick's pure five-second interrupt rather than merge the legacy prototype's
damage and second interrupt. Pummel's selected row is the level-38 rank, so
the contract does not permit it before its source unlock. Shield Bash remains
the only selected rank in its chain and retains its 29703 trigger alongside
its six-second interrupt.
## Source proof
The local `wow335a/Data/patch-A.MPQ/DBFilesClient/Spell.dbc` records for IDs
72, 1766, and 6552 share `DmgClass=2` (melee), physical `SchoolMask=1`,
`Attributes0=327696`, `Attributes3=8`, and `Attributes7=0`. `Attributes3=8`
is `SPELL_ATTR3_COMPLETELY_BLOCKED`. The relevant custom-attribute bits
`SPELL_ATTR0_CU_DIRECT_DAMAGE` (`0x00000100`) and
`SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET` (`0x00020000`) are both clear in
the pinned core: `SpellInfo::Initialize` starts `AttributesCu` at zero, and
the active custom-attribute update SQL contains no rows for these three IDs.
This proves only those two custom bits, not the complete custom word.
The exact effect slots are:
| Spell | Source effects | Selected projection |
| --- | --- | --- |
| Shield Bash 72 | Effect 68, mechanic 26, target A 6; effect 64, target A 6, trigger 29703 | Interrupt 6,000 ms; trigger spell 29703 |
| Kick 1766 | Effect 68, mechanic 26, target A 6; second slot empty | Interrupt 5,000 ms |
| Pummel 6552 | Effect 68, mechanic 26, target A 6; second slot empty | Interrupt 4,000 ms |
These signatures are also present in `src/game/wow335AbilityData.generated.json`
and are locked in `src/game/enemyUtilitySpellBlocking.ts`. `SpellInfo.cpp`
identifies effect 68 as `SPELL_EFFECT_INTERRUPT_CAST`; `SpellEffects.cpp`
dispatches it to `EffectInterruptCast`. It is not a direct-damage effect.
The pinned AzerothCore `Unit::MeleeSpellHitResult` in
`../wow-pvt-server-backups-2/azerothcore-wotlk/ElunaTrinityWotlk/src/server/game/Entities/Unit/Unit.cpp`
explains why the source proof does not justify the whole table:
- It checks `MeleeSpellMissChance` first. Attribute 7 bit `0x02000000`
(`SPELL_ATTR7_CANT_MISS`) is clear for all three records, so they can miss.
- It adds `GetMechanicResistChance` next. The interrupt effect's mechanic is
26; the target's `SPELL_AURA_MOD_MECHANIC_RESISTANCE` can resist it.
- It then considers dodge, parry, and block. Melee attacks can block; casting
or controlled defenders lose active avoidance/block; attacking from behind
disables parry/block absent hit-direction immunity. Creature no-dodge,
no-parry, and no-block flags and `SPELL_AURA_IGNORE_COMBAT_RESULT` also
alter eligibility.
The generated defense projection currently omits `Attributes7`, while the
utility resolver has no exact mechanic-resistance, miss-chance/weapon-skill,
or complete target-state input for these spells. Consequently, a generic
Magic miss/resist roll or guessed melee miss/dodge/parry values would not
match this source. The implementation keeps those outcomes gated and
resolves only the already modeled block result.
## Runtime boundary and verification
`enemyUtilitySpellBlockAbilityContract` binds the policy to the selected
ability ID (including the public Kick identity), class, exact source, DBC
rank, defense metadata, and full projected effect signature. It reconstructs
only the audited known custom-bit evidence when the generated row omits it;
conflicting explicit metadata fails closed. `resolveNpcUtilityBlockResult`
then restricts the check to player/party casters and ordinary source NPCs,
and asks the existing defender model for a physical melee block result with
miss, crit, dodge, and parry disabled. A block suppresses all utility effects
while preserving the accepted cast's cost/cooldown path. Player and party
effect application both consume that blocked result.
Validation: `npx vitest run src/game/enemyUtilitySpellBlocking.test.ts
src/game/wow335InterruptUtilityBlocking.integration.test.ts` passes 13 tests
across two files. The unit cases verify the three exact source/projection
contracts, selected-rank identity, and mismatch rejection. The integration
cases cover blocked player and companion Kick/Pummel casts and ensure the
interrupt effect is not applied on a full block.