TrinityCore
Loading...
Searching...
No Matches
boss_kiljaeden.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/* ScriptData
19SDName: Boss_Kiljaeden
20SD%Complete: 80
21SDComment: Sinister Reflection Model, Armageddon Visual, SAY_KJ_SHADOWSPIKE3, Emote, End Sequence
22SDCategory: Sunwell_Plateau
23EndScriptData */
24
26
27#include "ScriptMgr.h"
28#include "GameObject.h"
29#include "GameObjectAI.h"
30#include "InstanceScript.h"
31#include "Log.h"
32#include "MotionMaster.h"
33#include "ObjectAccessor.h"
34#include "Player.h"
35#include "ScriptedCreature.h"
36#include "sunwell_plateau.h"
37#include "TemporarySummon.h"
38
39/*** Speech and sounds***/
71
72/*** Spells used during the encounter ***/
74{
75 /* Hand of the Deceiver's spells and cosmetics */
76 SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage
77 SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry!
78 SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!)
79 SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat
80
81 /* Volatile Felfire Fiend's spells */
82 SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target.
83
84 /* Kil'Jaeden's spells and cosmetics */
85 SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?)
86 SPELL_REBIRTH = 44200, // Emerge from the Sunwell
87 SPELL_SOUL_FLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight.
89 SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5fk mana burn
90 SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK
91 SPELL_DESTROY_ALL_DRAKES = 46707, // when he use it?
92
93 SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work
94 // 45892 // right one for SPELL_SINISTER_REFLECTION but no EffectScriptEffect
95 SPELL_COPY_WEAPON = 41055, // }
96 SPELL_COPY_WEAPON2 = 41054, // }
97 SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation
99
100 SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs)
101 SPELL_FLAME_DART = 45737, // Bombards the raid with flames every 3(?) seconds
102 SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid
104
105 /* Armageddon spells wrong visual */
106 SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself
107 SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands
108 SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands
109 SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie
110 SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select
111 SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage
112
113 /* Shield Orb Spells*/
114 SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often /// @todo fix console error
115
116 /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */
117 SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble
118 SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this)
119 SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell
120
121 /* Sinister Reflection Spells */
124
126
128
130
133
136
140
142
144 //SPELL_SR_PLAGU STRIKE = 58843, Dk Spell!
145
146 /*** Other Spells (used by players, etc) ***/
147 SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid.
148 SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue
149 SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated
151
152/*** Others ***/
153#define SHIELD_ORB_Z 45.000f
154
156{
157 PHASE_DECEIVERS = 1, // Fight 3 adds
158 PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell
159 PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight
160 PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities
161 PHASE_SACRIFICE = 5 // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns.
163
164//Timers
184
185// Locations of the Hand of Deceiver adds
187{
188 {1682.949951f, 637.75000f, 28.0231f, 5.717090f},
189 {1684.699951f, 614.41998f, 28.0580f, 0.698392f},
190 {1707.609985f, 612.15002f, 28.0946f, 1.990370f}
191};
192
193// Locations, where Shield Orbs will spawn
195{
196 {1698.900f, 627.870f}, // middle pont of Sunwell
197 {12, 3.14f}, // First one spawns northeast of KJ
198 {12, 3.14f/0.7f}, // Second one spawns southeast
199 {12, 3.14f*3.8f} // Third one spawns (?)
200};
201
202struct Speech
203{
206};
207
208// Timers
210{
211 //Kil Phase 1 -> Phase 2
214 //Kil Phase 2 -> Phase 3
218 //Kil Phase 3 -> Phase 4
222 //Kil Phase 4 -> Phase 5
228
229 // use in End sequence?
231};
232
233//AI for Kalecgos
235{
236public:
237 boss_kalecgos_kj() : CreatureScript("boss_kalecgos_kj") { }
238
239 CreatureAI* GetAI(Creature* creature) const override
240 {
241 return GetSunwellPlateauAI<boss_kalecgos_kjAI>(creature);
242 }
243
245 {
247 {
248 Initialize();
249 instance = creature->GetInstanceScript();
250 }
251
253 {
254 OrbsEmpowered = 0;
255 EmpowerCount = 0;
256 }
257
261
262 void Reset() override
263 {
264 Initialize();
265 me->SetDisableGravity(true);
267 me->setActive(true);
268 me->SetFarVisible(true);
269
270 for (uint8 i = 0; i < 4; ++i)
271 if (GameObject* pOrb = GetOrb(i))
272 pOrb->SetGoType(GAMEOBJECT_TYPE_BUTTON);
273 }
274
291
293 {
295 for (uint8 i = 0; i < 4; ++i)
296 if (GameObject* pOrb = GetOrb(i))
297 pOrb->SetFaction(FACTION_NONE);
298 }
299
300 void EmpowerOrb(bool all)
301 {
302 GameObject* pOrbEmpowered = GetOrb(OrbsEmpowered);
303 if (!pOrbEmpowered)
304 return;
305
306 if (all)
307 {
309 for (uint8 i = 0; i < 4; ++i)
310 {
311 if (GameObject* pOrb = GetOrb(i))
312 {
313 pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES);
314 pOrb->SetFaction(FACTION_FRIENDLY);
315 pOrb->setActive(true);
316 pOrb->SetFarVisible(true);
317 pOrb->Refresh();
318 }
319 }
321 }
322 else
323 {
324 if (GameObject* pOrb = GetOrb(urand(0, 3)))
325 {
326 pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES);
327 pOrb->SetFaction(FACTION_FRIENDLY);
328 pOrb->setActive(true);
329 pOrb->SetFarVisible(true);
330 pOrb->Refresh();
331
333
334 ++EmpowerCount;
335 switch (EmpowerCount)
336 {
337 case 1: Talk(SAY_KALECGOS_READY1); break;
338 case 2: Talk(SAY_KALECGOS_READY2); break;
339 case 3: Talk(SAY_KALECGOS_READY3); break;
340 case 4: Talk(SAY_KALECGOS_READY4); break;
341 }
342 }
343 }
344 }
345
346 void UpdateAI(uint32 /*diff*/) override
347 {
348 }
349
351 {
353 for (uint8 i = 0; i < 4; ++i)
354 {
355 if (GameObject* pOrb = GetOrb(i))
356 {
357 if (pOrb->GetFaction() == FACTION_FRIENDLY)
358 {
359 pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES);
360 pOrb->setActive(true);
361 pOrb->SetFarVisible(true);
362 pOrb->Refresh();
363 }
364 }
365 }
366 }
367 };
368};
369
371{
372 public:
373 go_orb_of_the_blue_flight() : GameObjectScript("go_orb_of_the_blue_flight") { }
374
376 {
377 go_orb_of_the_blue_flightAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
378
380
381 bool OnGossipHello(Player* player) override
382 {
384 {
386 player->CastSpell(player, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false);
388
390 ENSURE_AI(boss_kalecgos_kj::boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames();
391
392 me->Refresh();
393 }
394 return true;
395 }
396 };
397
398 GameObjectAI* GetAI(GameObject* go) const override
399 {
400 return GetSunwellPlateauAI<go_orb_of_the_blue_flightAI>(go);
401 }
402};
403
404//AI for Kil'jaeden Event Controller
406{
407public:
408 npc_kiljaeden_controller() : CreatureScript("npc_kiljaeden_controller") { }
409
410 CreatureAI* GetAI(Creature* creature) const override
411 {
412 return GetSunwellPlateauAI<npc_kiljaeden_controllerAI>(creature);
413 }
414
416 {
418 {
419 Initialize();
420 instance = creature->GetInstanceScript();
421
422 SetCombatMovement(false);
423 }
424
426 {
429 bSummonedDeceivers = false;
430 bKiljaedenDeath = false;
431 uiRandomSayTimer = 30000;
432 }
433
436
439
443
452
453 void Reset() override
454 {
455 Initialize();
456
458 ENSURE_AI(boss_kalecgos_kj::boss_kalecgos_kjAI, pKalecKJ->AI())->ResetOrbs();
460 }
461
462 void JustSummoned(Creature* summoned) override
463 {
464 switch (summoned->GetEntry())
465 {
467 summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false);
468 break;
469 case NPC_ANVEENA:
470 summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true);
471 break;
472 case NPC_KILJAEDEN:
473 summoned->CastSpell(summoned, SPELL_REBIRTH, false);
474 AddThreat(me->GetVictim(), 1.0f, summoned);
475 break;
476 }
477 summons.Summon(summoned);
478 }
479
506 };
507};
508
509//AI for Kil'jaeden
511{
512public:
513 boss_kiljaeden() : CreatureScript("boss_kiljaeden") { }
514
516 {
518 {
519 Initialize();
520 instance = creature->GetInstanceScript();
521 speechPhaseEnd = 0;
522
523 SetCombatMovement(false);
524 }
525
527 {
529 Timer[TIMER_SPEECH] = 0;
530
531 //Phase 2 Timer
532 Timer[TIMER_SOUL_FLAY] = 11000;
534 Timer[TIMER_FIRE_BLOOM] = 20000;
536
537 //Phase 3 Timer
539 Timer[TIMER_FLAME_DART] = 3000;
540 Timer[TIMER_DARKNESS] = 45000;
541 Timer[TIMER_ORBS_EMPOWER] = 35000;
542
543 //Phase 4 Timer
544 Timer[TIMER_ARMAGEDDON] = 2000;
545
546 ActiveTimers = 5;
547 WaitTimer = 0;
548 speechCount = 0;
549 SpeechTimer = 0;
550
552
553 IsInDarkness = false;
554 IsWaiting = false;
555 OrbActivated = false;
556 SpeechBegins = true;
557
558 ChangeTimers(false, 0);
559 }
560
563
567
572
573 /* Boolean */
579
580 void InitializeAI() override
581 {
582 // Scripted_NoMovementAI::InitializeAI();
583 }
584
585 void Reset() override
586 {
587 Initialize();
588
590 pKalec->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES);
591
592 me->SetCombatReach(12);
594 }
595
596 void ChangeTimers(bool status, uint32 WTimer)
597 {
598 for (uint8 i = 1; i < ActiveTimers; ++i)
599 TimerIsDeactivated[i] = status;
600
601 if (WTimer > 0)
602 {
603 IsWaiting = true;
604 WaitTimer = WTimer;
605 }
606
607 if (OrbActivated)
609 if (Timer[TIMER_SHADOW_SPIKE] == 0)
611 if (Phase == PHASE_SACRIFICE)
613 }
614
615 void JustSummoned(Creature* summoned) override
616 {
617 if (summoned->GetEntry() == NPC_ARMAGEDDON_TARGET)
618 {
621 // summoned->SetVisibility(VISIBILITY_OFF); //with this we cant see the armageddon visuals
622 }
623 else
624 summoned->SetLevel(me->GetLevel());
625
626 summoned->SetFaction(me->GetFaction());
627 summons.Summon(summoned);
628 }
629
630 void JustDied(Unit* /*killer*/) override
631 {
635 }
636
637 void KilledUnit(Unit* /*victim*/) override
638 {
640 }
641
642 void EnterEvadeMode(EvadeReason why) override
643 {
645
647
648 // Reset the controller
651 }
652
653 void JustEngagedWith(Unit* /*who*/) override
654 {
656 }
657
659 {
660 SpeechBegins = true;
661 OrbActivated = false;
662 ChangeTimers(true, 0);//stop every cast Shadow spike will reactivate em all
665 // empowered orbs before darkness
666 Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(10000, 40000);
667 Timer[TIMER_ORBS_EMPOWER] = (Phase == PHASE_SACRIFICE) ? 10000 : 5000;
668 }
669
671 {
673 for (uint8 i = 0; i < 4; ++i)
674 {
676 {
677 float x, y, z;
678 target->GetPosition(x, y, z);
679 if (Creature* pSinisterReflection = me->SummonCreature(NPC_SINISTER_REFLECTION, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN))
680 {
681 pSinisterReflection->SetDisplayId(target->GetDisplayId());
682 pSinisterReflection->AI()->AttackStart(target);
683 }
684 }
685 }
686 }
687
688 void UpdateAI(uint32 diff) override
689 {
690 if (!UpdateVictim() || Phase < PHASE_NORMAL)
691 return;
692
693 if (IsWaiting)
694 {
695 if (WaitTimer <= diff)
696 {
697 IsWaiting = false;
698 ChangeTimers(false, 0);
699 } else WaitTimer -= diff;
700 }
701
702 for (uint8 t = 0; t < ActiveTimers; ++t)
703 {
704 if (Timer[t] < diff && !TimerIsDeactivated[t])
705 {
706 switch (t)
707 {
708 case TIMER_SPEECH:
709 if (SpeechBegins)
710 {
711 SpeechBegins = false;
712 switch (Phase)
713 {
714 case PHASE_NORMAL:
716 break;
717 case PHASE_DARKNESS:
719 break;
720 case PHASE_ARMAGEDDON:
722 break;
723 case PHASE_SACRIFICE:
725 break;
726 }
727 }
728 if (Speeches[speechCount].timer < SpeechTimer)
729 {
730 SpeechTimer = 0;
731 if (Creature* speechCreature = instance->GetCreature(Speeches[speechCount].creature))
732 speechCreature->AI()->Talk(Speeches[speechCount].textid);
733 if (speechCount == 12)
734 if (Creature* pAnveena = instance->GetCreature(DATA_ANVEENA))
735 pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false);
736 // ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds
739 speechCount++;
740 }
741 SpeechTimer += diff;
742 break;
743 case TIMER_SOUL_FLAY:
744 if (!me->IsNonMeleeSpellCast(false))
745 {
748 Timer[TIMER_SOUL_FLAY] = 3500;
749 }
750 break;
752 if (!me->IsNonMeleeSpellCast(false))
753 {
754 Unit* pRandomPlayer = nullptr;
755
757 for (uint8 z = 0; z < 6; ++z)
758 {
759 pRandomPlayer = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
760 if (!pRandomPlayer || !pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT))
761 break;
762 }
763
764 if (pRandomPlayer)
765 DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false);
766 else
767 TC_LOG_ERROR("scripts", "try to cast SPELL_LEGION_LIGHTNING on invalid target");
768
769 Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE
770 Timer[TIMER_SOUL_FLAY] = 2500;
771 }
772 break;
773 case TIMER_FIRE_BLOOM:
774 if (!me->IsNonMeleeSpellCast(false))
775 {
778 Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE
779 Timer[TIMER_SOUL_FLAY] = 1000;
780 }
781 break;
783 for (uint8 i = 1; i < Phase; ++i)
784 {
785 float sx, sy;
786 sx = ShieldOrbLocations[0][0] + std::sin(ShieldOrbLocations[i][0]);
787 sy = ShieldOrbLocations[0][1] + std::sin(ShieldOrbLocations[i][1]);
789 }
790 Timer[TIMER_SUMMON_SHILEDORB] = urand(30000, 60000); // 30-60seconds cooldown
791 Timer[TIMER_SOUL_FLAY] = 2000;
792 break;
793 case TIMER_SHADOW_SPIKE: //Phase 3
794 if (!me->IsNonMeleeSpellCast(false))
795 {
798 ChangeTimers(true, 30000);
801 }
802 break;
803 case TIMER_FLAME_DART: //Phase 3
805 Timer[TIMER_FLAME_DART] = 3000;
806 break;
807 case TIMER_DARKNESS: //Phase 3
808 if (!me->IsNonMeleeSpellCast(false))
809 {
810 // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members.
811 if (!IsInDarkness)
812 {
815 ChangeTimers(true, 9000);
816 Timer[TIMER_DARKNESS] = 8750;
818 if (Phase == PHASE_SACRIFICE)
820 IsInDarkness = true;
821 }
822 else
823 {
824 Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000, 70000);
825 IsInDarkness = false;
828 }
829 Timer[TIMER_SOUL_FLAY] = 9000;
830 }
831 break;
832 case TIMER_ORBS_EMPOWER: //Phase 3
834 {
835 switch (Phase)
836 {
837 case PHASE_SACRIFICE:
838 ENSURE_AI(boss_kalecgos_kj::boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true);
839 break;
840 default:
841 ENSURE_AI(boss_kalecgos_kj::boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false);
842 break;
843 }
844 }
845 OrbActivated = true;
847 break;
848 case TIMER_ARMAGEDDON: //Phase 4
849 Unit* target = nullptr;
850 for (uint8 z = 0; z < 6; ++z)
851 {
852 target = SelectTarget(SelectTargetMethod::Random, 0, 100, true);
853 if (!target || !target->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT)) break;
854 }
855 if (target)
856 {
857 float x, y, z;
858 target->GetPosition(x, y, z);
860 }
861 Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding
862 break;
863 }
864 }
865 }
867 //Time runs over!
868 for (uint8 i = 0; i < ActiveTimers; ++i)
869 if (!TimerIsDeactivated[i])
870 {
871 Timer[i] -= diff;
872 if (((int32)Timer[i]) < 0) Timer[i] = 0;
873 }
874
875 //Phase 3
877 {
878 if (Phase == PHASE_NORMAL && HealthBelowPct(85))
879 {
881 ActiveTimers = 9;
883 }
884 else return;
885 }
886
887 //Phase 4
889 {
890 if (Phase == PHASE_DARKNESS && HealthBelowPct(55))
891 {
893 ActiveTimers = 10;
895 }
896 else return;
897 }
898
899 //Phase 5 specific spells all we can
901 {
903 {
906 }
907 else return;
908 }
909 }
910 };
911
912 CreatureAI* GetAI(Creature* creature) const override
913 {
914 return GetSunwellPlateauAI<boss_kiljaedenAI>(creature);
915 }
916};
917
918//AI for Hand of the Deceiver
920{
921public:
922 npc_hand_of_the_deceiver() : CreatureScript("npc_hand_of_the_deceiver") { }
923
925 {
927 {
928 Initialize();
929 instance = creature->GetInstanceScript();
930 }
931
933 {
935 ShadowBoltVolleyTimer = urand(8000, 14000); // So they don't all cast it in the same moment.
936 FelfirePortalTimer = 20000;
937 }
938
940
943
944 void Reset() override
945 {
946 Initialize();
948 }
949
950 void JustSummoned(Creature* summoned) override
951 {
952 summoned->SetFaction(me->GetFaction());
953 summoned->SetLevel(me->GetLevel());
954 }
955
956 void JustEngagedWith(Unit* who) override
957 {
960 AddThreat(who, 1.0f, pControl);
961
963 }
964
965 void JustDied(Unit* /*killer*/) override
966 {
968 ++(ENSURE_AI(npc_kiljaeden_controller::npc_kiljaeden_controllerAI, pControl->AI())->deceiverDeathCount);
969 }
970
971 void UpdateAI(uint32 diff) override
972 {
973 if (!me->IsInCombat())
975
976 if (!UpdateVictim())
977 return;
978
979 // Gain Shadow Infusion at 20% health
982
983 // Shadow Bolt Volley - Shoots Shadow Bolts at all enemies within 30 yards, for ~2k Shadow damage.
984 if (ShadowBoltVolleyTimer <= diff)
985 {
987 ShadowBoltVolleyTimer = 12000;
988 }
989 else
990 ShadowBoltVolleyTimer -= diff;
991
992 // Felfire Portal - Creatres a portal, that spawns Volatile Felfire Fiends, which do suicide bombing.
993 if (FelfirePortalTimer <= diff)
994 {
997 AddThreat(ref->GetVictim(), 1.0f, pPortal);
998 FelfirePortalTimer = 20000;
999 } else FelfirePortalTimer -= diff;
1000
1002 }
1003 };
1004
1005 CreatureAI* GetAI(Creature* creature) const override
1006 {
1007 return GetSunwellPlateauAI<npc_hand_of_the_deceiverAI>(creature);
1008 }
1009};
1010
1011//AI for Felfire Portal
1013{
1014public:
1015 npc_felfire_portal() : CreatureScript("npc_felfire_portal") { }
1016
1017 CreatureAI* GetAI(Creature* creature) const override
1018 {
1019 return GetSunwellPlateauAI<npc_felfire_portalAI>(creature);
1020 }
1021
1023 {
1025 {
1026 Initialize();
1027 SetCombatMovement(false);
1028 }
1029
1031 {
1032 uiSpawnFiendTimer = 5000;
1033 }
1034
1036
1042
1043 void JustSummoned(Creature* summoned) override
1044 {
1045 summoned->SetFaction(me->GetFaction());
1046 summoned->SetLevel(me->GetLevel());
1047 }
1048
1049 void UpdateAI(uint32 diff) override
1050 {
1051 if (!UpdateVictim())
1052 return;
1053
1054 if (uiSpawnFiendTimer <= diff)
1055 {
1057 AddThreat(SelectTarget(SelectTargetMethod::Random, 0), 100000.0f, pFiend);
1058 uiSpawnFiendTimer = urand(4000, 8000);
1059 } else uiSpawnFiendTimer -= diff;
1060 }
1061 };
1062};
1063
1064//AI for Felfire Fiend
1066{
1067public:
1068 npc_volatile_felfire_fiend() : CreatureScript("npc_volatile_felfire_fiend") { }
1069
1070 CreatureAI* GetAI(Creature* creature) const override
1071 {
1072 return GetSunwellPlateauAI<npc_volatile_felfire_fiendAI>(creature);
1073 }
1074
1076 {
1078 {
1079 Initialize();
1080 }
1081
1083 {
1084 uiExplodeTimer = 2000;
1085 bLockedTarget = false;
1086 }
1087
1089
1091
1092 void Reset() override
1093 {
1094 Initialize();
1095 }
1096
1097 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1098 {
1099 if (damage > me->GetHealth())
1101 }
1102
1103 void UpdateAI(uint32 diff) override
1104 {
1105 if (!UpdateVictim())
1106 return;
1107
1108 if (!bLockedTarget)
1109 {
1110 AddThreat(me->GetVictim(), 10000000.0f);
1111 bLockedTarget = true;
1112 }
1113
1114 if (uiExplodeTimer)
1115 {
1116 if (uiExplodeTimer <= diff)
1117 uiExplodeTimer = 0;
1118 else uiExplodeTimer -= diff;
1119 }
1120 else if (me->IsWithinDistInMap(me->GetVictim(), 3)) // Explode if it's close enough to it's target
1121 {
1123 me->KillSelf();
1124 }
1125 }
1126 };
1127};
1128
1129//AI for Armageddon target
1131{
1132public:
1133 npc_armageddon() : CreatureScript("npc_armageddon") { }
1134
1135 CreatureAI* GetAI(Creature* creature) const override
1136 {
1137 return GetSunwellPlateauAI<npc_armageddonAI>(creature);
1138 }
1139
1141 {
1142 npc_armageddonAI(Creature* creature) : ScriptedAI(creature)
1143 {
1144 Initialize();
1145 SetCombatMovement(false);
1146 }
1147
1149 {
1150 spell = 0;
1151 uiTimer = 0;
1152 }
1153
1156
1157 void Reset() override
1158 {
1159 Initialize();
1160 }
1161
1162 void UpdateAI(uint32 diff) override
1163 {
1164 if (uiTimer <= diff)
1165 {
1166 switch (spell)
1167 {
1168 case 0:
1170 ++spell;
1171 break;
1172 case 1:
1174 uiTimer = 9000;
1175 ++spell;
1176 break;
1177 case 2:
1179 ++spell;
1180 uiTimer = 5000;
1181 break;
1182 case 3:
1184 break;
1185 }
1186 } else uiTimer -=diff;
1187 }
1188 };
1189};
1190
1191//AI for Shield Orbs
1193{
1194public:
1195 npc_shield_orb() : CreatureScript("npc_shield_orb") { }
1196
1197 CreatureAI* GetAI(Creature* creature) const override
1198 {
1199 return GetSunwellPlateauAI<npc_shield_orbAI>(creature);
1200 }
1201
1203 {
1204 npc_shield_orbAI(Creature* creature) : ScriptedAI(creature)
1205 {
1206 Initialize();
1207 instance = creature->GetInstanceScript();
1208 x = 0.f;
1209 y = 0.f;
1210 }
1211
1213 {
1214 bPointReached = true;
1215 uiTimer = urand(500, 1000);
1216 uiCheckTimer = 1000;
1217 r = 17;
1218 c = 0;
1219 mx = ShieldOrbLocations[0][0];
1220 my = ShieldOrbLocations[0][1];
1222 }
1223
1225
1230 float x, y, r, c, mx, my;
1231
1232 void Reset() override
1233 {
1234 me->SetDisableGravity(true);
1235 Initialize();
1236 }
1237
1238 void UpdateAI(uint32 diff) override
1239 {
1240 if (bPointReached)
1241 {
1242 if (bClockwise)
1243 {
1244 y = my - r * std::sin(c);
1245 x = mx - r * std::cos(c);
1246 }
1247 else
1248 {
1249 y = my + r * std::sin(c);
1250 x = mx + r * std::cos(c);
1251 }
1252 bPointReached = false;
1253 uiCheckTimer = 1000;
1255 c += float(M_PI)/32;
1256 if (c >= 2 * float(M_PI)) c = 0;
1257 }
1258 else
1259 {
1260 if (uiCheckTimer <= diff)
1261 {
1263 bPointReached = true;
1264 }
1265 else uiCheckTimer -= diff;
1266 }
1267
1268 if (uiTimer <= diff)
1269 {
1271 DoCast(random, SPELL_SHADOW_BOLT, false);
1272 uiTimer = urand(500, 1000);
1273 } else uiTimer -= diff;
1274 }
1275
1276 void MovementInform(uint32 type, uint32 /*id*/) override
1277 {
1278 if (type != POINT_MOTION_TYPE)
1279 return;
1280
1281 bPointReached = true;
1282 }
1283 };
1284};
1285
1286//AI for Sinister Reflection
1288{
1289public:
1290 npc_sinster_reflection() : CreatureScript("npc_sinster_reflection") { }
1291
1292 CreatureAI* GetAI(Creature* creature) const override
1293 {
1294 return GetSunwellPlateauAI<npc_sinster_reflectionAI>(creature);
1295 }
1296
1298 {
1300 {
1301 Initialize();
1302 }
1303
1305 {
1306 uiTimer[0] = 0;
1307 uiTimer[1] = 0;
1308 uiTimer[2] = 0;
1309 victimClass = 0;
1310 }
1311
1314
1315 void Reset() override
1316 {
1317 Initialize();
1318 }
1319
1320 void UpdateAI(uint32 diff) override
1321 {
1322 if (!UpdateVictim())
1323 return;
1324
1325 if ((victimClass == 0) && me->GetVictim())
1326 {
1328 switch (victimClass)
1329 {
1330 case CLASS_DRUID:
1331 break;
1332 case CLASS_HUNTER:
1333 break;
1334 case CLASS_MAGE:
1335 break;
1336 case CLASS_WARLOCK:
1337 break;
1338 case CLASS_WARRIOR:
1339 me->SetCanDualWield(true);
1340 break;
1341 case CLASS_PALADIN:
1342 break;
1343 case CLASS_PRIEST:
1344 break;
1345 case CLASS_SHAMAN:
1346 me->SetCanDualWield(true);
1347 break;
1348 case CLASS_ROGUE:
1349 me->SetCanDualWield(true);
1350 break;
1351 }
1352 }
1353
1354 switch (victimClass)
1355 {
1356 case CLASS_DRUID:
1357 if (uiTimer[1] <= diff)
1358 {
1360 uiTimer[1] = urand(2000, 4000);
1361 }
1363 break;
1364 case CLASS_HUNTER:
1365 if (uiTimer[1] <= diff)
1366 {
1368 uiTimer[1] = urand(8000, 10000);
1369 }
1370 if (uiTimer[2] <= diff)
1371 {
1373 uiTimer[2] = urand(4000, 6000);
1374 }
1376 {
1377 if (uiTimer[0] <= diff)
1378 {
1380 uiTimer[0] = urand(6000, 8000);
1381 }
1383 }
1384 break;
1385 case CLASS_MAGE:
1386 if (uiTimer[1] <= diff)
1387 {
1389 uiTimer[1] = urand(2000, 4000);
1390 }
1392 break;
1393 case CLASS_WARLOCK:
1394 if (uiTimer[1] <= diff)
1395 {
1397 uiTimer[1] = urand(3000, 5000);
1398 }
1399 if (uiTimer[2] <= diff)
1400 {
1402 uiTimer[2] = urand(2000, 4000);
1403 }
1405 break;
1406 case CLASS_WARRIOR:
1407 if (uiTimer[1] <= diff)
1408 {
1410 uiTimer[1] = urand(9000, 11000);
1411 }
1413 break;
1414 case CLASS_PALADIN:
1415 if (uiTimer[1] <= diff)
1416 {
1418 uiTimer[1] = urand(6000, 8000);
1419 }
1420 if (uiTimer[2] <= diff)
1421 {
1423 uiTimer[2] = urand(2000, 4000);
1424 }
1426 break;
1427 case CLASS_PRIEST:
1428 if (uiTimer[1] <= diff)
1429 {
1431 uiTimer[1] = urand(4000, 6000);
1432 }
1433 if (uiTimer[2] <= diff)
1434 {
1435 DoCast(me, SPELL_SR_RENEW, false);
1436 uiTimer[2] = urand(6000, 8000);
1437 }
1439 break;
1440 case CLASS_SHAMAN:
1441 if (uiTimer[1] <= diff)
1442 {
1444 uiTimer[1] = urand(4000, 6000);
1445 }
1447 break;
1448 case CLASS_ROGUE:
1449 if (uiTimer[1] <= diff)
1450 {
1452 uiTimer[1] = urand(4000, 6000);
1453 }
1455 break;
1456 }
1457 TC_LOG_DEBUG("scripts", "Sinister-Timer");
1458 for (uint8 i = 0; i < 3; ++i)
1459 uiTimer[i] -= diff;
1460 }
1461 };
1462};
1463
1465{
1467 new boss_kalecgos_kj();
1468 new boss_kiljaeden();
1471 new npc_felfire_portal();
1473 new npc_armageddon();
1474 new npc_shield_orb();
1476}
#define M_PI
Definition Common.h:72
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ POINT_MOTION_TYPE
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_MANUAL_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN
@ TEMPSUMMON_CORPSE_DESPAWN
Spells
Definition PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
bool roll_chance_i(int chance)
Definition Random.h:59
@ GAMEOBJECT_TYPE_BUTTON
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_PALADIN
@ CLASS_ROGUE
@ FACTION_FRIENDLY
@ FACTION_NONE
#define ENSURE_AI(a, b)
Definition UnitAI.h:28
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_UNINTERACTIBLE
@ UNIT_STATE_STUNNED
Definition Unit.h:223
DamageEffectType
Definition Unit.h:352
@ SAY_KJ_PHASE3
@ SAY_ANVEENA_GOODBYE
@ SAY_KALECGOS_READY1
@ SAY_KJ_DARKNESS
@ SAY_KJ_PHASE5
@ SAY_KALECGOS_FOCUS
@ SAY_KJ_EMERGE
@ SAY_KJ_SLAY
@ SAY_KJ_REFLECTION
@ SAY_KALECGOS_READY2
@ SAY_ANVEENA_LOST
@ SAY_KALECGOS_JOIN
@ SAY_KJ_DEATH
@ SAY_KJ_PHASE4
@ SAY_KALECGOS_LETGO
@ SAY_KALECGOS_GOODBYE
@ SAY_ANVEENA_IMPRISONED
@ SAY_ANVEENA_KALEC
@ SAY_KJ_OFFCOMBAT
@ SAY_KALECGOS_READY4
@ SAY_KALECGOS_AWAKEN
@ EMOTE_KJ_DARKNESS
@ SAY_KALECGOS_READY3
@ SAY_KALECGOS_ENCOURAGE
@ SAY_KALECGOS_FATE
void AddSC_boss_kiljaeden()
float ShieldOrbLocations[4][2]
@ SPELL_SHADOW_BOLT_VOLLEY
@ SPELL_SR_WING_CLIP
@ SPELL_SHADOW_SPIKE
@ SPELL_SR_MULTI_SHOT
@ SPELL_ENTROPIUS_BODY
@ SPELL_ARMAGEDDON_VISUAL3
@ SPELL_SR_HOLY_SHOCK
@ SPELL_DARKNESS_OF_A_THOUSAND_SOULS
@ SPELL_ARMAGEDDON_DAMAGE
@ SPELL_ARMAGEDDON_SUMMON_TRIGGER
@ SPELL_COPY_WEAPON
@ SPELL_COPY_WEAPON2
@ SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE
@ SPELL_FELFIRE_PORTAL
@ SPELL_SR_MOONFIRE
@ SPELL_ARMAGEDDON_VISUAL
@ SPELL_REBIRTH
@ SPELL_ANVEENA_PRISON
@ SPELL_TRANS
@ SPELL_RING_OF_BLUE_FLAMES
@ SPELL_SINISTER_REFLECTION
@ SPELL_DESTROY_ALL_DRAKES
@ SPELL_FIRE_BLOOM
@ SPELL_SR_HEMORRHAGE
@ SPELL_SHADOW_BOLT
@ SPELL_LEGION_LIGHTNING
@ SPELL_SR_WHIRLWIND
@ SPELL_SOUL_FLAY_SLOW
@ SPELL_SHADOW_INFUSION
@ SPELL_ARMAGEDDON_TRIGGER
@ SPELL_SR_HAMMER_OF_JUSTICE
@ SPELL_SR_RENEW
@ SPELL_SACRIFICE_OF_ANVEENA
@ SPELL_SR_HOLY_SMITE
@ SPELL_SR_EARTH_SHOCK
@ SPELL_SR_CURSE_OF_AGONY
@ SPELL_ARMAGEDDON_VISUAL2
@ SPELL_FLAME_DART
@ SPELL_SR_FIREBALL
@ SPELL_FELFIRE_FISSION
@ SPELL_SR_SHADOW_BOLT
@ SPELL_SOUL_FLAY
@ SPELL_ANVEENA_ENERGY_DRAIN
@ SPELL_SHADOW_CHANNELING
@ SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT
@ SPELL_SR_SHOOT
@ SPELL_COPY_OFFHAND
@ SPELL_COPY_OFFHAND_WEAPON
static Speech Speeches[]
Position DeceiverLocations[3]
#define SHIELD_ORB_Z
@ PHASE_SACRIFICE
@ PHASE_ARMAGEDDON
@ PHASE_DARKNESS
@ PHASE_DECEIVERS
@ PHASE_NORMAL
KilJaedenTimers
@ TIMER_ORBS_EMPOWER
@ TIMER_SPEECH
@ TIMER_ARMAGEDDON
@ TIMER_DARKNESS
@ TIMER_LEGION_LIGHTNING
@ TIMER_FLAME_DART
@ TIMER_FIRE_BLOOM
@ TIMER_SUMMON_SHILEDORB
@ TIMER_SOUL_FLAY
@ TIMER_SHADOW_SPIKE
Yells
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
virtual void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetCanDualWield(bool value) override
GameObject *const me
uint32 GetFaction() const override
Definition GameObject.h:285
void Refresh()
void SetFaction(uint32 faction) override
Definition GameObject.h:286
virtual bool SetBossState(uint32 id, EncounterState state)
Creature * GetCreature(uint32 type)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
uint32 GetEntry() const
Definition Object.h:81
void Summon(Creature const *summon)
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
virtual void InitializeAI()
Definition UnitAI.cpp:36
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:844
void KillSelf(bool durabilityLoss=true)
Definition Unit.h:1023
ThreatManager & GetThreatManager()
Definition Unit.h:1155
uint8 GetClass() const
Definition Unit.h:895
void SetFaction(uint32 faction) override
Definition Unit.h:974
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition Unit.cpp:3063
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
void AddUnitState(uint32 f)
Definition Unit.h:875
Unit * EnsureVictim() const
Definition Unit.h:861
void SetCombatReach(float combatReach)
Definition Unit.h:840
uint32 GetHealth() const
Definition Unit.h:913
uint32 GetFaction() const override
Definition Unit.h:973
void RemoveDynObject(uint32 spellId)
Definition Unit.cpp:5054
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
Unit * GetVictim() const
Definition Unit.h:859
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:9344
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
uint8 GetLevel() const
Definition Unit.h:889
bool IsInCombat() const
Definition Unit.h:1144
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
void setActive(bool isActiveObject)
Definition Object.cpp:991
void SetFarVisible(bool on)
Definition Object.cpp:1014
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
GameObjectAI * GetAI(GameObject *go) 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
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
float GetPositionZ() const
Definition Position.h:81
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
void SetCombatMovement(bool allowMovement)
void DoTeleportTo(float x, float y, float z, uint32 time=0)
bool HealthBelowPct(uint32 pct) const
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, Milliseconds despawntime)
void AddThreat(Unit *victim, float amount, Unit *who=nullptr)
uint32 creature
void EnterEvadeMode(EvadeReason why) override
void ChangeTimers(bool status, uint32 WTimer)
void JustSummoned(Creature *summoned) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
void JustSummoned(Creature *summoned) override
void UpdateAI(uint32 diff) override
void MovementInform(uint32 type, uint32) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
@ DATA_KILJAEDEN_CONTROLLER
@ DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4
@ DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1
@ DATA_MURU
@ DATA_KILJAEDEN
@ DATA_ANVEENA
@ DATA_PLAYER_GUID
@ DATA_KALECGOS_KJ
@ DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2
@ DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3
@ NPC_ARMAGEDDON_TARGET
@ NPC_POWER_OF_THE_BLUE_DRAGONFLIGHT
@ NPC_SHIELD_ORB
@ NPC_FELFIRE_PORTAL
@ NPC_VOLATILE_FELFIRE_FIEND
@ NPC_ANVEENA
@ NPC_KILJAEDEN
@ NPC_SINISTER_REFLECTION
@ NPC_HAND_OF_THE_DECEIVER