Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_reliquary_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/* ScriptData
7SDName: Boss_Reliquary_of_Souls
8SD%Complete: 90
9SDComment:
10SDCategory: Black Temple
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "black_temple.h"
16#include "Spell.h"
17
19{
20 //Sound'n'speech
21 //Suffering
28
29 //Desire
35
36 //Anger
42
43 //Spells
45 AURA_OF_SUFFERING_ARMOR = 42017, // linked aura, need core support
46 ESSENCE_OF_SUFFERING_PASSIVE = 41296, // periodic trigger 41294
48 SPELL_FIXATE_TARGET = 41294, // dummy, select target
49 SPELL_FIXATE_TAUNT = 41295, // force taunt
50 SPELL_ENRAGE = 41305,
52
56 SPELL_DEADEN = 41410,
58
60 SPELL_SELF_SEETHE = 41364, // force cast 41520
63 SPELL_SPITE_TARGET = 41376, // cast 41377 after 6 sec
65
68 SPELL_SUBMERGE = 37550, //dropout 'head'
69
72};
73
75{
76 float x, y;
77};
78
80{
81 {450.4f, 212.3f},
82 {542.1f, 212.3f},
83 {542.1f, 168.3f},
84 {542.1f, 137.4f},
85 {450.4f, 137.4f},
86 {450.4f, 168.3f}
87};
88
90{
91public:
92 npc_enslaved_soul() : CreatureScript("npc_enslaved_soul") { }
93
95 {
97 {
98 ReliquaryGUID = 0;
99 }
100
102
103 void EnterCombat(Unit* /*who*/) OVERRIDE
104 {
107 }
108
109 void JustDied(Unit* /*killer*/) OVERRIDE;
110
111 public:
113 };
114
116 {
117 return new npc_enslaved_soulAI(creature);
118 }
119};
120
122{
123public:
124 boss_reliquary_of_souls() : CreatureScript("boss_reliquary_of_souls") { }
125
127 {
129 {
130 instance = creature->GetInstanceScript();
131 EssenceGUID = 0;
132 Phase = 0;
133 Counter = 0;
134 Timer = 0;
135
136 SoulCount = 0;
137 SoulDeathCount = 0;
138 }
139
141 {
142 if (instance)
144
145 if (EssenceGUID)
146 {
148 essence->DespawnOrUnsummon();
149
150 EssenceGUID = 0;
151 }
152
153 Phase = 0;
154
157 me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
158 }
159
161 {
162 if (!who)
163 return;
164
165 if (me->IsInCombat())
166 return;
167
168 if (who->GetTypeId() != TypeID::TYPEID_PLAYER)
169 return;
170
171 if (me->GetDistance(who) > 50.0f)
172 return;
173
175 }
176
178 {
179 me->AddThreat(who, 10000.0f);
181 if (instance)
183
184 Phase = 1;
185 Counter = 0;
186 Timer = 0;
187 }
188
190 {
191 uint32 random = rand()%6;
192 float x = Coords[random].x;
193 float y = Coords[random].y;
194
195 Creature* Soul = me->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, me->GetPositionZ(), me->GetOrientation(), TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0);
196 if (!Soul)
197 return false;
198
199 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
200 {
201 CAST_AI(npc_enslaved_soul::npc_enslaved_soulAI, Soul->AI())->ReliquaryGUID = me->GetGUID();
202 Soul->AI()->AttackStart(target);
203 } else EnterEvadeMode();
204 return true;
205 }
206
208 {
209 if (!target)
210 return;
211
213 for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
214 {
215 Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid());
216 if (unit)
217 {
218 DoModifyThreatPercent(unit, -100);
219 float threat = target->getThreatManager().getThreat(unit);
220 me->AddThreat(unit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences).
221 }
222 }
223 }
224
225 void JustDied(Unit* /*killer*/) OVERRIDE
226 {
227 if (instance)
228 instance->SetBossState(DATA_RELIQUARY_OF_SOULS, DONE);
229 }
230
232 {
233 if (!Phase)
234 return;
235
236 if (me->getThreatManager().getThreatList().empty()) // Reset if event is begun and we don't have a threatlist
237 {
239 return;
240 }
241
242 Creature* Essence = NULL;
243 if (EssenceGUID)
244 {
245 Essence = Unit::GetCreature(*me, EssenceGUID);
246 if (!Essence)
247 {
249 return;
250 }
251 }
252
253 if (Timer <= diff)
254 {
255 switch (Counter)
256 {
257 case 0:
258 me->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, EMOTE_STATE_READY2H); // I R ANNNGRRRY!
260 Timer = 3000;
261 break;
262 case 1:
263 Timer = 2800;
264 me->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, EMOTE_ONESHOT_SUBMERGE); // Release the cube
267 break;
268 case 2:
269 Timer = 5000;
270 if (Creature* Summon = DoSpawnCreature(23417+Phase, 0, 0, 0, 0, TempSummonType::TEMPSUMMON_DEAD_DESPAWN, 0))
271 {
272 me->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); // Ribs: open
273 Summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO, 0));
274 EssenceGUID = Summon->GetGUID();
276 } else EnterEvadeMode();
277 break;
278 case 3:
279 Timer = 1000;
280 if (Phase == 3)
281 {
282 if (!Essence->IsAlive())
283 DoCast(me, 7, true);
284 else return;
285 }
286 else
287 {
289 {
290 MergeThreatList(Essence);
291 Essence->RemoveAllAuras();
292 Essence->DeleteThreatList();
293 Essence->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
294 } else return;
295 }
296 break;
297 case 4:
298 Timer = 1500;
299 if (Essence->IsWithinDistInMap(me, 10))
300 {
301 Essence->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, 374); //rotate and disappear
302 Timer = 2000;
303 me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
304 }
305 else
306 {
307 MergeThreatList(Essence);
308 Essence->RemoveAllAuras();
309 Essence->DeleteThreatList();
310 Essence->GetMotionMaster()->MoveFollow(me, 0, 0);
311 return;
312 }
313 break;
314 case 5:
315 if (Phase == 1)
316 {
317 Essence->AI()->Talk(SUFF_SAY_AFTER);
318 }
319 else
320 {
321 Essence->AI()->Talk(DESI_SAY_AFTER);
322 }
323 Essence->DespawnOrUnsummon();
324 me->SetUInt32Value(UNIT_FIELD_NPC_EMOTESTATE, 0);
325 EssenceGUID = 0;
326 SoulCount = 0;
327 SoulDeathCount = 0;
328 Timer = 3000;
329 break;
330 case 6:
332 {
333 if (SummonSoul())
334 ++SoulCount;
335 Timer = 500;
336 return;
337 }
338 break;
339 case 7:
341 {
342 Counter = 1;
343 ++Phase;
344 Timer = 5000;
345 }
346 return;
347 default:
348 break;
349 }
350 ++Counter;
351 } else Timer -= diff;
352 }
353
354 public:
356 private:
358
360
364
366 };
367
369 {
370 return new boss_reliquary_of_soulsAI(creature);
371 }
372};
373
375{
376 if (ReliquaryGUID)
377 if (Creature* Reliquary = (Unit::GetCreature((*me), ReliquaryGUID)))
378 ++(CAST_AI(boss_reliquary_of_souls::boss_reliquary_of_soulsAI, Reliquary->AI())->SoulDeathCount);
379
381}
382
384{
385public:
386 boss_essence_of_suffering() : CreatureScript("boss_essence_of_suffering") { }
387
389 {
391 {
392 StatAuraGUID = 0;
393
394 AggroYellTimer = 0;
395 FixateTimer = 0;
396 EnrageTimer = 0;
397 SoulDrainTimer = 0;
398 AuraTimer = 0;
399 }
400
402 {
403 StatAuraGUID = 0;
404
405 AggroYellTimer = 5000;
406 FixateTimer = 8000;
407 EnrageTimer = 30000;
408 SoulDrainTimer = 45000;
409 AuraTimer = 5000;
410 }
411
412 void DamageTaken(Unit* /*done_by*/, uint32 &damage) OVERRIDE
413 {
414 if (damage >= me->GetHealth())
415 {
416 damage = 0;
419 me->SetReactState(REACT_PASSIVE);
420 }
421 }
422
423 void EnterCombat(Unit* /*who*/) OVERRIDE
424 {
426 {
429 DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support
432 }
433 }
434
435 void KilledUnit(Unit* /*victim*/) OVERRIDE
436 {
438 }
439
441 {
442 ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();
443 if (threatlist.empty())
444 return; // No point continuing if empty threatlist.
445 std::list<Unit*> targets;
446 ThreatContainer::StorageType::const_iterator itr = threatlist.begin();
447 for (; itr != threatlist.end(); ++itr)
448 {
449 Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid());
450 if (unit && unit->IsAlive() && (unit->GetTypeId() == TypeID::TYPEID_PLAYER)) // Only alive players
451 targets.push_back(unit);
452 }
453 if (targets.empty())
454 return; // No targets added for some reason. No point continuing.
455 targets.sort(Skyfire::ObjectDistanceOrderPred(me)); // Sort players by distance.
456 targets.resize(1); // Only need closest target.
457 Unit* target = targets.front(); // Get the first target.
458 if (target)
459 target->CastSpell(me, SPELL_FIXATE_TAUNT, true);
461 me->AddThreat(target, 1000000);
462 }
463
465 {
466 if (me->IsInCombat())
467 {
468 //Supposed to be cast on nearest target
469 if (FixateTimer <= diff)
470 {
471 CastFixate();
472 FixateTimer = 5000;
473 if (!(rand()%16))
474 {
476 }
477 } else FixateTimer -= diff;
478 }
479
480 //Return since we have no target
481 if (!UpdateVictim())
482 return;
483
484 if (EnrageTimer <= diff)
485 {
487 EnrageTimer = 60000;
489 } else EnrageTimer -= diff;
490
491 if (SoulDrainTimer <= diff)
492 {
494 SoulDrainTimer = 60000;
495 } else SoulDrainTimer -= diff;
496
498 }
499
500 private:
502
508 };
509
511 {
512 return new boss_essence_of_sufferingAI(creature);
513 }
514};
515
517{
518public:
519 boss_essence_of_desire() : CreatureScript("boss_essence_of_desire") { }
520
522 {
524 {
525 RuneShieldTimer = 0;
526 DeadenTimer = 0;
527 SoulShockTimer = 0;
528 }
529
531 {
532 RuneShieldTimer = 60000;
533 DeadenTimer = 30000;
534 SoulShockTimer = 5000;
535 me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CONFUSE, true);
536 }
537
538 void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
539 {
540 if (done_by == me)
541 return;
542
543 if (damage >= me->GetHealth())
544 {
545 damage = 0;
548 me->SetReactState(REACT_PASSIVE);
549 }
550 else
551 {
552 int32 bp0 = damage / 2;
553 me->CastCustomSpell(done_by, AURA_OF_DESIRE_DAMAGE, &bp0, NULL, NULL, true);
554 }
555 }
556
557 void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
558 {
559 if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL))
560 for (uint8 i = 0; i < 3; ++i)
561 if (spell->Effects[i].Effect == SPELL_EFFECT_INTERRUPT_CAST)
562 if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK
563 || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN)
564 me->InterruptSpell(CURRENT_GENERIC_SPELL, false);
565 }
566
567 void EnterCombat(Unit* /*who*/) OVERRIDE
568 {
571 DoCast(me, AURA_OF_DESIRE, true);
572 }
573
574 void KilledUnit(Unit* /*victim*/) OVERRIDE
575 {
577 }
578
580 {
581 if (!UpdateVictim())
582 return;
583
584 if (RuneShieldTimer <= diff)
585 {
586 me->InterruptNonMeleeSpells(false);
588 SoulShockTimer += 2000;
589 DeadenTimer += 2000;
590 RuneShieldTimer = 60000;
591 } else RuneShieldTimer -= diff;
592
593 if (SoulShockTimer <= diff)
594 {
596 SoulShockTimer = 5000;
597 } else SoulShockTimer -= diff;
598
599 if (DeadenTimer <= diff)
600 {
601 me->InterruptNonMeleeSpells(false);
603 DeadenTimer = std::rand() % 35000 + 25000;
604 if (!(rand()%2))
605 {
607 }
608 } else DeadenTimer -= diff;
609
611 }
612
613 private:
617 };
618
620 {
621 return new boss_essence_of_desireAI(creature);
622 }
623};
624
626{
627public:
628 boss_essence_of_anger() : CreatureScript("boss_essence_of_anger") { }
629
631 {
633 {
634 AggroTargetGUID = 0;
635
636 CheckTankTimer = 0;
637 SoulScreamTimer = 0;
638 SpiteTimer = 0;
639
640 CheckedAggro = false;
641 }
642
644 {
645 AggroTargetGUID = 0;
646
647 CheckTankTimer = 5000;
648 SoulScreamTimer = 10000;
649 SpiteTimer = 30000;
650
651 SpiteTargetGUID.clear();
652
653 CheckedAggro = false;
654 }
655
656 void EnterCombat(Unit* /*who*/) OVERRIDE
657 {
659
661 DoCast(me, AURA_OF_ANGER, true);
662 }
663
664 void JustDied(Unit* /*killer*/) OVERRIDE
665 {
667 }
668
669 void KilledUnit(Unit* /*victim*/) OVERRIDE
670 {
672 }
673
675 {
676 //Return since we have no target
677 if (!UpdateVictim())
678 return;
679
680 if (!CheckedAggro)
681 {
682 AggroTargetGUID = me->GetVictim()->GetGUID();
683 CheckedAggro = true;
684 }
685
686 if (CheckTankTimer <= diff)
687 {
688 if (me->GetVictim()->GetGUID() != AggroTargetGUID)
689 {
692 AggroTargetGUID = me->GetVictim()->GetGUID();
693 }
694 CheckTankTimer = 2000;
695 } else CheckTankTimer -= diff;
696
697 if (SoulScreamTimer <= diff)
698 {
700 SoulScreamTimer = std::rand() % 11000 + 9000;
701 if (!(rand()%3))
702 {
704 }
705 } else SoulScreamTimer -= diff;
706
707 if (SpiteTimer <= diff)
708 {
710 SpiteTimer = 30000;
712 } else SpiteTimer -= diff;
713
715 }
716
717 private:
719
723
724 std::list<uint64> SpiteTargetGUID;
725
727 };
728
730 {
731 return new boss_essence_of_angerAI(creature);
732 }
733};
734
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ TEMPSUMMON_DEAD_DESPAWN
Definition Object.h:74
#define CAST_AI(a, b)
@ EMOTE_ONESHOT_SUBMERGE
@ EMOTE_STATE_READY2H
@ EMOTE_ONESHOT_NONE
@ EMOTE_STATE_SUBMERGED
@ SPELL_EFFECT_INTERRUPT_CAST
@ IMMUNITY_STATE
@ SPELL_AURA_MOD_CONFUSE
@ CURRENT_GENERIC_SPELL
Definition Unit.h:1109
@ REACT_PASSIVE
Definition Unit.h:1156
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_NPC_EMOTESTATE
@ SPELL_ENRAGE
@ DATA_RELIQUARY_OF_SOULS
@ SPELL_SUBMERGE
@ SPELL_SOUL_SCREAM
void AddSC_boss_reliquary_of_souls()
static Position2d Coords[]
@ CREATURE_ENSLAVED_SOUL
@ AURA_OF_DESIRE_DAMAGE
@ AURA_OF_SUFFERING_ARMOR
@ ESSENCE_OF_SUFFERING_PASSIVE
@ ESSENCE_OF_SUFFERING_PASSIVE2
@ ENSLAVED_SOUL_PASSIVE
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
void DespawnOrUnsummon(uint32 msTimeToDespawn=0)
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
void MoveFollow(Unit *target, float dist, float angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
static Creature * GetCreature(WorldObject const &u, uint64 guid)
TypeID GetTypeId() const
Definition Object.h:131
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
std::list< HostileReference * > StorageType
float getThreat(Unit *victim, bool alsoSearchOfflineList=false)
ThreatContainer::StorageType const & getThreatList() const
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
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
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)
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool IsAlive() const
Definition Unit.h:2032
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
void DeleteThreatList()
Definition Unit.cpp:4472
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
ThreatManager & getThreatManager()
Definition Unit.h:2455
void RemoveAllAuras()
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition Object.cpp:1735
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
void DoStartNoMovement(Unit *target)
Creature * me
void AttackStartNoMove(Unit *target)
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, TempSummonType type, uint32 despawntime)
ScriptedAI(Creature *creature)
void DoModifyThreatPercent(Unit *unit, int32 pct)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *done_by, uint32 &damage) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, const SpellInfo *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================