TrinityCore
boss_the_lich_king.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#include "icecrown_citadel.h"
19#include "CellImpl.h"
20#include "Containers.h"
21#include "CreatureTextMgr.h"
22#include "GridNotifiersImpl.h"
23#include "InstanceScript.h"
24#include "MotionMaster.h"
25#include "ObjectAccessor.h"
26#include "ScriptedCreature.h"
27#include "ScriptMgr.h"
28#include "SpellAuraEffects.h"
29#include "SpellScript.h"
30#include "TemporarySummon.h"
31#include "Vehicle.h"
32#include "Weather.h"
33
35{
36 // The Lich King
44 SAY_LK_FROSTMOURNE_ESCAPE = 8, // not said on heroic
45 SAY_LK_FROSTMOURNE_KILL = 9, // not said on heroic
58
59 // Highlord Tirion Fordring
64
65 // Terenas Menethil (outro)
68
69 // Terenas Menethil (Frostmourne)
73};
74
76{
77 // The Lich King
78 SPELL_PLAGUE_AVOIDANCE = 72846, // raging spirits also get it
83
84 // Phase 1
88 SPELL_INFEST = 70541,
96
97 // Phase Transition
110 SPELL_QUAKE = 72262,
111
112 // Phase 2
118 SPELL_HARVEST_SOUL_VALKYR = 68985, // Val'kyr Shadowguard vehicle aura
123 SPELL_CHARGE = 74399, // cast on selected target
124 SPELL_VALKYR_CARRY = 74445, // removes uninteractible flag
129
130 // Phase 3
136 SPELL_HARVEST_SOULS = 73654, // Heroic version, weird because it has all 4 difficulties just like above spell
140 SPELL_HARVEST_SOULS_TELEPORT = 73655, // Heroic version, also periodic damage (Frostmourne)
146
147 // Frostmourne
150 SPELL_RESTORE_SOULS = 73650, // Heroic
151 SPELL_DARK_HUNGER = 69383, // Passive proc healing
153 SPELL_DESTROY_SOUL = 74086, // Used when Terenas Menethil dies
154 SPELL_SOUL_RIP = 69397, // Deals increasing damage
157 SPELL_SUMMON_SPIRIT_BOMB_1 = 73581, // (Heroic)
158 SPELL_SUMMON_SPIRIT_BOMB_2 = 74299, // (Heroic)
159 SPELL_EXPLOSION = 73576, // Spirit Bomb (Heroic)
160
161 // Outro
167 SPELL_JUMP = 71809,
172 SPELL_SUMMON_BROKEN_FROSTMOURNE_3 = 73017, // real summon
180
181 // Shambling Horror
185};
186
187#define NECROTIC_PLAGUE_LK RAID_MODE<uint32>(70337, 73912, 73913, 73914)
188#define NECROTIC_PLAGUE_PLR RAID_MODE<uint32>(70338, 73785, 73786, 73787)
189#define REMORSELESS_WINTER_1 RAID_MODE<uint32>(68981, 74270, 74271, 74272)
190#define REMORSELESS_WINTER_2 RAID_MODE<uint32>(72259, 74273, 74274, 74275)
191#define SUMMON_VALKYR RAID_MODE<uint32>(69037, 74361, 69037, 74361)
192#define HARVEST_SOUL RAID_MODE<uint32>(68980, 74325, 74296, 74297)
193#define ENRAGE RAID_MODE<uint32>(72143, 72146, 72147, 72148)
194
196{
197 // The Lich King
198 // intro events
208
209 // combat events
214 EVENT_SHADOW_TRAP, // heroic only
217 EVENT_HARVEST_SOUL, // normal mode only
225 EVENT_LIFE_SIPHON, // heroic only
226 EVENT_MOVE_TO_CENTER, // heroic only
231 EVENT_HARVEST_SOULS, // heroic only
260
261 // Shambling Horror
264
265 // Raging Spirit
268
269 // Strangulate Vehicle (Harvest Soul)
273
274 //Spirit Bomb
277
279{
282};
283
285{
291 PHASE_FROSTMOURNE = 6, // only set on heroic mode when all players are sent into frostmourne
292 PHASE_OUTRO = 7
294
295#define PHASE_TWO_THREE (events.IsInPhase(PHASE_TWO) ? PHASE_TWO : PHASE_THREE)
296
297Position const CenterPosition = {503.6282f, -2124.655f, 840.8569f, 0.0f};
298Position const TirionSpawn = {505.2118f, -2124.353f, 840.9403f, 3.141593f};
299Position const TirionIntro = {489.2970f, -2124.840f, 840.8569f, 0.0f};
300Position const TirionCharge = {482.9019f, -2124.479f, 840.8570f, 0.0f};
302{
303 {432.0851f, -2123.673f, 864.6582f, 0.0f},
304 {457.8351f, -2123.423f, 841.1582f, 0.0f},
305 {465.0730f, -2123.470f, 840.8569f, 0.0f},
306};
307Position const OutroPosition1 = {493.6286f, -2124.569f, 840.8569f, 0.0f};
308Position const OutroFlying = {508.9897f, -2124.561f, 845.3565f, 0.0f};
309Position const TerenasSpawn = {495.5542f, -2517.012f, 1050.000f, 4.6993f};
310Position const TerenasSpawnHeroic = {495.7080f, -2523.760f, 1050.000f, 0.0f};
311Position const SpiritWardenSpawn = {495.3406f, -2529.983f, 1050.000f, 1.5592f};
312
314{
329 POINT_CHARGE = 1003, // globally used number for charge spell effects
330};
331
333{
345
347{
351 LIGHT_FOG = 2509,
352
354 MUSIC_SPECIAL = 17458, // Summon Shambling Horror, Remorseless Winter, Quake, Summon Val'kyr Periodic, Harvest Soul, Vile Spirits
356 MUSIC_FINAL = 17460, // Raise Dead, Light's Blessing
357
358 SOUND_PAIN = 17360, // separate sound, not attached to any text
359
363
365{
367 DATA_VILE = 45814622,
368
371
373{
374 public:
375 NecroticPlagueTargetCheck(Unit const* obj, uint32 notAura1 = 0, uint32 notAura2 = 0)
376 : _sourceObj(obj), _notAura1(notAura1), _notAura2(notAura2)
377 {
378 }
379
380 bool operator()(Unit* unit) const
381 {
382 if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
383 return false;
384 if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
385 return false;
386 return true;
387 }
388
389 private:
393};
394
396{
397 public:
399
401 {
402 switch (go->GetEntry())
403 {
406 break;
409 break;
412 break;
417 go->ResetDoorOrButton();
418 break;
419 default:
420 break;
421 }
422
423 return false;
424 }
425};
426
428{
429 public:
431 : _summonerGuid(summoner->GetGUID()), _owner(owner)
432 {
433 }
434
435 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
436 {
439 if (Unit* target = _summoner->AI()->SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(_summoner)))
440 _owner->AI()->AttackStart(target);
441 return true;
442 }
443
444 private:
447};
448
450{
451 public:
453 : _owner(owner)
454 {
455 }
456
457 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
458 {
462 return true;
463 }
464
465 private:
467};
468
470{
471 public:
473 : _owner(owner), _counter(13)
474 {
475 }
476
477 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
478 {
480
481 if (--_counter)
482 {
484 return false;
485 }
486
487 return true;
488 }
489
490 private:
493};
494
496{
498 {
499 Initialize();
500 }
501
503 {
506 }
507
508 void Reset() override
509 {
510 _Reset();
511 me->SetImmuneToPC(true);
514 Initialize();
515 SetEquipmentSlots(true);
516
517 // Reset The Frozen Throne gameobjects
520 Cell::VisitGridObjects(me, worker, 333.0f);
521
522 // Reset any light override
524
527 }
528
529 void JustDied(Unit* killer) override
530 {
531 _JustDied();
533 me->SetDisableGravity(false);
535 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
536 frostmourne->DespawnOrUnsummon();
539
540 if (Is25ManRaid())
541 if (Player* player = Object::ToPlayer(killer))
542 player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player);
543 }
544
545 void JustEngagedWith(Unit* target) override
546 {
548 {
551 return;
552 }
553
554 me->setActive(true);
557
564 if (IsHeroic())
566 }
567
568 bool CanAIAttack(Unit const* target) const override
569 {
570 // The Lich King must not select targets in frostmourne room if he killed everyone outside
571 return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target);
572 }
573
574 void EnterEvadeMode(EvadeReason /*why*/) override
575 {
577 tirion->DespawnOrUnsummon();
583 }
584
585 void KilledUnit(Unit* victim) override
586 {
589 }
590
591 void DoAction(int32 action) override
592 {
593 switch (action)
594 {
599 // schedule talks
602 break;
605 break;
608 break;
611 break;
617 break;
621 break;
623 {
626 if (!IsHeroic())
628 break;
629 }
630 default:
631 break;
632 }
633 }
634
635 uint32 GetData(uint32 type) const override
636 {
637 switch (type)
638 {
641 case DATA_VILE:
643 default:
644 break;
645 }
646
647 return 0;
648 }
649
650 void SetData(uint32 type, uint32 value) override
651 {
652 switch (type)
653 {
656 break;
657 case DATA_VILE:
658 _vileSpiritExplosions += value;
659 break;
660 default:
661 break;
662 }
663 }
664
665 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
666 {
668 {
671 me->AttackStop();
674 return;
675 }
676
678 {
681 me->AttackStop();
684 return;
685 }
686
688 {
690 me->AttackStop();
691 events.Reset();
697 me->SetWalk(true);
707 // stop here. rest will get scheduled from MovementInform
708 return;
709 }
710 }
711
712 void JustSummoned(Creature* summon) override
713 {
714 switch (summon->GetEntry())
715 {
717 case NPC_DRUDGE_GHOUL:
718 summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
721 summon->m_Events.AddEvent(new LichKingStartMovementEvent(me, summon), summon->m_Events.CalculateTime(5s));
722 break;
723 case NPC_SHADOW_TRAP:
724 summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true);
725 break;
726 case NPC_ICE_SPHERE:
727 {
728 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
729 {
731 summon->CastSpell(summon, SPELL_ICE_SPHERE, false);
732 summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false);
733 summon->CastSpell(target, SPELL_ICE_PULSE, false);
734 summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
735 }
736 else
737 summon->DespawnOrUnsummon();
738 break;
739 }
740 case NPC_DEFILE:
742 summon->CastSpell(summon, SPELL_DEFILE_AURA, false);
743 break;
745 {
746 summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true);
747
750
752 return;
753 }
754 case NPC_VILE_SPIRIT:
755 {
756 summons.Summon(summon);
758 summon->SetSpeedRate(MOVE_FLIGHT, 0.5f);
759 summon->GetMotionMaster()->MoveRandom(10.0f);
761 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s));
762 return;
763 }
765 summons.Summon(summon);
766 return;
768 return;
769 default:
770 break;
771 }
772
773 BossAI::JustSummoned(summon);
774 }
775
776 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
777 {
778 switch (summon->GetEntry())
779 {
781 case NPC_DRUDGE_GHOUL:
782 case NPC_ICE_SPHERE:
785 case NPC_VILE_SPIRIT:
787 break;
788 default:
789 break;
790 }
791 }
792
793 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
794 {
795 if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic())
797
798 if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2)
799 {
803 }
804 }
805
806 void MovementInform(uint32 type, uint32 pointId) override
807 {
808 if (type != POINT_MOTION_TYPE)
809 return;
810
811 switch (pointId)
812 {
813 case POINT_LK_INTRO_1:
814 // schedule for next update cycle, current update must finalize movement
816 break;
817 case POINT_LK_INTRO_2:
819 break;
820 case POINT_LK_INTRO_3:
822 tirion->AI()->DoAction(ACTION_CONTINUE_INTRO);
824 break;
825 case POINT_CENTER_1:
826 me->SetFacingTo(0.0f);
838 break;
839 case POINT_CENTER_2:
840 me->SetFacingTo(0.0f);
853 break;
854 case POINT_LK_OUTRO_1:
858 break;
859 case POINT_LK_OUTRO_2:
861 tirion->AI()->Talk(SAY_TIRION_OUTRO_2);
862 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
863 frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS);
864 break;
865 default:
866 break;
867 }
868 }
869
870 void UpdateAI(uint32 diff) override
871 {
872 // check phase first to prevent updating victim and entering evade mode when not wanted
874 if (!UpdateVictim())
875 return;
876
877 events.Update(diff);
878
879 // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells
881 return;
882
883 while (uint32 eventId = events.ExecuteEvent())
884 {
885 switch (eventId)
886 {
890 me->SetWalk(true);
892 break;
895 break;
898 break;
901 // for some reason blizz sends 2 emotes in row here so (we handle one in Talk)
907 break;
910 break;
913 break;
918 break;
920 me->SetWalk(false);
921 me->SetImmuneToPC(false);
925 break;
930 break;
934 break;
935 case EVENT_INFEST:
938 break;
941 {
944 }
946 break;
949 DoCast(target, SPELL_SHADOW_TRAP);
951 break;
955 break;
956 case EVENT_DEFILE:
957 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
958 {
960 DoCast(target, SPELL_DEFILE);
961 }
963 break;
967 DoCast(target, SPELL_HARVEST_SOUL);
969 break;
971 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
974 break;
978 break;
980 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
983 break;
985 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
988 break;
989 case EVENT_QUAKE:
991 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
995 break;
996 case EVENT_QUAKE_2:
998 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
1002 break;
1006 DoCastAOE(SUMMON_VALKYR, true);
1008 break;
1009 case EVENT_START_ATTACK:
1013 break;
1014 case EVENT_VILE_SPIRITS:
1018 break;
1023 events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading)
1025 me->AttackStop();
1031 for (ObjectGuid guid : summons)
1032 {
1033 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1034 {
1035 if (summon->GetEntry() == NPC_VILE_SPIRIT)
1036 {
1037 summon->m_Events.KillAllEvents(true);
1038 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms));
1039 summon->SetReactState(REACT_PASSIVE);
1040 summon->CombatStop(true);
1041 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
1042 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
1043 summon->GetMotionMaster()->MoveTargetedHome();
1044 }
1045 else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
1046 summon->AI()->DoAction(ACTION_DISABLE_RAGING);
1047 }
1048 }
1049 break;
1052 {
1053 terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
1054 std::list<Creature*> triggers;
1056 if (!triggers.empty())
1057 {
1058 triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
1059 Creature* spawner = triggers.front();
1060 spawner->setActive(true);
1061 spawner->SetFarVisible(true);
1062 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly
1063 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
1064 spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s));
1065 }
1066 }
1067 break;
1068 case EVENT_OUTRO_TALK_1:
1071 break;
1072 case EVENT_OUTRO_TALK_2:
1075 break;
1078 break;
1079 case EVENT_OUTRO_TALK_3:
1081 me->SetFacingToObject(tirion);
1083 break;
1086 break;
1087 case EVENT_OUTRO_TALK_4:
1088 me->SetFacingTo(0.01745329f);
1090 break;
1095 break;
1096 case EVENT_OUTRO_TALK_5:
1099 tirion->AI()->DoAction(ACTION_OUTRO);
1100 break;
1101 case EVENT_OUTRO_TALK_6:
1104 tirion->SetFacingToObject(me);
1107 break;
1111 // set flight
1112 me->SetDisableGravity(true);
1114 break;
1115 case EVENT_OUTRO_TALK_7:
1117 break;
1118 case EVENT_OUTRO_TALK_8:
1120 break;
1121 case EVENT_BERSERK:
1124 break;
1125 default:
1126 break;
1127 }
1128
1130 return;
1131 }
1132 }
1133
1134private:
1137};
1138
1140{
1141 npc_tirion_fordring_tft(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1142
1143 void Reset() override
1144 {
1145 _events.Reset();
1148 }
1149
1150 void MovementInform(uint32 type, uint32 id) override
1151 {
1152 if (type != POINT_MOTION_TYPE)
1153 return;
1154
1155 switch (id)
1156 {
1157 case POINT_TIRION_INTRO:
1160 theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER);
1161 break;
1164 break;
1165 }
1166 }
1167
1168 void DoAction(int32 action) override
1169 {
1170 switch (action)
1171 {
1175 break;
1176 case ACTION_OUTRO:
1182 break;
1183 }
1184 }
1185
1186 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1187 {
1188 if (spellInfo->Id == SPELL_ICE_LOCK)
1189 me->SetFacingTo(3.085098f);
1190 else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
1191 me->LoadEquipment(1); // remove glow on ashbringer
1192 }
1193
1194 bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
1195 {
1196 if (menuId == GOSSIP_MENU_START_INTRO && !gossipListId)
1197 {
1200 me->SetWalk(true);
1202 }
1203 return false;
1204 }
1205
1206 void JustReachedHome() override
1207 {
1209 }
1210
1211 void UpdateAI(uint32 diff) override
1212 {
1214 return;
1215
1216 _events.Update(diff);
1217
1219 return;
1220
1221 while (uint32 eventId = _events.ExecuteEvent())
1222 {
1223 switch (eventId)
1224 {
1225 case EVENT_INTRO_TALK_1:
1229 break;
1232 break;
1233 case EVENT_INTRO_CHARGE:
1234 me->SetWalk(false);
1236 break;
1237 case EVENT_OUTRO_TALK_1:
1239 break;
1240 case EVENT_OUTRO_BLESS:
1242 break;
1247 {
1248 me->SetFacingToObject(lichKing);
1249 lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
1250 }
1251 break;
1252 case EVENT_OUTRO_MOVE_1:
1254 break;
1255 case EVENT_OUTRO_JUMP:
1257 break;
1258 default:
1259 break;
1260 }
1261 }
1262 }
1263
1264private:
1267};
1268
1270{
1272 {
1273 _frenzied = false;
1274 }
1275
1276 void Reset() override
1277 {
1278 _events.Reset();
1281 }
1282
1283 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1284 {
1285 if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage))
1286 {
1287 _frenzied = true;
1288 DoCastSelf(SPELL_FRENZY, true);
1289 }
1290 }
1291
1292 void UpdateAI(uint32 diff) override
1293 {
1294 if (!UpdateVictim())
1295 return;
1296
1297 _events.Update(diff);
1298
1300 return;
1301
1302 while (uint32 eventId = _events.ExecuteEvent())
1303 {
1304 switch (eventId)
1305 {
1306 case EVENT_SHOCKWAVE:
1309 break;
1310 case EVENT_ENRAGE:
1313 else
1315 break;
1316 default:
1317 break;
1318 }
1319 }
1320 }
1321
1322 void OnSpellFailed(SpellInfo const* spell) override
1323 {
1324 if (spell->Id == ENRAGE)
1326 }
1327
1328private:
1331};
1332
1334{
1335 npc_raging_spirit(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1336
1337 void Reset() override
1338 {
1340 _events.Reset();
1345 if (TempSummon* summon = me->ToTempSummon())
1346 if (Unit* summoner = summon->GetSummonerUnit())
1347 summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true);
1349 }
1350
1351 void DoAction(int32 action) override
1352 {
1353 if (action == ACTION_DISABLE_RAGING)
1354 {
1355 _events.Reset();
1359 me->AttackStop();
1361 }
1362 }
1363
1364 void IsSummonedBy(WorldObject* /*summoner*/) override
1365 {
1366 // player is the spellcaster so register summon manually
1368 lichKing->AI()->JustSummoned(me);
1369 }
1370
1371 void JustDied(Unit* /*killer*/) override
1372 {
1374 lichKing->AI()->SummonedCreatureDespawn(me);
1375 if (TempSummon* summon = me->ToTempSummon())
1376 summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
1377 }
1378
1379 void UpdateAI(uint32 diff) override
1380 {
1382 return;
1383
1384 _events.Update(diff);
1385
1387 return;
1388
1389 while (uint32 eventId = _events.ExecuteEvent())
1390 {
1391 switch (eventId)
1392 {
1393 case EVENT_SOUL_SHRIEK:
1396 break;
1400 {
1403 }
1404 break;
1405 default:
1406 break;
1407 }
1408 }
1409 }
1410
1411private:
1414};
1415
1417{
1418 npc_valkyr_shadowguard(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
1419 {
1420 SetCombatMovement(false);
1421 }
1422
1423 void Reset() override
1424 {
1425 _events.Reset();
1428 }
1429
1430 void IsSummonedBy(WorldObject* /*summoner*/) override
1431 {
1432 _events.Reset();
1434 }
1435
1436 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1437 {
1438 if (!IsHeroic())
1439 return;
1440
1442 return;
1443
1444 if (me->HealthBelowPctDamaged(50, damage))
1445 {
1448 }
1449 }
1450
1452 {
1453 _events.Reset();
1456 }
1457
1458 void MovementInform(uint32 type, uint32 id) override
1459 {
1460 if (type != POINT_MOTION_TYPE)
1461 return;
1462
1463 switch (id)
1464 {
1465 case POINT_DROP_PLAYER:
1467 if (IsHeroic())
1469 else
1470 me->DespawnOrUnsummon(1s);
1471 break;
1472 case POINT_CHARGE:
1474 {
1475 me->SetUninteractible(false);
1477 {
1478 std::list<Creature*> triggers;
1480 triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true));
1481 if (triggers.empty())
1482 return;
1483
1484 triggers.sort(Trinity::ObjectDistanceOrderPred(me));
1485 DoCast(target, SPELL_VALKYR_CARRY);
1486 _dropPoint.Relocate(triggers.front());
1488 }
1489 }
1490 else
1492 break;
1493 case POINT_SIPHON:
1498 break;
1499 default:
1500 break;
1501 }
1502 }
1503
1504 void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
1505 {
1506 _grabbedPlayer = guid;
1507 }
1508
1509 void UpdateAI(uint32 diff) override
1510 {
1511 if (!UpdateVictim())
1512 return;
1513
1514 _events.Update(diff);
1515
1517 return;
1518
1519 while (uint32 eventId = _events.ExecuteEvent())
1520 {
1521 switch (eventId)
1522 {
1523 case EVENT_GRAB_PLAYER:
1524 if (!_grabbedPlayer)
1525 {
1528 }
1529 break;
1532 break;
1533 case EVENT_LIFE_SIPHON:
1535 _events.Repeat(2s + 500ms);
1536 break;
1538 {
1540 pos.m_positionZ = me->GetHomePosition().m_positionZ;
1542 break;
1543 }
1544 default:
1545 break;
1546 }
1547
1549 return;
1550 }
1551 }
1552
1553private:
1558};
1559
1561{
1562 npc_strangulate_vehicle(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1563
1564 void IsSummonedBy(WorldObject* summonerWO) override
1565 {
1566 Unit* summoner = summonerWO->ToUnit();
1567 if (!summoner)
1568 return;
1569 me->SetFacingToObject(summoner);
1571 _events.Reset();
1574
1575 // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back
1577 lichKing->AI()->JustSummoned(me);
1578 }
1579
1580 void DoAction(int32 action) override
1581 {
1582 if (action != ACTION_TELEPORT_BACK)
1583 return;
1584
1585 if (TempSummon* summ = me->ToTempSummon())
1586 {
1587 if (Unit* summoner = summ->GetSummonerUnit())
1588 {
1590 summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOULS_TELEPORT);
1591 }
1592 }
1593
1595 lichKing->AI()->SummonedCreatureDespawn(me);
1597 }
1598
1599 void UpdateAI(uint32 diff) override
1600 {
1601 UpdateVictim();
1602
1603 _events.Update(diff);
1604
1605 while (uint32 eventId = _events.ExecuteEvent())
1606 {
1607 switch (eventId)
1608 {
1609 case EVENT_TELEPORT:
1610 me->GetMotionMaster()->Clear();
1612 if (TempSummon* summ = me->ToTempSummon())
1613 {
1614 if (Unit* summoner = summ->GetSummonerUnit())
1615 {
1616 summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true);
1617 summoner->ExitVehicle(summoner);
1618 if (!IsHeroic())
1619 summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true);
1620 else
1621 {
1622 summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true);
1623 summoner->RemoveAurasDueToSpell(HARVEST_SOUL, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE);
1624 }
1625 }
1626 }
1627
1629 break;
1632 {
1633 if (me->GetExactDist(lichKing) > 10.0f)
1634 {
1635 Position pos = lichKing->GetNearPosition(rand_norm() * 5.0f + 7.5f, lichKing->GetAbsoluteAngle(me));
1636 me->GetMotionMaster()->MovePoint(0, pos);
1637 }
1638 }
1639 break;
1640 case EVENT_DESPAWN_SELF:
1642 lichKing->AI()->SummonedCreatureDespawn(me);
1643 me->DespawnOrUnsummon(1ms);
1644 break;
1645 default:
1646 break;
1647 }
1648 }
1649 }
1650
1651private:
1654};
1655
1657{
1658 npc_terenas_menethil(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1659
1660 bool CanAIAttack(Unit const* target) const override
1661 {
1662 return target->GetEntry() != NPC_THE_LICH_KING;
1663 }
1664
1665 void DoAction(int32 action) override
1666 {
1667 switch (action)
1668 {
1670 me->setActive(true);
1671 me->SetFarVisible(false);
1672 if (!IsHeroic())
1673 me->SetHealth(me->GetMaxHealth() / 2);
1675 _events.Reset();
1678 if (!IsHeroic())
1679 {
1682 }
1683 break;
1686 me->DespawnOrUnsummon(3s);
1687 break;
1688 default:
1689 break;
1690 }
1691 }
1692
1693 void EnterEvadeMode(EvadeReason /*why*/) override
1694 {
1695 // no running back home
1696 if (!me->IsAlive())
1697 return;
1698
1699 me->CombatStop(false);
1701 }
1702
1703 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1704 {
1705 if (damage >= me->GetHealth())
1706 {
1707 damage = me->GetHealth() - 1;
1709 {
1710 me->SetUninteractible(true);
1713 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1714 {
1715 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1716 warden->DespawnOrUnsummon(2s);
1717 }
1718
1719 me->DespawnOrUnsummon(2s);
1720 }
1721 }
1722 }
1723
1724 void IsSummonedBy(WorldObject* /*summoner*/) override
1725 {
1726 _events.Reset();
1729 me->SetFacingToObject(lichKing);
1730
1733 }
1734
1735 void UpdateAI(uint32 diff) override
1736 {
1737 UpdateVictim();
1738
1739 _events.Update(diff);
1740
1741 while (uint32 eventId = _events.ExecuteEvent())
1742 {
1743 switch (eventId)
1744 {
1747 if (IsHeroic())
1749 break;
1752 break;
1755 break;
1758 break;
1763 {
1764 lichKing->AI()->DoAction(ACTION_FINISH_OUTRO);
1765 lichKing->SetImmuneToNPC(false);
1767 tirion->AI()->AttackStart(lichKing);
1768 }
1769 break;
1770 case EVENT_DESTROY_SOUL:
1771 me->SetUninteractible(true);
1772 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1773 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1776 break;
1779 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
1780 break;
1781 default:
1782 break;
1783 }
1784 }
1785 }
1786
1787private:
1790};
1791
1793{
1794 npc_spirit_warden(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1795
1796 void Reset() override
1797 {
1798 _events.Reset();
1801 }
1802
1803 void JustDied(Unit* /*killer*/) override
1804 {
1806 terenas->AI()->DoAction(ACTION_TELEPORT_BACK);
1807 }
1808
1809 void UpdateAI(uint32 diff) override
1810 {
1811 if (!UpdateVictim())
1812 return;
1813
1814 _events.Update(diff);
1815
1816 while (uint32 eventId = _events.ExecuteEvent())
1817 {
1818 switch (eventId)
1819 {
1820 case EVENT_SOUL_RIP:
1823 break;
1824 default:
1825 break;
1826 }
1827 }
1828 }
1829
1830private:
1833};
1834
1836{
1837 npc_spirit_bomb(Creature* creature) : CreatureAI(creature) { }
1838
1839 void IsSummonedBy(WorldObject* /*summoner*/) override
1840 {
1841 float destX, destY, destZ;
1842 me->GetPosition(destX, destY);
1843 destZ = 1055.0f; // approximation, gets more precise later
1844 me->UpdateGroundPositionZ(destX, destY, destZ);
1845 me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ);
1846 }
1847
1848 void MovementInform(uint32 type, uint32 point) override
1849 {
1850 if (type != POINT_MOTION_TYPE || point != POINT_GROUND)
1851 return;
1852
1854 }
1855
1856 void AttackStart(Unit* /*victim*/) override
1857 {
1858 }
1859
1860 void UpdateAI(uint32 diff) override
1861 {
1862 UpdateVictim();
1863
1864 _events.Update(diff);
1865
1867 {
1868 me->RemoveAllAuras();
1870 me->DespawnOrUnsummon(1s);
1871 }
1872 }
1873
1874private:
1876};
1877
1879{
1880 npc_broken_frostmourne(Creature* creature) : CreatureAI(creature) { }
1881
1882 void Reset() override
1883 {
1884 _events.Reset();
1885 }
1886
1887 void IsSummonedBy(WorldObject* /*summoner*/) override
1888 {
1891 }
1892
1893 void DoAction(int32 action) override
1894 {
1895 if (action == ACTION_SUMMON_TERENAS)
1897 }
1898
1899 void EnterEvadeMode(EvadeReason /*why*/) override
1900 {
1901 }
1902
1903 void UpdateAI(uint32 diff) override
1904 {
1905 UpdateVictim();
1906
1907 _events.Update(diff);
1908
1909 while (uint32 eventId = _events.ExecuteEvent())
1910 {
1911 switch (eventId)
1912 {
1915 break;
1918 break;
1919 default:
1920 break;
1921 }
1922 }
1923 }
1924
1925private:
1927};
1928
1929// 70541, 73779, 73780, 73781 - Infest
1931{
1932 void OnPeriodic(AuraEffect const* /*aurEff*/)
1933 {
1934 if (GetUnitOwner()->HealthAbovePct(90))
1935 {
1938 }
1939 }
1940
1941 void OnUpdate(AuraEffect* aurEff)
1942 {
1943 // multiply, starting from 2nd tick
1944 if (aurEff->GetTickNumber() == 1)
1945 return;
1946
1947 aurEff->SetAmount(int32(aurEff->GetAmount() * 1.15f));
1948 }
1949
1950 void Register() override
1951 {
1954 }
1955};
1956
1957// 70337, 73912, 73913, 73914 - Necrotic Plague
1959{
1960 bool Validate(SpellInfo const* /*spell*/) override
1961 {
1963 }
1964
1965 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1966 {
1967 switch (GetTargetApplication()->GetRemoveMode())
1968 {
1972 break;
1973 default:
1974 return;
1975 }
1976
1981 if (Unit* caster = GetCaster())
1982 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
1983 }
1984
1985 void Register() override
1986 {
1988 }
1989};
1990
1991// 70338, 73785, 73786, 73787 - Necrotic Plague (Jump)
1993{
1994public:
1996 {
1997 _hadAura = false;
1998 }
1999
2000private:
2001 void SelectTarget(std::list<WorldObject*>& targets)
2002 {
2004 if (targets.size() < 2)
2005 return;
2006
2007 targets.resize(1);
2008 }
2009
2011 {
2012 if (missInfo != SPELL_MISS_NONE)
2013 return;
2014
2015 if (GetHitUnit()->HasAura(GetSpellInfo()->Id))
2016 _hadAura = true;
2017 }
2018
2019 void Register() override
2020 {
2023 }
2024
2026};
2027
2029{
2030public:
2032 {
2033 _lastAmount = 0;
2034 }
2035
2036private:
2037 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2038 {
2039 if (Unit* caster = GetCaster())
2040 if (caster->GetAI())
2041 caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount());
2042 }
2043
2044 void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2045 {
2046 _lastAmount = aurEff->GetAmount();
2047 switch (GetTargetApplication()->GetRemoveMode())
2048 {
2051 break;
2052 default:
2053 return;
2054 }
2055
2060 if (Unit* caster = GetCaster())
2061 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2062 }
2063
2064 void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2065 {
2066 _lastAmount = aurEff->GetAmount();
2067 }
2068
2069 void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2070 {
2071 // this means the stack increased so don't process as if dispelled
2072 if (aurEff->GetAmount() > _lastAmount)
2073 return;
2074
2078 args.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1)
2080 if (Unit* caster = GetCaster())
2081 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2082
2084 }
2085
2086 void Register() override
2087 {
2092 }
2093
2095};
2096
2097// 73530 - Shadow Trap (Visual)
2099{
2100 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2101 {
2102 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
2104 }
2105
2106 void Register() override
2107 {
2109 }
2110};
2111
2112// 74282 - Shadow Trap (Periodic)
2114{
2115 void CheckTargetCount(std::list<WorldObject*>& targets)
2116 {
2117 if (targets.empty())
2118 return;
2119
2121 }
2122
2123 void Register() override
2124 {
2126 }
2127};
2128
2129// 72262 - Quake
2131{
2132 bool Load() override
2133 {
2134 return GetCaster()->GetInstanceScript() != nullptr;
2135 }
2136
2137 void FilterTargets(std::list<WorldObject*>& targets)
2138 {
2139 if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetGuidData(DATA_ARTHAS_PLATFORM)))
2140 targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false));
2141 }
2142
2144 {
2145 if (UnitAI* AI = GetCaster()->GetAI())
2146 AI->DoAction(ACTION_START_ATTACK);
2147 }
2148
2149 void Register() override
2150 {
2153 }
2154};
2155
2156// 69110 - Ice Burst Target Search
2158{
2159 bool Validate(SpellInfo const* /*spell*/) override
2160 {
2162 }
2163
2164 void CheckTargetCount(std::list<WorldObject*>& unitList)
2165 {
2166 if (unitList.empty())
2167 return;
2168
2169 // if there is at least one affected target cast the explosion
2171 if (GetCaster()->GetTypeId() == TYPEID_UNIT)
2172 {
2174 GetCaster()->AttackStop();
2176 }
2177 }
2178
2179 void Register() override
2180 {
2182 }
2183};
2184
2185// 69200 - Raging Spirit
2187{
2189 {
2190 PreventHitDefaultEffect(effIndex);
2192 }
2193
2194 void Register() override
2195 {
2197 }
2198};
2199
2201{
2202 public:
2203 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
2204
2206 {
2207 return _source->GetExactDist2d(unit) > _dist;
2208 }
2209
2210 private:
2211 Unit* _source;
2212 float _dist;
2213};
2214
2215// 72754, 73708, 73709, 73710 - Defile
2217{
2218 void CorrectRange(std::list<WorldObject*>& targets)
2219 {
2220 targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale()));
2221 targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR));
2222 }
2223
2225 {
2226 SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale()));
2227 // HACK: target player should cast this spell on defile
2228 // however with current aura handling auras cast by different units
2229 // cannot stack on the same aura object increasing the stack count
2231 }
2232
2233 void Register() override
2234 {
2238 }
2239};
2240
2241/* 69037 - Summon Val'kyr
2242 70497 - Summon Vile Spirits Effect
2243 73579 - Summon Spirit Bomb
2244 74300 - Summon Spirit Bomb */
2246{
2247 void ModDestHeight(SpellEffIndex /*effIndex*/)
2248 {
2249 static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f};
2250 WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest());
2251 dest->RelocateOffset(offset);
2252 GetHitDest()->RelocateOffset(offset);
2253 // spirit bombs get higher
2254 if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB)
2255 {
2256 static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f };
2257 dest->RelocateOffset(offsetExtra);
2258 GetHitDest()->RelocateOffset(offsetExtra);
2259 }
2260 }
2261
2262 void Register() override
2263 {
2265 }
2266};
2267
2268// 69409, 73797, 73798, 73799 - Soul Reaper
2270{
2271 bool Validate(SpellInfo const* /*spell*/) override
2272 {
2274 }
2275
2276 void OnPeriodic(AuraEffect const* /*aurEff*/)
2277 {
2278 if (Unit* caster = GetCaster())
2279 GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true);
2280 }
2281
2282 void Register() override
2283 {
2285 }
2286};
2287
2288// 69030 - Val'kyr Target Search
2290{
2291 bool Validate(SpellInfo const* /*spell*/) override
2292 {
2293 return ValidateSpellInfo({ SPELL_CHARGE });
2294 }
2295
2296 void SelectTarget(std::list<WorldObject*>& targets)
2297 {
2298 if (targets.empty())
2299 return;
2300
2301 targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id));
2302 if (targets.empty())
2303 return;
2304
2306 targets.clear();
2307 targets.push_back(_target);
2309 }
2310
2311 void ReplaceTarget(std::list<WorldObject*>& targets)
2312 {
2313 targets.clear();
2314 if (_target)
2315 targets.push_back(_target);
2316 }
2317
2319 {
2320 PreventHitDefaultEffect(effIndex);
2322 }
2323
2324 void Register() override
2325 {
2329 }
2330
2332};
2333
2334// 68984 - Harvest Soul
2335// 74445 - Val'kyr Carry
2337{
2338 void HandleScript(SpellEffIndex /*effIndex*/)
2339 {
2341 }
2342
2343 void Register() override
2344 {
2346 }
2347};
2348
2349// 73488, 73782, 73783, 73784 - Life Siphon
2351{
2352 bool Validate(SpellInfo const* /*spell*/) override
2353 {
2355 }
2356
2358 {
2360 args.AddSpellBP0(GetHitDamage() * 10);
2362 }
2363
2364 void Register() override
2365 {
2367 }
2368};
2369
2370// 70498 - Vile Spirits
2372{
2373public:
2375 {
2376 _is25Man = false;
2377 }
2378
2379private:
2380 bool Load() override
2381 {
2383 return true;
2384 }
2385
2386 void OnPeriodic(AuraEffect const* aurEff)
2387 {
2388 if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5))
2390 .SetOriginalCaster(GetCasterGUID()));
2391 }
2392
2393 void Register() override
2394 {
2396 }
2397
2399};
2400
2401// 70499 - Summon Vile Spirits Effect
2403{
2404 void ModDestHeight(SpellEffIndex /*effIndex*/)
2405 {
2406 Position offset = {0.0f, 0.0f, 15.0f, 0.0f};
2407 const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset);
2408 }
2409
2410 void Register() override
2411 {
2413 }
2414};
2415
2416// 70501 - Vile Spirit Move Target Search
2418{
2419public:
2421 {
2422 _target = nullptr;
2423 }
2424
2425private:
2426 bool Load() override
2427 {
2428 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2429 }
2430
2431 void SelectTarget(std::list<WorldObject*>& targets)
2432 {
2433 if (targets.empty())
2434 return;
2435
2437 }
2438
2440 {
2441 PreventHitDefaultEffect(effIndex);
2442 // for this spell, all units are in target map, however it should select one to attack
2443 if (GetHitUnit() != _target)
2444 return;
2445
2448 }
2449
2450 void Register() override
2451 {
2454 }
2455
2457};
2458
2459// 70534 - Vile Spirit Damage Target Search
2461{
2462 bool Load() override
2463 {
2464 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2465 }
2466
2467 void CheckTargetCount(std::list<WorldObject*>& targets)
2468 {
2469 if (targets.empty())
2470 return;
2471
2472 // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this
2473 // searcher spell will be blocked
2474 if (TempSummon* summon = GetCaster()->ToTempSummon())
2475 if (Unit* summoner = summon->GetSummonerUnit())
2476 summoner->GetAI()->SetData(DATA_VILE, 1);
2477 GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true);
2480 }
2481
2482 void Register() override
2483 {
2485 }
2486};
2487
2488// 68980, 74296, 74297, 74325 - Harvest Soul
2490{
2491 bool Load() override
2492 {
2493 return GetOwner()->GetInstanceScript() != nullptr;
2494 }
2495
2496 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2497 {
2498 // m_originalCaster to allow stacking from different casters, meh
2499 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2501 .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING)));
2502 }
2503
2504 void Register() override
2505 {
2507 }
2508};
2509
2510// 69382 - Light's Favor
2512{
2513 void OnPeriodic(AuraEffect const* /*aurEff*/)
2514 {
2515 if (Unit* caster = GetCaster())
2516 if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
2517 effect->RecalculateAmount(caster);
2518 }
2519
2520 void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
2521 {
2522 canBeRecalculated = true;
2523 amount = 0;
2524 if (Unit* caster = GetCaster())
2525 amount = int32(caster->GetHealthPct());
2526 }
2527
2528 void Register() override
2529 {
2532 }
2533};
2534
2535// 69397 - Soul Rip
2537{
2538 void OnPeriodic(AuraEffect const* aurEff)
2539 {
2541 // shouldn't be needed, this is channeled
2542 if (Unit* caster = GetCaster())
2543 {
2544 CastSpellExtraArgs args(aurEff);
2546 args.AddSpellBP0(5000 * aurEff->GetTickNumber());
2547 caster->CastSpell(GetTarget(), SPELL_SOUL_RIP_DAMAGE, args);
2548 }
2549 }
2550
2551 void Register() override
2552 {
2554 }
2555};
2556
2557// 72595, 73650 - Restore Soul
2559{
2560public:
2562 {
2563 _instance = nullptr;
2564 }
2565
2566private:
2567 bool Load() override
2568 {
2570 return _instance != nullptr;
2571 }
2572
2573 void HandleScript(SpellEffIndex /*effIndex*/)
2574 {
2576 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
2577 if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f))
2578 spawner->RemoveAllAuras();
2579
2580 std::list<Creature*> spirits;
2582 for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr)
2583 {
2584 (*itr)->m_Events.KillAllEvents(true);
2585 (*itr)->SetReactState(REACT_PASSIVE);
2586 (*itr)->AI()->EnterEvadeMode();
2587 }
2588 }
2589
2591 {
2592 if (missInfo != SPELL_MISS_NONE)
2593 return;
2594
2595 if (Unit* target = GetHitUnit())
2596 target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT);
2597 }
2598
2599 void Register() override
2600 {
2603 }
2604
2606};
2607
2608// 69383 - Dark Hunger
2610{
2611 bool Validate(SpellInfo const* /*spellInfo*/) override
2612 {
2614 }
2615
2616 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
2617 {
2619 DamageInfo* damageInfo = eventInfo.GetDamageInfo();
2620 if (!damageInfo || !damageInfo->GetDamage())
2621 return;
2622
2623 CastSpellExtraArgs args(aurEff);
2624 args.AddSpellBP0(damageInfo->GetDamage() / 2);
2626 }
2627
2628 void Register() override
2629 {
2631 }
2632};
2633
2634// 74276 - In Frostmourne Room
2636{
2637 bool Load() override
2638 {
2639 return GetOwner()->GetInstanceScript() != nullptr;
2640 }
2641
2642 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2643 {
2644 // m_originalCaster to allow stacking from different casters, meh
2645 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2647 .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING)));
2648 }
2649
2650 void Register() override
2651 {
2653 }
2654};
2655
2656// 74302, 74341, 74342, 74343 - Summon Spirit Bomb
2658{
2660 {
2661 PreventHitDefaultEffect(effIndex);
2662 GetHitUnit()->CastSpell(nullptr, uint32(GetEffectValue()), true);
2663 }
2664
2665 void Register() override
2666 {
2668 }
2669};
2670
2671// 73582 - Trigger Vile Spirit (Inside, Heroic)
2673{
2675 {
2676 Creature* target = GetHitCreature();
2677 if (!target)
2678 return;
2679
2680 VileSpiritActivateEvent(target).Execute(0, 0);
2681 }
2682
2683 void Register() override
2684 {
2686 }
2687};
2688
2689// 71811 - Jump
2691{
2693 {
2694 PreventHitDefaultEffect(effIndex);
2696 GetHitUnit()->CastSpell(nullptr, SPELL_JUMP_2, true);
2697 if (Creature* creature = GetHitCreature())
2698 creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE);
2699 }
2700
2701 void Register() override
2702 {
2704 }
2705};
2706
2707// 72431 - Jump (Remove Aura)
2709{
2711 {
2712 PreventHitDefaultEffect(effIndex);
2714 }
2715
2716 void Register() override
2717 {
2719 }
2720};
2721
2722// 73655 - Harvest Soul (Teleport)
2724{
2726 {
2727 float randCoordX = frand(-18.0f, 18.0f);
2728 float randCoordY = frand(-18.0f, 18.0f);
2729 GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f });
2730 }
2731
2732 void Register() override
2733 {
2735 }
2736};
2737
2739{
2740 public:
2741 achievement_been_waiting_long_time() : AchievementCriteriaScript("achievement_been_waiting_long_time") { }
2742
2743 bool OnCheck(Player* /*source*/, Unit* target) override
2744 {
2745 if (!target)
2746 return false;
2747
2748 return target->GetAI()->GetData(DATA_PLAGUE_STACK) >= 30;
2749 }
2750};
2751
2753{
2754 public:
2755 achievement_neck_deep_in_vile() : AchievementCriteriaScript("achievement_neck_deep_in_vile") { }
2756
2757 bool OnCheck(Player* /*source*/, Unit* target) override
2758 {
2759 if (!target)
2760 return false;
2761
2762 return !target->GetAI()->GetData(DATA_VILE);
2763 }
2764};
2765
2767{
2768 // Creatures
2779
2780 // Spells
2811
2812 // Achievements
2815}
Texts
@ NPC_WORLD_TRIGGER
@ EQUIP_UNEQUIP
Definition: CreatureAI.h:55
@ TEXT_RANGE_NORMAL
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
@ IN_PROGRESS
@ DONE
@ POINT_MOTION_TYPE
@ TEMPSUMMON_MANUAL_DESPAWN
Definition: ObjectDefines.h:70
@ TEMPSUMMON_CORPSE_DESPAWN
Definition: ObjectDefines.h:67
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
Spells
Definition: PlayerAI.cpp:32
float frand(float min, float max)
Definition: Random.cpp:55
float rand_norm()
Definition: Random.cpp:75
#define RegisterSpellAndAuraScriptPair(script_1, script_2)
Definition: ScriptMgr.h:1371
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
#define RegisterSpellScriptWithArgs(spell_script, script_name,...)
Definition: ScriptMgr.h:1368
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_1
Definition: SharedDefines.h:31
@ EFFECT_0
Definition: SharedDefines.h:30
SpellMissInfo
@ SPELL_MISS_NONE
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ EMOTE_ONESHOT_POINT_NO_SHEATHE
@ EMOTE_ONESHOT_EMERGE
@ EMOTE_STATE_READY2H
@ EMOTE_ONESHOT_NONE
@ EMOTE_ONESHOT_TALK_NO_SHEATHE
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_TELEPORT_UNITS
@ SPELL_EFFECT_APPLY_AURA
@ GO_DESTRUCTIBLE_REBUILDING
@ TEAM_OTHER
@ SPELL_CAST_OK
@ CHAT_MSG_MONSTER_YELL
@ GO_STATE_READY
@ GO_STATE_ACTIVE
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK
@ AURA_EFFECT_HANDLE_REAPPLY
@ AURA_EFFECT_HANDLE_REAL
@ AURA_REMOVE_BY_DEATH
@ AURA_REMOVE_BY_EXPIRE
@ AURA_REMOVE_BY_ENEMY_SPELL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_PERIODIC_DUMMY
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
Definition: SpellDefines.h:266
@ TRIGGERED_IGNORE_CAST_IN_PROGRESS
Will not check if a current cast is in progress.
Definition: SpellDefines.h:252
@ TRIGGERED_NONE
Not triggered.
Definition: SpellDefines.h:246
@ SPELLVALUE_AURA_STACK
Definition: SpellDefines.h:231
@ SPELLVALUE_BASE_POINT1
Definition: SpellDefines.h:197
@ SPELLVALUE_MAX_TARGETS
Definition: SpellDefines.h:230
#define BeforeSpellHitFn(F)
Definition: SpellScript.h:847
#define AuraEffectProcFn(F, I, N)
Definition: SpellScript.h:2160
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define AuraEffectCalcAmountFn(F, I, N)
Definition: SpellScript.h:2058
#define SpellObjectAreaTargetSelectFn(F, I, N)
Definition: SpellScript.h:864
#define AuraEffectPeriodicFn(F, I, N)
Definition: SpellScript.h:2046
#define AuraEffectUpdatePeriodicFn(F, I, N)
Definition: SpellScript.h:2052
#define AuraEffectApplyFn(F, I, N, M)
Definition: SpellScript.h:2029
#define SpellHitFn(F)
Definition: SpellScript.h:854
#define AuraEffectRemoveFn(F, I, N, M)
Definition: SpellScript.h:2040
EvadeReason
Definition: UnitAICommon.h:30
@ MOVE_FLIGHT
Definition: UnitDefines.h:123
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
@ UNIT_STAND_STATE_STAND
Definition: UnitDefines.h:42
@ UNIT_NPC_FLAG_GOSSIP
Definition: UnitDefines.h:297
DamageEffectType
Definition: UnitDefines.h:131
@ SHEATH_STATE_MELEE
Definition: UnitDefines.h:83
@ UNIT_STATE_EVADE
Definition: Unit.h:277
@ UNIT_STATE_CASTING
Definition: Unit.h:270
MiscData
Position const TirionCharge
#define REMORSELESS_WINTER_1
@ EVENT_GROUP_VILE_SPIRITS
@ EVENT_GROUP_BERSERK
@ LIGHT_SOULSTORM
@ MUSIC_FURY_OF_FROSTMOURNE
@ MUSIC_FROZEN_THRONE
@ MUSIC_FINAL
@ LIGHT_DEFAULT
@ LIGHT_SNOWSTORM
@ SOUND_PAIN
@ EQUIP_BROKEN_FROSTMOURNE
@ MUSIC_SPECIAL
@ EQUIP_ASHBRINGER_GLOWING
#define REMORSELESS_WINTER_2
@ DATA_PLAGUE_STACK
@ GOSSIP_MENU_START_INTRO
Position const TirionSpawn
@ ACTION_TELEPORT_BACK
@ ACTION_PLAY_MUSIC
@ ACTION_OUTRO
@ ACTION_CONTINUE_INTRO
@ ACTION_BREAK_FROSTMOURNE
@ ACTION_START_ATTACK
@ ACTION_START_ENCOUNTER
@ ACTION_SUMMON_TERENAS
@ ACTION_DISABLE_RAGING
@ ACTION_FINISH_OUTRO
Position const TirionIntro
@ SPELL_RAGING_SPIRIT_VISUAL
@ SPELL_HARVEST_SOULS
@ SPELL_ICE_PULSE
@ SPELL_PAIN_AND_SUFFERING
@ SPELL_EXPLOSION
@ SPELL_DARK_HUNGER
@ SPELL_SPIRIT_BURST
@ SPELL_HARVEST_SOUL_VISUAL
@ SPELL_NECROTIC_PLAGUE
@ SPELL_SHADOW_TRAP
@ SPELL_JUMP
@ SPELL_SOUL_RIP
@ SPELL_WINGS_OF_THE_DAMNED
@ SPELL_ENRAGE
@ SPELL_SHADOW_TRAP_VISUAL
@ SPELL_SOUL_SHRIEK
@ SPELL_VALKYR_TARGET_SEARCH
@ SPELL_CHARGE
@ SPELL_TRIGGER_VILE_SPIRIT_HEROIC
@ SPELL_SUMMON_VALKYR
@ SPELL_TERENAS_LOSES_INSIDE
@ SPELL_SUMMON_BROKEN_FROSTMOURNE_2
@ SPELL_SHADOW_TRAP_AURA
@ SPELL_QUAKE
@ SPELL_REMORSELESS_WINTER_2
@ SPELL_SOUL_REAPER_BUFF
@ SPELL_SUMMON_BROKEN_FROSTMOURNE
@ SPELL_EMOTE_QUESTION_NO_SHEATH
@ SPELL_LIGHTS_FAVOR
@ SPELL_MASS_RESURRECTION
@ SPELL_HARVEST_SOUL_TELEPORT
@ SPELL_SUMMON_ICE_SPHERE
@ SPELL_SUMMON_DRUDGE_GHOULS
@ SPELL_PLAY_MOVIE
@ SPELL_SUMMON_SHAMBLING_HORROR
@ SPELL_VILE_SPIRIT_MOVE_SEARCH
@ SPELL_DEFILE_AURA
@ SPELL_HARVESTED_SOUL
@ SPELL_DARK_HUNGER_HEAL
@ SPELL_SUMMON_VALKYR_PERIODIC
@ SPELL_ICE_LOCK
@ SPELL_SUMMON_SPIRIT_BOMB_2
@ SPELL_VILE_SPIRIT_DAMAGE_SEARCH
@ SPELL_JUMP_TRIGGERED
@ SPELL_NECROTIC_PLAGUE_JUMP
@ SPELL_ICE_BURST
@ SPELL_MASS_RESURRECTION_REAL
@ SPELL_SOUL_BARRAGE
@ SPELL_HARVEST_SOUL_VEHICLE
@ SPELL_BROKEN_FROSTMOURNE_KNOCK
@ SPELL_SUMMON_BROKEN_FROSTMOURNE_3
@ SPELL_RESTORE_SOUL
@ SPELL_BOSS_HITTIN_YA
@ SPELL_SOUL_REAPER
@ SPELL_HARVEST_SOUL
@ SPELL_RISEN_WITCH_DOCTOR_SPAWN
@ SPELL_RAGING_SPIRIT_VISUAL_CLONE
@ SPELL_LIFE_SIPHON
@ SPELL_SUMMON_SPIRIT_BOMB_1
@ SPELL_KILL_FROSTMOURNE_PLAYERS
@ SPELL_DESTROY_SOUL
@ SPELL_LIGHTS_BLESSING
@ SPELL_BROKEN_FROSTMOURNE
@ SPELL_RAISE_DEAD
@ SPELL_SOUL_RIP_DAMAGE
@ SPELL_SHADOW_TRAP_KNOCKBACK
@ SPELL_RAGING_SPIRIT
@ SPELL_HARVEST_SOULS_TELEPORT
@ SPELL_HARVEST_SOUL_TELEPORT_BACK
@ SPELL_FRENZY
@ SPELL_SHOCKWAVE
@ SPELL_REMORSELESS_WINTER_1
@ SPELL_FURY_OF_FROSTMOURNE
@ SPELL_VALKYR_CARRY
@ SPELL_VILE_SPIRITS
@ SPELL_EJECT_ALL_PASSENGERS
@ SPELL_PLAGUE_AVOIDANCE
@ SPELL_SUMMON_TERENAS
@ SPELL_ICE_BURST_TARGET_SEARCH
@ SPELL_EMOTE_SHOUT_NO_SHEATH
@ SPELL_IN_FROSTMOURNE_ROOM
@ SPELL_LIFE_SIPHON_HEAL
@ SPELL_VALKYR_TRANSFORM
@ SPELL_EMOTE_SIT_NO_SHEATH
@ SPELL_PLAGUE_SIPHON
@ SPELL_RESTORE_SOULS
@ SPELL_DEFILE_GROW
@ SPELL_DEFILE
@ SPELL_HARVEST_SOUL_VALKYR
@ SPELL_JUMP_2
@ SPELL_ICE_SPHERE
@ SPELL_FURY_OF_FROSTMOURNE_NO_REZ
@ SPELL_INFEST
@ PHASE_INTRO
@ PHASE_FROSTMOURNE
@ PHASE_TRANSITION
@ PHASE_OUTRO
@ PHASE_THREE
@ POINT_LK_INTRO_2
@ POINT_GROUND
@ POINT_LK_OUTRO_1
@ POINT_TIRION_OUTRO_1
@ POINT_LK_OUTRO_2
@ POINT_CHARGE
@ POINT_CENTER_2
@ POINT_SIPHON
@ POINT_LK_INTRO_1
@ POINT_LK_INTRO_3
@ POINT_TIRION_INTRO
@ POINT_DROP_PLAYER
@ POINT_TIRION_CHARGE
@ POINT_CENTER_1
@ POINT_OUTRO_JUMP
Position const OutroPosition1
#define ENRAGE
Position const TerenasSpawn
@ SAY_LK_QUAKE
@ SAY_LK_OUTRO_2
@ SAY_LK_INTRO_2
@ SAY_LK_FROSTMOURNE_ESCAPE
@ SAY_LK_REMORSELESS_WINTER
@ SAY_LK_OUTRO_4
@ SAY_TERENAS_INTRO_3
@ SAY_LK_SUMMON_VALKYR
@ EMOTE_NECROTIC_PLAGUE_WARNING
@ SAY_TERENAS_INTRO_2
@ SAY_TIRION_OUTRO_1
@ SAY_LK_HARVEST_SOUL
@ SAY_LK_KILL
@ SAY_LK_INTRO_1
@ SAY_LK_INTRO_3
@ SAY_TERENAS_OUTRO_2
@ SAY_LK_OUTRO_7
@ EMOTE_DEFILE_WARNING
@ SAY_LK_OUTRO_1
@ SAY_LK_BERSERK
@ SAY_LK_OUTRO_6
@ SAY_LK_FROSTMOURNE_KILL
@ SAY_TERENAS_INTRO_1
@ SAY_LK_OUTRO_5
@ SAY_TIRION_INTRO_2
@ SAY_LK_OUTRO_3
@ SAY_TIRION_INTRO_1
@ SAY_LK_OUTRO_8
@ SAY_TIRION_OUTRO_2
@ SAY_TERENAS_OUTRO_1
#define NECROTIC_PLAGUE_PLR
#define SUMMON_VALKYR
void AddSC_boss_the_lich_king()
#define PHASE_TWO_THREE
#define NECROTIC_PLAGUE_LK
Position const TerenasSpawnHeroic
Position const CenterPosition
Position const OutroFlying
Position const LichKingIntro[3]
#define HARVEST_SOUL
Position const SpiritWardenSpawn
@ EVENT_DESTROY_SOUL
@ EVENT_SUMMON_ICE_SPHERE
@ EVENT_OUTRO_EMOTE_TALK
@ EVENT_OUTRO_TALK_3
@ EVENT_DEFILE
@ EVENT_OUTRO_TERENAS_TALK_1
@ EVENT_FROSTMOURNE_TALK_3
@ EVENT_SUMMON_SHAMBLING_HORROR
@ EVENT_MOVE_TO_LICH_KING
@ EVENT_INTRO_MOVE_3
@ EVENT_FROSTMOURNE_TALK_1
@ EVENT_FROSTMOURNE_HEROIC
@ EVENT_SHADOW_TRAP
@ EVENT_HARVEST_SOUL
@ EVENT_OUTRO_TERENAS_TALK_2
@ EVENT_GRAB_PLAYER
@ EVENT_OUTRO_TALK_4
@ EVENT_NECROTIC_PLAGUE
@ EVENT_OUTRO_MOVE_CENTER
@ EVENT_OUTRO_TALK_2
@ EVENT_ENRAGE
@ EVENT_OUTRO_TALK_7
@ EVENT_START_ATTACK
@ EVENT_OUTRO_KNOCK_BACK
@ EVENT_TELEPORT
@ EVENT_SUMMON_RAGING_SPIRIT
@ EVENT_INTRO_CAST_FREEZE
@ EVENT_BOMB_EXPLOSION
@ EVENT_TELEPORT_BACK
@ EVENT_INFEST
@ EVENT_OUTRO_TALK_8
@ EVENT_DESPAWN_SELF
@ EVENT_SUMMON_VALKYR
@ EVENT_QUAKE_2
@ EVENT_INTRO_MOVE_1
@ EVENT_HARVEST_SOULS
@ EVENT_OUTRO_JUMP
@ EVENT_LIFE_SIPHON
@ EVENT_OUTRO_SUMMON_TERENAS
@ EVENT_INTRO_MOVE_2
@ EVENT_BERSERK
@ EVENT_OUTRO_REMOVE_ICE
@ EVENT_MOVE_TO_DROP_POS
@ EVENT_INTRO_EMOTE_1
@ EVENT_INTRO_CHARGE
@ EVENT_SUMMON_RAGING_SPIRIT_2
@ EVENT_OUTRO_RAISE_DEAD
@ EVENT_OUTRO_BLESS
@ EVENT_FROSTMOURNE_TALK_2
@ EVENT_SOUL_SHRIEK
@ EVENT_SET_AGRESSIVE
@ EVENT_PAIN_AND_SUFFERING
@ EVENT_VILE_SPIRITS
@ EVENT_OUTRO_TALK_5
@ EVENT_SUMMON_DRUDGE_GHOUL
@ EVENT_SOUL_REAPER
@ EVENT_QUAKE
@ EVENT_SHOCKWAVE
@ EVENT_OUTRO_TALK_6
@ EVENT_MOVE_TO_CENTER
@ EVENT_INTRO_TALK_1
@ EVENT_FINISH_INTRO
@ EVENT_OUTRO_TALK_1
@ EVENT_EMOTE_CAST_SHOUT
@ EVENT_OUTRO_MOVE_1
@ EVENT_SOUL_RIP
@ EVENT_OUTRO_SOUL_BARRAGE
MovePoints
@ NPC_THE_LICH_KING
Definition: chapter5.cpp:162
uint32 GetTickNumber() const
SpellEffectInfo const & GetSpellEffectInfo() const
void SetAmount(int32 amount)
int32 GetAmount() const
void PreventDefaultAction()
AuraApplication const * GetTargetApplication() const
HookList< EffectApplyHandler > AfterEffectRemove
Definition: SpellScript.h:2039
HookList< EffectPeriodicHandler > OnEffectPeriodic
Definition: SpellScript.h:2045
WorldObject * GetOwner() const
HookList< EffectApplyHandler > AfterEffectApply
Definition: SpellScript.h:2028
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
Definition: SpellScript.h:2057
Unit * GetCaster() const
HookList< EffectUpdatePeriodicHandler > OnEffectUpdatePeriodic
Definition: SpellScript.h:2051
AuraEffect * GetEffect(uint8 effIndex) const
Aura * GetAura() const
Unit * GetTarget() const
ObjectGuid GetCasterGUID() const
HookList< AuraDispelHandler > OnDispel
Definition: SpellScript.h:2013
HookList< AuraDispelHandler > AfterDispel
Definition: SpellScript.h:2017
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
HookList< EffectProcHandler > OnEffectProc
Definition: SpellScript.h:2155
Unit * GetUnitOwner() const
uint8 GetStackAmount() const
HookList< EffectApplyHandler > OnEffectApply
Definition: SpellScript.h:2024
InstanceScript *const instance
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
bool CanAIAttack(Unit const *target) const override
SummonList summons
EventMap events
void _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:328
Creature *const me
Definition: CreatureAI.h:61
void EngagementOver()
Definition: CreatureAI.cpp:287
static void SendSound(Creature *source, uint32 sound, ChatMsg msgType, WorldObject const *whisperTarget=nullptr, CreatureTextRange range=TEXT_RANGE_NORMAL, Team team=TEAM_OTHER, bool gmOnly=false, uint32 keyBroadcastTextId=0, SoundKitPlayType playType=SoundKitPlayType::Normal)
void SetCombatPulseDelay(uint32 delay)
Definition: Creature.h:345
void SetImmuneToPC(bool apply) override
Definition: Creature.h:170
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition: Creature.h:373
void LoadEquipment(int8 id=1, bool force=false)
Definition: Creature.cpp:1946
void SetReactState(ReactStates st)
Definition: Creature.h:160
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
bool IsInEvadeMode() const
Definition: Creature.h:203
CreatureAI * AI() const
Definition: Creature.h:214
uint32 GetDamage() const
Definition: Unit.h:446
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void Repeat(Milliseconds time)
Definition: EventMap.cpp:63
void DelayEvents(Milliseconds delay)
Definition: EventMap.cpp:96
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
bool IsInPhase(uint8 phase) const
Definition: EventMap.h:217
void SetPhase(uint8 phase)
Definition: EventMap.cpp:28
void RescheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:52
void Reset()
Definition: EventMap.cpp:21
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
ExactDistanceCheck(Unit *source, float dist)
bool operator()(WorldObject *unit)
bool operator()(GameObject *go)
void SetGoState(GOState state)
void SetDestructibleState(GameObjectDestructibleState state, WorldObject *attackerOrHealer=nullptr, bool setHealth=false)
void ResetDoorOrButton()
virtual bool SetBossState(uint32 id, EncounterState state)
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
LichKingStartMovementEvent(Creature *summoner, Creature *owner)
bool Execute(uint64, uint32) override
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition: Map.cpp:3913
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
Definition: Map.cpp:3962
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty, SmoothPhasingInfo const *smoothPhasingInfo=nullptr)
Definition: Object.cpp:1836
bool Is25ManRaid() const
Definition: Map.cpp:3320
void SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
Definition: Map.cpp:3981
void MoveRandom(float wanderDistance=0.0f, Optional< Milliseconds > duration={}, MovementSlot slot=MOTION_SLOT_DEFAULT)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, Optional< Milliseconds > duration={}, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveFall(uint32 id=0)
NecroticPlagueTargetCheck(Unit const *obj, uint32 notAura1=0, uint32 notAura2=0)
bool operator()(Unit *unit) const
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
static Creature * ToCreature(Object *o)
Definition: Object.h:219
static Unit * ToUnit(Object *o)
Definition: Object.h:225
Player * ToPlayer()
Definition: Object.h:215
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
DamageInfo * GetDamageInfo() const
Definition: Unit.h:505
uint32 TriggerSpell
Definition: SpellInfo.h:237
uint32 const Id
Definition: SpellInfo.h:325
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
WorldLocation * GetHitDest() const
Creature * GetHitCreature() const
int32 GetHitDamage() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
Definition: SpellScript.h:852
HookList< HitHandler > OnHit
Definition: SpellScript.h:850
HookList< EffectHandler > OnEffectHit
Definition: SpellScript.h:839
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
int32 GetEffectValue() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
HookList< BeforeHitHandler > BeforeHit
Definition: SpellScript.h:846
void SetHitDamage(int32 damage)
WorldLocation const * GetExplTargetDest() const
HookList< EffectHandler > OnEffectLaunch
Definition: SpellScript.h:837
SpellInfo const * GetSpellInfo() const
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
Definition: SpellScript.h:863
void DespawnEntry(uint32 entry)
void Summon(Creature const *summon)
void DoAction(int32 info, Predicate &&predicate, uint16 max=0)
void SetTempSummonType(TempSummonType type)
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
bool Execute(uint64, uint32) override
TriggerWickedSpirit(Creature *owner)
Definition: UnitAI.h:50
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
virtual uint32 GetData(uint32) const
Definition: UnitAI.h:73
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition: UnitAI.h:75
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:161
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
void ClearUnitState(uint32 f)
Definition: Unit.h:733
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition: Unit.cpp:8168
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5827
void SetHealth(uint64 val)
Definition: Unit.cpp:9346
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition: Unit.cpp:12671
bool IsAlive() const
Definition: Unit.h:1164
void RemoveNpcFlag(NPCFlags flags)
Definition: Unit.h:983
TempSummon * ToTempSummon()
Definition: Unit.h:1756
UnitAI * GetAI() const
Definition: Unit.h:660
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition: Unit.cpp:12725
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
void SetSheath(SheathState sheathed)
Definition: Unit.cpp:5630
void SetEmoteState(Emote emote)
Definition: Unit.h:852
uint64 GetMaxHealth() const
Definition: Unit.h:777
uint64 GetHealth() const
Definition: Unit.h:776
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4674
bool SetWalk(bool enable)
Definition: Unit.cpp:12707
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition: Unit.cpp:8525
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:12653
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void RemoveAllAuras()
Definition: Unit.cpp:4242
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
bool AttackStop()
Definition: Unit.cpp:5781
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
bool IsInCombat() const
Definition: Unit.h:1043
bool Execute(uint64, uint32) override
VileSpiritActivateEvent(Creature *owner)
Map * GetMap() const
Definition: Object.h:624
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition: Object.cpp:3312
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
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:2025
void setActive(bool isActiveObject)
Definition: Object.cpp:922
void SetFarVisible(bool on)
Definition: Object.cpp:973
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2148
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1360
EventProcessor m_Events
Definition: Object.h:777
void GetRandomPoint(Position const &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const
Definition: Object.cpp:1331
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *, Unit *target) override
bool Validate(SpellInfo const *) override
void HandleProc(AuraEffect *aurEff, ProcEventInfo &eventInfo)
void CorrectRange(std::list< WorldObject * > &targets)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void CheckTargetCount(std::list< WorldObject * > &unitList)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void OnPeriodic(AuraEffect const *)
void OnUpdate(AuraEffect *aurEff)
void HandleScript(SpellEffIndex effIndex)
void HandleScript(SpellEffIndex effIndex)
bool Validate(SpellInfo const *) override
void CalculateBonus(AuraEffect const *, int32 &amount, bool &canBeRecalculated)
void AfterDispel(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnRemove(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnDispel(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void SelectTarget(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void FilterTargets(std::list< WorldObject * > &targets)
void HandleSendEvent(SpellEffIndex)
void HandleScript(SpellEffIndex effIndex)
void RemoveAura(SpellMissInfo missInfo)
void CheckTargetCount(std::list< WorldObject * > &targets)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *)
void OnPeriodic(AuraEffect const *aurEff)
void HandleScript(SpellEffIndex effIndex)
void ReplaceTarget(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void SelectTarget(std::list< WorldObject * > &targets)
void CheckTargetCount(std::list< WorldObject * > &targets)
void SelectTarget(std::list< WorldObject * > &targets)
void OnPeriodic(AuraEffect const *aurEff)
@ WEATHER_STATE_BLACKSNOW
Definition: Weather.h:61
@ WEATHER_STATE_LIGHT_SNOW
Definition: Weather.h:53
@ WEATHER_STATE_FOG
Definition: Weather.h:48
@ SPELL_BERSERK2
@ LIGHT_S_HAMMER_TELEPORT
#define RegisterIcecrownCitadelCreatureAI(ai_name)
@ AREA_ICECROWN_CITADEL
@ GO_DOODAD_ICESHARD_STANDING01
@ GO_DOODAD_ICESHARD_STANDING02
@ GO_DOODAD_ICESHARD_STANDING04
@ GO_ARTHAS_PLATFORM
@ GO_DOODAD_ICESHARD_STANDING03
@ GO_DOODAD_ICECROWN_THRONEFROSTYWIND01
@ GO_DOODAD_ICECROWN_THRONEFROSTYEDGE01
@ ACTION_FROSTMOURNE_INTRO
@ ACTION_RESTORE_LIGHT
@ DATA_THE_LICH_KING
@ DATA_TERENAS_MENETHIL
@ DATA_HIGHLORD_TIRION_FORDRING
@ DATA_ARTHAS_PLATFORM
@ NPC_THE_LICH_KING_QUEST
@ NPC_RAGING_SPIRIT
@ NPC_FROSTMOURNE_TRIGGER
@ NPC_VALKYR_SHADOWGUARD
@ NPC_SHAMBLING_HORROR
@ NPC_SPIRIT_WARDEN
@ NPC_SPIRIT_BOMB
@ NPC_WICKED_SPIRIT
@ NPC_STRANGULATE_VEHICLE
@ NPC_HIGHLORD_TIRION_FORDRING_LK
@ NPC_VILE_SPIRIT
@ NPC_SHADOW_TRAP
@ NPC_DEFILE
@ NPC_WORLD_TRIGGER_INFINITE_AOI
@ NPC_ICE_SPHERE
@ NPC_TERENAS_MENETHIL_FROSTMOURNE_H
@ NPC_DRUDGE_GHOUL
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
CastSpellExtraArgs & SetOriginalCaster(ObjectGuid const &guid)
Definition: SpellDefines.h:471
CastSpellExtraArgs & AddSpellBP0(int32 val)
Definition: SpellDefines.h:475
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
Definition: SpellDefines.h:474
ObjectGuid OriginalCaster
Definition: SpellDefines.h:482
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:179
float m_positionZ
Definition: Position.h:55
float GetExactDist2d(const float x, const float y) const
Definition: Position.h:106
float GetExactDist(float x, float y, float z) const
Definition: Position.h:118
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr void Relocate(float x, float y)
Definition: Position.h:63
void RelocateOffset(Position const &offset)
Definition: Position.cpp:34
bool IsHeroic() const
void SetEquipmentSlots(bool loadDefault, int32 mainHand=EQUIP_NO_CHANGE, int32 offHand=EQUIP_NO_CHANGE, int32 ranged=EQUIP_NO_CHANGE)
void SetCombatMovement(bool allowMovement)
bool HealthAbovePct(uint32 pct) const
bool Is25ManRaid() const
boss_the_lich_king(Creature *creature)
void SummonedCreatureDies(Creature *summon, Unit *) override
void MovementInform(uint32 type, uint32 pointId) override
void JustSummoned(Creature *summon) override
bool CanAIAttack(Unit const *target) const override
uint32 GetData(uint32 type) const override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void JustDied(Unit *killer) override
void KilledUnit(Unit *victim) override
void EnterEvadeMode(EvadeReason) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &, DamageEffectType, SpellInfo const *) override
void JustEngagedWith(Unit *target) override
void SetData(uint32 type, uint32 value) override
void UpdateAI(uint32 diff) override
void EnterEvadeMode(EvadeReason) override
void IsSummonedBy(WorldObject *) override
npc_broken_frostmourne(Creature *creature)
void DoAction(int32 action) override
void DoAction(int32 action) override
void IsSummonedBy(WorldObject *) override
void UpdateAI(uint32 diff) override
InstanceScript * _instance
npc_raging_spirit(Creature *creature)
void JustDied(Unit *) override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
npc_shambling_horror_icc(Creature *creature)
void OnSpellFailed(SpellInfo const *spell) override
npc_spirit_bomb(Creature *creature)
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void MovementInform(uint32 type, uint32 point) override
void UpdateAI(uint32 diff) override
void IsSummonedBy(WorldObject *) override
npc_spirit_warden(Creature *creature)
InstanceScript * _instance
void JustDied(Unit *) override
void UpdateAI(uint32 diff) override
void IsSummonedBy(WorldObject *summonerWO) override
void DoAction(int32 action) override
npc_strangulate_vehicle(Creature *creature)
void UpdateAI(uint32 diff) override
npc_terenas_menethil(Creature *creature)
void EnterEvadeMode(EvadeReason) override
bool CanAIAttack(Unit const *target) const override
void IsSummonedBy(WorldObject *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
npc_tirion_fordring_tft(Creature *creature)
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
bool OnGossipSelect(Player *, uint32 menuId, uint32 gossipListId) override
void MovementInform(uint32 type, uint32 id) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
void SetGUID(ObjectGuid const &guid, int32) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MovementInform(uint32 type, uint32 id) override
npc_valkyr_shadowguard(Creature *creature)
void IsSummonedBy(WorldObject *) override