TrinityCore
Loading...
Searching...
No Matches
boss_devourer_of_souls.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ScriptMgr.h"
19#include "Containers.h"
20#include "forge_of_souls.h"
21#include "InstanceScript.h"
22#include "Map.h"
23#include "MotionMaster.h"
24#include "ScriptedCreature.h"
25#include "SpellAuraEffects.h"
26#include "SpellInfo.h"
27#include "SpellScript.h"
28#include "TemporarySummon.h"
29
30/*
31 * @todo
32 * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing).
33 * - Fix outro npc movement
34 */
35
52
54{
63 SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase
64 SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual
65 SPELL_WAILING_SOULS = 68873, // the actual spell
67// 68871, 68873, 68875, 68876, 68899, 68912, 70324,
68// 68899 trigger 68871
69};
70
81
83{
87};
88
94{
95 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5590.47f, 2427.79f, 705.935f, 0.802851f } },
96 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5593.59f, 2428.34f, 705.935f, 0.977384f } },
97 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5600.81f, 2429.31f, 705.935f, 0.890118f } },
98 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5600.81f, 2421.12f, 705.935f, 0.890118f } },
99 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5601.43f, 2426.53f, 705.935f, 0.890118f } },
100 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5601.55f, 2418.36f, 705.935f, 1.15192f } },
101 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5598, 2429.14f, 705.935f, 1.0472f } },
102 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5594.04f, 2424.87f, 705.935f, 1.15192f } },
103 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5597.89f, 2421.54f, 705.935f, 0.610865f } },
104 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5598.57f, 2434.62f, 705.935f, 1.13446f } },
105 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5585.46f, 2417.99f, 705.935f, 1.06465f } },
106 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5605.81f, 2428.42f, 705.935f, 0.820305f } },
107 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5591.61f, 2412.66f, 705.935f, 0.925025f } },
108 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5593.9f, 2410.64f, 705.935f, 0.872665f } },
109 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5586.76f, 2416.73f, 705.935f, 0.942478f } },
110 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5592.23f, 2419.14f, 705.935f, 0.855211f } },
111 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5594.61f, 2416.87f, 705.935f, 0.907571f } },
112 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5589.77f, 2421.03f, 705.935f, 0.855211f } },
113
114 { { NPC_KORELN, NPC_LORALEN }, { 5602.58f, 2435.95f, 705.935f, 0.959931f } },
115 { { NPC_ELANDRA, NPC_KALIRA }, { 5606.13f, 2433.16f, 705.935f, 0.785398f } },
116 { { NPC_JAINA_PART2, NPC_SYLVANAS_PART2 }, { 5606.12f, 2436.6f, 705.935f, 0.890118f } },
117
118 { { 0, 0 }, { 0.0f, 0.0f, 0.0f, 0.0f } }
120
121static constexpr Position CrucibleSummonPos = { 5672.294f, 2520.686f, 713.4386f, 0.9599311f };
122
124{
126 {
127 beamAngle = 0.f;
128 beamAngleDiff = float(M_PI) / 20.0f;
129 wailingSoulTick = 0;
130 }
131
140
154
155 void KilledUnit(Unit* victim) override
156 {
157 if (victim->GetTypeId() != TYPEID_PLAYER)
158 return;
159
160 uint8 textId = 0;
161 switch (me->GetDisplayId())
162 {
163 case DISPLAY_ANGER:
164 textId = SAY_FACE_ANGER_SLAY;
165 break;
166 case DISPLAY_SORROW:
167 textId = SAY_FACE_SORROW_SLAY;
168 break;
169 case DISPLAY_DESIRE:
170 textId = SAY_FACE_DESIRE_SLAY;
171 break;
172 default:
173 break;
174 }
175
176 if (textId)
177 Talk(textId);
178 }
179
180 void JustDied(Unit* /*killer*/) override
181 {
182 _JustDied();
183
184 Position spawnPoint = {5618.139f, 2451.873f, 705.854f, 0};
185
187
188 int32 entryIndex;
190 entryIndex = 0;
191 else
192 entryIndex = 1;
193
194 for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i)
195 {
196 if (TempSummon* summon = instance->instance->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint))
197 {
198 summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN);
199 summon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition);
200 if (summon->GetEntry() == NPC_JAINA_PART2)
201 summon->AI()->Talk(SAY_JAINA_OUTRO);
202 else if (summon->GetEntry() == NPC_SYLVANAS_PART2)
203 summon->AI()->Talk(SAY_SYLVANAS_OUTRO);
204 }
205 }
206 }
207
208 void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override
209 {
210 if (spellInfo->Id == H_SPELL_PHANTOM_BLAST)
212 }
213
214 void UpdateAI(uint32 diff) override
215 {
216 // Return since we have no target
217 if (!UpdateVictim())
218 return;
219
220 events.Update(diff);
221
223 return;
224
225 while (uint32 eventId = events.ExecuteEvent())
226 {
227 switch (eventId)
228 {
232 break;
237 break;
242 break;
251 break;
252 case EVENT_FACE_ANGER:
254 break;
255
262 {
263 me->SetFacingToObject(target);
265 }
266
268
269 if (roll_chance(50))
271
274
275 //Remove any target
277
280
281 wailingSoulTick = 20;
282 events.DelayEvents(13s); // no other events during wailing souls
283 events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3s); // first one after 3 secs.
284 break;
285
287 if (--wailingSoulTick)
288 {
293 }
294 else
295 {
301 }
302 break;
303 }
304
306 return;
307 }
308 }
309
310private:
311 // wailing soul event
315};
316
317// 69051 - Mirrored Soul
319{
320 bool Validate(SpellInfo const* /*spellInfo*/) override
321 {
323 }
324
325 void HandleScript(SpellEffIndex /*effIndex*/)
326 {
327 if (Unit* target = GetHitUnit())
328 target->CastSpell(GetCaster(), SPELL_MIRRORED_SOUL_PROC_AURA, true);
329 }
330
335};
336
337// 69023 - Mirrored Soul (Proc)
339{
340 bool Validate(SpellInfo const* /*spellInfo*/) override
341 {
343 }
344
345 bool CheckProc(ProcEventInfo& /*eventInfo*/)
346 {
347 return GetCaster() && GetCaster()->IsAlive();
348 }
349
350 void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& eventInfo)
351 {
353 DamageInfo* damageInfo = eventInfo.GetDamageInfo();
354 if (!damageInfo || !damageInfo->GetDamage())
355 return;
356
358 args.AddSpellBP0(CalculatePct(damageInfo->GetDamage(), 45));
360 }
361
367};
368
369// 69048 - Mirrored Soul (Target Selector)
371{
372 bool Validate(SpellInfo const* /*spellInfo*/) override
373 {
375 }
376
377 void FilterTargets(std::list<WorldObject*>& targets)
378 {
379 if (targets.empty())
380 return;
381
383 targets.clear();
384 targets.push_back(target);
385 }
386
387 void HandleScript(SpellEffIndex /*effIndex*/)
388 {
389 if (Unit* target = GetHitUnit())
391 }
392
398};
399
#define M_PI
Definition Common.h:118
uint8_t uint8
Definition Define.h:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ TEMPSUMMON_DEAD_DESPAWN
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
Spells
Definition PlayerAI.cpp:32
bool roll_chance(T chance)
Definition Random.h:55
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
SpellEffIndex
@ EFFECT_0
@ TARGET_UNIT_SRC_AREA_ENTRY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ ALLIANCE
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
#define AuraEffectProcFn(F, I, N)
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraCheckProcFn(F)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STATE_ROOT
Definition Unit.h:271
@ UNIT_STATE_CASTING
Definition Unit.h:276
T CalculatePct(T base, U pct)
Definition Util.h:72
struct outroPosition outroPositions[]
@ SAY_FACE_ANGER_SLAY
@ SAY_FACE_DESIRE_SLAY
@ EMOTE_MIRRORED_SOUL
@ SAY_FACE_WAILING_SOUL
@ SAY_FACE_SORROW_SLAY
@ SAY_FACE_UNLEASH_SOUL
void AddSC_boss_devourer_of_souls()
@ SPELL_MIRRORED_SOUL_DAMAGE
@ SPELL_PHANTOM_BLAST
@ SPELL_MIRRORED_SOUL_PROC_AURA
@ SPELL_WAILING_SOULS_BEAM
@ H_SPELL_WAILING_SOULS
@ SPELL_MIRRORED_SOUL_TARGET_SELECTOR
@ H_SPELL_PHANTOM_BLAST
@ SPELL_WELL_OF_SOULS
@ SPELL_WAILING_SOULS_STARTING
@ SPELL_MIRRORED_SOUL_BUFF
@ SPELL_UNLEASHED_SOULS
@ SPELL_WAILING_SOULS
static constexpr Position CrucibleSummonPos
@ EVENT_WAILING_SOULS
@ EVENT_WELL_OF_SOULS
@ EVENT_UNLEASHED_SOULS
@ EVENT_WAILING_SOULS_TICK
@ EVENT_PHANTOM_BLAST
@ EVENT_MIRRORED_SOUL
Yells
void PreventDefaultAction()
Unit * GetCaster() const
Unit * GetTarget() const
HookList< CheckProcHandler > DoCheckProc
HookList< EffectProcHandler > OnEffectProc
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
EventMap events
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
void SetReactState(ReactStates st)
Definition Creature.h:174
void SetTarget(ObjectGuid const &guid) override
void SetDisplayId(uint32 displayId, bool setNative=false) override
uint32 GetDamage() const
Definition Unit.h:452
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:100
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
void DoUpdateWorldState(int32 worldStateId, int32 value)
InstanceMap * instance
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty, SmoothPhasingInfo const *smoothPhasingInfo=nullptr)
Definition Object.cpp:1186
static ObjectGuid const Empty
Definition ObjectGuid.h:314
DamageInfo * GetDamageInfo() const
Definition Unit.h:511
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:79
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:89
Definition Unit.h:635
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11545
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3231
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition Unit.cpp:13307
bool IsAlive() const
Definition Unit.h:1185
uint32 GetDisplayId() const
Definition Unit.h:1610
Unit * GetVictim() const
Definition Unit.h:726
void SetFacingTo(float const ori, bool force=true)
Definition Unit.cpp:13289
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1517
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:99
void HandleProc(AuraEffect *, ProcEventInfo &eventInfo)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
@ WORLD_STATE_THREE_FACED_FAILED
@ DATA_TEAM_IN_INSTANCE
@ DATA_DEVOURER_OF_SOULS
@ NPC_CHAMPION_1_ALLIANCE
@ NPC_JAINA_PART2
@ NPC_KALIRA
@ NPC_CRUCIBLE_OF_SOULS
@ NPC_KORELN
@ NPC_CHAMPION_1_HORDE
@ NPC_CHAMPION_2_ALLIANCE
@ NPC_SYLVANAS_PART2
@ NPC_LORALEN
@ NPC_ELANDRA
@ NPC_CHAMPION_3_HORDE
@ NPC_CHAMPION_2_HORDE
#define RegisterForgeOfSoulsCreatureAI(ai_name)
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
CastSpellExtraArgs & AddSpellBP0(SpellEffectValue val)
constexpr float GetOrientation() const
Definition Position.h:90
void JustEngagedWith(Unit *who) override
void UpdateAI(uint32 diff) override
boss_devourer_of_souls(Creature *creature)
void SpellHitTarget(WorldObject *, SpellInfo const *spellInfo) override
void KilledUnit(Unit *victim) override