TrinityCore
Loading...
Searching...
No Matches
boss_kaelthas.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/*
19 * Spells SPELL_ROOT_SELF and SPELL_PACIFY_SELF are guessed, based on effects received in packets
20 * Phoenix's on-death sequence requires sniff verification, partially based on a movie and MGT version
21 * The way Telonicus casts shoot and bomb requires additional research, can't figure out how exactly both are used
22 * Shock Barrier reflect damage calculation requires re-check, current formula may be wrong, based almost on nothing
23 * What does Script Effect of the Banish spell?
24 * Phoenix behavior during Gravity Lapse requires research. While in banish, they don't cast the Burn spell but
25 how it is implemented remains unknown. What happens to eggs and invisible phoenixes is unknown
26 * Combat timers requires to be revisited, especially in ground phase 5
27 * The way we change spells and stages requires additional research, current behavior is not entrirely correct but
28 correct approach remains unknown
29 * Spell 39254 probably is used to despawn advisors in case of wipe and death, currently we despawn them by despawning spawn groups
30 * What does Script Effect of spell 35879?
31 * Before some patch, doors were closed when first advisor was engaged, allowing players to kite advisors and Kael'thas through whole
32 instance. We close doors when encounter starts
33 * Nether Vapor's movement requires research, they send almost no move packets but they move. Currently we force them to move randomly but
34 on retail that doesn't look like random movement
35 * Visual effect of Pure Nether Beam doesn't stop. Looks like client bug, saw same in WoTLK classic
36 * Drowned emote during transition doesn't trigger, not set manually in sniffs (doesn't work if set manually either way). From my observation this boss has
37 different bugs in different expansions. Something is fixed in one and is broken in another
38 */
39
40#include "ScriptMgr.h"
41#include "Containers.h"
42#include "DB2Stores.h"
43#include "GameObject.h"
44#include "InstanceScript.h"
45#include "Map.h"
46#include "MotionMaster.h"
47#include "ObjectMgr.h"
48#include "ScriptedCreature.h"
49#include "SpellAuraEffects.h"
50#include "SpellInfo.h"
51#include "SpellScript.h"
52#include "the_eye.h"
53
90
92{
93 // Phase 1
96
101
102 // Phase 2
104
105 // Phase 3
107
108 // Phase 4
116
117 // Transition
132
133 // Phase 5
138
139 // Generic spells
142
143 // Thaladred the Darkener
145 SPELL_REND = 36965,
147
148 // Lord Sanguinar
150
151 // Grand Astromancer Capernian
155
156 // Master Engineer Telonicus
157 SPELL_SHOOT = 16496,
158 SPELL_BOMB = 37036,
160
161 // Flame Strike Trigger (Kael)
163
164 // Phoenix
172
173 // Nether Vapor
177
178 // Scripts
179 // Mind Control
181
182 // Shock Barrier
184
185 // Remote Toy
187
188 // Gravity Lapse
214
217
219
220 // Flame Strike
222
223 // Summon Weapons
231
232 // Remove Enchanted Weapons
240
241 // Kael Gaining Power
245
246 // Pure Nether Beam
250
251 // Summon Nether Vapor
256
257 // Nether Beam
260
315
323
332
340
350
357
368
374
382
383static constexpr std::array<uint32, 4> AdvisorsSpawnGroupsData =
384{
389};
390
401
412
441
449
450Position const TransitionStartPos = { 796.641f, -0.588817f, 48.728474f, 0.0f };
451Position const TransitionUpPos = { 795.007f, -0.471827f, 75.000000f, 0.0f };
452Position const TransitionDownPos = { 792.419f, -0.504778f, 50.050500f, 0.0f };
453
454// 19622 - Kael'thas Sunstrider
455struct boss_kaelthas : public BossAI
456{
459
460 void JustAppeared() override
461 {
463 me->SetRegenerateHealth(false);
464
466
467 for (uint32 group : AdvisorsSpawnGroupsData)
468 me->GetMap()->SpawnGroupSpawn(group, true);
469 }
470
471 void JustEngagedWith(Unit* who) override
472 {
474
475 if (_phase == PHASE_NONE)
477 }
478
479 void MoveInLineOfSight(Unit* who) override
480 {
481 if (_phase == PHASE_NONE && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 30.0f) && who->GetTypeId() == TYPEID_PLAYER)
483 }
484
491
492 void AttackStart(Unit* who) override
493 {
495 }
496
497 void DoAction(int32 action) override
498 {
499 if (action == ACTION_ENGAGE_COMBAT)
500 if (_phase == PHASE_3_ADVANCE)
502 }
503
504 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
505 {
506 switch (spellInfo->Id)
507 {
510 break;
513 break;
516 break;
519 break;
523 break;
524 default:
525 break;
526 }
527 }
528
529 void OnSpellStart(SpellInfo const* spellInfo) override
530 {
531 if (spellInfo->Id == SPELL_GRAVITY_LAPSE)
533 }
534
535 void OnSpellCast(SpellInfo const* spellInfo) override
536 {
537 switch (spellInfo->Id)
538 {
541 break;
544 break;
546 if (_phase == PHASE_4_ENGAGED)
547 {
549 _pyroblastCount = 0;
552 }
553 break;
556 break;
557 default:
558 break;
559 }
560 }
561
562 void OnSpellFailed(SpellInfo const* spellInfo) override
563 {
564 if (spellInfo->Id == SPELL_PYROBLAST)
565 {
568 }
569 }
570
572 {
573 switch (stage)
574 {
583 break;
587 break;
598 break;
607 break;
608 default:
609 break;
610 }
611 }
612
613 void MovementInform(uint32 type, uint32 point) override
614 {
615 if (type != POINT_MOTION_TYPE)
616 return;
617
618 switch (point)
619 {
622 break;
625 break;
626 default:
627 break;
628 }
629 }
630
631 void JustSummoned(Creature* summon) override
632 {
633 // Do not engage summons, handled manually in each script
634 summons.Summon(summon);
635 }
636
637 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
638 {
640 {
643 }
644 }
645
646 void EnterEvadeMode(EvadeReason /*why*/) override
647 {
649
651 statue->ResetDoorOrButton();
652
654 statue->ResetDoorOrButton();
655
657 window->ResetDoorOrButton();
658
659 for (uint32 group : AdvisorsSpawnGroupsData)
660 me->GetMap()->SpawnGroupDespawn(group);
661
662 if (Creature* controller = me->FindNearestCreatureWithOptions(250.0f, { .StringId = "KaelthasControllerTrigger" }))
663 controller->AI()->DoAction(ACTION_RESET_CONTROLLER);
664
666 _DespawnAtEvade(15s);
667 }
668
669 void KilledUnit(Unit* /*victim*/) override
670 {
671 Talk(SAY_SLAY);
672 }
673
674 void JustDied(Unit* /*killer*/) override
675 {
677 _JustDied();
678
679 for (uint32 group : AdvisorsSpawnGroupsData)
680 me->GetMap()->SpawnGroupDespawn(group);
681 }
682
683 void UpdateAI(uint32 diff) override
684 {
685 if (!UpdateVictim())
686 return;
687
688 specialEvents.Update(diff);
689
690 while (uint32 eventId = specialEvents.ExecuteEvent())
691 {
692 switch (eventId)
693 {
694 // Phase 4
695 case EVENT_PYROBLAST:
696 if (_pyroblastCount < 3)
697 {
701 }
702 else
704 break;
705
706 // Transition
708 me->AttackStop();
712 events.Reset();
713 break;
715 me->SetFacingTo(3.176499128341674804f);
717 me->SetUninteractible(true);
719 break;
723 break;
725 me->SetWalk(true);
726 me->SetDisableGravity(true);
727 me->SetHover(true);
729
730 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger1" }))
731 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_1);
732
733 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger2" }))
734 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_2);
735
738 break;
740 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger3" }))
741 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_1);
742
743 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger4" }))
744 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_2);
745
747 break;
749 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger5" }))
750 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_1);
751
752 if (Creature* trigger = me->FindNearestCreatureWithOptions(100.0f, { .StringId = "KaelthasNetherbeamChannelTrigger6" }))
753 trigger->CastSpell(trigger, SPELL_NETHERBEAM_CHANNEL_2);
754
756 break;
759 object->UseDoorOrButton();
760
762 object->UseDoorOrButton();
763
765 break;
767 {
772
773 std::vector<Creature*> triggers;
774 GetCreatureListWithOptionsInGrid(triggers, me, 150.0f, { .StringId = "KaelthasExplosionTrigger" });
775 for (Creature* trigger : triggers)
776 trigger->CastSpell(trigger, SPELL_KAEL_EXPLODES_4);
777
779 object->UseDoorOrButton();
780
783 break;
784 }
789 break;
793 break;
796 me->SetDisableGravity(false);
797 me->SetHover(false);
800 me->SetUninteractible(false);
802 break;
803
804 // Transition: Explosion
806 {
807 std::vector<Creature*> triggers;
808 GetCreatureListWithOptionsInGrid(triggers, me, 150.0f, { .StringId = "KaelthasExplosionTrigger" });
809 for (Creature* trigger : triggers)
810 trigger->CastSpell(trigger, SPELL_KAEL_EXPLODES_1);
811
813 break;
814 }
816 {
817 std::vector<Creature*> triggers;
818 GetCreatureListWithOptionsInGrid(triggers, me, 150.0f, { .StringId = "KaelthasExplosionTrigger" });
819 for (Creature* trigger : triggers)
820 trigger->CastSpell(trigger, SPELL_KAEL_EXPLODES_2);
821
823 break;
824 }
826 {
827 std::vector<Creature*> triggers;
828 GetCreatureListWithOptionsInGrid(triggers, me, 150.0f, { .StringId = "KaelthasExplosionTrigger" });
829 for (Creature* trigger : triggers)
830 trigger->CastSpell(trigger, SPELL_KAEL_EXPLODES_3);
831 break;
832 }
833
834 // Transition: Pure Nether Beam
836 {
837 std::vector<Creature*> triggersGroup1;
838 GetCreatureListWithOptionsInGrid(triggersGroup1, me, 150.0f, { .StringId = "KaelthasPureNetherBeamTriggerGroup1" });
839 for (Creature* trigger : triggersGroup1)
840 if (roll_chance(30))
841 trigger->CastSpell(trigger, SPELL_PURE_NETHER_BEAM_SCRIPT_1);
842
843 std::vector<Creature*> triggersGroup2;
844 GetCreatureListWithOptionsInGrid(triggersGroup2, me, 150.0f, { .StringId = "KaelthasPureNetherBeamTriggerGroup2" });
845 for (Creature* trigger : triggersGroup2)
846 if (roll_chance(20))
847 trigger->CastSpell(trigger, SPELL_PURE_NETHER_BEAM_SCRIPT_2);
848
849 std::vector<Creature*> triggersGroup3;
850 GetCreatureListWithOptionsInGrid(triggersGroup3, me, 150.0f, { .StringId = "KaelthasPureNetherBeamTriggerGroup3" });
851 for (Creature* trigger : triggersGroup3)
852 if (roll_chance(30))
853 trigger->CastSpell(trigger, SPELL_PURE_NETHER_BEAM_SCRIPT_3);
854
855 specialEvents.Repeat(400ms);
856 break;
857 }
858 default:
859 break;
860 }
861 }
862
863 events.Update(diff);
864
866 return;
867
868 while (uint32 eventId = events.ExecuteEvent())
869 {
870 switch (eventId)
871 {
872 // Phase 1
875 me->SetUninteractible(true);
877 break;
883 break;
886 advisor->AI()->DoAction(ACTION_ADVISOR_ENGAGED);
888 break;
889
890 // Phase 1, 2, 3: Special
891 case EVENT_SET_FACING:
892 // This is quite tricky event. What is known and verified:
893 // 1. This event starts when first advisor is engaged
894 // 2. Event stops when phase 4 begins
895 // 3. This is not SetTarget since boss constantly sends unit field target with 0 as value
896 // 4. This is pure SetFacingTo
897 // 5. Minimal delay between events is exactly 400ms
898 // 6. Event triggers even if player's position was changed a little (result FaceDirection: 3.00765 > FaceDirection: 3.00557)
899 // What remains unknown or not implemented:
900 // 1. Looks like event doesn't trigger if boss already faces that direction
901 // 2. Is delay between events random or always 400ms?
902 // 3. What happens if target dies remains unknown
903 // 4. Looks like he switches target every x second, we use max threat for now, maybe it's correct
905 {
907 events.Repeat(400ms);
908 }
909 break;
910
911 // Phase 2
917 break;
918
919 // Phase 3
924 break;
928 break;
933 me->SetUninteractible(false);
938 break;
939
940 // Phase 4
941 case EVENT_FIREBALL:
943 events.Repeat(2400ms);
944 break;
946 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.0f, true))
947 DoCast(target, SPELL_FLAME_STRIKE);
948 events.Repeat(30s, 40s);
949 break;
952 events.Repeat(20s, 30s);
953 break;
956 events.Repeat(45s, 55s);
957 break;
960 events.Repeat(30s, 45s);
961 break;
964 events.Repeat(_phase == PHASE_4_ENGAGED ? 60s : 7s);
965 break;
966
967 // Phase 5
970 break;
973 break;
976 break;
979 break;
982 events.Repeat(3600ms);
983 break;
984 default:
985 break;
986 }
987
989 return;
990 }
991 }
992
993private:
999};
1000
1002{
1003 AdvisorBaseAI(Creature* creature) : ScriptedAI(creature), HasRessurrected(false), IsFeigningDeath(false) { }
1004
1005 void InitializeAI() override
1006 {
1007 me->SetImmuneToPC(true);
1008
1009 Scheduler.SetValidator([this]
1010 {
1012 });
1013 }
1014
1015 void Reset() override
1016 {
1018 }
1019
1020 void JustEngagedWith(Unit* /*who*/) override
1021 {
1023 }
1024
1025 virtual void ScheduleEvents() = 0;
1026
1027 void DoAction(int32 action) override
1028 {
1029 if (action == ACTION_ADVISOR_ENGAGED)
1030 {
1031 me->SetImmuneToPC(false);
1033 }
1034 }
1035
1037 {
1038 if (Creature* controller = me->FindNearestCreatureWithOptions(250.0f, { .StringId = "KaelthasControllerTrigger" }))
1039 controller->AI()->DoAction(ACTION_ADVISOR_DEFEATED);
1040 }
1041
1042 bool IsEnemyInRange(float distance)
1043 {
1045 if (me->GetDistance2d(ref->GetVictim()) < distance)
1046 return true;
1047
1048 return false;
1049 }
1050
1051 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1052 {
1053 if (HasRessurrected)
1054 return;
1055
1056 if (damage >= me->GetHealth())
1057 {
1058 damage = me->GetHealth() -1;
1059
1060 if (!IsFeigningDeath)
1061 {
1062 IsFeigningDeath = true;
1063
1064 Scheduler.Schedule(0s, [this](TaskContext const& /*task*/)
1065 {
1067
1070 me->SetUninteractible(true);
1072 });
1073 }
1074 }
1075 }
1076
1077 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1078 {
1079 if (spellInfo->Id == SPELL_RESSURECTION)
1080 {
1081 Scheduler.Schedule(0s, [this](TaskContext& task)
1082 {
1083 switch (task.GetRepeatCounter())
1084 {
1085 case 0:
1086 me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
1087 me->SetReactState(REACT_PASSIVE);
1088 task.Repeat(2500ms);
1089 break;
1090 case 1:
1091 me->SetUninteractible(false);
1092 me->SetReactState(REACT_AGGRESSIVE);
1093 ResetThreatList();
1094 ScheduleEvents();
1095 HasRessurrected = true;
1096 IsFeigningDeath = false;
1097 break;
1098 default:
1099 break;
1100 }
1101 });
1102 }
1103 }
1104
1105 void JustDied(Unit* /*killer*/) override
1106 {
1108 }
1109
1110 void UpdateAI(uint32 diff) override
1111 {
1112 if (!UpdateVictim())
1113 return;
1114
1115 Scheduler.Update(diff);
1116 }
1117
1118protected:
1122};
1123
1124// 20064 - Thaladred the Darkener
1126{
1128
1129 void ScheduleEvents() override
1130 {
1131 Scheduler
1132 .Schedule(2s, 3s, [this](TaskContext& task)
1133 {
1134 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
1135 {
1137 AddThreat(target, 1000000.0f);
1138 Talk(EMOTE_THALADRED_GAZE, target);
1139 }
1140 task.Repeat(8s, 18s);
1141 })
1142 .Schedule(0s, [this](TaskContext& task)
1143 {
1144 if (IsEnemyInRange(10.0f))
1146 task.Repeat(5s);
1147 })
1148 .Schedule(0s, 5s, [this](TaskContext& task)
1149 {
1151 task.Repeat(3s, 5s);
1152 })
1153 .Schedule(0s, 5s, [this](TaskContext& task)
1154 {
1156 task.Repeat(15s, 20s);
1157 });
1158 }
1159
1160 void JustEngagedWith(Unit* who) override
1161 {
1164 }
1165
1166 void JustDied(Unit* killer) override
1167 {
1170 }
1171};
1172
1173// 20060 - Lord Sanguinar
1175{
1176 boss_lord_sanguinar(Creature* creature) : AdvisorBaseAI(creature) { }
1177
1178 void ScheduleEvents() override
1179 {
1180 Scheduler
1181 .Schedule(0s, 5s, [this](TaskContext& task)
1182 {
1183 if (IsEnemyInRange(35.0f))
1185 task.Repeat(30s, 45s);
1186 });
1187 }
1188
1189 void JustEngagedWith(Unit* who) override
1190 {
1193 }
1194
1195 void JustDied(Unit* killer) override
1196 {
1199 }
1200};
1201
1202// 20062 - Grand Astromancer Capernian
1204{
1206
1207 void ScheduleEvents() override
1208 {
1209 Scheduler
1210 .Schedule(0s, [this](TaskContext& task)
1211 {
1213 task.Repeat(2400ms);
1214 })
1215 .Schedule(0s, 20s, [this](TaskContext& task)
1216 {
1217 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1218 DoCast(target, SPELL_CONFLAGRATION);
1219 task.Repeat(15s);
1220 })
1221 .Schedule(0s, [this](TaskContext& task)
1222 {
1223 if (IsEnemyInRange(10.0f))
1225 task.Repeat(1200ms);
1226 });
1227 }
1228
1229 void AttackStart(Unit* who) override
1230 {
1232 }
1233
1234 void JustEngagedWith(Unit* who) override
1235 {
1238 }
1239
1240 void JustDied(Unit* killer) override
1241 {
1244 }
1245};
1246
1247// 20063 - Master Engineer Telonicus
1249{
1251
1252 void ScheduleEvents() override
1253 {
1254 Scheduler
1255 .Schedule(0s, [this](TaskContext& task)
1256 {
1258 task.Repeat(2400ms);
1259 })
1260 .Schedule(0s, [this](TaskContext& task)
1261 {
1263 task.Repeat(3600ms);
1264 })
1265 .Schedule(0s, 10s, [this](TaskContext& task)
1266 {
1267 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, false, true, -SPELL_REMOTE_TOY))
1268 DoCast(target, SPELL_REMOTE_TOY);
1269 task.Repeat(15s, 18s);
1270 });
1271 }
1272
1273 void AttackStart(Unit* who) override
1274 {
1276 }
1277
1278 void JustEngagedWith(Unit* who) override
1279 {
1282 }
1283
1284 void JustDied(Unit* killer) override
1285 {
1288 }
1289};
1290
1291// 22515 - World Trigger
1293{
1295 _instance(creature->GetInstanceScript()), _defeatedAdvisorCounter(0) { }
1296
1297 // The reasons why this script exists:
1298 // 1. We know that specific AIGroup actions autotargets invoker of event and this creature is receiver
1299 // of Kael'thas' texts in phase 1, 2 and 3, meaning this creature is invoker of those events
1300 // 2. This creature casts non-serverside spell (Kael Phase Two) that starts phase 2. Other spells are
1301 // serverside and are guessed but perfectly satisfies our needs
1302 void Reset() override
1303 {
1306 }
1307
1308 void DoAction(int32 action) override
1309 {
1310 switch (action)
1311 {
1313 {
1315
1317 {
1318 case ADVISOR_THALADRED:
1320 _scheduler.Schedule(12500ms, [this](TaskContext const& /*task*/)
1321 {
1323 advisor->AI()->DoAction(ACTION_ADVISOR_ENGAGED);
1324 });
1325 break;
1326 case ADVISOR_SANGUINAR:
1328 _scheduler.Schedule(7s, [this](TaskContext const& /*task*/)
1329 {
1331 advisor->AI()->DoAction(ACTION_ADVISOR_ENGAGED);
1332 });
1333 break;
1334 case ADVISOR_CAPERNIAN:
1336 _scheduler.Schedule(8s, [this](TaskContext const& /*task*/)
1337 {
1339 advisor->AI()->DoAction(ACTION_ADVISOR_ENGAGED);
1340 });
1341 break;
1342 case ADVISOR_TELONICUS:
1344 break;
1346 if (Creature* kaelthas = _instance->GetCreature(DATA_KAELTHAS))
1347 kaelthas->AI()->DoAction(ACTION_ENGAGE_COMBAT);
1348 break;
1349 default:
1350 break;
1351 }
1352 break;
1353 }
1355 Reset();
1356 break;
1357 default:
1358 break;
1359 }
1360 }
1361
1362 void UpdateAI(uint32 diff) override
1363 {
1364 _scheduler.Update(diff);
1365 }
1366
1367private:
1371};
1372
1373// 21369 - Flame Strike Trigger (Kael)
1375{
1377
1378 void InitializeAI() override
1379 {
1381 }
1382
1383 void JustAppeared() override
1384 {
1386 me->DespawnOrUnsummon(15s);
1387 }
1388};
1389
1390// 21362 - Phoenix
1392{
1393 npc_phoenix_the_eye(Creature* creature) : ScriptedAI(creature), _isDepleted(false), _summons(me) { }
1394
1395 void InitializeAI() override
1396 {
1398 }
1399
1400 void JustAppeared() override
1401 {
1404
1405 _scheduler.Schedule(3s, [this](TaskContext const& /*task*/)
1406 {
1409 });
1410 }
1411
1412 void OnSpellCast(SpellInfo const* spellInfo) override
1413 {
1414 if (spellInfo->Id == SPELL_BURN_TRIGGER)
1416 }
1417
1418 void JustSummoned(Creature* summon) override
1419 {
1420 _summons.Summon(summon);
1421 }
1422
1423 void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override
1424 {
1426 }
1427
1428 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1429 {
1430 if (damage >= me->GetHealth())
1431 {
1432 damage = me->GetHealth() - 1;
1433
1434 if (!_isDepleted)
1435 {
1436 _isDepleted = true;
1437
1442 me->SetUninteractible(true);
1444
1445 _scheduler.Schedule(15s, [this](TaskContext& task)
1446 {
1447 switch (task.GetRepeatCounter())
1448 {
1449 case 0:
1450 _summons.DespawnAll();
1451 me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST);
1452 me->RemoveAurasDueToSpell(SPELL_SUMMON_PHOENIX_EGG);
1453 task.Repeat(2s);
1454 break;
1455 case 1:
1456 me->SetStandState(UNIT_STAND_STATE_STAND);
1457 DoCastSelf(SPELL_REBIRTH_RESPAWN);
1458 task.Repeat(3s);
1459 break;
1460 case 2:
1461 _isDepleted = false;
1462 DoCastSelf(SPELL_FULL_HEAL);
1463 DoCastSelf(SPELL_BURN_PERIODIC);
1464 me->SetUninteractible(false);
1465 task.Repeat(2s);
1466 break;
1467 case 3:
1468 me->SetReactState(REACT_AGGRESSIVE);
1469 break;
1470 default:
1471 break;
1472 }
1473 });
1474 }
1475 }
1476 }
1477
1478 void UpdateAI(uint32 diff) override
1479 {
1480 _scheduler.Update(diff);
1481
1482 UpdateVictim();
1483 }
1484
1485private:
1489};
1490
1491// 21364 - Phoenix Egg
1493{
1494 npc_phoenix_egg_the_eye(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1495
1496 void InitializeAI() override
1497 {
1498 me->SetCorpseDelay(5, true);
1500 }
1501
1502 void JustAppeared() override
1503 {
1504 if (Creature* kaelthas = _instance->GetCreature(DATA_KAELTHAS))
1505 kaelthas->AI()->JustSummoned(me);
1506 }
1507
1508private:
1510};
1511
1512// 21002 - Nether Vapor
1514{
1515 npc_nether_vapor(Creature* creature) : ScriptedAI(creature) { }
1516
1517 void InitializeAI() override
1518 {
1520 }
1521
1530};
1531
1532// 36797 - Mind Control
1534{
1535 bool Load() override
1536 {
1537 return GetCaster()->IsUnit();
1538 }
1539
1540 void FilterTargets(std::list<WorldObject*>& targets)
1541 {
1542 targets.remove(GetCaster()->GetVictim());
1544 }
1545
1550};
1551
1575
1576// 36815 - Shock Barrier
1578{
1579 bool Validate(SpellInfo const* /*spellInfo*/) override
1580 {
1582 }
1583
1584 void OnAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
1585 {
1587 .SetTriggerFlags(TRIGGERED_FULL_MASK)
1588 .AddSpellMod(SPELLVALUE_BASE_POINT0, absorbAmount / 15));
1589 }
1590
1595};
1596
1597// 36819 - Pyroblast
1599{
1600 void FilterTargets(std::list<WorldObject*>& targets)
1601 {
1602 if (targets.empty())
1603 return;
1604
1605 if (WorldObject* target = GetCaster()->GetVictim())
1606 {
1607 targets.clear();
1608 targets.push_back(target);
1609 }
1610 }
1611
1616};
1617
1618// 37027 - Remote Toy
1620{
1621 bool Validate(SpellInfo const* /*spellInfo*/) override
1622 {
1624 }
1625
1626 void HandlePeriodic(AuraEffect const* /*aurEff*/)
1627 {
1628 if (roll_chance(50))
1630 }
1631
1636};
1637
1638// 35941 - Gravity Lapse
1640{
1641public:
1646
1651
1652 void HandleScript(SpellEffIndex /*effIndex*/)
1653 {
1654 Unit* caster = GetCaster();
1655 Unit* target = GetHitUnit();
1656
1657 caster->CastSpell(target, GravityLapseSpells[std::min(_targetCount, GravityLapseSpells.size() - 1)], true);
1658 target->CastSpell(target, SPELL_GRAVITY_LAPSE_FLIGHT_AURA, true);
1659 target->CastSpell(target, SPELL_GRAVITY_LAPSE_PERIODIC, true);
1660 _targetCount++;
1661 }
1662
1667
1668private:
1669 std::size_t _targetCount;
1670};
1671
1672// 34480 - Gravity Lapse
1674{
1675 bool Validate(SpellInfo const* /*spellInfo*/) override
1676 {
1678 }
1679
1680 void OnPeriodic(AuraEffect const* /*aurEff*/)
1681 {
1682 Unit* target = GetTarget();
1683 if (!target->IsFlying() || std::abs(target->GetPositionZ() - target->GetFloorZ()) < 0.5f)
1684 target->CastSpell(target, SPELL_GRAVITY_LAPSE_KNOCK_BACK, true);
1685 }
1686
1691};
1692
1693// 36730 - Flame Strike
1695{
1696 bool Validate(SpellInfo const* /*spellInfo*/) override
1697 {
1699 }
1700
1701 void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1702 {
1704 }
1705
1710};
1711
1712// 36976 - Summon Weapons
1714{
1715 bool Validate(SpellInfo const* /*spellInfo*/) override
1716 {
1718 }
1719
1720 void HandleScript(SpellEffIndex /*effIndex*/)
1721 {
1722 Unit* caster = GetCaster();
1723 for (uint32 spell : SummonWeaponsSpells)
1724 caster->CastSpell(caster, spell, true);
1725 }
1726
1731};
1732
1733// 39497 - Remove Enchanted Weapons
1735{
1736 bool Validate(SpellInfo const* /*spellInfo*/) override
1737 {
1739 }
1740
1741 void HandleScript(SpellEffIndex /*effIndex*/)
1742 {
1743 Unit* target = GetHitUnit();
1744 for (uint32 spell : RemoveWeaponsSpells)
1746 }
1747
1752};
1753
1754// 36091 - Kael Gaining Power
1756{
1757 bool Validate(SpellInfo const* /*spellInfo*/) override
1758 {
1762 }
1763
1764 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1765 {
1766 Unit* target = GetTarget();
1769 }
1770
1771 void OnPeriodic(AuraEffect const* aurEff)
1772 {
1773 Unit* target = GetTarget();
1774
1775 switch (aurEff->GetTickNumber())
1776 {
1777 case 1:
1778 target->CastSpell(target, SPELL_NETHERBEAM_1, true);
1781 break;
1782 case 2:
1784 target->CastSpell(target, SPELL_NETHERBEAM_2, true);
1787 break;
1788 case 3:
1790 target->CastSpell(target, SPELL_NETHERBEAM_3, true);
1793 break;
1794 default:
1795 break;
1796 }
1797 }
1798
1804};
1805
1806// 36092 - Kael Explodes
1832
1833// 36201, 36290, 36291 - Pure Nether Beam
1862
1863// 36196, 36197, 36198 - Pure Nether Beam
1877
1878// 35865 - Summon Nether Vapor
1880{
1881 bool Validate(SpellInfo const* /*spellInfo*/) override
1882 {
1884 }
1885
1886 void HandleScript(SpellEffIndex /*effIndex*/)
1887 {
1888 Unit* caster = GetCaster();
1889 for (uint32 spell : SummonNetherVaporSpells)
1890 caster->CastSpell(caster, spell, true);
1891 }
1892
1897};
1898
1899// 35861, 35862, 35863, 35864 - Summon Nether Vapor
1928
1929// 45960 - Nether Vapor Lightning
1931{
1932 bool Validate(SpellInfo const* spellInfo) override
1933 {
1934 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValueAsInt()) });
1935 }
1936
1937 void OnPeriodic(AuraEffect const* aurEff)
1938 {
1939 GetTarget()->CastSpell(GetTarget()->GetNearPosition(10.0f, frand(0.0f, 2.0f * float(M_PI))), aurEff->GetAmountAsInt());
1940 }
1941
1946};
1947
1948// 35869 - Nether Beam
1950{
1951 bool Validate(SpellInfo const* /*spellInfo*/) override
1952 {
1954 }
1955
1956 void HandleScript(SpellEffIndex /*effIndex*/)
1957 {
1958 if (Creature* caster = GetCaster()->ToCreature())
1959 {
1960 std::vector<Unit*> targets;
1961 for (ThreatReference const* ref : caster->GetThreatManager().GetUnsortedThreatList())
1962 targets.push_back(ref->GetVictim());
1963
1965
1966 for (Unit* target : targets)
1967 caster->CastSpell(target, SPELL_NETHER_BEAM_CHAIN, true);
1968 }
1969 }
1970
1975};
1976
1978{
2005}
#define M_PI
Definition Common.h:118
First const & RAND(First const &first, Second const &second, Rest const &... rest)
DB2Storage< SoundKitEntry > sSoundKitStore("SoundKit.db2", &SoundKitLoadInfo::Instance)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
float frand(float min, float max)
Definition Random.cpp:56
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
#define RegisterSpellAndAuraScriptPair(script_1, script_2)
Definition ScriptMgr.h:1381
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
void GetCreatureListWithOptionsInGrid(Container &container, WorldObject *source, float maxSearchRange, FindCreatureOptions const &options)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ TARGET_DEST_CASTER_FRONT
@ TARGET_DEST_CASTER_LEFT
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_DEST_CASTER_RIGHT
@ TARGET_DEST_CASTER_BACK
@ TARGET_UNIT_SRC_AREA_ENEMY
#define EFFECT_ALL
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_AOE_CHARM
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ TRIGGERED_IGNORE_REAGENT_COST
Will ignore reagent cost.
@ SPELLVALUE_BASE_POINT0
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellDestinationTargetSelectFn(F, I, N)
#define AuraEffectAbsorbFn(F, I)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
EvadeReason
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:49
DamageEffectType
@ NODAMAGE
@ UNIT_STATE_CASTING
Definition Unit.h:290
KaelthasSounds
@ SOUND_FIRE_WARD_TARGET
@ SOUND_PRECAST_FROST_HIGH
@ SOUND_HOLY_BOLT
@ SOUND_EXORCISM
@ SOUND_GHOSTLY_STRIKE_IMPACT
@ SOUND_ARCANE_EXPLOSION
@ SOUND_PRECAST_NATURE_LOW
Position const TransitionStartPos
KaelthasSpawnGroups
@ SPAWN_GROUP_SANGUINAR
@ SPAWN_GROUP_CAPERNIAN
@ SPAWN_GROUP_TELONICUS
@ SPAWN_GROUP_THALADRED
Position const TransitionDownPos
@ PHASE_3_ADVANCE
@ PHASE_4_ENGAGED
@ PHASE_NONE
@ PHASE_5_TRUE_POWER
@ PHASE_2_WEAPONS
@ PHASE_1_INTRO
@ SAY_DEATH
@ SAY_THALADRED_DEATH
@ SAY_SANGUINAR_AGGRO
@ SAY_INTRO_SANGUINAR
@ SAY_PHASE_3_ADVANCE
@ SAY_TELONICUS_AGGRO
@ SAY_PHASE_5_NUTS
@ SAY_INTRO_TELONICUS
@ SAY_CAPERNIAN_AGGRO
@ SAY_THALADRED_AGGRO
@ SAY_PHASE_4_INTRO_2
@ SAY_SLAY
@ SAY_CAPERNIAN_DEATH
@ SAY_SUMMON_PHOENIX
@ EMOTE_PYROBLAST
@ SAY_GRAVITY_LAPSE
@ SAY_MIND_CONTROL
@ EMOTE_THALADRED_GAZE
@ SAY_INTRO_THALADRED
@ SAY_INTRO_CAPERNIAN
@ SAY_INTRO
@ SAY_SANGUINAR_DEATH
@ SAY_TELONICUS_DEATH
@ SAY_PHASE_2_WEAPONS
static constexpr std::array< uint32, 4 > SummonNetherVaporSpells
KaelthasSpellVisualKits
@ SPELL_VISUAL_KIT_2
@ SPELL_VISUAL_KIT_1
KaelthasCombatStages
@ COMBAT_STAGE_PHASE_5_GRAVITY
@ COMBAT_STAGE_PHASE_5_INITIAL
@ COMBAT_STAGE_PHASE_5_GROUND
@ COMBAT_STAGE_PHASE_4
KaelthasAdvisors
@ ADVISOR_CAPERNIAN
@ MAX_DEFEATED_ADVISORS
@ ADVISOR_SANGUINAR
@ ADVISOR_TELONICUS
@ ADVISOR_THALADRED
static constexpr std::array< uint32, 7 > RemoveWeaponsSpells
@ SPELL_SUMMON_NETHER_VAPOR_3
@ SPELL_CAPERNIAN_FIREBALL
@ SPELL_REMOVE_WEAPON_C
@ SPELL_PURE_NETHER_BEAM_SCRIPT_3
@ SPELL_GRAVITY_LAPSE_TELE_BACK
@ SPELL_SUMMON_WEAPON_A
@ SPELL_REBIRTH_SPAWN
@ SPELL_PURE_NETHER_BEAM_2
@ SPELL_KAEL_TELONICUS
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT3
@ SPELL_REMOVE_WEAPONS
@ SPELL_SHOOT
@ SPELL_KAEL_STUNNED
@ SPELL_FLAME_STRIKE_DAMAGE
@ SPELL_KAEL_EXPLODES_1
@ SPELL_SUMMON_WEAPON_F
@ SPELL_MIND_CONTROL
@ SPELL_GRAVITY_LAPSE_FLIGHT_AURA
@ SPELL_NETHERBEAM_1
@ SPELL_GRAVITY_LAPSE_TELE_BACK_LEFT
@ SPELL_GRAVITY_LAPSE_PERIODIC
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT
@ SPELL_BELLOWING_ROAR
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT2
@ SPELL_SHOCK_BARRIER
@ SPELL_SILENCE
@ SPELL_NETHERBEAM_2
@ SPELL_NETHER_BEAM_CHAIN
@ SPELL_NETHERBEAM_3
@ SPELL_REMOTE_TOY
@ SPELL_BOMB
@ SPELL_CONFLAGRATION
@ SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT
@ SPELL_SUMMON_WEAPON_E
@ SPELL_SUMMON_NETHER_VAPOR
@ SPELL_REMOVE_WEAPON_E
@ SPELL_PURE_NETHER_BEAM_SCRIPT_1
@ SPELL_ARCANE_DISRUPTION
@ SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT
@ SPELL_REMOVE_WEAPON_A
@ SPELL_KAEL_GROW
@ SPELL_REMOTE_TOY_STUN
@ SPELL_SUMMON_WEAPON_G
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT2
@ SPELL_SUMMON_NETHER_VAPOR_4
@ SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT3
@ SPELL_SUMMON_NETHER_VAPOR_1
@ SPELL_SUMMON_WEAPONS
@ SPELL_NETHER_VAPOR_SCRIPT
@ SPELL_REMOVE_WEAPON_B
@ SPELL_KAEL_EXPLODES_2
@ SPELL_SUMMON_WEAPON_B
@ SPELL_NETHER_BEAM
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT2
@ SPELL_KAEL_CAPERNIAN
@ SPELL_KAEL_FULL_POWER
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_RIGHT
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT
@ SPELL_FIREBALL
@ SPELL_NETHERBEAM_CHANNEL_1
@ SPELL_ROOT_SELF
@ SPELL_SUMMON_NETHER_VAPOR_2
@ SPELL_SUMMON_WEAPON_C
@ SPELL_GRAVITY_LAPSE
@ SPELL_SHOCK_BARRIER_DAMAGE
@ SPELL_MIND_CONTROL_2
@ SPELL_ARCANE_BURST
@ SPELL_GRAVITY_LAPSE_KNOCK_BACK
@ SPELL_PSYCHIC_BLOW
@ SPELL_GRAVITY_LAPSE_TELE_FRONT
@ SPELL_PACIFY_SELF
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT
@ SPELL_BANISH
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT2
@ SPELL_NETHER_VAPOR_DAMAGE
@ SPELL_NETHER_VAPOR_LIGHTNING
@ SPELL_GRAVITY_LAPSE_TELE_TO_CASTER
@ SPELL_SUMMON_PHOENIX
@ SPELL_KAEL_PHASE_TWO
@ SPELL_PURE_NETHER_BEAM_1
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK
@ SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT2
@ SPELL_BURN_TRIGGER
@ SPELL_REND
@ SPELL_FULL_HEAL
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT2
@ SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT2
@ SPELL_SUMMON_WEAPON_D
@ SPELL_KAEL_EXPLODES_3
@ SPELL_REMOVE_WEAPON_F
@ SPELL_REBIRTH_RESPAWN
@ SPELL_PURE_NETHER_BEAM_3
@ SPELL_PERMANENT_FEIGN_DEATH
@ SPELL_BURN_PERIODIC
@ SPELL_SUMMON_PHOENIX_EGG
@ SPELL_PURE_NETHER_BEAM_SCRIPT_2
@ SPELL_PYROBLAST
@ SPELL_FLAME_STRIKE
@ SPELL_EMBER_BLAST
@ SPELL_KAEL_EXPLODES_4
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_LEFT
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK2
@ SPELL_REMOVE_WEAPON_D
@ SPELL_KAEL_EXPLODES
@ SPELL_KAEL_GAINING_POWER
@ SPELL_NETHERBEAM_CHANNEL_2
@ SPELL_RESSURECTION
@ SPELL_KAEL_SANGUINAR
@ SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT3
@ SPELL_FLAME_STRIKE_DUMMY
@ SPELL_REMOVE_WEAPON_G
void AddSC_boss_kaelthas()
Position const TransitionUpPos
KaelthasMovementPoints
@ POINT_TRANSITION_UP
@ POINT_TRANSITION_DOWN
@ POINT_TRANSITION_START
static constexpr std::array< uint32, 4 > AdvisorsSpawnGroupsData
KaelthasActions
@ ACTION_RESET_CONTROLLER
@ ACTION_ADVISOR_ENGAGED
@ ACTION_ADVISOR_DEFEATED
@ ACTION_ENGAGE_COMBAT
@ EVENT_TRANSITION_4
@ EVENT_START_ENCOUNTER_1
@ EVENT_STAGE_GROUND
@ EVENT_TRANSITION_5
@ EVENT_FIREBALL
@ EVENT_NETHER_BEAM
@ EVENT_SUMMON_NETHER_VAPOR
@ EVENT_TRANSITION_7
@ EVENT_GRAVITY_LAPSE
@ EVENT_TRANSITION_11
@ EVENT_EXPLOSION_1
@ EVENT_SUMMON_PHOENIX
@ EVENT_ARCANE_DISRUPTION
@ EVENT_STAGE_GRAVITY
@ EVENT_ENGAGE_COMBAT
@ EVENT_TRANSITION_9
@ EVENT_SET_FACING
@ EVENT_PURE_NETHER_BEAM
@ EVENT_TRANSITION_1
@ EVENT_SUMMON_WEAPONS
@ EVENT_EXPLOSION_2
@ EVENT_MIND_CONTROL
@ EVENT_TRANSITION_6
@ EVENT_EXPLOSION_3
@ EVENT_REVIVE_ADVISORS_2
@ EVENT_TRANSITION_8
@ EVENT_REVIVE_ADVISORS_1
@ EVENT_TRANSITION_2
@ EVENT_FLAME_STRIKE
@ EVENT_SHOCK_BARRIER
@ EVENT_PYROBLAST
@ EVENT_START_ENCOUNTER_3
@ EVENT_START_ENCOUNTER_2
@ EVENT_TRANSITION_3
@ EVENT_TRANSITION_10
static constexpr std::array< uint32, 25 > GravityLapseSpells
static constexpr std::array< uint32, 7 > SummonWeaponsSpells
uint32 GetTickNumber() const
int32 GetAmountAsInt() const
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
HookList< EffectAbsorbHandler > AfterEffectAbsorb
Unit * GetTarget() const
bool IsUnit() const
Definition BaseEntity.h:171
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetImmuneToPC(bool apply) override
Definition Creature.h:190
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetRegenerateHealth(bool value)
Definition Creature.h:381
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:118
Unit * GetAttacker() const
Definition Unit.h:460
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:56
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
Creature * GetCreature(uint32 type)
GameObject * GetGameObject(uint32 type)
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:2360
bool SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes=false, size_t *count=nullptr)
Definition Map.cpp:2449
void MoveRandom(float wanderDistance=0.0f, Optional< Milliseconds > duration={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::ForceWalk, MovementSlot slot=MOTION_SLOT_DEFAULT, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
int32 CalcValueAsInt(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 const Id
Definition SpellInfo.h:328
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
uint32 m_scriptSpellId
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
HookList< DestinationTargetSelectHandler > OnDestinationTargetSelect
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
HookList< EffectHandler > OnEffectLaunchTarget
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
void Summon(Creature const *summon)
TaskScheduler::repeated_t GetRepeatCounter() const
Returns the repeat counter which increases every time the task is repeated.
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & SetValidator(P &&predicate)
Sets a validator which is asked if tasks are allowed to be executed.
TaskScheduler & Update()
Update the scheduler to the current time.
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
void AttackStartCaster(Unit *victim, float dist)
Definition UnitAI.cpp:47
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
static uint32 DealDamage(Unit *attacker, Unit *victim, uint32 damage, CleanDamage const *cleanDamage=nullptr, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=nullptr, bool durabilityLoss=true)
Definition Unit.cpp:825
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:809
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10804
ThreatManager & GetThreatManager()
Definition Unit.h:1093
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3253
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13656
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
uint64 GetHealth() const
Definition Unit.h:800
bool SetWalk(bool enable)
Definition Unit.cpp:13422
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:805
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void SendPlaySpellVisualKit(uint32 id, uint32 type, uint32 duration) const
Definition Unit.cpp:12437
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
bool IsFlying() const
Definition Unit.h:1823
bool SetDisableGravity(bool disable, bool updateAnimTier=true, bool updatePlayHoverAnim=true)
Definition Unit.cpp:13440
bool AttackStop()
Definition Unit.cpp:5984
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition Object.cpp:2941
Map * GetMap() const
Definition Object.h:411
Creature * FindNearestCreatureWithOptions(float range, FindCreatureOptions const &options) const
Definition Object.cpp:1531
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2329
float GetDistance2d(WorldObject const *obj) const
Definition Object.cpp:448
float GetFloorZ() const
Definition Object.cpp:3109
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:499
void HandleScript(SpellEffIndex)
bool Validate(SpellInfo const *) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void HandleScript(SpellEffIndex)
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void HandleScript(SpellEffIndex)
bool Validate(SpellInfo const *spellInfo) override
void OnPeriodic(AuraEffect const *aurEff)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void FilterTargets(std::list< WorldObject * > &targets)
void HandlePeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void OnAbsorb(AuraEffect *aurEff, DamageInfo &dmgInfo, uint32 &absorbAmount)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:67
bool IsEnemyInRange(float distance)
void Reset() override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
TaskScheduler Scheduler
void InitializeAI() override
void JustEngagedWith(Unit *) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
AdvisorBaseAI(Creature *creature)
void JustDied(Unit *) override
void DoAction(int32 action) override
virtual void ScheduleEvents()=0
void UpdateAI(uint32 diff) override
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:136
constexpr float GetPositionZ() const
Definition Position.h:89
void ResetThreatList(Unit *who=nullptr)
void AddThreat(Unit *victim, float amount, Unit *who=nullptr)
void RelocateOffset(Position const &offset)
Definition Spell.cpp:90
boss_grand_astromancer_capernian(Creature *creature)
void AttackStart(Unit *who) override
void JustDied(Unit *killer) override
void JustEngagedWith(Unit *who) override
EventMap specialEvents
void JustAppeared() override
void JustEngagedWith(Unit *who) override
void ScheduleCombatEventsForStage(uint8 stage)
boss_kaelthas(Creature *creature)
void KilledUnit(Unit *) override
void JustDied(Unit *) override
void OnSpellStart(SpellInfo const *spellInfo) override
void MoveInLineOfSight(Unit *who) override
void JustSummoned(Creature *summon) override
void UpdateAI(uint32 diff) override
void OnSpellFailed(SpellInfo const *spellInfo) override
void EnterEvadeMode(EvadeReason) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MovementInform(uint32 type, uint32 point) override
void AttackStart(Unit *who) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void DoAction(int32 action) override
void OnSpellCast(SpellInfo const *spellInfo) override
void ScheduleEvents() override
boss_lord_sanguinar(Creature *creature)
void JustEngagedWith(Unit *who) override
void JustDied(Unit *killer) override
void JustDied(Unit *killer) override
void JustEngagedWith(Unit *who) override
boss_master_engineer_telonicus(Creature *creature)
void AttackStart(Unit *who) override
void JustEngagedWith(Unit *who) override
void JustDied(Unit *killer) override
boss_thaladred_the_darkener(Creature *creature)
npc_flame_strike_trigger_kael(Creature *creature)
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
npc_kaelthas_controller(Creature *creature)
void InitializeAI() override
npc_nether_vapor(Creature *creature)
void JustAppeared() override
npc_phoenix_egg_the_eye(Creature *creature)
void JustSummoned(Creature *summon) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
npc_phoenix_the_eye(Creature *creature)
void SummonedCreatureDies(Creature *, Unit *) override
void InitializeAI() override
void OnSpellCast(SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
void JustAppeared() override
#define RegisterTheEyeCreatureAI(ai_name)
Definition the_eye.h:74
@ DATA_KAEL_STATUE_RIGHT
Definition the_eye.h:43
@ DATA_TEMPEST_BRIDGE_WINDOW
Definition the_eye.h:44
@ DATA_SANGUINAR
Definition the_eye.h:38
@ DATA_TELONICUS
Definition the_eye.h:39
@ DATA_KAELTHAS
Definition the_eye.h:34
@ DATA_KAEL_STATUE_LEFT
Definition the_eye.h:42
@ DATA_CAPERNIAN
Definition the_eye.h:37
@ DATA_THALADRED
Definition the_eye.h:40