TrinityCore
Loading...
Searching...
No Matches
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
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
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
331
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
362
364 DATA_VILE = 45814622,
366
368};
369
371{
372 public:
373 NecroticPlagueTargetCheck(Unit const* obj, uint32 notAura1 = 0, uint32 notAura2 = 0)
374 : _sourceObj(obj), _notAura1(notAura1), _notAura2(notAura2)
375 {
376 }
377
378 bool operator()(Unit* unit) const
379 {
380 if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
381 return false;
382 if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
383 return false;
384 return true;
385 }
386
387 private:
391};
392
394{
395 public:
397
399 {
400 switch (go->GetEntry())
401 {
404 break;
407 break;
410 break;
415 go->ResetDoorOrButton();
416 break;
417 default:
418 break;
419 }
420
421 return false;
422 }
423};
424
426{
427 public:
429 : _owner(owner)
430 {
431 }
432
433 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
434 {
438 return true;
439 }
440
441 private:
443};
444
446{
447 public:
449 : _owner(owner), _counter(13)
450 {
451 }
452
453 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
454 {
456
457 if (--_counter)
458 {
460 return false;
461 }
462
463 return true;
464 }
465
466 private:
469};
470
471// 36597 - The Lich King
473{
475 {
476 Initialize();
477 }
478
480 {
483 }
484
485 void Reset() override
486 {
487 _Reset();
488 me->SetImmuneToPC(true);
491 Initialize();
492 SetEquipmentSlots(true);
493
494 // Reset The Frozen Throne gameobjects
497 Cell::VisitGridObjects(me, worker, 333.0f);
498
499 // Reset any light override
501
504 }
505
506 void JustDied(Unit* killer) override
507 {
508 _JustDied();
510 me->SetDisableGravity(false);
512 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
513 frostmourne->DespawnOrUnsummon();
516
517 if (Is25ManRaid())
518 if (Player* player = Object::ToPlayer(killer))
519 player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player);
520 }
521
543
544 bool CanAIAttack(Unit const* target) const override
545 {
546 // The Lich King must not select targets in frostmourne room if he killed everyone outside
547 return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target);
548 }
549
560
561 void KilledUnit(Unit* victim) override
562 {
565 }
566
567 void DoAction(int32 action) override
568 {
569 switch (action)
570 {
575 // schedule talks
578 break;
581 break;
584 break;
587 break;
593 break;
597 break;
599 {
602 if (!IsHeroic())
604 break;
605 }
606 default:
607 break;
608 }
609 }
610
611 uint32 GetData(uint32 type) const override
612 {
613 switch (type)
614 {
617 case DATA_VILE:
619 default:
620 break;
621 }
622
623 return 0;
624 }
625
626 void SetData(uint32 type, uint32 value) override
627 {
628 switch (type)
629 {
632 break;
633 case DATA_VILE:
634 _vileSpiritExplosions += value;
635 break;
636 default:
637 break;
638 }
639 }
640
641 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
642 {
644 {
647 me->AttackStop();
650 return;
651 }
652
654 {
657 me->AttackStop();
660 return;
661 }
662
664 {
666 me->AttackStop();
667 events.Reset();
673 me->SetWalk(true);
683 // stop here. rest will get scheduled from MovementInform
684 return;
685 }
686 }
687
688 void JustSummoned(Creature* summon) override
689 {
690 switch (summon->GetEntry())
691 {
693 case NPC_DRUDGE_GHOUL:
694 summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
697 SetAggressiveStateAfter(5s, summon, true, me, StartCombatArgs().SetAvoidTargetVictim(true));
698 break;
699 case NPC_SHADOW_TRAP:
700 summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true);
701 break;
702 case NPC_ICE_SPHERE:
703 {
704 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
705 {
707 summon->CastSpell(summon, SPELL_ICE_SPHERE, false);
708 summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false);
709 summon->CastSpell(target, SPELL_ICE_PULSE, false);
710 summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
711 }
712 else
713 summon->DespawnOrUnsummon();
714 break;
715 }
716 case NPC_DEFILE:
718 summon->CastSpell(summon, SPELL_DEFILE_AURA, false);
719 break;
721 {
722 summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true);
723
726
728 return;
729 }
730 case NPC_VILE_SPIRIT:
731 {
732 summons.Summon(summon);
734 summon->SetSpeedRate(MOVE_FLIGHT, 0.5f);
735 summon->GetMotionMaster()->MoveRandom(10.0f);
737 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s));
738 return;
739 }
741 summons.Summon(summon);
742 return;
744 return;
745 default:
746 break;
747 }
748
749 BossAI::JustSummoned(summon);
750 }
751
752 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
753 {
754 switch (summon->GetEntry())
755 {
757 case NPC_DRUDGE_GHOUL:
758 case NPC_ICE_SPHERE:
761 case NPC_VILE_SPIRIT:
763 break;
764 default:
765 break;
766 }
767 }
768
769 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
770 {
771 if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic())
773
774 if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2)
775 {
779 }
780 }
781
782 void MovementInform(uint32 type, uint32 pointId) override
783 {
784 if (type != POINT_MOTION_TYPE)
785 return;
786
787 switch (pointId)
788 {
789 case POINT_LK_INTRO_1:
790 // schedule for next update cycle, current update must finalize movement
792 break;
793 case POINT_LK_INTRO_2:
795 break;
796 case POINT_LK_INTRO_3:
798 tirion->AI()->DoAction(ACTION_CONTINUE_INTRO);
800 break;
801 case POINT_CENTER_1:
802 me->SetFacingTo(0.0f);
814 break;
815 case POINT_CENTER_2:
816 me->SetFacingTo(0.0f);
829 break;
830 case POINT_LK_OUTRO_1:
834 break;
835 case POINT_LK_OUTRO_2:
837 tirion->AI()->Talk(SAY_TIRION_OUTRO_2);
838 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
839 frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS);
840 break;
841 default:
842 break;
843 }
844 }
845
846 void UpdateAI(uint32 diff) override
847 {
848 // check phase first to prevent updating victim and entering evade mode when not wanted
850 if (!UpdateVictim())
851 return;
852
853 events.Update(diff);
854
855 // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells
857 return;
858
859 while (uint32 eventId = events.ExecuteEvent())
860 {
861 switch (eventId)
862 {
866 me->SetWalk(true);
868 break;
871 break;
874 break;
877 // for some reason blizz sends 2 emotes in row here so (we handle one in Talk)
883 break;
886 break;
889 break;
894 break;
896 me->SetWalk(false);
897 me->SetImmuneToPC(false);
901 break;
906 break;
910 break;
911 case EVENT_INFEST:
914 break;
917 {
920 }
922 break;
925 DoCast(target, SPELL_SHADOW_TRAP);
927 break;
931 break;
932 case EVENT_DEFILE:
933 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
934 {
936 DoCast(target, SPELL_DEFILE);
937 }
939 break;
943 DoCast(target, SPELL_HARVEST_SOUL);
945 break;
947 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
950 break;
954 break;
956 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
959 break;
961 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
964 break;
965 case EVENT_QUAKE:
967 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
971 break;
972 case EVENT_QUAKE_2:
974 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
978 break;
984 break;
989 break;
994 break;
999 events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading)
1001 me->AttackStop();
1007 for (ObjectGuid guid : summons)
1008 {
1009 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1010 {
1011 if (summon->GetEntry() == NPC_VILE_SPIRIT)
1012 {
1013 summon->m_Events.KillAllEvents(true);
1014 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms));
1015 summon->SetReactState(REACT_PASSIVE);
1016 summon->CombatStop(true);
1017 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
1018 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
1019 summon->GetMotionMaster()->MoveTargetedHome();
1020 }
1021 else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
1022 summon->AI()->DoAction(ACTION_DISABLE_RAGING);
1023 }
1024 }
1025 break;
1028 {
1029 terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
1030 std::list<Creature*> triggers;
1032 if (!triggers.empty())
1033 {
1034 triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
1035 Creature* spawner = triggers.front();
1036 spawner->setActive(true);
1037 spawner->SetFarVisible(true);
1038 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly
1039 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
1040 spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s));
1041 }
1042 }
1043 break;
1044 case EVENT_OUTRO_TALK_1:
1047 break;
1048 case EVENT_OUTRO_TALK_2:
1051 break;
1054 break;
1055 case EVENT_OUTRO_TALK_3:
1057 me->SetFacingToObject(tirion);
1059 break;
1062 break;
1063 case EVENT_OUTRO_TALK_4:
1064 me->SetFacingTo(0.01745329f);
1066 break;
1071 break;
1072 case EVENT_OUTRO_TALK_5:
1075 tirion->AI()->DoAction(ACTION_OUTRO);
1076 break;
1077 case EVENT_OUTRO_TALK_6:
1080 tirion->SetFacingToObject(me);
1083 break;
1087 // set flight
1088 me->SetDisableGravity(true);
1090 break;
1091 case EVENT_OUTRO_TALK_7:
1093 break;
1094 case EVENT_OUTRO_TALK_8:
1096 break;
1097 case EVENT_BERSERK:
1100 break;
1101 default:
1102 break;
1103 }
1104
1106 return;
1107 }
1108 }
1109
1110private:
1113};
1114
1115// 38995 - Highlord Tirion Fordring
1117{
1118 npc_tirion_fordring_tft(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1119
1120 void Reset() override
1121 {
1122 _events.Reset();
1125 }
1126
1127 void MovementInform(uint32 type, uint32 id) override
1128 {
1129 if (type != POINT_MOTION_TYPE)
1130 return;
1131
1132 switch (id)
1133 {
1134 case POINT_TIRION_INTRO:
1137 theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER);
1138 break;
1141 break;
1142 }
1143 }
1144
1145 void DoAction(int32 action) override
1146 {
1147 switch (action)
1148 {
1152 break;
1153 case ACTION_OUTRO:
1159 break;
1160 }
1161 }
1162
1163 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1164 {
1165 if (spellInfo->Id == SPELL_ICE_LOCK)
1166 me->SetFacingTo(3.085098f);
1167 else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
1168 me->LoadEquipment(1); // remove glow on ashbringer
1169 }
1170
1171 bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
1172 {
1173 if (menuId == GOSSIP_MENU_START_INTRO && !gossipListId)
1174 {
1177 me->SetWalk(true);
1179 }
1180 return false;
1181 }
1182
1183 void JustReachedHome() override
1184 {
1186 }
1187
1188 void UpdateAI(uint32 diff) override
1189 {
1191 return;
1192
1193 _events.Update(diff);
1194
1196 return;
1197
1198 while (uint32 eventId = _events.ExecuteEvent())
1199 {
1200 switch (eventId)
1201 {
1202 case EVENT_INTRO_TALK_1:
1206 break;
1209 break;
1210 case EVENT_INTRO_CHARGE:
1211 me->SetWalk(false);
1213 break;
1214 case EVENT_OUTRO_TALK_1:
1216 break;
1217 case EVENT_OUTRO_BLESS:
1219 break;
1224 {
1225 me->SetFacingToObject(lichKing);
1226 lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
1227 }
1228 break;
1229 case EVENT_OUTRO_MOVE_1:
1231 break;
1232 case EVENT_OUTRO_JUMP:
1234 break;
1235 default:
1236 break;
1237 }
1238 }
1239 }
1240
1241private:
1244};
1245
1246// 37698 - Shambling Horror
1248{
1250 {
1251 _frenzied = false;
1252 }
1253
1254 void Reset() override
1255 {
1256 _events.Reset();
1259 }
1260
1261 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1262 {
1263 if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage))
1264 {
1265 _frenzied = true;
1266 DoCastSelf(SPELL_FRENZY, true);
1267 }
1268 }
1269
1270 void UpdateAI(uint32 diff) override
1271 {
1272 if (!UpdateVictim())
1273 return;
1274
1275 _events.Update(diff);
1276
1278 return;
1279
1280 while (uint32 eventId = _events.ExecuteEvent())
1281 {
1282 switch (eventId)
1283 {
1284 case EVENT_SHOCKWAVE:
1287 break;
1288 case EVENT_ENRAGE:
1291 else
1293 break;
1294 default:
1295 break;
1296 }
1297 }
1298 }
1299
1300 void OnSpellFailed(SpellInfo const* spell) override
1301 {
1302 if (spell->Id == ENRAGE)
1304 }
1305
1306private:
1309};
1310
1311// 36701 - Raging Spirit
1313{
1314 npc_raging_spirit(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1315
1316 void Reset() override
1317 {
1319 _events.Reset();
1324 if (TempSummon* summon = me->ToTempSummon())
1325 if (Unit* summoner = summon->GetSummonerUnit())
1326 summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true);
1328 }
1329
1330 void DoAction(int32 action) override
1331 {
1332 if (action == ACTION_DISABLE_RAGING)
1333 {
1334 _events.Reset();
1338 me->AttackStop();
1340 }
1341 }
1342
1343 void IsSummonedBy(WorldObject* /*summoner*/) override
1344 {
1345 // player is the spellcaster so register summon manually
1347 lichKing->AI()->JustSummoned(me);
1348 }
1349
1350 void JustDied(Unit* /*killer*/) override
1351 {
1353 lichKing->AI()->SummonedCreatureDespawn(me);
1354 if (TempSummon* summon = me->ToTempSummon())
1355 summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
1356 }
1357
1358 void UpdateAI(uint32 diff) override
1359 {
1361 return;
1362
1363 _events.Update(diff);
1364
1366 return;
1367
1368 while (uint32 eventId = _events.ExecuteEvent())
1369 {
1370 switch (eventId)
1371 {
1372 case EVENT_SOUL_SHRIEK:
1375 break;
1379 {
1382 }
1383 break;
1384 default:
1385 break;
1386 }
1387 }
1388 }
1389
1390private:
1393};
1394
1395// 36609 - Val'kyr Shadowguard
1397{
1398 npc_valkyr_shadowguard(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
1399 {
1400 SetCombatMovement(false);
1401 }
1402
1403 void Reset() override
1404 {
1405 _events.Reset();
1408 }
1409
1410 void IsSummonedBy(WorldObject* /*summoner*/) override
1411 {
1412 _events.Reset();
1414 }
1415
1416 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1417 {
1418 if (!IsHeroic())
1419 return;
1420
1422 return;
1423
1424 if (me->HealthBelowPctDamaged(50, damage))
1425 {
1428 }
1429 }
1430
1437
1438 void MovementInform(uint32 type, uint32 id) override
1439 {
1440 if (type != POINT_MOTION_TYPE)
1441 return;
1442
1443 switch (id)
1444 {
1445 case POINT_DROP_PLAYER:
1447 if (IsHeroic())
1449 else
1450 me->DespawnOrUnsummon(1s);
1451 break;
1452 case POINT_CHARGE:
1454 {
1455 me->SetUninteractible(false);
1457 {
1458 std::list<Creature*> triggers;
1460 triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true));
1461 if (triggers.empty())
1462 return;
1463
1464 triggers.sort(Trinity::ObjectDistanceOrderPred(me));
1465 DoCast(target, SPELL_VALKYR_CARRY);
1466 _dropPoint.Relocate(triggers.front()->GetPositionX(), triggers.front()->GetPositionY(), me->GetFloorZ() + 2.f);
1468 }
1469 }
1470 else
1472 break;
1473 case POINT_SIPHON:
1478 break;
1479 default:
1480 break;
1481 }
1482 }
1483
1484 void SetGUID(ObjectGuid const& guid, int32 id) override
1485 {
1486 if (id != DATA_GRABBED_PLAYER_GUID)
1487 return;
1488
1489 _grabbedPlayer = guid;
1490 }
1491
1492 void UpdateAI(uint32 diff) override
1493 {
1494 if (!UpdateVictim())
1495 return;
1496
1497 _events.Update(diff);
1498
1500 return;
1501
1502 while (uint32 eventId = _events.ExecuteEvent())
1503 {
1504 switch (eventId)
1505 {
1506 case EVENT_GRAB_PLAYER:
1507 if (!_grabbedPlayer)
1508 {
1511 }
1512 break;
1515 break;
1516 case EVENT_LIFE_SIPHON:
1518 _events.Repeat(2s + 500ms);
1519 break;
1521 {
1523 pos.m_positionZ = me->GetHomePosition().m_positionZ;
1525 break;
1526 }
1527 default:
1528 break;
1529 }
1530
1532 return;
1533 }
1534 }
1535
1536private:
1541};
1542
1543// 36598 - Strangulate Vehicle
1545{
1546 npc_strangulate_vehicle(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1547
1548 void IsSummonedBy(WorldObject* summonerWO) override
1549 {
1550 Unit* summoner = summonerWO->ToUnit();
1551 if (!summoner)
1552 return;
1553 me->SetFacingToObject(summoner);
1555 _events.Reset();
1558
1559 // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back
1561 lichKing->AI()->JustSummoned(me);
1562 }
1563
1564 void DoAction(int32 action) override
1565 {
1566 if (action != ACTION_TELEPORT_BACK)
1567 return;
1568
1569 if (TempSummon* summ = me->ToTempSummon())
1570 {
1571 if (Unit* summoner = summ->GetSummonerUnit())
1572 {
1574 summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOULS_TELEPORT);
1575 }
1576 }
1577
1579 lichKing->AI()->SummonedCreatureDespawn(me);
1581 }
1582
1583 void UpdateAI(uint32 diff) override
1584 {
1585 UpdateVictim();
1586
1587 _events.Update(diff);
1588
1589 while (uint32 eventId = _events.ExecuteEvent())
1590 {
1591 switch (eventId)
1592 {
1593 case EVENT_TELEPORT:
1594 me->GetMotionMaster()->Clear();
1596 if (TempSummon* summ = me->ToTempSummon())
1597 {
1598 if (Unit* summoner = summ->GetSummonerUnit())
1599 {
1600 summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true);
1601 summoner->ExitVehicle(summoner);
1602 if (!IsHeroic())
1603 summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true);
1604 else
1605 {
1606 summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true);
1607 summoner->RemoveAurasDueToSpell(HARVEST_SOUL, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE);
1608 }
1609 }
1610 }
1611
1613 break;
1616 {
1617 if (me->GetExactDist(lichKing) > 10.0f)
1618 {
1619 Position pos = lichKing->GetNearPosition(rand_norm() * 5.0f + 7.5f, lichKing->GetAbsoluteAngle(me));
1620 me->GetMotionMaster()->MovePoint(0, pos);
1621 }
1622 }
1623 break;
1624 case EVENT_DESPAWN_SELF:
1626 lichKing->AI()->SummonedCreatureDespawn(me);
1627 me->DespawnOrUnsummon(1ms);
1628 break;
1629 default:
1630 break;
1631 }
1632 }
1633 }
1634
1635private:
1638};
1639
1640// 36823, 38579, 39217 - Terenas Menethil
1642{
1643 npc_terenas_menethil(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1644
1645 bool CanAIAttack(Unit const* target) const override
1646 {
1647 return target->GetEntry() != NPC_THE_LICH_KING;
1648 }
1649
1650 void DoAction(int32 action) override
1651 {
1652 switch (action)
1653 {
1655 me->setActive(true);
1656 me->SetFarVisible(false);
1657 if (!IsHeroic())
1658 me->SetHealth(me->GetMaxHealth() / 2);
1660 _events.Reset();
1663 if (!IsHeroic())
1664 {
1667 }
1668 break;
1671 me->DespawnOrUnsummon(3s);
1672 break;
1673 default:
1674 break;
1675 }
1676 }
1677
1678 void EnterEvadeMode(EvadeReason /*why*/) override
1679 {
1680 // no running back home
1681 if (!me->IsAlive())
1682 return;
1683
1684 me->CombatStop(false);
1686 }
1687
1688 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1689 {
1690 if (damage >= me->GetHealth())
1691 {
1692 damage = me->GetHealth() - 1;
1694 {
1695 me->SetUninteractible(true);
1698 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1699 {
1700 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1701 warden->DespawnOrUnsummon(2s);
1702 }
1703
1704 me->DespawnOrUnsummon(2s);
1705 }
1706 }
1707 }
1708
1719
1720 void UpdateAI(uint32 diff) override
1721 {
1722 UpdateVictim();
1723
1724 _events.Update(diff);
1725
1726 while (uint32 eventId = _events.ExecuteEvent())
1727 {
1728 switch (eventId)
1729 {
1732 if (IsHeroic())
1734 break;
1737 break;
1740 break;
1743 break;
1748 {
1749 lichKing->AI()->DoAction(ACTION_FINISH_OUTRO);
1750 lichKing->SetImmuneToNPC(false);
1752 tirion->AI()->AttackStart(lichKing);
1753 }
1754 break;
1755 case EVENT_DESTROY_SOUL:
1756 me->SetUninteractible(true);
1757 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1758 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1761 break;
1764 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
1765 break;
1766 default:
1767 break;
1768 }
1769 }
1770 }
1771
1772private:
1775};
1776
1777// 36824 - Spirit Warden
1779{
1780 npc_spirit_warden(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1781
1782 void Reset() override
1783 {
1784 _events.Reset();
1787 }
1788
1789 void JustDied(Unit* /*killer*/) override
1790 {
1792 terenas->AI()->DoAction(ACTION_TELEPORT_BACK);
1793 }
1794
1795 void UpdateAI(uint32 diff) override
1796 {
1797 if (!UpdateVictim())
1798 return;
1799
1800 _events.Update(diff);
1801
1802 while (uint32 eventId = _events.ExecuteEvent())
1803 {
1804 switch (eventId)
1805 {
1806 case EVENT_SOUL_RIP:
1809 break;
1810 default:
1811 break;
1812 }
1813 }
1814 }
1815
1816private:
1819};
1820
1821// 39189 - Spirit Bomb
1823{
1824 npc_spirit_bomb(Creature* creature) : CreatureAI(creature) { }
1825
1826 void IsSummonedBy(WorldObject* /*summoner*/) override
1827 {
1828 float destX, destY, destZ;
1829 me->GetPosition(destX, destY);
1830 destZ = 1055.0f; // approximation, gets more precise later
1831 me->UpdateGroundPositionZ(destX, destY, destZ);
1832 me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ);
1833 }
1834
1835 void MovementInform(uint32 type, uint32 point) override
1836 {
1837 if (type != POINT_MOTION_TYPE || point != POINT_GROUND)
1838 return;
1839
1841 }
1842
1843 void AttackStart(Unit* /*victim*/) override
1844 {
1845 }
1846
1847 void UpdateAI(uint32 diff) override
1848 {
1849 UpdateVictim();
1850
1851 _events.Update(diff);
1852
1854 {
1855 me->RemoveAllAuras();
1857 me->DespawnOrUnsummon(1s);
1858 }
1859 }
1860
1861private:
1863};
1864
1865// 38584 - Frostmourne Trigger
1867{
1868 npc_broken_frostmourne(Creature* creature) : CreatureAI(creature) { }
1869
1870 void Reset() override
1871 {
1872 _events.Reset();
1873 }
1874
1875 void IsSummonedBy(WorldObject* /*summoner*/) override
1876 {
1879 }
1880
1881 void DoAction(int32 action) override
1882 {
1883 if (action == ACTION_SUMMON_TERENAS)
1885 }
1886
1887 void EnterEvadeMode(EvadeReason /*why*/) override
1888 {
1889 }
1890
1891 void UpdateAI(uint32 diff) override
1892 {
1893 UpdateVictim();
1894
1895 _events.Update(diff);
1896
1897 while (uint32 eventId = _events.ExecuteEvent())
1898 {
1899 switch (eventId)
1900 {
1903 break;
1906 break;
1907 default:
1908 break;
1909 }
1910 }
1911 }
1912
1913private:
1915};
1916
1917// 70541, 73779, 73780, 73781 - Infest
1919{
1920 void OnPeriodic(AuraEffect const* /*aurEff*/)
1921 {
1922 if (GetUnitOwner()->HealthAbovePct(90))
1923 {
1926 }
1927 }
1928
1929 void OnUpdate(AuraEffect* aurEff)
1930 {
1931 // multiply, starting from 2nd tick
1932 if (aurEff->GetTickNumber() == 1)
1933 return;
1934
1935 aurEff->SetAmount(aurEff->GetAmount() * 1.15);
1936 }
1937
1943};
1944
1945// 70337, 73912, 73913, 73914 - Necrotic Plague
1947{
1948 bool Validate(SpellInfo const* /*spell*/) override
1949 {
1951 }
1952
1953 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1954 {
1955 switch (GetTargetApplication()->GetRemoveMode())
1956 {
1960 break;
1961 default:
1962 return;
1963 }
1964
1969 if (Unit* caster = GetCaster())
1970 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
1971 }
1972
1977};
1978
1979// 70338, 73785, 73786, 73787 - Necrotic Plague (Jump)
1981{
1982public:
1987
1988private:
1989 void SelectTarget(std::list<WorldObject*>& targets)
1990 {
1992 if (targets.size() < 2)
1993 return;
1994
1995 targets.resize(1);
1996 }
1997
1999 {
2000 if (missInfo != SPELL_MISS_NONE)
2001 return;
2002
2003 if (GetHitUnit()->HasAura(GetSpellInfo()->Id))
2004 _hadAura = true;
2005 }
2006
2012
2014};
2015
2017{
2018public:
2023
2024private:
2025 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2026 {
2027 if (Unit* caster = GetCaster())
2028 if (caster->GetAI())
2029 caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount());
2030 }
2031
2032 void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2033 {
2034 _lastAmount = aurEff->GetAmount();
2035 switch (GetTargetApplication()->GetRemoveMode())
2036 {
2039 break;
2040 default:
2041 return;
2042 }
2043
2048 if (Unit* caster = GetCaster())
2049 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2050 }
2051
2052 void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2053 {
2054 _lastAmount = aurEff->GetAmount();
2055 }
2056
2057 void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2058 {
2059 // this means the stack increased so don't process as if dispelled
2060 if (aurEff->GetAmount() > _lastAmount)
2061 return;
2062
2066 args.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1)
2068 if (Unit* caster = GetCaster())
2069 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2070
2072 }
2073
2081
2083};
2084
2085// 73530 - Shadow Trap (Visual)
2099
2100// 74282 - Shadow Trap (Periodic)
2102{
2103 void CheckTargetCount(std::list<WorldObject*>& targets)
2104 {
2105 if (targets.empty())
2106 return;
2107
2109 }
2110
2115};
2116
2117// 72262 - Quake
2119{
2120 bool Load() override
2121 {
2122 return GetCaster()->GetInstanceScript() != nullptr;
2123 }
2124
2125 void FilterTargets(std::list<WorldObject*>& targets)
2126 {
2127 if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetGuidData(DATA_ARTHAS_PLATFORM)))
2128 targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false));
2129 }
2130
2132 {
2133 if (UnitAI* AI = GetCaster()->GetAI())
2134 AI->DoAction(ACTION_START_ATTACK);
2135 }
2136
2142};
2143
2144// 69110 - Ice Burst Target Search
2146{
2147 bool Validate(SpellInfo const* /*spell*/) override
2148 {
2150 }
2151
2152 void CheckTargetCount(std::list<WorldObject*>& unitList)
2153 {
2154 if (unitList.empty())
2155 return;
2156
2157 // if there is at least one affected target cast the explosion
2159 if (GetCaster()->GetTypeId() == TYPEID_UNIT)
2160 {
2162 GetCaster()->AttackStop();
2164 }
2165 }
2166
2171};
2172
2173// 69200 - Raging Spirit
2187
2189{
2190 public:
2191 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
2192
2194 {
2195 return _source->GetExactDist2d(unit) > _dist;
2196 }
2197
2198 private:
2199 Unit* _source;
2200 float _dist;
2201};
2202
2203// 72754, 73708, 73709, 73710 - Defile
2205{
2206 void CorrectRange(std::list<WorldObject*>& targets)
2207 {
2208 targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale()));
2209 targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR));
2210 }
2211
2213 {
2214 SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale()));
2215 // HACK: target player should cast this spell on defile
2216 // however with current aura handling auras cast by different units
2217 // cannot stack on the same aura object increasing the stack count
2219 }
2220
2227};
2228
2229/* 69037 - Summon Val'kyr
2230 70497 - Summon Vile Spirits Effect
2231 73579 - Summon Spirit Bomb
2232 74300 - Summon Spirit Bomb */
2234{
2235 void ModDestHeight(SpellEffIndex /*effIndex*/)
2236 {
2237 static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f};
2238 WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest());
2239 dest->RelocateOffset(offset);
2240 GetHitDest()->RelocateOffset(offset);
2241 // spirit bombs get higher
2242 if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB)
2243 {
2244 static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f };
2245 dest->RelocateOffset(offsetExtra);
2246 GetHitDest()->RelocateOffset(offsetExtra);
2247 }
2248 }
2249
2254};
2255
2256// 69409, 73797, 73798, 73799 - Soul Reaper
2258{
2259 bool Validate(SpellInfo const* /*spell*/) override
2260 {
2262 }
2263
2264 void OnPeriodic(AuraEffect const* /*aurEff*/)
2265 {
2266 if (Unit* caster = GetCaster())
2267 GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true);
2268 }
2269
2274};
2275
2276// 69030 - Val'kyr Target Search
2278{
2279 bool Validate(SpellInfo const* /*spell*/) override
2280 {
2281 return ValidateSpellInfo({ SPELL_CHARGE });
2282 }
2283
2284 void SelectTarget(std::list<WorldObject*>& targets)
2285 {
2286 if (targets.empty())
2287 return;
2288
2289 targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id));
2290 if (targets.empty())
2291 return;
2292
2294 targets.clear();
2295 targets.push_back(_target);
2297 }
2298
2299 void ReplaceTarget(std::list<WorldObject*>& targets)
2300 {
2301 targets.clear();
2302 if (_target)
2303 targets.push_back(_target);
2304 }
2305
2307 {
2308 PreventHitDefaultEffect(effIndex);
2310 }
2311
2318
2320};
2321
2322// 68984 - Harvest Soul
2323// 74445 - Val'kyr Carry
2336
2337// 73488, 73782, 73783, 73784 - Life Siphon
2339{
2340 bool Validate(SpellInfo const* /*spell*/) override
2341 {
2343 }
2344
2351
2356};
2357
2358// 70498 - Vile Spirits
2360{
2361public:
2363 {
2364 _is25Man = false;
2365 }
2366
2367private:
2368 bool Load() override
2369 {
2371 return true;
2372 }
2373
2374 void OnPeriodic(AuraEffect const* aurEff)
2375 {
2376 if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5))
2378 .SetOriginalCaster(GetCasterGUID()));
2379 }
2380
2385
2387};
2388
2389// 70499 - Summon Vile Spirits Effect
2391{
2392 void ModDestHeight(SpellEffIndex /*effIndex*/)
2393 {
2394 Position offset = {0.0f, 0.0f, 15.0f, 0.0f};
2395 const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset);
2396 }
2397
2402};
2403
2404// 70501 - Vile Spirit Move Target Search
2406{
2407public:
2412
2413private:
2414 bool Load() override
2415 {
2416 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2417 }
2418
2419 void SelectTarget(std::list<WorldObject*>& targets)
2420 {
2421 if (targets.empty())
2422 return;
2423
2425 }
2426
2428 {
2429 PreventHitDefaultEffect(effIndex);
2430 // for this spell, all units are in target map, however it should select one to attack
2431 if (GetHitUnit() != _target)
2432 return;
2433
2436 }
2437
2443
2445};
2446
2447// 70534 - Vile Spirit Damage Target Search
2449{
2450 bool Load() override
2451 {
2452 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2453 }
2454
2455 void CheckTargetCount(std::list<WorldObject*>& targets)
2456 {
2457 if (targets.empty())
2458 return;
2459
2460 // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this
2461 // searcher spell will be blocked
2462 if (TempSummon* summon = GetCaster()->ToTempSummon())
2463 if (Unit* summoner = summon->GetSummonerUnit())
2464 summoner->GetAI()->SetData(DATA_VILE, 1);
2465 GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true);
2468 }
2469
2474};
2475
2476// 68980, 74296, 74297, 74325 - Harvest Soul
2478{
2479 bool Load() override
2480 {
2481 return GetOwner()->GetInstanceScript() != nullptr;
2482 }
2483
2484 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2485 {
2486 // m_originalCaster to allow stacking from different casters, meh
2487 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2489 .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING)));
2490 }
2491
2496};
2497
2498// 69382 - Light's Favor
2500{
2501 void OnPeriodic(AuraEffect const* /*aurEff*/)
2502 {
2503 if (Unit* caster = GetCaster())
2504 if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
2505 effect->RecalculateAmount(caster);
2506 }
2507
2508 void CalculateBonus(AuraEffect const* /*aurEff*/, SpellEffectValue& amount, bool& canBeRecalculated)
2509 {
2510 canBeRecalculated = true;
2511 amount = 0;
2512 if (Unit* caster = GetCaster())
2513 amount = caster->GetHealthPct();
2514 }
2515
2521};
2522
2523// 69397 - Soul Rip
2525{
2526 void OnPeriodic(AuraEffect const* aurEff)
2527 {
2529 // shouldn't be needed, this is channeled
2530 if (Unit* caster = GetCaster())
2531 {
2532 CastSpellExtraArgs args(aurEff);
2534 args.AddSpellBP0(5000 * aurEff->GetTickNumber());
2535 caster->CastSpell(GetTarget(), SPELL_SOUL_RIP_DAMAGE, args);
2536 }
2537 }
2538
2543};
2544
2545// 72595, 73650 - Restore Soul
2547{
2548public:
2550 {
2551 _instance = nullptr;
2552 }
2553
2554private:
2555 bool Load() override
2556 {
2558 return _instance != nullptr;
2559 }
2560
2561 void HandleScript(SpellEffIndex /*effIndex*/)
2562 {
2564 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
2565 if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f))
2566 spawner->RemoveAllAuras();
2567
2568 std::list<Creature*> spirits;
2570 for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr)
2571 {
2572 (*itr)->m_Events.KillAllEvents(true);
2573 (*itr)->SetReactState(REACT_PASSIVE);
2574 (*itr)->AI()->EnterEvadeMode();
2575 }
2576 }
2577
2579 {
2580 if (missInfo != SPELL_MISS_NONE)
2581 return;
2582
2583 if (Unit* target = GetHitUnit())
2584 target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT);
2585 }
2586
2592
2594};
2595
2596// 69383 - Dark Hunger
2598{
2599 bool Validate(SpellInfo const* /*spellInfo*/) override
2600 {
2602 }
2603
2604 void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)
2605 {
2607 DamageInfo* damageInfo = eventInfo.GetDamageInfo();
2608 if (!damageInfo || !damageInfo->GetDamage())
2609 return;
2610
2611 CastSpellExtraArgs args(aurEff);
2612 args.AddSpellBP0(damageInfo->GetDamage() / 2);
2614 }
2615
2620};
2621
2622// 74276 - In Frostmourne Room
2624{
2625 bool Load() override
2626 {
2627 return GetOwner()->GetInstanceScript() != nullptr;
2628 }
2629
2630 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2631 {
2632 // m_originalCaster to allow stacking from different casters, meh
2633 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2635 .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING)));
2636 }
2637
2642};
2643
2644// 74302, 74341, 74342, 74343 - Summon Spirit Bomb
2658
2659// 73582 - Trigger Vile Spirit (Inside, Heroic)
2661{
2663 {
2664 Creature* target = GetHitCreature();
2665 if (!target)
2666 return;
2667
2668 VileSpiritActivateEvent(target).Execute(0, 0);
2669 }
2670
2675};
2676
2677// 71811 - Jump
2679{
2681 {
2682 PreventHitDefaultEffect(effIndex);
2684 GetHitUnit()->CastSpell(nullptr, SPELL_JUMP_2, true);
2685 if (Creature* creature = GetHitCreature())
2686 creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE);
2687 }
2688
2693};
2694
2695// 72431 - Jump (Remove Aura)
2709
2710// 73655 - Harvest Soul (Teleport)
2712{
2714 {
2715 float randCoordX = frand(-18.0f, 18.0f);
2716 float randCoordY = frand(-18.0f, 18.0f);
2717 GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f });
2718 }
2719
2724};
2725
2726// 74399 - Charge (Valkyr)
2728{
2730 {
2731 PreventHitDefaultEffect(effIndex);
2732
2733 Unit* caster = GetCaster();
2734 Unit* target = GetExplTargetUnit();
2735 if (!target)
2736 return;
2737
2738 Position pos = target->GetPosition();
2739 caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, caster->GetFloorZ() + 2.f);
2740 }
2741
2746};
2747
2749{
2750 public:
2751 achievement_been_waiting_long_time() : AchievementCriteriaScript("achievement_been_waiting_long_time") { }
2752
2753 bool OnCheck(Player* /*source*/, Unit* target) override
2754 {
2755 if (!target)
2756 return false;
2757
2758 return target->GetAI()->GetData(DATA_PLAGUE_STACK) >= 30;
2759 }
2760};
2761
2763{
2764 public:
2765 achievement_neck_deep_in_vile() : AchievementCriteriaScript("achievement_neck_deep_in_vile") { }
2766
2767 bool OnCheck(Player* /*source*/, Unit* target) override
2768 {
2769 if (!target)
2770 return false;
2771
2772 return !target->GetAI()->GetData(DATA_VILE);
2773 }
2774};
2775
2777{
2778 // Creatures
2789
2790 // Spells
2822
2823 // Achievements
2826}
@ EQUIP_UNEQUIP
Definition CreatureAI.h:57
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
@ IN_PROGRESS
@ DONE
@ POINT_MOTION_TYPE
@ TEMPSUMMON_MANUAL_DESPAWN
@ TEMPSUMMON_CORPSE_DESPAWN
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
float frand(float min, float max)
Definition Random.cpp:56
float rand_norm()
Definition Random.cpp:76
#define RegisterSpellAndAuraScriptPair(script_1, script_2)
Definition ScriptMgr.h:1381
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
#define RegisterSpellScriptWithArgs(spell_script, script_name,...)
Definition ScriptMgr.h:1382
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_CHARGE_DEST
@ SPELL_EFFECT_TELEPORT_UNITS
@ SPELL_EFFECT_APPLY_AURA
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
@ GO_DESTRUCTIBLE_REBUILDING
@ SPELL_CAST_OK
@ 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
@ SPELLVALUE_AURA_STACK
@ SPELLVALUE_MAX_TARGETS
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ TRIGGERED_IGNORE_CAST_IN_PROGRESS
Will not check if a current cast is in progress.
@ TRIGGERED_NONE
Not triggered.
@ SPELLVALUE_BASE_POINT1
#define BeforeSpellHitFn(F)
#define AuraEffectProcFn(F, I, N)
#define SpellEffectFn(F, I, N)
#define AuraEffectCalcAmountFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectUpdatePeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define SpellHitFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
EvadeReason
@ MOVE_FLIGHT
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:42
@ UNIT_NPC_FLAG_GOSSIP
DamageEffectType
@ SHEATH_STATE_MELEE
Definition UnitDefines.h:83
@ UNIT_STATE_EVADE
Definition Unit.h:297
@ UNIT_STATE_CASTING
Definition Unit.h:290
Position const TirionCharge
#define REMORSELESS_WINTER_1
@ 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
@ ACTION_TELEPORT_BACK
@ ACTION_PLAY_MUSIC
@ ACTION_CONTINUE_INTRO
@ ACTION_BREAK_FROSTMOURNE
@ ACTION_START_ATTACK
@ ACTION_START_ENCOUNTER
@ ACTION_SUMMON_TERENAS
@ ACTION_DISABLE_RAGING
@ ACTION_FINISH_OUTRO
#define REMORSELESS_WINTER_2
Position const TirionSpawn
@ 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_SOUL_RIP
@ SPELL_WINGS_OF_THE_DAMNED
@ SPELL_SHADOW_TRAP_VISUAL
@ SPELL_SOUL_SHRIEK
@ SPELL_VALKYR_TARGET_SEARCH
@ SPELL_TRIGGER_VILE_SPIRIT_HEROIC
@ SPELL_SUMMON_VALKYR
@ SPELL_TERENAS_LOSES_INSIDE
@ SPELL_SUMMON_BROKEN_FROSTMOURNE_2
@ SPELL_SHADOW_TRAP_AURA
@ 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_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_HARVEST_SOUL_VALKYR
@ SPELL_ICE_SPHERE
@ SPELL_FURY_OF_FROSTMOURNE_NO_REZ
@ SPELL_INFEST
Position const TirionIntro
@ EVENT_DESTROY_SOUL
@ EVENT_SUMMON_ICE_SPHERE
@ EVENT_OUTRO_EMOTE_TALK
@ EVENT_OUTRO_TALK_3
@ 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_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_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_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
Position const OutroPosition1
#define ENRAGE
Position const TerenasSpawn
#define NECROTIC_PLAGUE_PLR
@ PHASE_FROSTMOURNE
@ PHASE_TRANSITION
#define SUMMON_VALKYR
void AddSC_boss_the_lich_king()
#define PHASE_TWO_THREE
@ POINT_LK_INTRO_2
@ POINT_LK_OUTRO_1
@ POINT_TIRION_OUTRO_1
@ POINT_LK_OUTRO_2
@ POINT_CENTER_2
@ POINT_LK_INTRO_1
@ POINT_LK_INTRO_3
@ POINT_TIRION_INTRO
@ POINT_DROP_PLAYER
@ POINT_TIRION_CHARGE
@ POINT_CENTER_1
@ POINT_OUTRO_JUMP
#define NECROTIC_PLAGUE_LK
Position const TerenasSpawnHeroic
Position const CenterPosition
Position const OutroFlying
Position const LichKingIntro[3]
@ LIGHT_SOULSTORM
@ MUSIC_FURY_OF_FROSTMOURNE
@ DATA_PLAGUE_STACK
@ MUSIC_FROZEN_THRONE
@ LIGHT_DEFAULT
@ GOSSIP_MENU_START_INTRO
@ LIGHT_SNOWSTORM
@ DATA_GRABBED_PLAYER_GUID
@ EQUIP_BROKEN_FROSTMOURNE
@ MUSIC_SPECIAL
@ EQUIP_ASHBRINGER_GLOWING
LichKingEventGroups
@ EVENT_GROUP_VILE_SPIRITS
@ EVENT_GROUP_BERSERK
#define HARVEST_SOUL
Position const SpiritWardenSpawn
@ NPC_THE_LICH_KING
Definition chapter5.cpp:162
uint32 GetTickNumber() const
SpellEffectInfo const & GetSpellEffectInfo() const
void SetAmount(SpellEffectValue amount)
SpellEffectValue GetAmount() const
void PreventDefaultAction()
AuraApplication const * GetTargetApplication() const
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
WorldObject * GetOwner() const
HookList< EffectApplyHandler > AfterEffectApply
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
Unit * GetCaster() const
HookList< EffectUpdatePeriodicHandler > OnEffectUpdatePeriodic
AuraEffect * GetEffect(uint8 effIndex) const
Aura * GetAura() const
Unit * GetTarget() const
ObjectGuid GetCasterGUID() const
HookList< AuraDispelHandler > OnDispel
HookList< AuraDispelHandler > AfterDispel
HookList< EffectProcHandler > OnEffectProc
Unit * GetUnitOwner() const
uint8 GetStackAmount() const
HookList< EffectApplyHandler > OnEffectApply
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
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 DoZoneInCombat()
Definition CreatureAI.h:169
bool UpdateVictim()
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Creature *const me
Definition CreatureAI.h:63
void EngagementOver()
void SetImmuneToPC(bool apply) override
Definition Creature.h:190
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:396
void LoadEquipment(int8 id=1, bool force=false)
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
bool IsInEvadeMode() const
Definition Creature.h:224
CreatureAI * AI() const
Definition Creature.h:235
uint32 GetDamage() const
Definition Unit.h:466
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:100
EventId ExecuteEvent()
Definition EventMap.cpp:77
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:246
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:56
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:32
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
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
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition Map.cpp:4021
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
Definition Map.cpp:4061
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:1191
bool Is25ManRaid() const
Definition Map.cpp:3385
void SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
Definition Map.cpp:4080
void MoveFall(uint32 id=0, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MoveFollow(Unit *target, float dist, Optional< ChaseAngle > angle={}, Optional< Milliseconds > duration={}, bool ignoreTargetWalk=false, MovementSlot slot=MOTION_SLOT_ACTIVE, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
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={})
void MoveCharge(float x, float y, float z, float speed=SPEED_CHARGE, uint32 id=EVENT_CHARGE, bool generatePath=false, Unit const *target=nullptr, Movement::SpellEffectExtraData const *spellEffectExtraData=nullptr)
NecroticPlagueTargetCheck(Unit const *obj, uint32 notAura1=0, uint32 notAura2=0)
bool operator()(Unit *unit) const
static ObjectGuid const Empty
Definition ObjectGuid.h:314
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
DamageInfo * GetDamageInfo() const
Definition Unit.h:524
uint32 TriggerSpell
Definition SpellInfo.h:234
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
WorldLocation * GetHitDest() const
Creature * GetHitCreature() const
int32 GetHitDamage() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
int32 GetEffectValueAsInt() const
HookList< HitHandler > OnHit
HookList< EffectHandler > OnEffectHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
HookList< BeforeHitHandler > BeforeHit
void SetHitDamage(int32 damage)
WorldLocation const * GetExplTargetDest() const
HookList< EffectHandler > OnEffectLaunch
Unit * GetExplTargetUnit() const
SpellInfo const * GetSpellInfo() const
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
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)
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
virtual void SetGUID(ObjectGuid const &guid, int32 id)
Definition UnitAI.h:76
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 DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
virtual uint32 GetData(uint32 id) const
Definition UnitAI.h:74
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
void ClearUnitState(uint32 f)
Definition Unit.h:756
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition Unit.cpp:8604
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6031
void SetHealth(uint64 val)
Definition Unit.cpp:10041
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 IsAlive() const
Definition Unit.h:1205
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
TempSummon * ToTempSummon()
Definition Unit.h:1844
UnitAI * GetAI() const
Definition Unit.h:680
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
void SetSheath(SheathState sheathed)
Definition Unit.cpp:5832
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13394
void SetEmoteState(Emote emote)
Definition Unit.h:880
uint64 GetMaxHealth() const
Definition Unit.h:801
uint64 GetHealth() const
Definition Unit.h:800
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4832
bool SetWalk(bool enable)
Definition Unit.cpp:13422
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:805
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8961
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void RemoveAllAuras()
Definition Unit.cpp:4400
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1662
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
bool IsInCombat() const
Definition Unit.h:1073
bool Execute(uint64, uint32) override
VileSpiritActivateEvent(Creature *owner)
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition Object.cpp:2941
Map * GetMap() const
Definition Object.h:411
Position GetRandomPoint(Position const &srcPos, float distance, float minDistance=0.0f) const
Definition Object.cpp:678
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:2663
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
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:1403
void setActive(bool isActiveObject)
Definition Object.cpp:274
float GetFloorZ() const
Definition Object.cpp:3109
void SetFarVisible(bool on)
Definition Object.cpp:325
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1522
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:698
EventProcessor m_Events
Definition Object.h:561
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 *, SpellEffectValue &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 *aurEff)
void ChargeDest(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:62
@ WEATHER_STATE_LIGHT_SNOW
Definition Weather.h:54
@ WEATHER_STATE_FOG
Definition Weather.h:49
@ 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) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
CastSpellExtraArgs & SetOriginalCaster(ObjectGuid const &guid)
CastSpellExtraArgs & AddSpellBP0(SpellEffectValue val)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:140
float m_positionZ
Definition Position.h:66
float GetExactDist2d(const float x, const float y) const
Definition Position.h:117
float GetExactDist(float x, float y, float z) const
Definition Position.h:129
float m_positionX
Definition Position.h:64
float m_positionY
Definition Position.h:65
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr void Relocate(float x, float y)
Definition Position.h:74
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
void SetAggressiveStateAfter(Milliseconds timer, Creature *who=nullptr, bool startCombat=true, Creature *summoner=nullptr, StartCombatArgs const &combatArgs={ })
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 DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MovementInform(uint32 type, uint32 id) override
npc_valkyr_shadowguard(Creature *creature)
void IsSummonedBy(WorldObject *) override
void SetGUID(ObjectGuid const &guid, int32 id) override