Broaden OnPlayerIsClass for CLASS_CONTEXT_ABILITY, pet/charm/equip contexts; add PARAA C RESET PET TALENTS handler. Update CLIENT-PATCHES.md for patch-enUS-5/6 and PARAA.
Co-authored-by: Cursor <cursoragent@cursor.com>
- SpellInfoCorrections: zero Reagent/ReagentCount on spells with non-zero
SpellFamilyName so class abilities no longer require shards, candles,
etc., while profession crafts (SpellFamilyName 0) keep mats. Matches
the client Spell.dbc bake in patch-enUS-4.MPQ.
- Paragon_SC: OnPlayerIsClass returns true for CLASS_CONTEXT_EQUIP_RELIC
for paladin/druid/shaman/warlock/dk so Paragon can equip all relic types
in the ranged slot.
- CLIENT-PATCHES: document Spell.dbc reagent pass, rune script order, and
stock ammo slot behavior in patch-enUS-5.
Co-authored-by: Cursor <cursoragent@cursor.com>
Stock 3.3.5 hardcodes per-class stat -> AP/SP formulas in
Player::UpdateAttackPowerAndDamage and Unit::SpellBase{Damage,Healing}BonusDone,
so class 12 fell into the default branches and ended up with 0 AP and 0 SP
regardless of STR / AGI / INT / SPI. The character sheet, combat log, and
ability damage all reflected this, and Mental Quickness-style AP->SP plumbing
silently no-oped on Paragon characters.
Add Paragon-specific branches in core (no PlayerScript hooks - those caused
SIGSEGVs when the new mid-list enum entry shifted later hook ordinals and
broke vtable dispatch):
- StatSystem.cpp: melee and ranged AP = level*2 + STR + AGI - 20, mirroring
the formula the UI patch already advertises in tooltips.
- Unit.cpp: intrinsic SP = level*2 + INT + SPI - 20 (clamped >=0),
added symmetrically to SpellBaseDamageBonusDone and
SpellBaseHealingBonusDone so the single advertised Spell Power value the
character sheet renders matches what spells actually use in combat.
Drop the now-unused UnitDefines.h include in Paragon_SC.cpp - it was only
needed by the AP PlayerScript hook that was rolled back in favor of the
core change.
Co-authored-by: Cursor <cursoragent@cursor.com>
RevokeUnwantedCascadeSpellsForPlayer and RevokeBlockedSpellsForPlayer
built their allowlist only from character_paragon_panel_spells and
panel_spell_children. Many Character Advancement "abilities" (e.g.
Scourge Strike) are panel talents stored in character_paragon_panel_talents,
so learning Death Coil afterward activated DK skill lines and the sweep
removed those spells as false orphans.
Add BuildPanelOwnedSpellsAllowlist to union spell chains, talent rank spell
IDs up to the purchased rank, and passive children. Also keep the prior
fixes: clear stale panel_spell_revoked rows on purchase and skip+delete
revoke entries that now match the allowlist on login.
Co-authored-by: Cursor <cursoragent@cursor.com>
Paragon OnPlayerHasActivePowerType only reported POWER_RAGE when
Paragon.MultiResource.HasActivePowers was true. Core melee rage uses
Unit::DealDamage -> HasActivePowerType(POWER_RAGE) before RewardRage;
missing module config (common on fresh clones / Docker without merged
mod_paragon.conf) fell through to GetOption(..., false) and white swings
never generated rage. Match mod_paragon.conf.dist and default the C++
fallback to true so Paragon behaves correctly out of the box. Set
Paragon.MultiResource.HasActivePowers = 0 only for intentional test builds.
Co-authored-by: Cursor <cursoragent@cursor.com>
Extend spell_paragon_arcane_torrent to EnergizeBySpell POWER_RAGE 150 (15
displayed; rage uses the same 10x internal scaling as runic power, see the
`-20` rage decay step in Player::Regenerate). Paragon's combined Arcane
Torrent now refunds mana, rage, energy, and runic power -- whichever pool
the character is using at the moment. ModifyPower no-ops on pools with
MaxPower == 0, so it's safe even before the Paragon picks up rage abilities.
Co-authored-by: Cursor <cursoragent@cursor.com>
Building on the previous fix that hid the rogue and DK Arcane Torrent variants
for Paragon Blood Elves: instead of just dropping the duplicates, turn the
remaining mana variant (28730) into a single combined racial that refunds
whichever resource pool the character is using at the moment.
Add SpellScript spell_paragon_arcane_torrent in modules/mod-paragon/src/
Paragon_SC.cpp. Hooks AfterCast on 28730: when the caster is class 12 the
script EnergizeBySpell's 15 energy and 150 internal runic power (= 15 displayed,
matching stock 25046 / 50613 amounts) on top of the spell's stock mana effect.
ModifyPower no-ops on pools the player has no max for, so it is safe even
before the Paragon picks up energy- or RP-using abilities. Non-Paragon Blood
Elves are untouched and keep learning their stock racial.
Update migration 2026_05_10_03.sql to also register the script binding via
spell_script_names (28730 -> 'spell_paragon_arcane_torrent'). Idempotent
DELETE + INSERT.
Co-authored-by: Cursor <cursoragent@cursor.com>
Blood Elf racial skill line 756 grants three different Arcane Torrent spell
IDs (28730 mana, 25046 rogue energy, 50613 DK runic power). The blanket
SkillLineAbility overlay in 2026_05_10_02 OR'd class 12 into all three, so
Paragon Blood Elves auto-learned every variant and the spellbook listed three
identical "Arcane Torrent" entries.
Add db-world migration 2026_05_10_03.sql to clear the class-12 bit on the rogue
and DK rows only (SkillLineAbility IDs 13338 and 17510), leaving 28730 as the
sole Paragon-visible racial cast. OnPlayerLogin removes 25046/50613 if still
present so existing characters self-heal without a manual unlearn.
The fractured-tooling DBC overlay generator is updated in the same workspace
to skip those two rows when regenerating SkillLineAbility SQL.
Co-authored-by: Cursor <cursoragent@cursor.com>
mod-paragon Paragon_Essence.cpp:
- Broaden SkillLinesLinkedToSpell: collect every SkillLineAbility row for
an anchor spell regardless of AcquireMethod, so anchor spells whose
primary SLA uses AcquireMethod 0 (e.g. Blood Strike) correctly identify
their skill lines and let the dependent classifier do its job.
- IsSpellSkillLineCascadeDependent / RevokeUnwantedCascadeSpellsForPlayer
use the broadened helper. HandleCommit calls the post-purchase sweep
immediately so the spellbook never carries lingering cascade dependents
(Blood Presence / Forceful Deflection / Death Coil / Death Grip).
- New character_paragon_panel_spell_revoked table tracks which active
dependents we've revoked per (guid, parent) so OnPlayerLogin can
re-revoke them after AC's _LoadSkills -> learnSkillRewardedSpells
silently re-grants them.
- OnPlayerLogin opens the client SILENCE window via SendSilenceOpenForCommit
with an empty allow list and intentionally omits the matching
SendSilenceClose: the chat frame buffers CHAT_MSG_SYSTEM during the
loading screen and only flushes after PLAYER_ENTERING_WORLD, so a paired
CLOSE would shut the filter before the buffered "you have unlearned X"
toasts hit it. The addon's 8s fail-open closes the window after the flush.
- New `.paragon hat` chat command for diagnosing Honor Among Thieves
triggers (talent rank, learned spell, applied aura, proc table entry).
mod-paragon Paragon_SC.cpp:
- OnPlayerUpdate pushes server-authoritative combo points to the client
via PARAA "R CP <n>" whenever the count changes. The client-side
ComboFrame Paragon simulator listens for this and updates the target
frame, fixing HAT-generated CP not displaying (HAT's trigger casts
with a null target, which the combat-log inference path can't see).
- OnPlayerUpdate also pushes "R RUNES <cd0..cd5>" (ms remaining per
rune slot) on rune mask changes, so the client RuneFrame simulator
stays in lock-step with Spell::TakeRunePower instead of drifting
through combat-log latency.
mod-paragon SQL:
- New updates/2026_05_09_00.sql migration creates
character_paragon_panel_spell_revoked for AC's auto-DBUpdater so a
fresh checkout can stand up an existing characters DB without
manual intervention. Matching CREATE TABLE IF NOT EXISTS in
base/character_paragon_panel_learned.sql for fresh installs.
mod-paragon conf:
- New Paragon.Diag.PanelLearn flag traces every PanelLearnSpellChain
commit (chain ids, before/after spell-map sizes, side-spell
classification) for diagnosing "spell reappears on relog" bugs.
Co-authored-by: Cursor <cursoragent@cursor.com>