From e8d4837aba183849b1cf51d22475a6be55b5e1f1 Mon Sep 17 00:00:00 2001 From: Cristian Vintila <127750549+cristianvnt@users.noreply.github.com> Date: Tue, 30 Dec 2025 22:59:51 +0200 Subject: [PATCH] Scripts/Spells: Implement Entropic Rift (#31447) --- .../world/master/2025_12_30_00_world.sql | 20 ++ src/server/scripts/Spells/spell_priest.cpp | 203 +++++++++++++++++- 2 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 sql/updates/world/master/2025_12_30_00_world.sql diff --git a/sql/updates/world/master/2025_12_30_00_world.sql b/sql/updates/world/master/2025_12_30_00_world.sql new file mode 100644 index 00000000000..96c84942bf6 --- /dev/null +++ b/sql/updates/world/master/2025_12_30_00_world.sql @@ -0,0 +1,20 @@ +DELETE FROM `areatrigger_template` WHERE `Id`=35700 AND `IsCustom`=0; +INSERT INTO `areatrigger_template` (`Id`,`IsCustom`,`Flags`,`ActionSetId`,`ActionSetFlags`,`VerifiedBuild`) VALUES +(35700,0,0,0,0,0); + +DELETE FROM `areatrigger_create_properties` WHERE `Id`=33200 AND `IsCustom`=0; +INSERT INTO `areatrigger_create_properties` (`Id`,`IsCustom`,`AreaTriggerId`,`IsAreatriggerCustom`,`Flags`,`MoveCurveId`,`ScaleCurveId`,`MorphCurveId`,`FacingCurveId`,`AnimId`,`AnimKitId`,`DecalPropertiesId`,`SpellForVisuals`,`TimeToTargetScale`,`Speed`,`SpeedIsTime`,`Shape`,`ShapeData0`,`ShapeData1`,`ShapeData2`,`ShapeData3`,`ShapeData4`,`ShapeData5`,`ShapeData6`,`ShapeData7`,`ScriptName`,`VerifiedBuild`) VALUES +(33200,0,35700,0,0,0,0,0,0,-1,0,0,447445,1000,12,0,0,4,4,0,0,0,0,0,0,'areatrigger_pri_entropic_rift',64978); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_pri_entropic_rift','spell_pri_entropic_rift_aura','spell_pri_entropic_rift_periodic'); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(8092,'spell_pri_entropic_rift'), +(263165,'spell_pri_entropic_rift'), +(450193,'spell_pri_entropic_rift_aura'), +(459314,'spell_pri_entropic_rift_periodic'); + +UPDATE `creature_template` SET `unit_flags3`=0x1000000,`AIName`='SmartAI' WHERE `entry`=223273; -- Entropic Rift +DELETE FROM `smart_scripts` WHERE `entryorguid`=223273 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`Difficulties`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`event_param5`,`event_param_string`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`action_param7`,`action_param_string`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_param4`,`target_param_string`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(223273,0,0,0,'',86,0,100,0,0,0,0,0,0,'',28,450193,0,0,0,0,0,0,NULL,23,0,0,0,0,NULL,0,0,0,0,'Entropic Rift - remove 450193 from summoner on despawn'), +(223273,0,1,0,'',86,0,100,0,0,0,0,0,0,'',28,459314,0,0,0,0,0,0,NULL,23,0,0,0,0,NULL,0,0,0,0,'Entropic Rift - remove 459314 from summoner on despawn'); diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 712705d43ad..f624db6729f 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -26,7 +26,6 @@ #include "Containers.h" #include "G3DPosition.hpp" #include "GridNotifiers.h" -#include "ListUtils.h" #include "Log.h" #include "MoveSplineInitArgs.h" #include "ObjectAccessor.h" @@ -91,6 +90,12 @@ enum PriestSpells SPELL_PRIEST_DIVINE_STAR_SHADOW_HEAL = 390981, SPELL_PRIEST_DIVINE_WRATH = 40441, SPELL_PRIEST_EMPOWERED_RENEW = 391339, + SPELL_PRIEST_EMPOWERED_RENEW_HEAL = 391359, + SPELL_PRIEST_ENTROPIC_RIFT = 447444, + SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER = 447445, + SPELL_PRIEST_ENTROPIC_RIFT_AURA = 450193, + SPELL_PRIEST_ENTROPIC_RIFT_DAMAGE = 447448, + SPELL_PRIEST_ENTROPIC_RIFT_PERIODIC = 459314, SPELL_PRIEST_EPIPHANY = 414553, SPELL_PRIEST_EPIPHANY_HIGHLIGHT = 414556, SPELL_PRIEST_ESSENCE_DEVOURER = 415479, @@ -131,6 +136,7 @@ enum PriestSpells SPELL_PRIEST_MASOCHISM_TALENT = 193063, SPELL_PRIEST_MASOCHISM_PERIODIC_HEAL = 193065, SPELL_PRIEST_MASTERY_GRACE = 271534, + SPELL_PRIEST_MIND_BLAST = 8092, SPELL_PRIEST_MIND_DEVOURER = 373202, SPELL_PRIEST_MIND_DEVOURER_AURA = 373204, SPELL_PRIEST_MINDBENDER_DISC = 123040, @@ -217,6 +223,7 @@ enum PriestSpells SPELL_PRIEST_VAMPIRIC_TOUCH = 34914, SPELL_PRIEST_VOID_SHIELD = 199144, SPELL_PRIEST_VOID_SHIELD_EFFECT = 199145, + SPELL_PRIEST_VOID_TORRENT = 263165, SPELL_PRIEST_WEAKENED_SOUL = 6788, SPELL_PRIEST_WHISPERING_SHADOWS = 406777, SPELL_PRIEST_WHISPERING_SHADOWS_DUMMY = 391286, @@ -1309,6 +1316,196 @@ class spell_pri_empowered_renew_heal : public AuraScript } }; +// 447444 - Entropic Rift +// Triggered by 8092 - Mind Blast (Discipline) and 263165 - Void Torrent (Shadow) +class spell_pri_entropic_rift : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PRIEST_ENTROPIC_RIFT }); + } + + bool Load() override + { + Unit* caster = GetCaster(); + return caster->HasAura(SPELL_PRIEST_ENTROPIC_RIFT) + && caster->IsPlayer() + && GetSpellInfo()->Id == uint32(caster->ToPlayer()->GetPrimarySpecialization() == ChrSpecialization::PriestShadow + ? SPELL_PRIEST_VOID_TORRENT + : SPELL_PRIEST_MIND_BLAST); + } + + void HandleEffectHit(SpellEffIndex /*effIndex*/) const + { + Unit* target = GetHitUnit(); + + GetCaster()->CastSpell(target->GetPosition(), SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .CustomArg = target->GetGUID() + }); + } + + void Register() override + { + if (m_scriptSpellId == SPELL_PRIEST_MIND_BLAST) + OnEffectHitTarget += SpellEffectFn(spell_pri_entropic_rift::HandleEffectHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + else + OnEffectHitTarget += SpellEffectFn(spell_pri_entropic_rift::HandleEffectHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +// 450193 - Entropic Rift (Aura) +class spell_pri_entropic_rift_aura : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER }); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const + { + if (AreaTrigger* at = GetTarget()->GetAreaTrigger(SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER)) + at->Remove(); + } + + void Register() override + { + OnEffectRemove += AuraEffectApplyFn(spell_pri_entropic_rift_aura::HandleRemove, EFFECT_0, SPELL_AURA_MOD_SPEED_ALWAYS, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 459314 - Entropic Rift (Periodic) +class spell_pri_entropic_rift_periodic : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER, SPELL_PRIEST_ENTROPIC_RIFT_DAMAGE }); + } + + void HandlePeriodic(AuraEffect const* /*aurEff*/) const + { + Unit* caster = GetTarget(); + + AreaTrigger const* at = caster->GetAreaTrigger(SPELL_PRIEST_ENTROPIC_RIFT_AREATRIGGER); + if (!at) + return; + + SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_ENTROPIC_RIFT_DAMAGE, GetCastDifficulty()); + + for (ObjectGuid const& unitInAreaTrigger : at->GetInsideUnits()) + if (Unit* target = ObjectAccessor::GetUnit(*at, unitInAreaTrigger)) + if (caster->IsValidAttackTarget(target, damageSpell)) + caster->CastSpell(target, SPELL_PRIEST_ENTROPIC_RIFT_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_pri_entropic_rift_periodic::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +// 447445 - Entropic Rift (AreaTrigger) +struct areatrigger_pri_entropic_rift : public AreaTriggerAI +{ + using AreaTriggerAI::AreaTriggerAI; + + static constexpr std::array OverrideScaleCurve = + {{ + { .X = 0.0f, .Y = 1.0f }, + { .X = 1.0f, .Y = 1.0f }, + }}; + + void OnCreate(Spell const* creatingSpell) override + { + Unit* caster = at->GetCaster(); + if (!caster) + return; + + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR; + + if (creatingSpell) + { + args.OriginalCastId = creatingSpell->m_castId; + + if (ObjectGuid const* targetGUID = std::any_cast(&creatingSpell->m_customArg)) + at->SetPathTarget(*targetGUID); + + _searchRadius = creatingSpell->GetSpellInfo()->GetMaxRange(); + } + + caster->CastSpell(caster, SPELL_PRIEST_ENTROPIC_RIFT_AURA, args); + caster->CastSpell(caster, SPELL_PRIEST_ENTROPIC_RIFT_PERIODIC, args); + + UpdateMovement(); + _scheduler.Schedule(500ms, [this](TaskContext task) + { + UpdateMovement(); + task.Repeat(500ms); + }); + } + + void OnUpdate(uint32 diff) override + { + _scheduler.Update(diff); + } + + void OnDestinationReached() override + { + _movementSpeed = 7.0f; // Entropic Rift moves slower after reaching its target + } + + void UpdateMovement() + { + at->SetOverrideScaleCurve(OverrideScaleCurve); // updates StartTimeOffset of the curve + + Unit* target = UpdateTarget(); + if (!target) + return; + + at->SetPathTarget(target->GetGUID()); + + if (at->IsInDist2d(target, 0.5f)) + return; + + PathGenerator path(at); + path.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), false); + at->InitSplines(path.GetPath(), _movementSpeed); + } + + Unit* UpdateTarget() const + { + SpellInfo const* damageSpell = sSpellMgr->GetSpellInfo(SPELL_PRIEST_ENTROPIC_RIFT_DAMAGE, DIFFICULTY_NONE); + if (!damageSpell || damageSpell->GetEffects().empty()) + return nullptr; + + Unit* caster = at->GetCaster(); + if (!caster) + return nullptr; + + SpellEffectInfo const& damageEffect = damageSpell->GetEffect(EFFECT_0); + Trinity::WorldObjectSpellAreaTargetCheck check(_searchRadius, caster, caster, caster, damageSpell, TARGET_CHECK_ENEMY, damageEffect.ImplicitTargetConditions.get(), TARGET_OBJECT_TYPE_UNIT); + + Unit* target = ObjectAccessor::GetUnit(*at, at->m_areaTriggerData->OrbitPathTarget); + if (!target || !check(target)) + { + std::vector targets; + Trinity::UnitListSearcher searcher(at, targets, check); + Spell::SearchTargets(searcher, GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER, caster, caster, _searchRadius); + Trinity::Containers::EraseIf(targets, [caster](Unit const* target) { return !caster->IsInCombatWith(target); }); + if (!targets.empty()) + target = Trinity::Containers::SelectRandomContainerElement(targets); + } + + return target; + } + +private: + TaskScheduler _scheduler; + float _movementSpeed = 12.0f; + float _searchRadius = 0.0f; +}; + // 414553 - Epiphany class spell_pri_epiphany : public AuraScript { @@ -4051,6 +4248,10 @@ void AddSC_priest_spell_scripts() RegisterSpellScript(spell_pri_divine_procession); RegisterSpellScript(spell_pri_empowered_renew); RegisterSpellScript(spell_pri_empowered_renew_heal); + RegisterSpellScript(spell_pri_entropic_rift); + RegisterSpellScript(spell_pri_entropic_rift_aura); + RegisterSpellScript(spell_pri_entropic_rift_periodic); + RegisterAreaTriggerAI(areatrigger_pri_entropic_rift); RegisterSpellScript(spell_pri_epiphany); RegisterSpellScript(spell_pri_essence_devourer_heal); RegisterSpellScript(spell_pri_evangelism);