diff --git a/modules/mod-paragon/data/sql/db-world/updates/2026_05_10_03.sql b/modules/mod-paragon/data/sql/db-world/updates/2026_05_10_03.sql index 73e71d7..bb8d487 100644 --- a/modules/mod-paragon/data/sql/db-world/updates/2026_05_10_03.sql +++ b/modules/mod-paragon/data/sql/db-world/updates/2026_05_10_03.sql @@ -4,10 +4,24 @@ -- every SkillLineAbility delta from patch-enUS-4, so Paragon Blood Elves -- auto-learned all three and the spellbook showed three identical entries. -- --- Paragon uses mana as its primary display power; keep only the mana --- variant (28730) for class 12. IDs 13338 / 17510 match stock WotLK --- SkillLineAbility rows for 25046 / 50613 on skill line 756. +-- Paragon should learn a single combined Arcane Torrent that refunds mana, +-- energy, AND runic power -- whichever pool the character is using at the +-- moment. We keep spell 28730 as the in-book entry for class 12 and attach +-- the SpellScript spell_paragon_arcane_torrent (modules/mod-paragon/src/ +-- Paragon_SC.cpp) so casts by a Paragon also EnergizeBySpell energy + RP on +-- top of the stock mana effect. Other classes' Blood Elves are unaffected. +-- +-- IDs 13338 / 17510 match stock WotLK SkillLineAbility rows for spells 25046 +-- / 50613 on skill line 756. UPDATE `skilllineability_dbc` SET `ClassMask` = `ClassMask` & ~2048 WHERE `ID` IN (13338, 17510); + +-- Bind spell_paragon_arcane_torrent (defined in Paragon_SC.cpp) to spell +-- 28730. AC's `spell_script_names` is the standard mapping: script name on +-- the right, spell id on the left. Idempotent via DELETE + INSERT. +DELETE FROM `spell_script_names` +WHERE `spell_id` = 28730 AND `ScriptName` = 'spell_paragon_arcane_torrent'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES + (28730, 'spell_paragon_arcane_torrent'); diff --git a/modules/mod-paragon/src/Paragon_SC.cpp b/modules/mod-paragon/src/Paragon_SC.cpp index 44570a1..dfd263b 100644 --- a/modules/mod-paragon/src/Paragon_SC.cpp +++ b/modules/mod-paragon/src/Paragon_SC.cpp @@ -13,6 +13,8 @@ #include "Player.h" #include "ScriptMgr.h" #include "SharedDefines.h" +#include "SpellScript.h" +#include "SpellScriptLoader.h" #include "UnitDefines.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -268,7 +270,54 @@ private: std::unordered_map Paragon_PlayerScript::runeSyncByGuid; +// Arcane Torrent (28730) for Paragon: Blood Elf racial skill line 756 has +// three Arcane Torrent variants in stock WotLK (28730 mana, 25046 rogue +// energy, 50613 DK runic power). For Paragon Blood Elves we keep only 28730 +// (see migration 2026_05_10_03.sql) and turn it into a "combined" version: +// the stock spell already silences nearby enemies and energizes mana via its +// own effects; this script adds energy and runic power energize on top when +// the caster is class 12, so a single button refunds whichever resource pool +// the player is actually using. Non-Paragon casters are untouched and keep +// learning their stock racial variant. +class spell_paragon_arcane_torrent : public SpellScript +{ + PrepareSpellScript(spell_paragon_arcane_torrent); + + void HandleAfterCast() + { + Unit* caster = GetCaster(); + if (!caster || !caster->IsPlayer()) + return; + + Player* player = caster->ToPlayer(); + if (player->getClass() != CLASS_PARAGON) + return; + + // Stock energize amounts from spell_dbc: + // 25046 Arcane Torrent (Energy) -> 15 energy + // 50613 Arcane Torrent (Runic Power) -> 15 displayed RP (= 150 + // internal; AC stores RP scaled 10x, see Player::SetMaxPower + // POWER_RUNIC_POWER, 1000). + // ModifyPower no-ops on pools the player has no max for, so this is + // safe even before the Paragon picks up energy/RP-using abilities. + constexpr int32 kEnergyGain = 15; + constexpr int32 kRunicPowerGain = 150; + + SpellInfo const* spellInfo = GetSpellInfo(); + uint32 const spellId = spellInfo ? spellInfo->Id : 28730u; + + caster->EnergizeBySpell(player, spellId, kEnergyGain, POWER_ENERGY); + caster->EnergizeBySpell(player, spellId, kRunicPowerGain, POWER_RUNIC_POWER); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_paragon_arcane_torrent::HandleAfterCast); + } +}; + void AddSC_paragon() { new Paragon_PlayerScript(); + RegisterSpellScript(spell_paragon_arcane_torrent); }