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

110 lines
6.3 KiB
Markdown
Raw 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.
# Stockade Rend periodic damage source audit — 2026-10-05
This adds a source-backed timing and amount descriptor for Stockade Rend spells
6547 and 16509. The active Stockade catalog uses the Ascension patch-D profile;
the distinct Epoch profile is retained in the helper so imports cannot silently
reuse the wrong 6547 amount.
## Spell rows
| Profile | Spell | Stockade users | Duration | Tick interval/count | BasePoints / DieSides | Raw tick before core scaling | Creature-level scaling |
| --- | ---: | --- | ---: | ---: | ---: | ---: | --- |
| Ascension patch-D | 6547 | Defias Inmate (1708) | 15 s | 3 s / 5 | 13 / 1 | 14 | No |
| Ascension patch-D | 16509 | Captive (1707), Prisoner (1706), Convict (1711) | 15 s | 3 s / 5 | 26 / 1 | 27 | Yes |
| Epoch client | 6547 | Separate Epoch profile | 15 s | 3 s / 5 | 9 / 1 | 10 | No |
| Epoch client | 16509 | Separate Epoch profile | 15 s | 3 s / 5 | 26 / 1 | 27 | Yes |
Each row has effect 6 (`APPLY_AURA`) with aura 3 (`PERIODIC_DAMAGE`), effect
mechanic 15 (`BLEED`), implicit target A 6 and no secondary target. The shared
SpellDuration row 8 is `[8, 15000, 0, 15000]`; the Spell.dbc rows use duration
index 8 and period 3000 ms. School mask 1 is physical, damage class 2 is melee,
and Spell.dbc `StackAmount` is 0 (one active stack).
`EffectRealPointsPerLevel` is 0 on all four rows. `BasePoints` is stored one
below its effective value; AzerothCore `SpellEffectInfo::CalcValue` adds the
1..DieSides roll, so DieSides 1 yields the raw amounts above. These are inputs
before core damage modifiers. Spell 16509 also carries
`SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL` in both DBC profiles, with
`BaseLevel=SpellLevel=20` and `MaxLevel=0`. For a non-player caster whose level
differs from 20, the referenced core scales that raw amount by
`CreatureBaseStats.BaseDamage[caster level][creature expansion] /
CreatureBaseStats.BaseDamage[spell level 20][creature expansion]`, then truncates
to `int32`. Spell 6547 has no such attribute. No `spell_bonus_data` row exists
for either spell in the inspected core SQL snapshot.
The new helper resolves that 16509 ratio only when both exact class-level rows
and the creature template are present. It reads `BaseDamage` directly; it does
not fold in `CreatureTemplate.damageModifier`, attack power, weapon variance,
or swing time. A missing template or stats row returns an explicit unsupported
result; the source-tagged runtime fails closed instead of inventing a scale.
Caster damage-done modifiers are snapshotted at aura application. Target
damage-taken modifiers remain dynamic at each pulse.
## Runtime contract
The source effect is periodic-only, so a cast must not create an immediate
direct-damage packet. For a fresh aura, schedule the first pulse after 3000 ms
and the fifth pulse at 15000 ms. Same-caster recasts keep at most one stack and
refresh the duration and tick count. An ordinary recast restarts the tick phase,
so its next pulse is three seconds later. The core preserves the old phase only
for casts marked `TRIGGERED_NO_PERIODIC_RESET`. Separate casters may retain
independent bleed auras on the same target.
Core applies DOT done/taken modifiers, then checks armor. Its
`Unit::IsDamageReducedByArmor` explicitly exempts periodic effects whose
mechanic mask includes `BLEED`; therefore the runtime needs an armor-only bypass
for these pulses. Do not use `targetMitigationSnapshotted` for this purpose,
because that also skips resistance. The attack remains physical/melee typed for
the sourced cast and hit table; the periodic pulses use the existing common
periodic damage resolution.
The generated catalog currently has authored attack `damageMultiplier` values
for the Rend cast rows. Those are not DBC periodic tick amounts. Keep any
source-level cast scalar separate from the periodic amount. The game may still
apply its outer entity `mob.damageMultiplier` after resolving the source tick.
## Integration points
- `src/game/enemyPeriodicDamage.ts` provides the exact Ascension patch-D and
Epoch source profiles, five-tick schedule helper, armor and stack metadata,
and NPC core scaling calculation for 6547/16509.
- `src/game/azerothCoreReference.ts` exposes the pinned template/class-level
`BaseDamage` input with no template multiplier. The strict helper rejects
levels outside 1–80, missing templates, invalid expansion indices, and absent
class-level rows.
- The campaign compiler/runtime adapter should select `ascension-patch-d` for
the active Stockade catalog and preserve the `epoch-client` variant only for
Epoch imports. Serialize the source identity (`spellId` plus profile) and let
runtime resolve it through this helper. Emit no direct damage effect; carry
`periodicIgnoresArmor` to tick resolution. If 16509 lacks a source template or
class-level base-damage row, omit that source effect instead of inventing
a ratio or substituting the old attack scalar.
The runtime integration tests cover player and party NPC defenders in both
WoW-compatible and native RoM stat modes, the application hit gate, five full
pulses, armor bypass, refresh, independent casters and magic-dispel exclusion.
The fourteen integration checks also verify caster bonus expiry/gain after
application and changing target-side damage-taken modifiers. Nine pure source
contract/amount checks pass separately.
## Source pins
The Ascension Spell.dbc is
`../LadiksMPQEditor/client-current/area-52/patch-D/DBFilesClient/Spell.dbc`,
SHA-256 `2f77f18b91ffbae32a19568e4bc05ec78ee384b6ba8dd2a6e05f0e97abbb2dce`.
The Epoch Spell.dbc is
`../HealerMan-Storage/pipeline-work/dungeons/epoch-client/DBFilesClient/Spell.dbc`,
SHA-256 `D5CCE1A83550DCFA9EB2F0251DBB11FD24C272534B2B1A9B230924A44D817AB3`.
Neither profile has a sibling SpellDuration.dbc; both use the established
patch-S duration fallback, SHA-256
`EEAE44EF0185924F3D6EC57AB2701C66566DB86E51AB0BAE017A9449126EB3A0`.
Core behavior was checked in the read-only historical AzerothCore reference:
`src/server/game/Spells/SpellInfo.cpp` (`SpellEffectInfo::CalcValue`),
`src/server/game/Spells/Spell.cpp` (the ordinary-cast periodic-reset flag),
`src/server/game/Spells/Auras/SpellAuraEffects.cpp` (periodic setup, ticks, and
damage mitigation), `src/server/game/Spells/Auras/SpellAuras.cpp` (refresh and
stack behavior), and `src/server/game/Entities/Unit/Unit.cpp`
(`_TryStackingOrRefreshingExistingAura` and `IsDamageReducedByArmor`). These
files are source references, not HealerMan runtime dependencies.