Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_devourer_of_souls.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ScriptMgr.h"
7#include "ScriptedCreature.h"
8#include "Player.h"
9#include "SpellInfo.h"
10#include "SpellAuraEffects.h"
11#include "SpellScript.h"
12#include "forge_of_souls.h"
13
14/*
15 * @todo
16 * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing).
17 * - Fix outro npc movement
18 */
19
36
38{
47 SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase
48 SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual
49 SPELL_WAILING_SOULS = 68873, // the actual spell
51// 68871, 68873, 68875, 68876, 68899, 68912, 70324,
52// 68899 trigger 68871
53};
54
65
67{
71};
72
78{
79 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5590.47f, 2427.79f, 705.935f, 0.802851f } },
80 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5593.59f, 2428.34f, 705.935f, 0.977384f } },
81 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5600.81f, 2429.31f, 705.935f, 0.890118f } },
82 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5600.81f, 2421.12f, 705.935f, 0.890118f } },
83 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5601.43f, 2426.53f, 705.935f, 0.890118f } },
84 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5601.55f, 2418.36f, 705.935f, 1.15192f } },
85 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5598, 2429.14f, 705.935f, 1.0472f } },
86 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5594.04f, 2424.87f, 705.935f, 1.15192f } },
87 { { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE }, { 5597.89f, 2421.54f, 705.935f, 0.610865f } },
88 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5598.57f, 2434.62f, 705.935f, 1.13446f } },
89 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5585.46f, 2417.99f, 705.935f, 1.06465f } },
90 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5605.81f, 2428.42f, 705.935f, 0.820305f } },
91 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5591.61f, 2412.66f, 705.935f, 0.925025f } },
92 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5593.9f, 2410.64f, 705.935f, 0.872665f } },
93 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE }, { 5586.76f, 2416.73f, 705.935f, 0.942478f } },
94 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5592.23f, 2419.14f, 705.935f, 0.855211f } },
95 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5594.61f, 2416.87f, 705.935f, 0.907571f } },
96 { { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE }, { 5589.77f, 2421.03f, 705.935f, 0.855211f } },
97
98 { { NPC_KORELN, NPC_LORALEN }, { 5602.58f, 2435.95f, 705.935f, 0.959931f } },
99 { { NPC_ELANDRA, NPC_KALIRA }, { 5606.13f, 2433.16f, 705.935f, 0.785398f } },
100 { { NPC_JAINA_PART2, NPC_SYLVANAS_PART2 }, { 5606.12f, 2436.6f, 705.935f, 0.890118f } },
101
102 { { 0, 0 }, { 0.0f, 0.0f, 0.0f, 0.0f } }
104
105Position const CrucibleSummonPos = {5672.294f, 2520.686f, 713.4386f, 0.9599311f};
106
108{
110};
111
113{
114 public:
115 boss_devourer_of_souls() : CreatureScript("boss_devourer_of_souls") { }
116
118 {
120 {
121 }
122
124 {
125 if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(FoSScriptName))
126 me->IsAIEnabled = false;
127 else if (!me->isDead())
128 Reset();
129 }
130
132 {
134 me->SetDisplayId(DISPLAY_ANGER);
135 me->SetReactState(REACT_AGGRESSIVE);
136
137 events.Reset();
138 summons.DespawnAll();
139
140 threeFaced = true;
141
143 }
144
145 void EnterCombat(Unit* /*who*/) OVERRIDE
146 {
148
149 if (!me->FindNearestCreature(NPC_CRUCIBLE_OF_SOULS, 60)) // Prevent double spawn
150 instance->instance->SummonCreature(NPC_CRUCIBLE_OF_SOULS, CrucibleSummonPos);
151 events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000);
152 events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000);
153 events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000);
154 events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000);
155 events.ScheduleEvent(EVENT_WAILING_SOULS, std::rand() % 70000 + 60000);
156
158 }
159
161 {
162 if (victim->GetTypeId() != TypeID::TYPEID_PLAYER)
163 return;
164
165 int32 textId = 0;
166 switch (me->GetDisplayId())
167 {
168 case DISPLAY_ANGER:
169 textId = SAY_FACE_ANGER_SLAY;
170 break;
171 case DISPLAY_SORROW:
172 textId = SAY_FACE_SORROW_SLAY;
173 break;
174 case DISPLAY_DESIRE:
175 textId = SAY_FACE_DESIRE_SLAY;
176 break;
177 default:
178 break;
179 }
180
181 if (textId)
182 Talk(textId);
183 }
184
185 void JustDied(Unit* /*killer*/) OVERRIDE
186 {
187 summons.DespawnAll();
188
189 Position spawnPoint = {5618.139f, 2451.873f, 705.854f, 0};
190
192
194
195 int32 entryIndex;
196 if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
197 entryIndex = 0;
198 else
199 entryIndex = 1;
200
201 for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i)
202 {
203 if (Creature* summon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TempSummonType::TEMPSUMMON_DEAD_DESPAWN))
204 {
205 summon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition);
206 if (summon->GetEntry() == NPC_JAINA_PART2)
207 summon->AI()->Talk(SAY_JAINA_OUTRO);
208 else if (summon->GetEntry() == NPC_SYLVANAS_PART2)
209 summon->AI()->Talk(SAY_SYLVANAS_OUTRO);
210 }
211 }
212 }
213
214 void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) OVERRIDE
215 {
216 if (spell->Id == H_SPELL_PHANTOM_BLAST)
217 threeFaced = false;
218 }
219
221 {
222 if (type == DATA_THREE_FACED)
223 return threeFaced;
224
225 return 0;
226 }
227
229 {
230 // Return since we have no target
231 if (!UpdateVictim())
232 return;
233
234 events.Update(diff);
235
236 if (me->HasUnitState(UNIT_STATE_CASTING))
237 return;
238
239 while (uint32 eventId = events.ExecuteEvent())
240 {
241 switch (eventId)
242 {
245 events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000);
246 break;
250 events.ScheduleEvent(EVENT_MIRRORED_SOUL, std::rand() % 30000 + 15000);
251 break;
253 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
255 events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000);
256 break;
258 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
260 me->SetDisplayId(DISPLAY_SORROW);
263 events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000);
264 events.ScheduleEvent(EVENT_FACE_ANGER, 5000);
265 break;
266 case EVENT_FACE_ANGER:
267 me->SetDisplayId(DISPLAY_ANGER);
268 break;
269
271 me->SetDisplayId(DISPLAY_DESIRE);
275 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
276 {
277 me->SetFacingToObject(target);
279 }
280
281 beamAngle = me->GetOrientation();
282
283 beamAngleDiff = M_PI/30.0f; // PI/2 in 15 sec = PI/30 per tick
284 if (RAND(true, false))
286
287 me->InterruptNonMeleeSpells(false);
288 me->SetReactState(REACT_PASSIVE);
289
290 //Remove any target
291 me->SetTarget(0);
292
293 me->GetMotionMaster()->Clear();
295
296 wailingSoulTick = 15;
297 events.DelayEvents(18000); // no other events during wailing souls
298 events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs.
299 break;
300
303 me->SetFacingTo(beamAngle);
304 me->StopMoving();
305
307
308 if (--wailingSoulTick)
309 events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000);
310 else
311 {
312 me->SetReactState(REACT_AGGRESSIVE);
313 me->SetDisplayId(DISPLAY_ANGER);
315 me->GetMotionMaster()->MoveChase(me->GetVictim());
316 events.ScheduleEvent(EVENT_WAILING_SOULS, std::rand() % 70000 + 60000);
317 }
318 break;
319 }
320 }
321
323 }
324
325 private:
327
328 // wailing soul event
332 };
333
335 {
336 return new boss_devourer_of_soulsAI(creature);
337 }
338};
339
340// 69051 - Mirrored Soul
374
375// 69023 - Mirrored Soul (Proc)
421
422// 69048 - Mirrored Soul (Target Selector)
424{
425 public:
426 spell_devourer_of_souls_mirrored_soul_target_selector() : SpellScriptLoader("spell_devourer_of_souls_mirrored_soul_target_selector") { }
427
461
466};
467
469{
470 public:
472 {
473 }
474
475 bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
476 {
477 if (!target)
478 return false;
479
480 if (Creature* Devourer = target->ToCreature())
481 if (Devourer->AI()->GetData(DATA_THREE_FACED))
482 return true;
483
484 return false;
485 }
486};
487
#define M_PI
Definition Common.h:192
const T & RAND(const T &v1, const T &v2)
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_DEAD_DESPAWN
Definition Object.h:74
#define sObjectMgr
Definition ObjectMgr.h:1617
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_SCRIPT_EFFECT
@ TARGET_UNIT_SRC_AREA_ENTRY
@ ALLIANCE
@ SPELL_AURA_PROC_TRIGGER_SPELL
#define sSpellMgr
Definition SpellMgr.h:744
#define AuraEffectProcFn(F, I, N)
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraCheckProcFn(F)
@ SPELLVALUE_BASE_POINT0
Definition Unit.h:114
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_DISABLE_MOVE
Definition Unit.h:627
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
T CalculatePct(T base, U pct)
Definition Util.h:103
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
Position const CrucibleSummonPos
@ EVENT_WAILING_SOULS
@ EVENT_WELL_OF_SOULS
@ EVENT_UNLEASHED_SOULS
@ EVENT_WAILING_SOULS_TICK
@ EVENT_PHANTOM_BLAST
@ EVENT_MIRRORED_SOUL
AchievementCriteriaScript(const char *name)
void PreventDefaultAction()
Unit * GetCaster() const
Unit * GetTarget() const
HookList< CheckProcHandler > DoCheckProc
HookList< EffectProcHandler > OnEffectProc
InstanceScript *const instance
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
uint32 GetDamage() const
Definition Unit.h:923
uint32 GetScriptId() const
Definition Map.h:646
Creature * ToCreature()
Definition Object.h:207
DamageInfo * GetDamageInfo() const
Definition Unit.h:985
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
bool IsAlive() const
Definition Unit.h:2032
void CastCustomSpell(Unit *victim, uint32 spellId, int32 const *bp0, int32 const *bp1, int32 const *bp2, bool triggered, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ 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 FoSScriptName
@ DATA_TEAM_IN_INSTANCE
@ DATA_DEVOURER_EVENT
C::value_type const & SelectRandomContainerElement(C const &container)
Definition Containers.h:48
Creature * me
void SpellHitTarget(Unit *, const SpellInfo *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================