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

6.3 KiB
Raw Blame History

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.