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
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 : _summonerGuid(summoner->GetGUID()), _owner(owner)
430 {
431 }
432
433 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
434 {
437 if (Unit* target = _summoner->AI()->SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(_summoner)))
438 _owner->AI()->AttackStart(target);
439 return true;
440 }
441
442 private:
445};
446
448{
449 public:
451 : _owner(owner)
452 {
453 }
454
455 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
456 {
460 return true;
461 }
462
463 private:
465};
466
468{
469 public:
471 : _owner(owner), _counter(13)
472 {
473 }
474
475 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
476 {
478
479 if (--_counter)
480 {
482 return false;
483 }
484
485 return true;
486 }
487
488 private:
491};
492
494{
496 {
497 Initialize();
498 }
499
501 {
504 }
505
506 void Reset() override
507 {
508 _Reset();
509 me->SetImmuneToPC(true);
512 Initialize();
513 SetEquipmentSlots(true);
514
515 // Reset The Frozen Throne gameobjects
518 Cell::VisitGridObjects(me, worker, 333.0f);
519
520 // Reset any light override
522
525 }
526
527 void JustDied(Unit* killer) override
528 {
529 _JustDied();
531 me->SetDisableGravity(false);
533 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
534 frostmourne->DespawnOrUnsummon();
537
538 if (Is25ManRaid())
539 if (Player* player = Object::ToPlayer(killer))
540 player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player);
541 }
542
564
565 bool CanAIAttack(Unit const* target) const override
566 {
567 // The Lich King must not select targets in frostmourne room if he killed everyone outside
568 return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target);
569 }
570
581
582 void KilledUnit(Unit* victim) override
583 {
586 }
587
588 void DoAction(int32 action) override
589 {
590 switch (action)
591 {
596 // schedule talks
599 break;
602 break;
605 break;
608 break;
614 break;
618 break;
620 {
623 if (!IsHeroic())
625 break;
626 }
627 default:
628 break;
629 }
630 }
631
632 uint32 GetData(uint32 type) const override
633 {
634 switch (type)
635 {
638 case DATA_VILE:
640 default:
641 break;
642 }
643
644 return 0;
645 }
646
647 void SetData(uint32 type, uint32 value) override
648 {
649 switch (type)
650 {
653 break;
654 case DATA_VILE:
655 _vileSpiritExplosions += value;
656 break;
657 default:
658 break;
659 }
660 }
661
662 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
663 {
665 {
668 me->AttackStop();
671 return;
672 }
673
675 {
678 me->AttackStop();
681 return;
682 }
683
685 {
687 me->AttackStop();
688 events.Reset();
694 me->SetWalk(true);
704 // stop here. rest will get scheduled from MovementInform
705 return;
706 }
707 }
708
709 void JustSummoned(Creature* summon) override
710 {
711 switch (summon->GetEntry())
712 {
714 case NPC_DRUDGE_GHOUL:
715 summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
718 summon->m_Events.AddEvent(new LichKingStartMovementEvent(me, summon), summon->m_Events.CalculateTime(5s));
719 break;
720 case NPC_SHADOW_TRAP:
721 summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true);
722 break;
723 case NPC_ICE_SPHERE:
724 {
725 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
726 {
728 summon->CastSpell(summon, SPELL_ICE_SPHERE, false);
729 summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false);
730 summon->CastSpell(target, SPELL_ICE_PULSE, false);
731 summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
732 }
733 else
734 summon->DespawnOrUnsummon();
735 break;
736 }
737 case NPC_DEFILE:
739 summon->CastSpell(summon, SPELL_DEFILE_AURA, false);
740 break;
742 {
743 summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true);
744
747
749 return;
750 }
751 case NPC_VILE_SPIRIT:
752 {
753 summons.Summon(summon);
755 summon->SetSpeedRate(MOVE_FLIGHT, 0.5f);
756 summon->GetMotionMaster()->MoveRandom(10.0f);
758 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s));
759 return;
760 }
762 summons.Summon(summon);
763 return;
765 return;
766 default:
767 break;
768 }
769
770 BossAI::JustSummoned(summon);
771 }
772
773 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
774 {
775 switch (summon->GetEntry())
776 {
778 case NPC_DRUDGE_GHOUL:
779 case NPC_ICE_SPHERE:
782 case NPC_VILE_SPIRIT:
784 break;
785 default:
786 break;
787 }
788 }
789
790 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
791 {
792 if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic())
794
795 if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2)
796 {
800 }
801 }
802
803 void MovementInform(uint32 type, uint32 pointId) override
804 {
805 if (type != POINT_MOTION_TYPE)
806 return;
807
808 switch (pointId)
809 {
810 case POINT_LK_INTRO_1:
811 // schedule for next update cycle, current update must finalize movement
813 break;
814 case POINT_LK_INTRO_2:
816 break;
817 case POINT_LK_INTRO_3:
819 tirion->AI()->DoAction(ACTION_CONTINUE_INTRO);
821 break;
822 case POINT_CENTER_1:
823 me->SetFacingTo(0.0f);
835 break;
836 case POINT_CENTER_2:
837 me->SetFacingTo(0.0f);
850 break;
851 case POINT_LK_OUTRO_1:
855 break;
856 case POINT_LK_OUTRO_2:
858 tirion->AI()->Talk(SAY_TIRION_OUTRO_2);
859 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
860 frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS);
861 break;
862 default:
863 break;
864 }
865 }
866
867 void UpdateAI(uint32 diff) override
868 {
869 // check phase first to prevent updating victim and entering evade mode when not wanted
871 if (!UpdateVictim())
872 return;
873
874 events.Update(diff);
875
876 // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells
878 return;
879
880 while (uint32 eventId = events.ExecuteEvent())
881 {
882 switch (eventId)
883 {
887 me->SetWalk(true);
889 break;
892 break;
895 break;
898 // for some reason blizz sends 2 emotes in row here so (we handle one in Talk)
904 break;
907 break;
910 break;
915 break;
917 me->SetWalk(false);
918 me->SetImmuneToPC(false);
922 break;
927 break;
931 break;
932 case EVENT_INFEST:
935 break;
938 {
941 }
943 break;
946 DoCast(target, SPELL_SHADOW_TRAP);
948 break;
952 break;
953 case EVENT_DEFILE:
954 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
955 {
957 DoCast(target, SPELL_DEFILE);
958 }
960 break;
964 DoCast(target, SPELL_HARVEST_SOUL);
966 break;
968 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
971 break;
975 break;
977 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
980 break;
982 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
985 break;
986 case EVENT_QUAKE:
988 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
992 break;
993 case EVENT_QUAKE_2:
995 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
999 break;
1003 DoCastAOE(SUMMON_VALKYR, true);
1005 break;
1006 case EVENT_START_ATTACK:
1010 break;
1011 case EVENT_VILE_SPIRITS:
1015 break;
1020 events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading)
1022 me->AttackStop();
1028 for (ObjectGuid guid : summons)
1029 {
1030 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1031 {
1032 if (summon->GetEntry() == NPC_VILE_SPIRIT)
1033 {
1034 summon->m_Events.KillAllEvents(true);
1035 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms));
1036 summon->SetReactState(REACT_PASSIVE);
1037 summon->CombatStop(true);
1038 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
1039 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
1040 summon->GetMotionMaster()->MoveTargetedHome();
1041 }
1042 else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
1043 summon->AI()->DoAction(ACTION_DISABLE_RAGING);
1044 }
1045 }
1046 break;
1049 {
1050 terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
1051 std::list<Creature*> triggers;
1053 if (!triggers.empty())
1054 {
1055 triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
1056 Creature* spawner = triggers.front();
1057 spawner->setActive(true);
1058 spawner->SetFarVisible(true);
1059 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly
1060 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
1061 spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s));
1062 }
1063 }
1064 break;
1065 case EVENT_OUTRO_TALK_1:
1068 break;
1069 case EVENT_OUTRO_TALK_2:
1072 break;
1075 break;
1076 case EVENT_OUTRO_TALK_3:
1078 me->SetFacingToObject(tirion);
1080 break;
1083 break;
1084 case EVENT_OUTRO_TALK_4:
1085 me->SetFacingTo(0.01745329f);
1087 break;
1092 break;
1093 case EVENT_OUTRO_TALK_5:
1096 tirion->AI()->DoAction(ACTION_OUTRO);
1097 break;
1098 case EVENT_OUTRO_TALK_6:
1101 tirion->SetFacingToObject(me);
1104 break;
1108 // set flight
1109 me->SetDisableGravity(true);
1111 break;
1112 case EVENT_OUTRO_TALK_7:
1114 break;
1115 case EVENT_OUTRO_TALK_8:
1117 break;
1118 case EVENT_BERSERK:
1121 break;
1122 default:
1123 break;
1124 }
1125
1127 return;
1128 }
1129 }
1130
1131private:
1134};
1135
1137{
1138 npc_tirion_fordring_tft(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1139
1140 void Reset() override
1141 {
1142 _events.Reset();
1145 }
1146
1147 void MovementInform(uint32 type, uint32 id) override
1148 {
1149 if (type != POINT_MOTION_TYPE)
1150 return;
1151
1152 switch (id)
1153 {
1154 case POINT_TIRION_INTRO:
1157 theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER);
1158 break;
1161 break;
1162 }
1163 }
1164
1165 void DoAction(int32 action) override
1166 {
1167 switch (action)
1168 {
1172 break;
1173 case ACTION_OUTRO:
1179 break;
1180 }
1181 }
1182
1183 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1184 {
1185 if (spellInfo->Id == SPELL_ICE_LOCK)
1186 me->SetFacingTo(3.085098f);
1187 else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
1188 me->LoadEquipment(1); // remove glow on ashbringer
1189 }
1190
1191 bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
1192 {
1193 if (menuId == GOSSIP_MENU_START_INTRO && !gossipListId)
1194 {
1197 me->SetWalk(true);
1199 }
1200 return false;
1201 }
1202
1203 void JustReachedHome() override
1204 {
1206 }
1207
1208 void UpdateAI(uint32 diff) override
1209 {
1211 return;
1212
1213 _events.Update(diff);
1214
1216 return;
1217
1218 while (uint32 eventId = _events.ExecuteEvent())
1219 {
1220 switch (eventId)
1221 {
1222 case EVENT_INTRO_TALK_1:
1226 break;
1229 break;
1230 case EVENT_INTRO_CHARGE:
1231 me->SetWalk(false);
1233 break;
1234 case EVENT_OUTRO_TALK_1:
1236 break;
1237 case EVENT_OUTRO_BLESS:
1239 break;
1244 {
1245 me->SetFacingToObject(lichKing);
1246 lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
1247 }
1248 break;
1249 case EVENT_OUTRO_MOVE_1:
1251 break;
1252 case EVENT_OUTRO_JUMP:
1254 break;
1255 default:
1256 break;
1257 }
1258 }
1259 }
1260
1261private:
1264};
1265
1267{
1269 {
1270 _frenzied = false;
1271 }
1272
1273 void Reset() override
1274 {
1275 _events.Reset();
1278 }
1279
1280 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1281 {
1282 if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage))
1283 {
1284 _frenzied = true;
1285 DoCastSelf(SPELL_FRENZY, true);
1286 }
1287 }
1288
1289 void UpdateAI(uint32 diff) override
1290 {
1291 if (!UpdateVictim())
1292 return;
1293
1294 _events.Update(diff);
1295
1297 return;
1298
1299 while (uint32 eventId = _events.ExecuteEvent())
1300 {
1301 switch (eventId)
1302 {
1303 case EVENT_SHOCKWAVE:
1306 break;
1307 case EVENT_ENRAGE:
1310 else
1312 break;
1313 default:
1314 break;
1315 }
1316 }
1317 }
1318
1319 void OnSpellFailed(SpellInfo const* spell) override
1320 {
1321 if (spell->Id == ENRAGE)
1323 }
1324
1325private:
1328};
1329
1331{
1332 npc_raging_spirit(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1333
1334 void Reset() override
1335 {
1337 _events.Reset();
1342 if (TempSummon* summon = me->ToTempSummon())
1343 if (Unit* summoner = summon->GetSummonerUnit())
1344 summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true);
1346 }
1347
1348 void DoAction(int32 action) override
1349 {
1350 if (action == ACTION_DISABLE_RAGING)
1351 {
1352 _events.Reset();
1356 me->AttackStop();
1358 }
1359 }
1360
1361 void IsSummonedBy(WorldObject* /*summoner*/) override
1362 {
1363 // player is the spellcaster so register summon manually
1365 lichKing->AI()->JustSummoned(me);
1366 }
1367
1368 void JustDied(Unit* /*killer*/) override
1369 {
1371 lichKing->AI()->SummonedCreatureDespawn(me);
1372 if (TempSummon* summon = me->ToTempSummon())
1373 summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
1374 }
1375
1376 void UpdateAI(uint32 diff) override
1377 {
1379 return;
1380
1381 _events.Update(diff);
1382
1384 return;
1385
1386 while (uint32 eventId = _events.ExecuteEvent())
1387 {
1388 switch (eventId)
1389 {
1390 case EVENT_SOUL_SHRIEK:
1393 break;
1397 {
1400 }
1401 break;
1402 default:
1403 break;
1404 }
1405 }
1406 }
1407
1408private:
1411};
1412
1414{
1415 npc_valkyr_shadowguard(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
1416 {
1417 SetCombatMovement(false);
1418 }
1419
1420 void Reset() override
1421 {
1422 _events.Reset();
1425 }
1426
1427 void IsSummonedBy(WorldObject* /*summoner*/) override
1428 {
1429 _events.Reset();
1431 }
1432
1433 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1434 {
1435 if (!IsHeroic())
1436 return;
1437
1439 return;
1440
1441 if (me->HealthBelowPctDamaged(50, damage))
1442 {
1445 }
1446 }
1447
1454
1455 void MovementInform(uint32 type, uint32 id) override
1456 {
1457 if (type != POINT_MOTION_TYPE)
1458 return;
1459
1460 switch (id)
1461 {
1462 case POINT_DROP_PLAYER:
1464 if (IsHeroic())
1466 else
1467 me->DespawnOrUnsummon(1s);
1468 break;
1469 case POINT_CHARGE:
1471 {
1472 me->SetUninteractible(false);
1474 {
1475 std::list<Creature*> triggers;
1477 triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true));
1478 if (triggers.empty())
1479 return;
1480
1481 triggers.sort(Trinity::ObjectDistanceOrderPred(me));
1482 DoCast(target, SPELL_VALKYR_CARRY);
1483 _dropPoint.Relocate(triggers.front());
1485 }
1486 }
1487 else
1489 break;
1490 case POINT_SIPHON:
1495 break;
1496 default:
1497 break;
1498 }
1499 }
1500
1501 void SetGUID(ObjectGuid const& guid, int32 id) override
1502 {
1503 if (id != DATA_GRABBED_PLAYER_GUID)
1504 return;
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
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(aurEff->GetAmount() * 1.15);
1948 }
1949
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
1989};
1990
1991// 70338, 73785, 73786, 73787 - Necrotic Plague (Jump)
1993{
1994public:
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
2024
2026};
2027
2029{
2030public:
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
2093
2095};
2096
2097// 73530 - Shadow Trap (Visual)
2111
2112// 74282 - Shadow Trap (Periodic)
2114{
2115 void CheckTargetCount(std::list<WorldObject*>& targets)
2116 {
2117 if (targets.empty())
2118 return;
2119
2121 }
2122
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
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
2183};
2184
2185// 69200 - Raging Spirit
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
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
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
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
2330
2332};
2333
2334// 68984 - Harvest Soul
2335// 74445 - Val'kyr Carry
2348
2349// 73488, 73782, 73783, 73784 - Life Siphon
2351{
2352 bool Validate(SpellInfo const* /*spell*/) override
2353 {
2355 }
2356
2363
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
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
2414};
2415
2416// 70501 - Vile Spirit Move Target Search
2418{
2419public:
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
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
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
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*/, SpellEffectValue& amount, bool& canBeRecalculated)
2521 {
2522 canBeRecalculated = true;
2523 amount = 0;
2524 if (Unit* caster = GetCaster())
2525 amount = caster->GetHealthPct();
2526 }
2527
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
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
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
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
2654};
2655
2656// 74302, 74341, 74342, 74343 - Summon Spirit Bomb
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
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
2705};
2706
2707// 72431 - Jump (Remove Aura)
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
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}
@ 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
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: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
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
@ 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:283
@ UNIT_STATE_CASTING
Definition Unit.h:276
Position const TirionCharge
#define REMORSELESS_WINTER_1
@ EVENT_GROUP_VILE_SPIRITS
@ EVENT_GROUP_BERSERK
@ 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
#define REMORSELESS_WINTER_2
Position const TirionSpawn
@ 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
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_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
@ PHASE_FROSTMOURNE
@ PHASE_TRANSITION
@ 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
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_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
MovePoints
@ 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:184
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:388
void LoadEquipment(int8 id=1, bool force=false)
void SetReactState(ReactStates st)
Definition Creature.h:174
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
bool IsInEvadeMode() const
Definition Creature.h:217
CreatureAI * AI() const
Definition Creature.h:228
uint32 GetDamage() const
Definition Unit.h:452
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:100
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
bool IsInPhase(uint8 phase) const
Definition EventMap.h:222
void SetPhase(uint8 phase)
Definition EventMap.cpp:32
void RescheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:56
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
LichKingStartMovementEvent(Creature *summoner, Creature *owner)
bool Execute(uint64, uint32) override
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition Map.cpp:3976
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
Definition Map.cpp:4025
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:1186
bool Is25ManRaid() const
Definition Map.cpp:3349
void SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
Definition Map.cpp:4044
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={})
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:511
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
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: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
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:89
Definition Unit.h:635
void ClearUnitState(uint32 f)
Definition Unit.h:744
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition Unit.cpp:8585
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6012
void SetHealth(uint64 val)
Definition Unit.cpp:9973
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10731
ThreatManager & GetThreatManager()
Definition Unit.h:1078
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3231
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition Unit.cpp:13307
bool IsAlive() const
Definition Unit.h:1185
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:998
TempSummon * ToTempSummon()
Definition Unit.h:1828
UnitAI * GetAI() const
Definition Unit.h:668
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13361
void SetUninteractible(bool apply)
Definition Unit.cpp:8564
void SetSheath(SheathState sheathed)
Definition Unit.cpp:5813
void SetEmoteState(Emote emote)
Definition Unit.h:865
uint64 GetMaxHealth() const
Definition Unit.h:789
uint64 GetHealth() const
Definition Unit.h:788
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4814
bool SetWalk(bool enable)
Definition Unit.cpp:13343
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:793
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8942
void SetFacingTo(float const ori, bool force=true)
Definition Unit.cpp:13289
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
void RemoveAllAuras()
Definition Unit.cpp:4382
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1657
bool AttackStop()
Definition Unit.cpp:5965
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
bool IsInCombat() const
Definition Unit.h:1058
bool Execute(uint64, uint32) override
VileSpiritActivateEvent(Creature *owner)
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition Object.cpp:2938
Map * GetMap() const
Definition Object.h:411
Position GetRandomPoint(Position const &srcPos, float distance, float minDistance=0.0f) const
Definition Object.cpp:680
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:2658
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
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:1398
void setActive(bool isActiveObject)
Definition Object.cpp:276
void SetFarVisible(bool on)
Definition Object.cpp:327
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1517
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:700
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 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) -> 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, bool dont_load=true)
Definition CellImpl.h:179
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
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
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