Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_kaelthas.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_Kaelthas
8SD%Complete: 60
9SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse
10SDCategory: Tempest Keep, The Eye
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "the_eye.h"
16#include "WorldPacket.h"
17#include "Opcodes.h"
18
20{
21 // Kael'thas Speech
36
37 // Thaladred the Darkener speech
41
42 //Lord Sanguinar speech
45
46 // Grand Astromancer Capernian speech
49
50 // Master Engineer Telonicus speech
53};
54
56{
57 // Phase 2 spells
67
68 // Phase 4 spells
69 SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell
78
79 // Phase 5 spells
86
87 // Thaladred the Darkener spells
90 // Lord Sanguinar spells
92 // Grand Astromancer Capernian spells
93
97 //Master Engineer Telonicus spells
98 SPELL_BOMB = 37036,
100 //Nether Vapor spell
102 //Phoenix spell
103 SPELL_BURN = 36720,
106};
107
109{
110 NPC_PHOENIX = 21362,
112};
113
115{
116 //Phoenix egg and phoenix model
119};
120
122{
124};
125
131
132const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target
133//const float KAEL_VISIBLE_RANGE = 50.0f;
134
135const float afGravityPos[3] = {795.0f, 0.0f, 70.0f};
136
137#define TIME_PHASE_2_3 120000
138#define TIME_PHASE_3_4 180000
139
140//Base AI for Advisors
142{
143 advisorbase_ai(Creature* creature) : ScriptedAI(creature)
144 {
145 instance = creature->GetInstanceScript();
146 m_bDoubled_Health = false;
147 }
148
154
156 {
158 {
159 me->SetMaxHealth(me->GetMaxHealth() / 2);
160 m_bDoubled_Health = false;
161 }
162
163 FakeDeath = false;
164 DelayRes_Timer = 0;
165 DelayRes_Target = 0;
166
167 me->SetStandState(UNIT_STAND_STATE_STAND);
170
171 //reset encounter
172 if (instance && (instance->GetData(DATA_KAELTHASEVENT) == 1 || instance->GetData(DATA_KAELTHASEVENT) == 3))
173 if (Creature* Kaelthas = Unit::GetCreature(*me, instance->GetData64(DATA_KAELTHAS)))
174 Kaelthas->AI()->EnterEvadeMode();
175 }
176
178
179 {
180 if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
181 return;
182
184 }
185
187 {
188 if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
189 return;
190
192 }
193
194 void Revive(Unit* /*Target*/)
195 {
197 // double health for phase 3
198 me->SetMaxHealth(me->GetMaxHealth() * 2);
199 m_bDoubled_Health = true;
200 me->SetFullHealth();
201 me->SetStandState(UNIT_STAND_STATE_STAND);
202
203 DoCast(me, SPELL_RES_VISUAL, false);
204 DelayRes_Timer = 2000;
205 }
206
207 void DamageTaken(Unit* killer, uint32 &damage) OVERRIDE
208 {
209 if (damage < me->GetHealth())
210 return;
211
212 //Prevent glitch if in fake death
213 if (FakeDeath && instance && instance->GetData(DATA_KAELTHASEVENT) != 0)
214 {
215 damage = 0;
216 return;
217 }
218
219 //Don't really die in phase 1 & 3, only die after that
220 if (instance && instance->GetData(DATA_KAELTHASEVENT) != 0)
221 {
222 //prevent death
223 damage = 0;
224 FakeDeath = true;
225
226 me->InterruptNonMeleeSpells(false);
227 me->SetHealth(0);
228 me->StopMoving();
229 me->ClearComboPointHolders();
230 me->RemoveAllAurasOnDeath();
231 me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
232 me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
234 me->ClearAllReactives();
235 me->SetTarget(0);
236 me->GetMotionMaster()->Clear();
237 me->GetMotionMaster()->MoveIdle();
238 me->SetStandState(UNIT_STAND_STATE_DEAD);
239 JustDied(killer);
240 }
241 }
242
244 {
245 if (DelayRes_Timer)
246 {
247 if (DelayRes_Timer <= diff)
248 {
249 DelayRes_Timer = 0;
250 FakeDeath = false;
251
253 if (!Target)
254 Target = me->GetVictim();
255
257 AttackStart(Target);
258 me->GetMotionMaster()->Clear();
259 me->GetMotionMaster()->MoveChase(Target);
260 me->AddThreat(Target, 0.0f);
261 } else DelayRes_Timer -= diff;
262 }
263 }
264};
265
267{
268 public:
270 : CreatureScript("boss_kaelthas")
271 {
272 }
273 //Kael'thas AI
275 {
277 {
278 instance = creature->GetInstanceScript();
279 memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid));
280 }
281
283
296 uint32 Phase_Timer; //generic timer
298
302
304
306
308 {
309 Fireball_Timer = 5000+rand()%10000;
311 MindControl_Timer = 40000;
312 Phoenix_Timer = 50000;
313 ShockBarrier_Timer = 60000;
314 FlameStrike_Timer = 30000;
315 GravityLapse_Timer = 20000;
317 NetherBeam_Timer = 8000;
318 NetherVapor_Timer = 10000;
319 PyrosCasted = 0;
320 Phase = 0;
321 InGravityLapse = false;
322 IsCastingFireball = false;
323 ChainPyros = false;
324
325 if (me->IsInCombat())
327
328 summons.DespawnAll();
329
332
333 if (instance)
334 instance->SetData(DATA_KAELTHASEVENT, 0);
335 }
336
338 {
339 for (uint8 i = 0; i < MAX_ADVISORS; ++i)
340 {
341 if (Creature* creature = Unit::GetCreature(*me, m_auiAdvisorGuid[i]))
342 {
343 creature->Respawn();
344 creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
345 creature->setFaction(me->getFaction());
346 creature->AI()->EnterEvadeMode();
347 }
348 }
349 }
350
352 {
353 if (!instance)
354 return;
355
360
362 {
363 SF_LOG_ERROR("scripts", "Kael'Thas One or more advisors missing, Skipping Phases 1-3");
364
366
367 Phase = 4;
368
369 instance->SetData(DATA_KAELTHASEVENT, 4);
370
373
374 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
375 AttackStart(target);
376 }
377 else
378 {
380
382
383 instance->SetData(DATA_KAELTHASEVENT, 1);
385
386 PhaseSubphase = 0;
387 Phase_Timer = 23000;
388 Phase = 1;
389 }
390 }
391
393
394 {
395 if (!me->HasUnitState(UNIT_STATE_STUNNED) && me->CanCreatureAttack(who))
396 {
397 if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
398 return;
399
400 float attackRadius = me->GetAttackDistance(who);
401 if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who))
402 {
403 if (!me->GetVictim() && Phase >= 4)
404 {
405 who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
406 AttackStart(who);
407 }
408 else if (me->GetMap()->IsDungeon())
409 {
410 if (instance && !instance->GetData(DATA_KAELTHASEVENT) && !Phase)
411 StartEvent();
412
413 who->SetInCombatWith(me);
414 me->AddThreat(who, 0.0f);
415 }
416 }
417 }
418 }
419
420 void EnterCombat(Unit* /*who*/) OVERRIDE
421 {
422 if (instance && !instance->GetData(DATA_KAELTHASEVENT) && !Phase)
423 StartEvent();
424 }
425
426 void KilledUnit(Unit* /*victim*/) OVERRIDE
427 {
428 Talk(SAY_SLAY);
429 }
430
432 {
433 // if not phoenix, then it's one of the 7 weapons
434 if (summoned->GetEntry() != NPC_PHOENIX)
435 {
436 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
437 summoned->AI()->AttackStart(target);
438
439 summons.Summon(summoned);
440 }
441 }
442
444 {
445 summons.Despawn(summon);
446 }
447
448 void JustDied(Unit* /*killer*/) OVERRIDE
449 {
452
454
455 summons.DespawnAll();
456
457 if (instance)
458 instance->SetData(DATA_KAELTHASEVENT, 0);
459
460 for (uint8 i = 0; i < MAX_ADVISORS; ++i)
461 {
462 if (Unit* pAdvisor = Unit::GetUnit(*me, m_auiAdvisorGuid[i]))
463 pAdvisor->Kill(pAdvisor);
464 }
465 }
466
468 {
469 //Phase 1
470 switch (Phase)
471 {
472 case 1:
473 {
474 Unit* target = NULL;
475 Creature* Advisor = NULL;
476
477 //Subphase switch
478 switch (PhaseSubphase)
479 {
480 //Subphase 1 - Start
481 case 0:
482 if (Phase_Timer <= diff)
483 {
485
486 //start advisor within 7 seconds
487 Phase_Timer = 7000;
489 } else Phase_Timer -= diff;
490 break;
491
492 //Subphase 1 - Unlock advisor
493 case 1:
494 if (Phase_Timer <= diff)
495 {
496 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[0]));
497
498 if (Advisor)
499 {
501 Advisor->setFaction(me->getFaction());
502
504 if (target)
505 Advisor->AI()->AttackStart(target);
506 }
507
509 } else Phase_Timer -= diff;
510 break;
511
512 //Subphase 2 - Start
513 case 2:
514 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[0]));
515
516 if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD))
517 {
519
520 //start advisor within 12.5 seconds
521 Phase_Timer = 12500;
523 }
524 break;
525
526 //Subphase 2 - Unlock advisor
527 case 3:
528 if (Phase_Timer <= diff)
529 {
530 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[1]));
531
532 if (Advisor)
533 {
535 Advisor->setFaction(me->getFaction());
536
538 if (target)
539 Advisor->AI()->AttackStart(target);
540 }
541
543 } else Phase_Timer -= diff;
544 break;
545
546 //Subphase 3 - Start
547 case 4:
548 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[1]));
549
550 if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD))
551 {
553
554 //start advisor within 7 seconds
555 Phase_Timer = 7000;
557 }
558 break;
559
560 //Subphase 3 - Unlock advisor
561 case 5:
562 if (Phase_Timer <= diff)
563 {
564 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[2]));
565
566 if (Advisor)
567 {
569 Advisor->setFaction(me->getFaction());
570
572 if (target)
573 Advisor->AI()->AttackStart(target);
574 }
575
577 } else Phase_Timer -= diff;
578 break;
579
580 //Subphase 4 - Start
581 case 6:
582 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[2]));
583
584 if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD))
585 {
587
588 //start advisor within 8.4 seconds
589 Phase_Timer = 8400;
591 }
592 break;
593
594 //Subphase 4 - Unlock advisor
595 case 7:
596 if (Phase_Timer <= diff)
597 {
598 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[3]));
599
600 if (Advisor)
601 {
603 Advisor->setFaction(me->getFaction());
604
606 if (target)
607 Advisor->AI()->AttackStart(target);
608 }
609
610 Phase_Timer = 3000;
612 } else Phase_Timer -= diff;
613 break;
614
615 //End of phase 1
616 case 8:
617 Advisor = (Unit::GetCreature(*me, m_auiAdvisorGuid[3]));
618
619 if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD))
620 {
621 Phase = 2;
622 if (instance)
623 instance->SetData(DATA_KAELTHASEVENT, 2);
624
626
627 PhaseSubphase = 0;
628 Phase_Timer = 3500;
630 }
631 break;
632 }
633 }
634 break;
635
636 case 2:
637 {
638 if (PhaseSubphase == 0)
639 {
640 if (Phase_Timer <= diff)
641 {
642 PhaseSubphase = 1;
643 }
644 else
645 Phase_Timer -= diff;
646 }
647
648 //Spawn weapons
649 if (PhaseSubphase == 1)
650 {
652
653 uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32);
654
655 for (uint32 i = 0; i < uiMaxWeapon; ++i)
657
658 PhaseSubphase = 2;
660 }
661
662 if (PhaseSubphase == 2)
663 {
664 if (Phase_Timer <= diff)
665 {
667 if (instance)
668 instance->SetData(DATA_KAELTHASEVENT, 3);
669 Phase = 3;
670 PhaseSubphase = 0;
671 }
672 else
673 Phase_Timer -= diff;
674 }
675 }
676 break;
677
678 case 3:
679 {
680 if (PhaseSubphase == 0)
681 {
682 //Respawn advisors
684
685 Creature* Advisor;
686 for (uint8 i = 0; i < MAX_ADVISORS; ++i)
687 {
688 Advisor = Unit::GetCreature(*me, m_auiAdvisorGuid[i]);
689
690 if (!Advisor)
691 SF_LOG_ERROR("scripts", "SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i);
692 else
693 CAST_AI(advisorbase_ai, Advisor->AI())->Revive(target);
694 }
695
696 PhaseSubphase = 1;
698 }
699
700 if (Phase_Timer <= diff)
701 {
703 Phase = 4;
704
705 if (instance)
706 instance->SetData(DATA_KAELTHASEVENT, 4);
707
708 // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael.
710
713
714 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
715 AttackStart(target);
716
717 Phase_Timer = 30000;
718 }
719 else
720 Phase_Timer -= diff;
721 }
722 break;
723
724 case 4:
725 case 5:
726 case 6:
727 {
728 //Return since we have no target
729 if (!UpdateVictim())
730 return;
731
732 //Fireball_Timer
733 if (!InGravityLapse && !ChainPyros && Phase != 5)
734 {
735 if (Fireball_Timer <= diff)
736 {
738 {
739 if (!me->IsNonMeleeSpellCasted(false))
740 {
741 //interruptable
742 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
743 int32 dmg = 20000+rand()%5000;
744 me->CastCustomSpell(me->GetVictim(), SPELL_FIREBALL, &dmg, 0, 0, false);
745 IsCastingFireball = true;
746 Fireball_Timer = 2500;
747 }
748 }
749 else
750 {
751 //apply resistance
752 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
753 IsCastingFireball = false;
754 Fireball_Timer = 5000+rand()%10000;
755 }
756 }
757 else
758 Fireball_Timer -= diff;
759
760 //ArcaneDisruption_Timer
761 if (ArcaneDisruption_Timer <= diff)
762 {
765 }
766 else
768
769 if (FlameStrike_Timer <= diff)
770 {
771 if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0))
773
774 FlameStrike_Timer = 30000;
775 }
776 else
777 FlameStrike_Timer -= diff;
778
779 if (MindControl_Timer <= diff)
780 {
781 if (me->getThreatManager().getThreatList().size() >= 2)
782 for (uint32 i = 0; i < 3; ++i)
783 {
784 SF_LOG_DEBUG("scripts", "Kael'Thas mind control not supported.");
785 //DoCast(unit, SPELL_MIND_CONTROL);
786 }
787
788 MindControl_Timer = 60000;
789 }
790 else
791 MindControl_Timer -= diff;
792 }
793
794 //Phoenix_Timer
795 if (Phoenix_Timer <= diff)
796 {
799
800 Phoenix_Timer = 60000;
801 }
802 else
803 Phoenix_Timer -= diff;
804
805 //Phase 4 specific spells
806 if (Phase == 4)
807 {
808 if (HealthBelowPct(50))
809 {
810 if (instance)
811 instance->SetData(DATA_KAELTHASEVENT, 4);
812 Phase = 5;
813 Phase_Timer = 10000;
814
816
817 me->StopMoving();
818 me->GetMotionMaster()->Clear();
819 me->GetMotionMaster()->MoveIdle();
820 me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
821 me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 1);
822
823 me->InterruptNonMeleeSpells(false);
826 }
827
828 //ShockBarrier_Timer
829 if (ShockBarrier_Timer <= diff)
830 {
832 ChainPyros = true;
833 PyrosCasted = 0;
834 ShockBarrier_Timer = 60000;
835 }
836 else
837 ShockBarrier_Timer -= diff;
838
839 //Chain Pyros (3 of them max)
840 if (ChainPyros && !me->IsNonMeleeSpellCasted(false))
841 {
842 if (PyrosCasted < 3)
843 {
845 ++PyrosCasted;
846 }
847 else
848 {
849 ChainPyros = false;
850 Fireball_Timer = 2500;
852 }
853 }
854 }
855
856 if (Phase == 5)
857 {
858 if (Phase_Timer <= diff)
859 {
860 me->InterruptNonMeleeSpells(false);
861 me->RemoveAurasDueToSpell(SPELL_FULLPOWER);
862
864
866 Phase = 6;
867 AttackStart(me->GetVictim());
868 }
869 else
870 Phase_Timer -= diff;
871 }
872
873 //Phase 5
874 if (Phase == 6)
875 {
876 //GravityLapse_Timer
877 if (GravityLapse_Timer <= diff)
878 {
879 ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
880 ThreatContainer::StorageType::const_iterator i = threatlist.begin();
881
882 switch (GravityLapse_Phase)
883 {
884 case 0:
885 me->StopMoving();
886 me->GetMotionMaster()->Clear();
887 me->GetMotionMaster()->MoveIdle();
888 me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
889 me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0);
890
891 // 1) Kael'thas will portal the whole raid right into his body
892 for (i = threatlist.begin(); i != threatlist.end(); ++i)
893 {
894 Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid());
895 if (unit && (unit->GetTypeId() == TypeID::TYPEID_PLAYER))
896 {
897 //Use work around packet to prevent player from being dropped from combat
899 }
900 }
901
902 GravityLapse_Timer = 500;
904 InGravityLapse = true;
905 ShockBarrier_Timer = 1000;
906 NetherBeam_Timer = 5000;
907 break;
908
909 case 1:
911
912 // 2) At that point he will put a Gravity Lapse debuff on everyone
913 for (i = threatlist.begin(); i != threatlist.end(); ++i)
914 {
915 if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()))
916 {
917 DoCast(unit, SPELL_KNOCKBACK, true);
918 //Gravity lapse - needs an exception in Spell system to work
919
920 unit->CastSpell(unit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID());
921 unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID());
922
923 //Using packet workaround
925 data.append(unit->GetPackGUID());
926 data << uint32(0);
927 unit->SendMessageToSet(&data, true);
928 }
929 }
930 GravityLapse_Timer = 10000;
932 break;
933
934 case 2:
935 //Cast nether vapor aura on self
936 me->InterruptNonMeleeSpells(false);
938
939 GravityLapse_Timer = 20000;
941 break;
942
943 case 3:
944 //Remove flight
945 for (i = threatlist.begin(); i != threatlist.end(); ++i)
946 {
947 if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()))
948 {
949 //Using packet workaround
951 data.append(unit->GetPackGUID());
952 data << uint32(0);
953 unit->SendMessageToSet(&data, true);
954 }
955 }
956
957 me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR);
958 InGravityLapse = false;
959 GravityLapse_Timer = 60000;
961 AttackStart(me->GetVictim());
962 break;
963 }
964 }
965 else
966 GravityLapse_Timer -= diff;
967
968 if (InGravityLapse)
969 {
970 //ShockBarrier_Timer
971 if (ShockBarrier_Timer <= diff)
972 {
974 ShockBarrier_Timer = 20000;
975 }
976 else
977 ShockBarrier_Timer -= diff;
978
979 //NetherBeam_Timer
980 if (NetherBeam_Timer <= diff)
981 {
982 if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0))
984
985 NetherBeam_Timer = 4000;
986 }
987 else
988 NetherBeam_Timer -= diff;
989 }
990 }
991
992 if (!InGravityLapse)
994 }
995 }
996 }
997 };
999 {
1000 return new boss_kaelthasAI(creature);
1001 }
1002};
1003
1004//Thaladred the Darkener AI
1006{
1007public:
1009 : CreatureScript("boss_thaladred_the_darkener")
1010 {
1011 }
1013 {
1015
1019
1021 {
1022 Gaze_Timer = 100;
1023 Silence_Timer = 20000;
1024 PsychicBlow_Timer = 10000;
1025
1027 }
1028
1030 {
1032 return;
1033
1034 if (!who || FakeDeath)
1035 return;
1036
1038 me->AddThreat(who, 5000000.0f);
1039 }
1040
1041 void JustDied(Unit* /*killer*/) OVERRIDE
1042 {
1043 if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3)
1045 }
1046
1048 {
1050
1051 //Faking death, don't do anything
1052 if (FakeDeath)
1053 return;
1054
1055 //Return since we have no target
1056 if (!UpdateVictim())
1057 return;
1058
1059 //Gaze_Timer
1060 if (Gaze_Timer <= diff)
1061 {
1062 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
1063 {
1064 DoResetThreat();
1065 me->AddThreat(target, 5000000.0f);
1066 Talk(EMOTE_THALADRED_GAZE, target);
1067 Gaze_Timer = 8500;
1068 }
1069 }
1070 else
1071 Gaze_Timer -= diff;
1072
1073 //Silence_Timer
1074 if (Silence_Timer <= diff)
1075 {
1077 Silence_Timer = 20000;
1078 }
1079 else
1080 Silence_Timer -= diff;
1081
1082 //PsychicBlow_Timer
1083 if (PsychicBlow_Timer <= diff)
1084 {
1086 PsychicBlow_Timer = 20000+rand()%5000;
1087 }
1088 else
1089 PsychicBlow_Timer -= diff;
1090
1092 }
1093 };
1094
1096 {
1097 return new boss_thaladred_the_darkenerAI(creature);
1098 }
1099};
1100
1101//Lord Sanguinar AI
1103{
1104public:
1106 : CreatureScript("boss_lord_sanguinar")
1107 {
1108 }
1110 {
1112
1114
1116 {
1117 Fear_Timer = 20000;
1119 }
1120
1122 {
1124 return;
1125
1126 if (!who || FakeDeath)
1127 return;
1128
1130 }
1131
1132 void JustDied(Unit* /*killer*/) OVERRIDE
1133 {
1134 if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3)
1136 }
1137
1139 {
1141
1142 //Faking death, don't do anything
1143 if (FakeDeath)
1144 return;
1145
1146 //Return since we have no target
1147 if (!UpdateVictim())
1148 return;
1149
1150 //Fear_Timer
1151 if (Fear_Timer <= diff)
1152 {
1154 Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds
1155 }
1156 else
1157 Fear_Timer -= diff;
1158
1160 }
1161 };
1163 {
1164 return new boss_lord_sanguinarAI(creature);
1165 }
1166};
1167//Grand Astromancer Capernian AI
1169{
1170public:
1172 : CreatureScript("boss_grand_astromancer_capernian")
1173 {
1174 }
1176 {
1178
1183 bool Yell;
1184
1186 {
1187 Fireball_Timer = 2000;
1188 Conflagration_Timer = 20000;
1189 ArcaneExplosion_Timer = 5000;
1190 Yell_Timer = 2000;
1191 Yell = false;
1192
1194 }
1195
1196 void JustDied(Unit* /*killer*/) OVERRIDE
1197 {
1198 if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3)
1200 }
1201
1203 {
1204 if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
1205 return;
1206
1207 if (me->Attack(who, true))
1208 {
1209 me->AddThreat(who, 0.0f);
1210 me->SetInCombatWith(who);
1211 who->SetInCombatWith(me);
1212
1213 me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE);
1214 }
1215 }
1216
1218 {
1220 return;
1221
1222 if (!who || FakeDeath)
1223 return;
1224 }
1225
1227 {
1229
1230 //Faking Death, don't do anything
1231 if (FakeDeath)
1232 return;
1233
1234 //Return since we have no target
1235 if (!UpdateVictim())
1236 return;
1237
1238 //Yell_Timer
1239 if (!Yell)
1240 {
1241 if (Yell_Timer <= diff)
1242 {
1244 Yell = true;
1245 }
1246 else
1247 Yell_Timer -= diff;
1248 }
1249
1250 //Fireball_Timer
1251 if (Fireball_Timer <= diff)
1252 {
1254 Fireball_Timer = 4000;
1255 }
1256 else
1257 Fireball_Timer -= diff;
1258
1259 //Conflagration_Timer
1260 if (Conflagration_Timer <= diff)
1261 {
1262 Unit* target = NULL;
1264
1265 if (target && me->IsWithinDistInMap(target, 30))
1266 DoCast(target, SPELL_CONFLAGRATION);
1267 else
1269
1270 Conflagration_Timer = 10000+rand()%5000;
1271 }
1272 else
1273 Conflagration_Timer -= diff;
1274
1275 //ArcaneExplosion_Timer
1276 if (ArcaneExplosion_Timer <= diff)
1277 {
1278 bool InMeleeRange = false;
1279 Unit* target = NULL;
1280 ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();
1281 for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i!= threatlist.end(); ++i)
1282 {
1283 Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid());
1284 //if in melee range
1285 if (unit && unit->IsWithinDistInMap(me, 5))
1286 {
1287 InMeleeRange = true;
1288 target = unit;
1289 break;
1290 }
1291 }
1292
1293 if (InMeleeRange)
1295
1296 ArcaneExplosion_Timer = 4000+rand()%2000;
1297 }
1298 else
1299 ArcaneExplosion_Timer -= diff;
1300
1301 //Do NOT deal any melee damage.
1302 }
1303 };
1304
1306 {
1307 return new boss_grand_astromancer_capernianAI(creature);
1308 }
1309};
1310
1311//Master Engineer Telonicus AI
1313{
1314public:
1316 : CreatureScript("boss_master_engineer_telonicus")
1317 {
1318 }
1320 {
1322
1325
1327 {
1328 Bomb_Timer = 10000;
1329 RemoteToy_Timer = 5000;
1330
1332 }
1333
1334 void JustDied(Unit* /*killer*/) OVERRIDE
1335 {
1336 if (instance && instance->GetData(DATA_KAELTHASEVENT) == 3)
1338 }
1339
1341 {
1343 return;
1344
1345 if (!who || FakeDeath)
1346 return;
1347
1349 }
1350
1352 {
1354
1355 //Faking Death, do nothing
1356 if (FakeDeath)
1357 return;
1358
1359 //Return since we have no target
1360 if (!UpdateVictim())
1361 return;
1362
1363 //Bomb_Timer
1364 if (Bomb_Timer <= diff)
1365 {
1367 Bomb_Timer = 25000;
1368 }
1369 else
1370 Bomb_Timer -= diff;
1371
1372 //RemoteToy_Timer
1373 if (RemoteToy_Timer <= diff)
1374 {
1375 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
1376 DoCast(target, SPELL_REMOTE_TOY);
1377
1378 RemoteToy_Timer = 10000+rand()%5000;
1379 }
1380 else
1381 RemoteToy_Timer -= diff;
1382
1384 }
1385 };
1386
1388 {
1389 return new boss_master_engineer_telonicusAI(creature);
1390 }
1391};
1392
1393//Flame Strike AI
1395{
1396public:
1398 : CreatureScript("npc_kael_flamestrike")
1399 {
1400 }
1402 {
1404 {
1405 SetCombatMovement(false);
1406 }
1407
1411
1413 {
1414 Timer = 5000;
1415 Casting = false;
1416 KillSelf = false;
1417
1419 me->setFaction(14);
1420 }
1421
1423
1424
1425 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1426
1428 {
1429 if (!Casting)
1430 {
1432 Casting = true;
1433 }
1434
1435 //Timer
1436 if (Timer <= diff)
1437 {
1438 if (!KillSelf)
1439 {
1440 me->InterruptNonMeleeSpells(false);
1442 }
1443 else
1444 me->Kill(me);
1445
1446 KillSelf = true;
1447 Timer = 1000;
1448 }
1449 else
1450 Timer -= diff;
1451 }
1452 };
1453
1455 {
1456 return new npc_kael_flamestrikeAI(creature);
1457 }
1458};
1459
1460//Phoenix AI
1462{
1463public:
1465 : CreatureScript("npc_phoenix_tk")
1466 {
1467 }
1469 {
1470 npc_phoenix_tkAI(Creature* creature) : ScriptedAI(creature) { }
1471
1473
1475 {
1476 Cycle_Timer = 2000;
1477 DoCast(me, SPELL_BURN, true);
1478 }
1479
1480 void JustDied(Unit* /*killer*/) OVERRIDE
1481 {
1482 //is this spell in use anylonger?
1483 //DoCast(me, SPELL_EMBER_BLAST, true);
1484 me->SummonCreature(NPC_PHOENIX_EGG, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 16000);
1485 }
1486
1488 {
1489 if (!UpdateVictim())
1490 return;
1491
1492 if (Cycle_Timer <= diff)
1493 {
1494 //spell Burn should possible do this, but it doesn't, so do this for now.
1495 uint32 dmg = std::rand() % 5500 + 4500;
1496 if (me->GetHealth() > dmg)
1497 me->ModifyHealth(-int32(dmg));
1498 Cycle_Timer = 2000;
1499 }
1500 else
1501 Cycle_Timer -= diff;
1502
1504 }
1505 };
1506
1508 {
1509 return new npc_phoenix_tkAI(creature);
1510 }
1511};
1512
1513//Phoenix Egg AI
1515{
1516public:
1518 : CreatureScript("npc_phoenix_egg_tk")
1519 {
1520 }
1522 {
1523 npc_phoenix_egg_tkAI(Creature* creature) : ScriptedAI(creature) { }
1524
1526
1528 {
1529 Rebirth_Timer = 15000;
1530 }
1531
1532 //ignore any
1534
1535
1537 {
1538 if (me->Attack(who, false))
1539 {
1540 me->SetInCombatWith(who);
1541 who->SetInCombatWith(me);
1542
1543 DoStartNoMovement(who);
1544 }
1545 }
1546
1548 {
1549 summoned->AddThreat(me->GetVictim(), 0.0f);
1550 summoned->CastSpell(summoned, SPELL_REBIRTH, false);
1551 }
1552
1554 {
1555 if (!Rebirth_Timer)
1556 return;
1557
1558 if (Rebirth_Timer <= diff)
1559 {
1560 me->SummonCreature(NPC_PHOENIX, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 5000);
1561 Rebirth_Timer = 0;
1562 }
1563 else
1564 Rebirth_Timer -= diff;
1565 }
1566 };
1567
1569 {
1570 return new npc_phoenix_egg_tkAI(creature);
1571 }
1572};
1573
#define CREATURE_Z_ATTACK_RANGE
Definition Creature.h:422
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
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
#define CAST_AI(a, b)
@ SPELL_EFFECT_INTERRUPT_CAST
@ IMMUNITY_EFFECT
@ AURA_STATE_HEALTHLESS_35_PERCENT
@ AURA_STATE_HEALTHLESS_20_PERCENT
@ SPELL_AURA_MOD_STEALTH
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
@ UNIT_STATE_STUNNED
Definition Unit.h:515
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
Creatures
@ SPELL_EMBER_BLAST
Definition boss_alar.cpp:30
@ SAY_SLAY
@ SAY_INTRO
@ SPELL_ARCANE_EXPLOSION
@ SPELL_FIREBALL
@ SPELL_BURN
@ SPELL_EXPLODE
Definition boss_buru.cpp:24
#define SAY_DEATH
#define MAX_ADVISORS
@ SPELL_SHOCK_BARRIER
const float CAPERNIAN_DISTANCE
@ NPC_PHOENIX_EGG
@ NPC_PHOENIX
@ MAX_ADVISORS
@ SAY_DEATH
@ SAY_THALADRED_DEATH
@ SAY_SANGUINAR_AGGRO
@ SAY_INTRO_SANGUINAR
@ SAY_PHASE2_WEAPON
@ SAY_GRAVITYLAPSE
@ SAY_TELONICUS_AGGRO
@ SAY_PHASE4_INTRO2
@ SAY_INTRO_TELONICUS
@ SAY_CAPERNIAN_AGGRO
@ SAY_THALADRED_AGGRO
@ SAY_PHASE5_NUTS
@ SAY_SLAY
@ SAY_CAPERNIAN_DEATH
@ SAY_SUMMON_PHOENIX
@ EMOTE_THALADRED_GAZE
@ SAY_MINDCONTROL
@ SAY_INTRO_THALADRED
@ SAY_INTRO_CAPERNIAN
@ SAY_INTRO
@ SAY_PHASE3_ADVANCE
@ SAY_SANGUINAR_DEATH
@ SAY_TELONICUS_DEATH
#define TIME_PHASE_3_4
uint32 m_auiSpellSummonWeapon[]
#define TIME_PHASE_2_3
@ SPELL_CAPERNIAN_FIREBALL
@ SPELL_SUMMON_WEAPOND
@ SPELL_KNOCKBACK
@ SPELL_MIND_CONTROL
@ SPELL_SUMMON_WEAPONF
@ SPELL_NETHER_VAPOR
@ SPELL_BELLOWING_ROAR
@ SPELL_SHOCK_BARRIER
@ SPELL_SILENCE
@ SPELL_PHOENIX_ANIMATION
@ SPELL_REMOTE_TOY
@ SPELL_BOMB
@ SPELL_CONFLAGRATION
@ SPELL_ARCANE_DISRUPTION
@ SPELL_SUMMON_WEAPONE
@ SPELL_SUMMON_WEAPONG
@ SPELL_REBIRTH
@ SPELL_SUMMON_WEAPONS
@ SPELL_ARCANE_EXPLOSION
@ SPELL_SUMMON_WEAPONB
@ SPELL_NETHER_BEAM
@ SPELL_FLAME_STRIKE_VIS
@ SPELL_FIREBALL
@ SPELL_GRAVITY_LAPSE
@ SPELL_FULLPOWER
@ SPELL_PSYCHIC_BLOW
@ SPELL_BURN
@ SPELL_EXPLODE
@ SPELL_GRAVITY_LAPSE_AURA
@ SPELL_FLAME_STRIKE_DMG
@ SPELL_SUMMON_WEAPONC
@ SPELL_SUMMON_WEAPONA
@ SPELL_PYROBLAST
@ SPELL_FLAME_STRIKE
@ SPELL_RES_VISUAL
void AddSC_boss_kaelthas()
@ MODEL_ID_PHOENIX
@ MODEL_ID_PHOENIX_EGG
const float afGravityPos[3]
@ SPELL_REBIRTH
@ SPELL_BELLOWING_ROAR
@ SPELL_CONFLAGRATION
@ SPELL_RES_VISUAL
void append(T value)
Definition ByteBuffer.h:147
virtual void MoveInLineOfSight(Unit *)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
TypeID GetTypeId() const
Definition Object.h:131
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
std::list< HostileReference * > StorageType
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 setFaction(uint32 faction)
Definition Unit.h:1699
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
uint8 getStandState() const
Definition Unit.h:1724
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
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ SPELL_ARCANE_DISRUPTION
@ SMSG_MOVE_SET_CAN_FLY
Definition Opcodes.h:797
@ SMSG_MOVE_UNSET_CAN_FLY
Definition Opcodes.h:814
float GetOrientation() const
Definition Object.h:331
void DoStartNoMovement(Unit *target)
void SetCombatMovement(bool allowMovement)
Creature * me
void DoTeleportPlayer(Unit *unit, float x, float y, float z, float o)
bool HealthBelowPct(uint32 pct) const
void JustDied(Unit *) OVERRIDE
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void AttackStart(Unit *who) OVERRIDE
void DamageTaken(Unit *killer, uint32 &damage) OVERRIDE
void MoveInLineOfSight(Unit *who) OVERRIDE
void Revive(Unit *)
advisorbase_ai(Creature *creature)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void Reset() OVERRIDE
InstanceScript * instance
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
uint64 m_auiAdvisorGuid[MAX_ADVISORS]
void KilledUnit(Unit *) OVERRIDE
void JustSummoned(Creature *summoned) OVERRIDE
void MoveInLineOfSight(Unit *who) OVERRIDE
void JustDied(Unit *) OVERRIDE
boss_kaelthasAI(Creature *creature)
void SummonedCreatureDespawn(Creature *summon) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void JustSummoned(Creature *summoned) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
@ DATA_MASTERENGINEERTELONICUS
Definition the_eye.h:18
@ DATA_GRANDASTROMANCERCAPERNIAN
Definition the_eye.h:13
@ DATA_KAELTHAS
Definition the_eye.h:15
@ DATA_LORDSANGUINAR
Definition the_eye.h:17
@ DATA_KAELTHASEVENT
Definition the_eye.h:16
@ DATA_THALADREDTHEDARKENER
Definition the_eye.h:19