diff --git a/sql/updates/world/master/2026_02_28_02_world.sql b/sql/updates/world/master/2026_02_28_02_world.sql new file mode 100644 index 0000000000..d16a4923a5 --- /dev/null +++ b/sql/updates/world/master/2026_02_28_02_world.sql @@ -0,0 +1,14 @@ +DELETE FROM `areatrigger_create_properties` WHERE `IsCustom`=0 AND `Id`=36671; +INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `SpellForVisuals`, `TimeToTargetScale`, `Speed`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES +(36671, 0, 38618, 0, 0, 0, 0, 0, 0, -1, 0, 0, NULL, 20000, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 'at_dh_shattered_souls_devourer', 65727); -- Spell: 1223412 (Soul Fragment) + +DELETE FROM `areatrigger_template` WHERE `IsCustom`=0 AND `Id`=38618; +INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `VerifiedBuild`) VALUES +(38618, 0, 65727); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_dh_shattered_souls_devourer', 'spell_dh_shattered_souls_devourer_missile', 'spell_dh_shattered_souls_devourer_dummy'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(1227619, 'spell_dh_shattered_souls_devourer'), +(1223445, 'spell_dh_shattered_souls_devourer_trigger'), +(1223448, 'spell_dh_shattered_souls_devourer_trigger'), +(1223450, 'spell_dh_shattered_souls_devourer_dummy'); diff --git a/src/server/scripts/Spells/spell_dh.cpp b/src/server/scripts/Spells/spell_dh.cpp index e8235e3273..f26e68c357 100644 --- a/src/server/scripts/Spells/spell_dh.cpp +++ b/src/server/scripts/Spells/spell_dh.cpp @@ -66,6 +66,7 @@ enum DemonHunterSpells SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM_DAMAGE = 391058, SPELL_DH_COLLECTIVE_ANGUISH_FEL_DEVASTATION = 393831, SPELL_DH_CONSUME_ENERGIZE = 1261710, + SPELL_DH_CONSUME_SOUL_DEVOURER = 1223423, SPELL_DH_CONSUME_SOUL_HAVOC_DEMON = 228556, SPELL_DH_CONSUME_SOUL_HAVOC_LESSER = 228542, SPELL_DH_CONSUME_SOUL_HAVOC_SHATTERED = 228540, @@ -186,8 +187,12 @@ enum DemonHunterSpells SPELL_DH_SHATTERED_SOUL = 226258, SPELL_DH_SHATTERED_SOULS_V_DEMON_TRIGGER = 226264, SPELL_DH_SHATTERED_SOULS_V_SHATTERED_TRIGGER = 226263, + SPELL_DH_SHATTERED_SOUL_DEVOURER_LESSER_RIGHT = 1223445, + SPELL_DH_SHATTERED_SOUL_DEVOURER_LESSER_LEFT = 1223448, SPELL_DH_SHATTERED_SOUL_LESSER_RIGHT = 228533, SPELL_DH_SHATTERED_SOUL_LESSER_LEFT = 237867, + SPELL_DH_SHATTERED_SOULS_DEVOURER = 1227619, + SPELL_DH_SHATTERED_SOULS_DEVOURER_DUMMY = 1223450, SPELL_DH_SHATTERED_SOULS_HAVOC = 209651, SPELL_DH_SHATTERED_SOULS_HAVOC_DEMON_TRIGGER = 226370, SPELL_DH_SHATTERED_SOULS_HAVOC_LESSER_TRIGGER = 228536, @@ -221,6 +226,8 @@ enum DemonHunterSpells SPELL_DH_SOUL_CLEAVE = 228477, SPELL_DH_SOUL_CLEAVE_DMG = 228478, SPELL_DH_SOUL_FRAGMENT_COUNTER = 203981, + SPELL_DH_SOUL_FRAGMENT_DEVOURER = 1223412, + SPELL_DH_SOUL_FRAGMENTS_DEVOURER_COUNTER = 1245577, SPELL_DH_SOUL_FRAGMENTS_DAMAGE_TAKEN_TRACKER = 210788, SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF = 391172, SPELL_DH_SOUL_RENDING = 204909, @@ -1019,21 +1026,27 @@ class spell_dh_demon_spikes : public SpellScript struct spell_dh_shattered_souls_base_lesser { + static constexpr std::array DevourerSpells = { SPELL_DH_SHATTERED_SOUL_DEVOURER_LESSER_RIGHT, SPELL_DH_SHATTERED_SOUL_DEVOURER_LESSER_LEFT }; + static constexpr std::array HavocSpells = { SPELL_DH_SHATTERED_SOUL_LESSER_RIGHT, SPELL_DH_SHATTERED_SOUL_LESSER_LEFT }; + static constexpr std::array VengeanceSpells = { SPELL_DH_SHATTER_SOUL_VENGEANCE_FRONT_RIGHT, SPELL_DH_SHATTER_SOUL_VENGEANCE_BACK_RIGHT }; + static bool Validate() { - return SpellScriptBase::ValidateSpellInfo({ - SPELL_DH_SHATTERED_SOUL_LESSER_RIGHT, - SPELL_DH_SHATTERED_SOUL_LESSER_LEFT, - SPELL_DH_SHATTER_SOUL_VENGEANCE_FRONT_RIGHT, - SPELL_DH_SHATTER_SOUL_VENGEANCE_BACK_RIGHT - }); + return SpellScriptBase::ValidateSpellInfo(DevourerSpells) + && SpellScriptBase::ValidateSpellInfo(HavocSpells) + && SpellScriptBase::ValidateSpellInfo(VengeanceSpells); } static void CreateFragments(Unit* source, Unit* dh, int32 count) { - std::array spells = dh->IsPlayer() && dh->ToPlayer()->GetPrimarySpecialization() == ChrSpecialization::DemonHunterHavoc - ? std::array{ SPELL_DH_SHATTERED_SOUL_LESSER_RIGHT, SPELL_DH_SHATTERED_SOUL_LESSER_LEFT } - : std::array{ SPELL_DH_SHATTER_SOUL_VENGEANCE_FRONT_RIGHT, SPELL_DH_SHATTER_SOUL_VENGEANCE_BACK_RIGHT }; + std::span spells = HavocSpells; + if (Player* player = dh->ToPlayer()) + { + if (player->GetPrimarySpecialization() == ChrSpecialization::DemonHunterDevourer) + spells = DevourerSpells; + else if (player->GetPrimarySpecialization() == ChrSpecialization::DemonHunterVengeance) + spells = VengeanceSpells; + } for (int32 i = 0; i < count; ++i) source->CastSpell(dh, Trinity::Containers::SelectRandomContainerElement(spells), TRIGGERED_DONT_REPORT_CAST_ERROR); @@ -1987,8 +2000,57 @@ private: uint32 _triggeredSpellId; }; +// 1227619 - Shattered Souls +class spell_dh_shattered_souls_devourer : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return spell_dh_shattered_souls_base_lesser::Validate(); + } + + static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/) + { + return roll_chance_i(aurEff->GetAmount()); + } + + static void HandleProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo) + { + spell_dh_shattered_souls_base_lesser::CreateFragments(eventInfo.GetActionTarget(), eventInfo.GetActor(), 1); + } + + void Register() override + { + DoCheckEffectProc += AuraCheckEffectProcFn(spell_dh_shattered_souls_devourer::CheckProc, EFFECT_0, SPELL_AURA_DUMMY); + OnEffectProc += AuraEffectProcFn(spell_dh_shattered_souls_devourer::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } +}; + +// 1223450 - Shattered Souls +class spell_dh_shattered_souls_devourer_dummy : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_DH_SOUL_FRAGMENT_DEVOURER }); + } + + void HandleSoulFragment(SpellEffIndex /*effIndex*/) const + { + GetCaster()->CastSpell(GetHitDest()->GetPosition(), SPELL_DH_SOUL_FRAGMENT_DEVOURER, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_dh_shattered_souls_devourer_dummy::HandleSoulFragment, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + // 209651 - Shattered Souls // 210038 - Shatter Soul +// 1223445 - Shattered Souls +// 1223448 - Shattered Souls class spell_dh_shattered_souls_trigger : public SpellScript { public: @@ -2020,8 +2082,8 @@ private: uint32 _triggeredSpellIdDemon; }; -// 209693 - Shattered Souls and 209788 - Shattered Souls -// Id - 3680 and 6659 +// 209693 - Shattered Souls, 209788 - Shattered Souls and 1223412 - Soul Fragment +// Id - 3680, 6659 and 36671 template struct at_dh_shattered_souls : public AreaTriggerAI { @@ -2036,19 +2098,25 @@ struct at_dh_shattered_souls : public AreaTriggerAI void OnInitialize() override { if (Unit* caster = at->GetCaster()) + { if (caster->HasAura(SPELL_DH_SHATTERED_SOULS_VENGEANCE)) - caster->CastSpell(caster, SPELL_DH_SOUL_FRAGMENT_COUNTER, CastSpellExtraArgsInit{ - .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, - }); + caster->CastSpell(caster, SPELL_DH_SOUL_FRAGMENT_COUNTER, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + else if (caster->HasAura(SPELL_DH_SHATTERED_SOULS_DEVOURER)) + caster->CastSpell(caster, SPELL_DH_SOUL_FRAGMENTS_DEVOURER_COUNTER, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + } } void OnRemove() override { if (Unit* caster = at->GetCaster()) + { caster->RemoveAuraFromStack(SPELL_DH_SOUL_FRAGMENT_COUNTER); + caster->RemoveAuraFromStack(SPELL_DH_SOUL_FRAGMENTS_DEVOURER_COUNTER); + } } }; +using at_dh_shattered_souls_devourer = at_dh_shattered_souls; using at_dh_shattered_souls_havoc_demon = at_dh_shattered_souls; using at_dh_shattered_souls_havoc_lesser = at_dh_shattered_souls; using at_dh_shattered_souls_havoc_shattered = at_dh_shattered_souls; @@ -2644,10 +2712,14 @@ void AddSC_demon_hunter_spell_scripts() RegisterSpellScript(spell_dh_shattered_restoration); RegisterSpellScriptWithArgs(spell_dh_shattered_souls, "spell_dh_shattered_souls_havoc", SPELL_DH_SHATTERED_SOULS_HAVOC); RegisterSpellScriptWithArgs(spell_dh_shattered_souls, "spell_dh_shattered_souls_vengeance", SPELL_DH_SHATTER_SOUL); + RegisterSpellScriptWithArgs(spell_dh_shattered_souls_trigger, "spell_dh_shattered_souls_devourer_trigger", SPELL_DH_SHATTERED_SOULS_DEVOURER_DUMMY, 0); RegisterSpellScriptWithArgs(spell_dh_shattered_souls_trigger, "spell_dh_shattered_souls_havoc_trigger", SPELL_DH_SHATTERED_SOULS_HAVOC_SHATTERED_TRIGGER, SPELL_DH_SHATTERED_SOULS_HAVOC_DEMON_TRIGGER); RegisterSpellScriptWithArgs(spell_dh_shattered_souls_trigger, "spell_dh_shattered_souls_havoc_trigger_lesser", SPELL_DH_SHATTERED_SOULS_HAVOC_LESSER_TRIGGER, 0); RegisterSpellScriptWithArgs(spell_dh_shattered_souls_trigger, "spell_dh_shattered_souls_vengeance_trigger", SPELL_DH_SHATTERED_SOULS_V_SHATTERED_TRIGGER, SPELL_DH_SHATTERED_SOULS_V_DEMON_TRIGGER); RegisterSpellScriptWithArgs(spell_dh_shattered_souls_trigger, "spell_dh_shattered_souls_vengeance_trigger_lesser", SPELL_DH_SHATTERED_SOUL, 0); + RegisterSpellScript(spell_dh_shattered_souls_devourer); + RegisterSpellScript(spell_dh_shattered_souls_devourer_dummy); + RegisterAreaTriggerAI(at_dh_shattered_souls_devourer); RegisterAreaTriggerAI(at_dh_shattered_souls_havoc_demon); RegisterAreaTriggerAI(at_dh_shattered_souls_havoc_lesser); RegisterAreaTriggerAI(at_dh_shattered_souls_havoc_shattered);