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 "DBCStores.h"
23#include "GridNotifiersImpl.h"
24#include "InstanceScript.h"
25#include "MotionMaster.h"
26#include "ObjectAccessor.h"
27#include "ScriptedCreature.h"
28#include "ScriptMgr.h"
29#include "SpellAuraEffects.h"
30#include "SpellScript.h"
31#include "TemporarySummon.h"
32#include "Vehicle.h"
33#include "Weather.h"
34
75
77{
78 // The Lich King
79 SPELL_PLAGUE_AVOIDANCE = 72846, // raging spirits also get it
84
85 // Phase 1
89 SPELL_INFEST = 70541,
97
98 // Phase Transition
111 SPELL_QUAKE = 72262,
112
113 // Phase 2
119 SPELL_HARVEST_SOUL_VALKYR = 68985, // Val'kyr Shadowguard vehicle aura
124 SPELL_CHARGE = 74399, // cast on selected target
125 SPELL_VALKYR_CARRY = 74445, // removes uninteractible flag
130
131 // Phase 3
137 SPELL_HARVEST_SOULS = 73654, // Heroic version, weird because it has all 4 difficulties just like above spell
141 SPELL_HARVEST_SOULS_TELEPORT = 73655, // Heroic version, also periodic damage (Frostmourne)
147
148 // Frostmourne
151 SPELL_RESTORE_SOULS = 73650, // Heroic
152 SPELL_DARK_HUNGER = 69383, // Passive proc healing
154 SPELL_DESTROY_SOUL = 74086, // Used when Terenas Menethil dies
155 SPELL_SOUL_RIP = 69397, // Deals increasing damage
158 SPELL_SUMMON_SPIRIT_BOMB_1 = 73581, // (Heroic)
159 SPELL_SUMMON_SPIRIT_BOMB_2 = 74299, // (Heroic)
160 SPELL_EXPLOSION = 73576, // Spirit Bomb (Heroic)
161
162 // Outro
168 SPELL_JUMP = 71809,
173 SPELL_SUMMON_BROKEN_FROSTMOURNE_3 = 73017, // real summon
181
182 // Shambling Horror
186};
187
188#define NECROTIC_PLAGUE_LK RAID_MODE<uint32>(70337, 73912, 73913, 73914)
189#define NECROTIC_PLAGUE_PLR RAID_MODE<uint32>(70338, 73785, 73786, 73787)
190#define REMORSELESS_WINTER_1 RAID_MODE<uint32>(68981, 74270, 74271, 74272)
191#define REMORSELESS_WINTER_2 RAID_MODE<uint32>(72259, 74273, 74274, 74275)
192#define SUMMON_VALKYR RAID_MODE<uint32>(69037, 74361, 69037, 74361)
193#define HARVEST_SOUL RAID_MODE<uint32>(68980, 74325, 74296, 74297)
194#define ENRAGE RAID_MODE<uint32>(72143, 72146, 72147, 72148)
195
197{
198 // The Lich King
199 // intro events
209
210 // combat events
215 EVENT_SHADOW_TRAP, // heroic only
218 EVENT_HARVEST_SOUL, // normal mode only
226 EVENT_LIFE_SIPHON, // heroic only
227 EVENT_MOVE_TO_CENTER, // heroic only
232 EVENT_HARVEST_SOULS, // heroic only
261
262 // Shambling Horror
265
266 // Raging Spirit
269
270 // Strangulate Vehicle (Harvest Soul)
274
275 //Spirit Bomb
278
284
286{
292 PHASE_FROSTMOURNE = 6, // only set on heroic mode when all players are sent into frostmourne
293 PHASE_OUTRO = 7
295
296#define PHASE_TWO_THREE (events.IsInPhase(PHASE_TWO) ? PHASE_TWO : PHASE_THREE)
297
298Position const CenterPosition = {503.6282f, -2124.655f, 840.8569f, 0.0f};
299Position const TirionSpawn = {505.2118f, -2124.353f, 840.9403f, 3.141593f};
300Position const TirionIntro = {489.2970f, -2124.840f, 840.8569f, 0.0f};
301Position const TirionCharge = {482.9019f, -2124.479f, 840.8570f, 0.0f};
303{
304 {432.0851f, -2123.673f, 864.6582f, 0.0f},
305 {457.8351f, -2123.423f, 841.1582f, 0.0f},
306 {465.0730f, -2123.470f, 840.8569f, 0.0f},
307};
308Position const OutroPosition1 = {493.6286f, -2124.569f, 840.8569f, 0.0f};
309Position const OutroFlying = {508.9897f, -2124.561f, 845.3565f, 0.0f};
310Position const TerenasSpawn = {495.5542f, -2517.012f, 1050.000f, 4.6993f};
311Position const TerenasSpawnHeroic = {495.7080f, -2523.760f, 1050.000f, 0.0f};
312Position const SpiritWardenSpawn = {495.3406f, -2529.983f, 1050.000f, 1.5592f};
313
332
346
348{
352 LIGHT_FOG = 2509,
353
355 MUSIC_SPECIAL = 17458, // Summon Shambling Horror, Remorseless Winter, Quake, Summon Val'kyr Periodic, Harvest Soul, Vile Spirits
357 MUSIC_FINAL = 17460, // Raise Dead, Light's Blessing
358
359 SOUND_PAIN = 17360, // separate sound, not attached to any text
360
363
365};
366
368{
370 DATA_VILE = 45814622
372
374{
375 public:
376 NecroticPlagueTargetCheck(Unit const* obj, uint32 notAura1 = 0, uint32 notAura2 = 0)
377 : _sourceObj(obj), _notAura1(notAura1), _notAura2(notAura2)
378 {
379 }
380
381 bool operator()(Unit* unit) const
382 {
383 if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
384 return false;
385 if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
386 return false;
387 return true;
388 }
389
390 private:
394};
395
397{
398 public:
400
402 {
403 switch (go->GetEntry())
404 {
407 break;
410 break;
413 break;
418 go->ResetDoorOrButton();
419 break;
420 default:
421 break;
422 }
423
424 return false;
425 }
426};
427
429{
430 public:
432 : _owner(owner)
433 {
434 }
435
436 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
437 {
441 return true;
442 }
443
444 private:
446};
447
449{
450 public:
452 : _owner(owner), _counter(13)
453 {
454 }
455
456 bool Execute(uint64 /*time*/, uint32 /*diff*/) override
457 {
459
460 if (--_counter)
461 {
463 return false;
464 }
465
466 return true;
467 }
468
469 private:
472};
473
474// 36597 - The Lich King
476{
478 {
479 Initialize();
480 }
481
483 {
486 }
487
488 void Reset() override
489 {
490 _Reset();
491 me->SetImmuneToPC(true);
494 Initialize();
495 SetEquipmentSlots(true);
496
497 // Reset The Frozen Throne gameobjects
500 Cell::VisitGridObjects(me, worker, 333.0f);
501
502 // Reset any light override
504
507 }
508
509 void JustDied(Unit* /*killer*/) override
510 {
511 _JustDied();
513 me->SetDisableGravity(false);
515 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
516 frostmourne->DespawnOrUnsummon();
519
520 if (Is25ManRaid())
521 if (Player* player = me->GetLootRecipient())
522 player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player);
523 }
524
547
548 bool CanAIAttack(Unit const* target) const override
549 {
550 // The Lich King must not select targets in frostmourne room if he killed everyone outside
551 return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target);
552 }
553
564
565 void KilledUnit(Unit* victim) override
566 {
569 }
570
571 void DoAction(int32 action) override
572 {
573 switch (action)
574 {
579 // schedule talks
582 break;
585 break;
588 break;
591 break;
597 break;
601 break;
603 {
606 if (!IsHeroic())
608 break;
609 }
610 default:
611 break;
612 }
613 }
614
615 uint32 GetData(uint32 type) const override
616 {
617 switch (type)
618 {
621 case DATA_VILE:
623 default:
624 break;
625 }
626
627 return 0;
628 }
629
630 void SetData(uint32 type, uint32 value) override
631 {
632 switch (type)
633 {
636 break;
637 case DATA_VILE:
638 _vileSpiritExplosions += value;
639 break;
640 default:
641 break;
642 }
643 }
644
645 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
646 {
648 {
651 me->AttackStop();
654 return;
655 }
656
658 {
661 me->AttackStop();
664 return;
665 }
666
668 {
670 me->AttackStop();
671 events.Reset();
677 me->SetWalk(true);
687 // stop here. rest will get scheduled from MovementInform
688 return;
689 }
690 }
691
692 void JustSummoned(Creature* summon) override
693 {
694 switch (summon->GetEntry())
695 {
697 case NPC_DRUDGE_GHOUL:
698 summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
701 SetAggressiveStateAfter(5s, summon, true, me, StartCombatArgs().SetAvoidTargetVictim(true));
702 break;
703 case NPC_SHADOW_TRAP:
704 summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true);
705 break;
706 case NPC_ICE_SPHERE:
707 {
708 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
709 {
711 summon->CastSpell(summon, SPELL_ICE_SPHERE, false);
712 summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false);
713 summon->CastSpell(target, SPELL_ICE_PULSE, false);
714 summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
715 }
716 else
717 summon->DespawnOrUnsummon();
718 break;
719 }
720 case NPC_DEFILE:
722 summon->CastSpell(summon, SPELL_DEFILE_AURA, false);
723 break;
725 {
726 summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true);
727
730
732 return;
733 }
734 case NPC_VILE_SPIRIT:
735 {
736 summons.Summon(summon);
738 summon->SetSpeedRate(MOVE_FLIGHT, 0.5f);
739 summon->GetMotionMaster()->MoveRandom(10.0f);
741 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s));
742 return;
743 }
745 summons.Summon(summon);
746 return;
748 return;
749 default:
750 break;
751 }
752
753 BossAI::JustSummoned(summon);
754 }
755
756 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
757 {
758 switch (summon->GetEntry())
759 {
761 case NPC_DRUDGE_GHOUL:
762 case NPC_ICE_SPHERE:
765 case NPC_VILE_SPIRIT:
767 break;
768 default:
769 break;
770 }
771 }
772
773 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
774 {
775 if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic())
777
778 if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2)
779 {
783 }
784 }
785
786 void MovementInform(uint32 type, uint32 pointId) override
787 {
788 if (type != POINT_MOTION_TYPE)
789 return;
790
791 switch (pointId)
792 {
793 case POINT_LK_INTRO_1:
794 // schedule for next update cycle, current update must finalize movement
796 break;
797 case POINT_LK_INTRO_2:
799 break;
800 case POINT_LK_INTRO_3:
802 tirion->AI()->DoAction(ACTION_CONTINUE_INTRO);
804 break;
805 case POINT_CENTER_1:
806 me->SetFacingTo(0.0f);
818 break;
819 case POINT_CENTER_2:
820 me->SetFacingTo(0.0f);
833 break;
834 case POINT_LK_OUTRO_1:
838 break;
839 case POINT_LK_OUTRO_2:
841 tirion->AI()->Talk(SAY_TIRION_OUTRO_2);
842 if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
843 frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS);
844 break;
845 default:
846 break;
847 }
848 }
849
850 void UpdateAI(uint32 diff) override
851 {
852 // check phase first to prevent updating victim and entering evade mode when not wanted
854 if (!UpdateVictim())
855 return;
856
857 events.Update(diff);
858
859 // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells
861 return;
862
863 while (uint32 eventId = events.ExecuteEvent())
864 {
865 switch (eventId)
866 {
870 me->SetWalk(true);
872 break;
875 break;
878 break;
881 // for some reason blizz sends 2 emotes in row here so (we handle one in Talk)
887 break;
890 break;
893 break;
898 break;
900 me->SetWalk(false);
901 me->SetImmuneToPC(false);
905 break;
910 break;
914 break;
915 case EVENT_INFEST:
918 break;
921 {
924 }
926 break;
929 DoCast(target, SPELL_SHADOW_TRAP);
931 break;
935 break;
936 case EVENT_DEFILE:
937 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR))
938 {
940 DoCast(target, SPELL_DEFILE);
941 }
943 break;
947 DoCast(target, SPELL_HARVEST_SOUL);
949 break;
951 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
954 break;
958 break;
960 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
963 break;
965 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
968 break;
969 case EVENT_QUAKE:
971 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
975 break;
976 case EVENT_QUAKE_2:
978 me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
982 break;
988 break;
993 break;
998 break;
1003 events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading)
1005 me->AttackStop();
1011 for (ObjectGuid guid : summons)
1012 {
1013 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1014 {
1015 if (summon->GetEntry() == NPC_VILE_SPIRIT)
1016 {
1017 summon->m_Events.KillAllEvents(true);
1018 summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms));
1019 summon->SetReactState(REACT_PASSIVE);
1020 summon->CombatStop(true);
1021 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
1022 summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
1023 summon->GetMotionMaster()->MoveTargetedHome();
1024 }
1025 else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
1026 summon->AI()->DoAction(ACTION_DISABLE_RAGING);
1027 }
1028 }
1029 break;
1032 {
1033 terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
1034 std::list<Creature*> triggers;
1036 if (!triggers.empty())
1037 {
1038 triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
1039 Creature* spawner = triggers.front();
1040 spawner->setActive(true);
1041 spawner->SetFarVisible(true);
1042 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly
1043 spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
1044 spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s));
1045 }
1046 }
1047 break;
1048 case EVENT_OUTRO_TALK_1:
1051 break;
1052 case EVENT_OUTRO_TALK_2:
1055 break;
1058 break;
1059 case EVENT_OUTRO_TALK_3:
1061 me->SetFacingToObject(tirion);
1063 break;
1066 break;
1067 case EVENT_OUTRO_TALK_4:
1068 me->SetFacingTo(0.01745329f);
1070 break;
1075 break;
1076 case EVENT_OUTRO_TALK_5:
1079 tirion->AI()->DoAction(ACTION_OUTRO);
1080 break;
1081 case EVENT_OUTRO_TALK_6:
1084 tirion->SetFacingToObject(me);
1087 break;
1091 // set flight
1092 me->SetDisableGravity(true);
1094 break;
1095 case EVENT_OUTRO_TALK_7:
1097 break;
1098 case EVENT_OUTRO_TALK_8:
1100 break;
1101 case EVENT_BERSERK:
1104 break;
1105 default:
1106 break;
1107 }
1108
1110 return;
1111 }
1112
1114 }
1115
1116private:
1119};
1120
1121// 38995 - Highlord Tirion Fordring
1123{
1124 npc_tirion_fordring_tft(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1125
1126 void Reset() override
1127 {
1128 _events.Reset();
1131 }
1132
1133 void MovementInform(uint32 type, uint32 id) override
1134 {
1135 if (type != POINT_MOTION_TYPE)
1136 return;
1137
1138 switch (id)
1139 {
1140 case POINT_TIRION_INTRO:
1143 theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER);
1144 break;
1147 break;
1148 }
1149 }
1150
1151 void DoAction(int32 action) override
1152 {
1153 switch (action)
1154 {
1158 break;
1159 case ACTION_OUTRO:
1165 break;
1166 }
1167 }
1168
1169 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1170 {
1171 if (spellInfo->Id == SPELL_ICE_LOCK)
1172 me->SetFacingTo(3.085098f);
1173 else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
1174 me->LoadEquipment(1); // remove glow on ashbringer
1175 }
1176
1177 bool OnGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
1178 {
1179 if (me->GetCreatureTemplate()->GossipMenuId == menuId && !gossipListId)
1180 {
1183 me->SetWalk(true);
1185 }
1186 return false;
1187 }
1188
1189 void JustReachedHome() override
1190 {
1192 }
1193
1194 void UpdateAI(uint32 diff) override
1195 {
1197 return;
1198
1199 _events.Update(diff);
1200
1202 return;
1203
1204 while (uint32 eventId = _events.ExecuteEvent())
1205 {
1206 switch (eventId)
1207 {
1208 case EVENT_INTRO_TALK_1:
1212 break;
1215 break;
1216 case EVENT_INTRO_CHARGE:
1217 me->SetWalk(false);
1219 break;
1220 case EVENT_OUTRO_TALK_1:
1222 break;
1223 case EVENT_OUTRO_BLESS:
1225 break;
1230 {
1231 me->SetFacingToObject(lichKing);
1232 lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
1233 }
1234 break;
1235 case EVENT_OUTRO_MOVE_1:
1237 break;
1238 case EVENT_OUTRO_JUMP:
1240 break;
1241 default:
1242 break;
1243 }
1244 }
1245
1247 }
1248
1249private:
1252};
1253
1254// 37698 - Shambling Horror
1256{
1258 {
1259 _frenzied = false;
1260 }
1261
1262 void Reset() override
1263 {
1264 _events.Reset();
1267 }
1268
1269 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1270 {
1271 if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage))
1272 {
1273 _frenzied = true;
1274 DoCastSelf(SPELL_FRENZY, true);
1275 }
1276 }
1277
1278 void UpdateAI(uint32 diff) override
1279 {
1280 if (!UpdateVictim())
1281 return;
1282
1283 _events.Update(diff);
1284
1286 return;
1287
1288 while (uint32 eventId = _events.ExecuteEvent())
1289 {
1290 switch (eventId)
1291 {
1292 case EVENT_SHOCKWAVE:
1295 break;
1296 case EVENT_ENRAGE:
1299 else
1301 break;
1302 default:
1303 break;
1304 }
1305 }
1306
1308 }
1309
1310 void OnSpellFailed(SpellInfo const* spell) override
1311 {
1312 if (spell->Id == ENRAGE)
1314 }
1315
1316private:
1319};
1320
1321// 36701 - Raging Spirit
1323{
1324 npc_raging_spirit(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1325
1326 void Reset() override
1327 {
1329 _events.Reset();
1334 if (TempSummon* summon = me->ToTempSummon())
1335 if (Unit* summoner = summon->GetSummonerUnit())
1336 summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true);
1338 }
1339
1340 void DoAction(int32 action) override
1341 {
1342 if (action == ACTION_DISABLE_RAGING)
1343 {
1344 _events.Reset();
1348 me->AttackStop();
1350 }
1351 }
1352
1353 void IsSummonedBy(WorldObject* /*summoner*/) override
1354 {
1355 // player is the spellcaster so register summon manually
1357 lichKing->AI()->JustSummoned(me);
1358 }
1359
1360 void JustDied(Unit* /*killer*/) override
1361 {
1363 lichKing->AI()->SummonedCreatureDespawn(me);
1364 if (TempSummon* summon = me->ToTempSummon())
1365 summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
1366 }
1367
1368 void UpdateAI(uint32 diff) override
1369 {
1371 return;
1372
1373 _events.Update(diff);
1374
1376 return;
1377
1378 while (uint32 eventId = _events.ExecuteEvent())
1379 {
1380 switch (eventId)
1381 {
1382 case EVENT_SOUL_SHRIEK:
1385 break;
1389 {
1392 }
1393 break;
1394 default:
1395 break;
1396 }
1397 }
1398
1400 }
1401
1402private:
1405};
1406
1407// 36609 - Val'kyr Shadowguard
1409{
1410 npc_valkyr_shadowguard(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
1411 {
1412 SetCombatMovement(false);
1413 }
1414
1415 void Reset() override
1416 {
1417 _events.Reset();
1420 }
1421
1422 void IsSummonedBy(WorldObject* /*summoner*/) override
1423 {
1424 _events.Reset();
1426 }
1427
1428 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1429 {
1430 if (!IsHeroic())
1431 return;
1432
1434 return;
1435
1436 if (me->HealthBelowPctDamaged(50, damage))
1437 {
1440 }
1441 }
1442
1449
1450 void MovementInform(uint32 type, uint32 id) override
1451 {
1452 if (type != POINT_MOTION_TYPE)
1453 return;
1454
1455 switch (id)
1456 {
1457 case POINT_DROP_PLAYER:
1459 if (IsHeroic())
1461 else
1462 me->DespawnOrUnsummon(1s);
1463 break;
1464 case POINT_CHARGE:
1466 {
1469 {
1470 std::list<Creature*> triggers;
1472 triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true));
1473 if (triggers.empty())
1474 return;
1475
1476 triggers.sort(Trinity::ObjectDistanceOrderPred(me));
1477 DoCast(target, SPELL_VALKYR_CARRY);
1478 _dropPoint.Relocate(triggers.front()->GetPositionX(), triggers.front()->GetPositionY(), me->GetFloorZ() + 2.f);
1480 }
1481 }
1482 else
1484 break;
1485 case POINT_SIPHON:
1490 break;
1491 default:
1492 break;
1493 }
1494 }
1495
1496 void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
1497 {
1498 _grabbedPlayer = guid;
1499 }
1500
1501 void UpdateAI(uint32 diff) override
1502 {
1503 if (!UpdateVictim())
1504 return;
1505
1506 _events.Update(diff);
1507
1509 return;
1510
1511 while (uint32 eventId = _events.ExecuteEvent())
1512 {
1513 switch (eventId)
1514 {
1515 case EVENT_GRAB_PLAYER:
1516 if (!_grabbedPlayer)
1517 {
1520 }
1521 break;
1524 break;
1525 case EVENT_LIFE_SIPHON:
1527 _events.Repeat(2s + 500ms);
1528 break;
1530 {
1532 pos.m_positionZ = me->GetHomePosition().m_positionZ;
1534 break;
1535 }
1536 default:
1537 break;
1538 }
1539
1541 return;
1542 }
1543
1544 // no melee attacks
1545 }
1546
1547private:
1552};
1553
1554// 36598 - Strangulate Vehicle
1556{
1557 npc_strangulate_vehicle(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1558
1559 void IsSummonedBy(WorldObject* summonerWO) override
1560 {
1561 Unit* summoner = summonerWO->ToUnit();
1562 if (!summoner)
1563 return;
1564 me->SetFacingToObject(summoner);
1566 _events.Reset();
1569
1570 // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back
1572 lichKing->AI()->JustSummoned(me);
1573 }
1574
1575 void DoAction(int32 action) override
1576 {
1577 if (action != ACTION_TELEPORT_BACK)
1578 return;
1579
1580 if (TempSummon* summ = me->ToTempSummon())
1581 {
1582 if (Unit* summoner = summ->GetSummonerUnit())
1583 {
1585 summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOULS_TELEPORT);
1586 }
1587 }
1588
1590 lichKing->AI()->SummonedCreatureDespawn(me);
1592 }
1593
1594 void UpdateAI(uint32 diff) override
1595 {
1596 UpdateVictim();
1597
1598 _events.Update(diff);
1599
1600 while (uint32 eventId = _events.ExecuteEvent())
1601 {
1602 switch (eventId)
1603 {
1604 case EVENT_TELEPORT:
1605 me->GetMotionMaster()->Clear();
1607 if (TempSummon* summ = me->ToTempSummon())
1608 {
1609 if (Unit* summoner = summ->GetSummonerUnit())
1610 {
1611 summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true);
1612 summoner->ExitVehicle(summoner);
1613 if (!IsHeroic())
1614 summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true);
1615 else
1616 {
1617 summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true);
1618 summoner->RemoveAurasDueToSpell(HARVEST_SOUL, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE);
1619 }
1620 }
1621 }
1622
1624 break;
1627 {
1628 if (me->GetExactDist(lichKing) > 10.0f)
1629 {
1630 Position pos = lichKing->GetNearPosition(float(rand_norm()) * 5.0f + 7.5f, lichKing->GetAbsoluteAngle(me));
1631 me->GetMotionMaster()->MovePoint(0, pos);
1632 }
1633 }
1634 break;
1635 case EVENT_DESPAWN_SELF:
1637 lichKing->AI()->SummonedCreatureDespawn(me);
1638 me->DespawnOrUnsummon(1ms);
1639 break;
1640 default:
1641 break;
1642 }
1643 }
1644 }
1645
1646private:
1649};
1650
1651// 36823, 38579, 39217 - Terenas Menethil
1653{
1654 npc_terenas_menethil(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1655
1656 bool CanAIAttack(Unit const* target) const override
1657 {
1658 return target->GetEntry() != NPC_THE_LICH_KING;
1659 }
1660
1661 void DoAction(int32 action) override
1662 {
1663 switch (action)
1664 {
1666 me->setActive(true);
1667 me->SetFarVisible(false);
1668 if (!IsHeroic())
1669 me->SetHealth(me->GetMaxHealth() / 2);
1671 _events.Reset();
1674 if (!IsHeroic())
1675 {
1678 }
1679 break;
1682 me->DespawnOrUnsummon(3s);
1683 break;
1684 default:
1685 break;
1686 }
1687 }
1688
1689 void EnterEvadeMode(EvadeReason /*why*/) override
1690 {
1691 // no running back home
1692 if (!me->IsAlive())
1693 return;
1694
1695 me->CombatStop(false);
1697 }
1698
1699 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1700 {
1701 if (damage >= me->GetHealth())
1702 {
1703 damage = me->GetHealth() - 1;
1705 {
1709 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1710 {
1711 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1712 warden->DespawnOrUnsummon(2s);
1713 }
1714
1715 me->DespawnOrUnsummon(2s);
1716 }
1717 }
1718 }
1719
1730
1731 void UpdateAI(uint32 diff) override
1732 {
1733 UpdateVictim();
1734
1735 _events.Update(diff);
1736
1737 while (uint32 eventId = _events.ExecuteEvent())
1738 {
1739 switch (eventId)
1740 {
1743 if (IsHeroic())
1745 break;
1748 break;
1751 break;
1754 break;
1759 {
1760 lichKing->AI()->DoAction(ACTION_FINISH_OUTRO);
1761 lichKing->SetImmuneToNPC(false);
1763 tirion->AI()->AttackStart(lichKing);
1764 }
1765 break;
1766 case EVENT_DESTROY_SOUL:
1768 if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1769 warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1772 break;
1775 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
1776 break;
1777 default:
1778 break;
1779 }
1780 }
1781
1782 // fighting Spirit Warden
1783 if (me->IsInCombat())
1785 }
1786
1787private:
1790};
1791
1792// 36824 - Spirit Warden
1794{
1795 npc_spirit_warden(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
1796
1797 void Reset() override
1798 {
1799 _events.Reset();
1802 }
1803
1804 void JustDied(Unit* /*killer*/) override
1805 {
1807 terenas->AI()->DoAction(ACTION_TELEPORT_BACK);
1808 }
1809
1810 void UpdateAI(uint32 diff) override
1811 {
1812 if (!UpdateVictim())
1813 return;
1814
1815 _events.Update(diff);
1816
1817 while (uint32 eventId = _events.ExecuteEvent())
1818 {
1819 switch (eventId)
1820 {
1821 case EVENT_SOUL_RIP:
1824 break;
1825 default:
1826 break;
1827 }
1828 }
1829
1831 }
1832
1833private:
1836};
1837
1838// 39189 - Spirit Bomb
1840{
1841 npc_spirit_bomb(Creature* creature) : CreatureAI(creature) { }
1842
1843 void IsSummonedBy(WorldObject* /*summoner*/) override
1844 {
1845 float destX, destY, destZ;
1846 me->GetPosition(destX, destY);
1847 destZ = 1055.0f; // approximation, gets more precise later
1848 me->UpdateGroundPositionZ(destX, destY, destZ);
1849 me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ);
1850 }
1851
1852 void MovementInform(uint32 type, uint32 point) override
1853 {
1854 if (type != POINT_MOTION_TYPE || point != POINT_GROUND)
1855 return;
1856
1858 }
1859
1860 void AttackStart(Unit* /*victim*/) override
1861 {
1862 }
1863
1864 void UpdateAI(uint32 diff) override
1865 {
1866 UpdateVictim();
1867
1868 _events.Update(diff);
1869
1871 {
1872 me->RemoveAllAuras();
1874 me->DespawnOrUnsummon(1s);
1875 }
1876 }
1877
1878private:
1880};
1881
1882// 38584 - Frostmourne Trigger
1884{
1885 npc_broken_frostmourne(Creature* creature) : CreatureAI(creature) { }
1886
1887 void Reset() override
1888 {
1889 _events.Reset();
1890 }
1891
1892 void IsSummonedBy(WorldObject* /*summoner*/) override
1893 {
1896 }
1897
1898 void DoAction(int32 action) override
1899 {
1900 if (action == ACTION_SUMMON_TERENAS)
1902 }
1903
1904 void EnterEvadeMode(EvadeReason /*why*/) override
1905 {
1906 }
1907
1908 void UpdateAI(uint32 diff) override
1909 {
1910 UpdateVictim();
1911
1912 _events.Update(diff);
1913
1914 while (uint32 eventId = _events.ExecuteEvent())
1915 {
1916 switch (eventId)
1917 {
1920 break;
1923 break;
1924 default:
1925 break;
1926 }
1927 }
1928
1929 // no melee attacks
1930 }
1931
1932private:
1934};
1935
1936// 70541, 73779, 73780, 73781 - Infest
1938{
1940
1941 void OnPeriodic(AuraEffect const* /*aurEff*/)
1942 {
1943 if (GetUnitOwner()->HealthAbovePct(90))
1944 {
1947 }
1948 }
1949
1950 void OnUpdate(AuraEffect* aurEff)
1951 {
1952 // multiply, starting from 2nd tick
1953 if (aurEff->GetTickNumber() == 1)
1954 return;
1955
1956 aurEff->SetAmount(int32(aurEff->GetAmount() * 1.15f));
1957 }
1958
1964};
1965
1966// 70337, 73912, 73913, 73914 - Necrotic Plague
1968{
1970
1971 bool Validate(SpellInfo const* /*spell*/) override
1972 {
1974 }
1975
1976 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1977 {
1978 switch (GetTargetApplication()->GetRemoveMode())
1979 {
1983 break;
1984 default:
1985 return;
1986 }
1987
1991 if (Unit* caster = GetCaster())
1992 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
1993 }
1994
1999};
2000
2001// 70338, 73785, 73786, 73787 - Necrotic Plague (Jump)
2003{
2005
2006public:
2011
2012private:
2013 void SelectTarget(std::list<WorldObject*>& targets)
2014 {
2016 if (targets.size() < 2)
2017 return;
2018
2019 targets.resize(1);
2020 }
2021
2023 {
2024 if (missInfo != SPELL_MISS_NONE)
2025 return;
2026
2027 if (GetHitUnit()->HasAura(GetSpellInfo()->Id))
2028 _hadAura = true;
2029 }
2030
2036
2038};
2039
2041{
2043
2044public:
2049
2050private:
2051 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2052 {
2053 if (Unit* caster = GetCaster())
2054 if (caster->GetAI())
2055 caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount());
2056 }
2057
2058 void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2059 {
2060 _lastAmount = aurEff->GetAmount();
2061 switch (GetTargetApplication()->GetRemoveMode())
2062 {
2065 break;
2066 default:
2067 return;
2068 }
2069
2073 if (Unit* caster = GetCaster())
2074 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2075 }
2076
2077 void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2078 {
2079 _lastAmount = aurEff->GetAmount();
2080 }
2081
2082 void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2083 {
2084 // this means the stack increased so don't process as if dispelled
2085 if (aurEff->GetAmount() > _lastAmount)
2086 return;
2087
2090 args.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1)
2092 if (Unit* caster = GetCaster())
2093 caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2094
2096 }
2097
2105
2107};
2108
2109// 73530 - Shadow Trap (Visual)
2125
2126// 74282 - Shadow Trap (Periodic)
2144
2145// 72262 - Quake
2147{
2149
2150 bool Load() override
2151 {
2152 return GetCaster()->GetInstanceScript() != nullptr;
2153 }
2154
2155 void FilterTargets(std::list<WorldObject*>& targets)
2156 {
2157 if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetGuidData(DATA_ARTHAS_PLATFORM)))
2158 targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false));
2159 }
2160
2162 {
2163 if (UnitAI* AI = GetCaster()->GetAI())
2164 AI->DoAction(ACTION_START_ATTACK);
2165 }
2166
2172};
2173
2174// 69110 - Ice Burst Target Search
2176{
2178
2179 bool Validate(SpellInfo const* /*spell*/) override
2180 {
2182 }
2183
2184 void CheckTargetCount(std::list<WorldObject*>& unitList)
2185 {
2186 if (unitList.empty())
2187 return;
2188
2189 // if there is at least one affected target cast the explosion
2191 if (GetCaster()->GetTypeId() == TYPEID_UNIT)
2192 {
2194 GetCaster()->AttackStop();
2196 }
2197 }
2198
2203};
2204
2205// 69200 - Raging Spirit
2221
2223{
2224 public:
2225 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
2226
2228 {
2229 return _source->GetExactDist2d(unit) > _dist;
2230 }
2231
2232 private:
2233 Unit* _source;
2234 float _dist;
2235};
2236
2237// 72754, 73708, 73709, 73710 - Defile
2239{
2241
2242 void CorrectRange(std::list<WorldObject*>& targets)
2243 {
2244 targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale()));
2245 targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR));
2246 }
2247
2249 {
2250 SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale()));
2251 // HACK: target player should cast this spell on defile
2252 // however with current aura handling auras cast by different units
2253 // cannot stack on the same aura object increasing the stack count
2255 }
2256
2263};
2264
2265/* 69037 - Summon Val'kyr
2266 70497 - Summon Vile Spirits Effect
2267 73579 - Summon Spirit Bomb
2268 74300 - Summon Spirit Bomb */
2270{
2272
2273 void ModDestHeight(SpellEffIndex /*effIndex*/)
2274 {
2275 static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f};
2276 WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest());
2277 dest->RelocateOffset(offset);
2278 GetHitDest()->RelocateOffset(offset);
2279 // spirit bombs get higher
2280 if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB)
2281 {
2282 static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f };
2283 dest->RelocateOffset(offsetExtra);
2284 GetHitDest()->RelocateOffset(offsetExtra);
2285 }
2286 }
2287
2292};
2293
2294// 69409, 73797, 73798, 73799 - Soul Reaper
2296{
2298
2299 bool Validate(SpellInfo const* /*spell*/) override
2300 {
2302 }
2303
2304 void OnPeriodic(AuraEffect const* /*aurEff*/)
2305 {
2306 if (Unit* caster = GetCaster())
2307 GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true);
2308 }
2309
2314};
2315
2316// 69030 - Val'kyr Target Search
2318{
2320
2321 bool Validate(SpellInfo const* /*spell*/) override
2322 {
2323 return ValidateSpellInfo({ SPELL_CHARGE });
2324 }
2325
2326 void SelectTarget(std::list<WorldObject*>& targets)
2327 {
2328 if (targets.empty())
2329 return;
2330
2331 targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id));
2332 if (targets.empty())
2333 return;
2334
2336 targets.clear();
2337 targets.push_back(_target);
2339 }
2340
2341 void ReplaceTarget(std::list<WorldObject*>& targets)
2342 {
2343 targets.clear();
2344 if (_target)
2345 targets.push_back(_target);
2346 }
2347
2349 {
2350 PreventHitDefaultEffect(effIndex);
2352 }
2353
2360
2362};
2363
2364// 68984 - Harvest Soul
2365// 74445 - Val'kyr Carry
2380
2381// 73488, 73782, 73783, 73784 - Life Siphon
2403
2404// 70498 - Vile Spirits
2406{
2408
2409public:
2411 {
2412 _is25Man = false;
2413 }
2414
2415private:
2416 bool Load() override
2417 {
2419 return true;
2420 }
2421
2422 void OnPeriodic(AuraEffect const* aurEff)
2423 {
2424 if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5))
2425 GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, { aurEff, GetCasterGUID() });
2426 }
2427
2432
2434};
2435
2436// 70499 - Summon Vile Spirits Effect
2438{
2440
2441 void ModDestHeight(SpellEffIndex /*effIndex*/)
2442 {
2443 Position offset = {0.0f, 0.0f, 15.0f, 0.0f};
2444 const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset);
2445 }
2446
2451};
2452
2453// 70501 - Vile Spirit Move Target Search
2455{
2457
2458public:
2463
2464private:
2465 bool Load() override
2466 {
2467 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2468 }
2469
2470 void SelectTarget(std::list<WorldObject*>& targets)
2471 {
2472 if (targets.empty())
2473 return;
2474
2476 }
2477
2479 {
2480 PreventHitDefaultEffect(effIndex);
2481 // for this spell, all units are in target map, however it should select one to attack
2482 if (GetHitUnit() != _target)
2483 return;
2484
2487 }
2488
2494
2496};
2497
2498// 70534 - Vile Spirit Damage Target Search
2500{
2502
2503 bool Load() override
2504 {
2505 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2506 }
2507
2508 void CheckTargetCount(std::list<WorldObject*>& targets)
2509 {
2510 if (targets.empty())
2511 return;
2512
2513 // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this
2514 // searcher spell will be blocked
2515 if (TempSummon* summon = GetCaster()->ToTempSummon())
2516 if (Unit* summoner = summon->GetSummonerUnit())
2517 summoner->GetAI()->SetData(DATA_VILE, 1);
2518 GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true);
2521 }
2522
2527};
2528
2529// 68980, 74296, 74297, 74325 - Harvest Soul
2531{
2533
2534 bool Load() override
2535 {
2536 return GetOwner()->GetInstanceScript() != nullptr;
2537 }
2538
2539 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2540 {
2541 // m_originalCaster to allow stacking from different casters, meh
2542 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2543 GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
2544 }
2545
2550};
2551
2552// 69382 - Light's Favor
2554{
2556
2557 void OnPeriodic(AuraEffect const* /*aurEff*/)
2558 {
2559 if (Unit* caster = GetCaster())
2560 if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
2561 effect->RecalculateAmount(caster);
2562 }
2563
2564 void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
2565 {
2566 canBeRecalculated = true;
2567 amount = 0;
2568 if (Unit* caster = GetCaster())
2569 amount = int32(caster->GetHealthPct());
2570 }
2571
2577};
2578
2579// 69397 - Soul Rip
2581{
2583
2584 void OnPeriodic(AuraEffect const* aurEff)
2585 {
2587 // shouldn't be needed, this is channeled
2588 if (Unit* caster = GetCaster())
2589 {
2590 CastSpellExtraArgs args(aurEff);
2592 args.AddSpellBP0(5000 * aurEff->GetTickNumber());
2593 caster->CastSpell(GetTarget(), SPELL_SOUL_RIP_DAMAGE, args);
2594 }
2595 }
2596
2601};
2602
2603// 72595, 73650 - Restore Soul
2605{
2607
2608public:
2610 {
2611 _instance = nullptr;
2612 }
2613
2614private:
2615 bool Load() override
2616 {
2618 return _instance != nullptr;
2619 }
2620
2621 void HandleScript(SpellEffIndex /*effIndex*/)
2622 {
2624 lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
2625 if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f))
2626 spawner->RemoveAllAuras();
2627
2628 std::list<Creature*> spirits;
2630 for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr)
2631 {
2632 (*itr)->m_Events.KillAllEvents(true);
2633 (*itr)->SetReactState(REACT_PASSIVE);
2634 (*itr)->AI()->EnterEvadeMode();
2635 }
2636 }
2637
2639 {
2640 if (missInfo != SPELL_MISS_NONE)
2641 return;
2642
2643 if (Unit* target = GetHitUnit())
2644 target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT);
2645 }
2646
2652
2654};
2655
2656// 69383 - Dark Hunger
2658{
2660
2661 bool Validate(SpellInfo const* /*spellInfo*/) override
2662 {
2664 }
2665
2666 void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
2667 {
2669 DamageInfo* damageInfo = eventInfo.GetDamageInfo();
2670 if (!damageInfo || !damageInfo->GetDamage())
2671 return;
2672
2673 CastSpellExtraArgs args(aurEff);
2674 args.AddSpellBP0(damageInfo->GetDamage() / 2);
2676 }
2677
2682};
2683
2684// 74276 - In Frostmourne Room
2686{
2688
2689 bool Load() override
2690 {
2691 return GetOwner()->GetInstanceScript() != nullptr;
2692 }
2693
2694 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2695 {
2696 // m_originalCaster to allow stacking from different casters, meh
2697 if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2698 GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING));
2699 }
2700
2705};
2706
2707// 74302, 74341, 74342, 74343 - Summon Spirit Bomb
2723
2724// 73582 - Trigger Vile Spirit (Inside, Heroic)
2726{
2728
2730 {
2731 Creature* target = GetHitCreature();
2732 if (!target)
2733 return;
2734
2735 VileSpiritActivateEvent(target).Execute(0, 0);
2736 }
2737
2742};
2743
2744// 71811 - Jump
2763
2764// 72431 - Jump (Remove Aura)
2780
2781// 73159 - Play Movie
2783{
2785
2786 bool Validate(SpellInfo const* /*spell*/) override
2787 {
2788 if (!sMovieStore.LookupEntry(MOVIE_FALL_OF_THE_LICH_KING))
2789 return false;
2790 return true;
2791 }
2792
2794 {
2795 PreventHitDefaultEffect(effIndex);
2796 if (Player* player = GetHitPlayer())
2797 player->SendMovieStart(MOVIE_FALL_OF_THE_LICH_KING);
2798 }
2799
2804};
2805
2806// 73655 - Harvest Soul (Teleport)
2808{
2810
2812 {
2813 float randCoordX = frand(-18.0f, 18.0f);
2814 float randCoordY = frand(-18.0f, 18.0f);
2815 GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f });
2816 }
2817
2822};
2823
2824// 74399 - Charge (Valkyr)
2826{
2828
2830 {
2831 PreventHitDefaultEffect(effIndex);
2832
2833 Unit* caster = GetCaster();
2834 Unit* target = GetExplTargetUnit();
2835 if (!target)
2836 return;
2837
2838 Position pos = target->GetPosition();
2839 caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, caster->GetFloorZ() + 2.f);
2840 }
2841
2846};
2847
2849{
2850 public:
2851 achievement_been_waiting_long_time() : AchievementCriteriaScript("achievement_been_waiting_long_time") { }
2852
2853 bool OnCheck(Player* /*source*/, Unit* target) override
2854 {
2855 if (!target)
2856 return false;
2857
2858 return target->GetAI()->GetData(DATA_PLAGUE_STACK) >= 30;
2859 }
2860};
2861
2863{
2864 public:
2865 achievement_neck_deep_in_vile() : AchievementCriteriaScript("achievement_neck_deep_in_vile") { }
2866
2867 bool OnCheck(Player* /*source*/, Unit* target) override
2868 {
2869 if (!target)
2870 return false;
2871
2872 return !target->GetAI()->GetData(DATA_VILE);
2873 }
2874};
2875
2877{
2878 // Creatures
2889
2890 // Spells
2923
2924 // Achievements
2927}
@ NPC_WORLD_TRIGGER
@ EQUIP_UNEQUIP
Definition CreatureAI.h:76
#define sCreatureTextMgr
@ TEXT_RANGE_NORMAL
DBCStorage< MovieEntry > sMovieStore(MovieEntryfmt)
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint32_t uint32
Definition Define.h:133
@ IN_PROGRESS
@ DONE
@ POINT_MOTION_TYPE
@ TEMPSUMMON_MANUAL_DESPAWN
@ TEMPSUMMON_CORPSE_DESPAWN
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
float frand(float min, float max)
Definition Random.cpp:55
double rand_norm()
Definition Random.cpp:75
#define RegisterSpellAndAuraScriptPair(script_1, script_2)
Definition ScriptMgr.h:1130
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
#define RegisterSpellScriptWithArgs(spell_script, script_name,...)
Definition ScriptMgr.h:1127
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
@ 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
@ TEAM_OTHER
@ CHAT_MSG_MONSTER_YELL
SpellMissInfo
@ SPELL_MISS_NONE
@ SPELL_CAST_OK
@ GO_STATE_READY
@ GO_STATE_ACTIVE
@ AURA_REMOVE_BY_DEATH
@ AURA_REMOVE_BY_EXPIRE
@ AURA_REMOVE_BY_ENEMY_SPELL
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK
@ AURA_EFFECT_HANDLE_REAPPLY
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_PERIODIC_DUMMY
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
@ TRIGGERED_IGNORE_CAST_IN_PROGRESS
Will ignore aura scaling.
@ TRIGGERED_NONE
@ SPELLVALUE_AURA_STACK
@ SPELLVALUE_BASE_POINT1
@ SPELLVALUE_MAX_TARGETS
#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)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_NPC_FLAG_GOSSIP
@ SHEATH_STATE_MELEE
Definition UnitDefines.h:99
@ MOVE_FLIGHT
@ UNIT_FLAG_UNINTERACTIBLE
@ UNIT_STATE_EVADE
Definition Unit.h:242
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
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
@ DATA_PLAGUE_STACK
Position const OutroFlying
Position const LichKingIntro[3]
@ LIGHT_SOULSTORM
@ MUSIC_FURY_OF_FROSTMOURNE
@ MOVIE_FALL_OF_THE_LICH_KING
@ MUSIC_FROZEN_THRONE
@ LIGHT_DEFAULT
@ LIGHT_SNOWSTORM
@ 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:161
uint32 GetTickNumber() const
SpellEffectInfo const & GetSpellEffectInfo() const
void SetAmount(int32 amount)
int32 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
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
HookList< EffectProcHandler > OnEffectProc
Unit * GetUnitOwner() const
uint8 GetStackAmount() const
HookList< EffectApplyHandler > OnEffectApply
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
@ EVADE_REASON_OTHER
Definition CreatureAI.h:98
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void EngagementOver()
void SetCombatPulseDelay(uint32 delay)
Definition Creature.h:269
void SetImmuneToPC(bool apply) override
Definition Creature.h:129
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:295
void LoadEquipment(int8 id=1, bool force=false)
void SetReactState(ReactStates st)
Definition Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Player * GetLootRecipient() const
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:186
bool IsInEvadeMode() const
Definition Creature.h:146
CreatureAI * AI() const
Definition Creature.h:154
uint32 GetDamage() const
Definition Unit.h:464
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
void DelayEvents(Milliseconds delay)
Definition EventMap.cpp:95
EventId ExecuteEvent()
Definition EventMap.cpp:73
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:236
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:52
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:28
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
ExactDistanceCheck(Unit *source, float dist)
bool operator()(WorldObject *unit)
bool operator()(GameObject *go)
void SetGoState(GOState state)
void SetDestructibleState(GameObjectDestructibleState state, WorldObject *attackerOrHealer=nullptr, bool setHealth=false)
void ResetDoorOrButton()
virtual bool SetBossState(uint32 id, EncounterState state)
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
virtual bool CheckRequiredBosses(uint32, Player const *=nullptr) const
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition Map.cpp:4764
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
Definition Map.cpp:4789
bool Is25ManRaid() const
Definition Map.cpp:4261
void SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
Definition Map.cpp:4798
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, uint32 duration=0, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1852
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
void MoveCharge(float x, float y, float z, float speed=SPEED_CHARGE, uint32 id=EVENT_CHARGE, bool generatePath=false)
void MoveFollow(Unit *target, float dist, ChaseAngle angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveFall(uint32 id=0)
void MoveRandom(float wanderDistance=0.0f)
NecroticPlagueTargetCheck(Unit const *obj, uint32 notAura1=0, uint32 notAura2=0)
bool operator()(Unit *unit) const
static ObjectGuid const Empty
Definition ObjectGuid.h:140
static Creature * ToCreature(Object *o)
Definition Object.h:186
static Unit * ToUnit(Object *o)
Definition Object.h:192
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
DamageInfo * GetDamageInfo() const
Definition Unit.h:519
uint32 TriggerSpell
Definition SpellInfo.h:228
uint32 Id
Definition SpellInfo.h:289
WorldLocation * GetHitDest() const
Creature * GetHitCreature() const
Player * GetHitPlayer() const
int32 GetHitDamage() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
HookList< HitHandler > OnHit
HookList< EffectHandler > OnEffectHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
int32 GetEffectValue() 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)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
virtual uint32 GetData(uint32) const
Definition UnitAI.h:155
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition UnitAI.h:157
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:30
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void ClearUnitState(uint32 f)
Definition Unit.h:877
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition Unit.cpp:8367
ThreatManager & GetThreatManager()
Definition Unit.h:1155
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
uint32 GetMaxHealth() const
Definition Unit.h:914
bool IsAlive() const
Definition Unit.h:1234
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1098
void SetHealth(uint32 val)
Definition Unit.cpp:9361
TempSummon * ToTempSummon()
Definition Unit.h:1794
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
UnitAI * GetAI() const
Definition Unit.h:800
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
virtual void SetSheath(SheathState sheathed)
Definition Unit.h:970
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13259
void SetEmoteState(Emote emote)
Definition Unit.h:967
uint32 GetHealth() const
Definition Unit.h:913
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4542
bool SetWalk(bool enable)
Definition Unit.cpp:13268
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8678
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13250
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
void RemoveAllAuras()
Definition Unit.cpp:4157
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition Unit.h:918
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:5691
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
bool AttackStop()
Definition Unit.cpp:5645
bool IsInCombat() const
Definition Unit.h:1144
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
bool Execute(uint64, uint32) override
VileSpiritActivateEvent(Creature *owner)
Map * GetMap() const
Definition Object.h:449
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:3153
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
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:1992
void setActive(bool isActiveObject)
Definition Object.cpp:991
float GetFloorZ() const
Definition Object.cpp:3586
void SetFarVisible(bool on)
Definition Object.cpp:1014
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2099
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:1405
EventProcessor m_Events
Definition Object.h:591
void GetRandomPoint(Position const &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const
Definition Object.cpp:1376
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *, Unit *target) override
PrepareSpellScript(spell_the_lich_king_cast_back_to_caster)
PrepareAuraScript(spell_the_lich_king_dark_hunger)
bool Validate(SpellInfo const *) override
void HandleProc(AuraEffect const *aurEff, ProcEventInfo &eventInfo)
PrepareSpellScript(spell_the_lich_king_defile)
void CorrectRange(std::list< WorldObject * > &targets)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_the_lich_king_harvest_soul)
PrepareSpellScript(spell_the_lich_king_harvest_souls_teleport)
void CheckTargetCount(std::list< WorldObject * > &unitList)
PrepareSpellScript(spell_the_lich_king_ice_burst_target_search)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_the_lich_king_in_frostmourne_room)
PrepareAuraScript(spell_the_lich_king_infest)
void OnPeriodic(AuraEffect const *)
void OnUpdate(AuraEffect *aurEff)
PrepareSpellScript(spell_the_lich_king_jump_remove_aura)
void HandleScript(SpellEffIndex effIndex)
PrepareSpellScript(spell_the_lich_king_jump)
void HandleScript(SpellEffIndex effIndex)
PrepareSpellScript(spell_the_lich_king_life_siphon)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_the_lich_king_lights_favor)
void CalculateBonus(AuraEffect const *, int32 &amount, bool &canBeRecalculated)
void AfterDispel(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnRemove(AuraEffect const *aurEff, AuraEffectHandleModes)
PrepareAuraScript(spell_the_lich_king_necrotic_plague_jump_aura)
void OnDispel(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void SelectTarget(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_the_lich_king_necrotic_plague_jump)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_the_lich_king_necrotic_plague)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void HandleScript(SpellEffIndex effIndex)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_the_lich_king_play_movie)
PrepareSpellScript(spell_the_lich_king_quake)
void FilterTargets(std::list< WorldObject * > &targets)
void HandleSendEvent(SpellEffIndex)
void HandleScript(SpellEffIndex effIndex)
PrepareSpellScript(spell_the_lich_king_raging_spirit)
PrepareSpellScript(spell_the_lich_king_restore_soul)
void RemoveAura(SpellMissInfo missInfo)
void CheckTargetCount(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic)
PrepareAuraScript(spell_the_lich_king_shadow_trap_visual)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_the_lich_king_soul_reaper)
void OnPeriodic(AuraEffect const *aurEff)
PrepareAuraScript(spell_the_lich_king_soul_rip)
PrepareSpellScript(spell_the_lich_king_summon_into_air)
PrepareSpellScript(spell_the_lich_king_summon_spirit_bomb)
PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit)
void ChargeDest(SpellEffIndex effIndex)
PrepareSpellScript(spell_the_lich_king_valkyr_charge)
void ReplaceTarget(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void SelectTarget(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_the_lich_king_valkyr_target_search)
PrepareSpellScript(spell_the_lich_king_vile_spirit_damage_target_search)
void CheckTargetCount(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_the_lich_king_vile_spirit_move_target_search)
void SelectTarget(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_the_lich_king_vile_spirits_visual)
void OnPeriodic(AuraEffect const *aurEff)
PrepareAuraScript(spell_the_lich_king_vile_spirits)
@ 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) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
CastSpellExtraArgs & AddSpellBP0(int32 val)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
ObjectGuid OriginalCaster
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:168
float m_positionZ
Definition Position.h:58
float GetExactDist2d(const float x, const float y) const
Definition Position.h:109
float GetExactDist(float x, float y, float z) const
Definition Position.h:121
float m_positionX
Definition Position.h:56
float m_positionY
Definition Position.h:57
void GetPosition(float &x, float &y) const
Definition Position.h:84
void RelocateOffset(Position const &offset)
Definition Position.cpp:36
void Relocate(float x, float y)
Definition Position.h:66
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
void JustDied(Unit *) override
bool CanAIAttack(Unit const *target) const override
uint32 GetData(uint32 type) const override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) 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
void MovementInform(uint32 type, uint32 point) override
void UpdateAI(uint32 diff) override
void IsSummonedBy(WorldObject *) override
npc_spirit_warden(Creature *creature)
InstanceScript * _instance
void JustDied(Unit *) override
void UpdateAI(uint32 diff) override
void IsSummonedBy(WorldObject *summonerWO) override
void DoAction(int32 action) override
npc_strangulate_vehicle(Creature *creature)
void UpdateAI(uint32 diff) override
npc_terenas_menethil(Creature *creature)
void EnterEvadeMode(EvadeReason) override
bool CanAIAttack(Unit const *target) const override
void IsSummonedBy(WorldObject *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
npc_tirion_fordring_tft(Creature *creature)
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
bool OnGossipSelect(Player *, uint32 menuId, uint32 gossipListId) override
void MovementInform(uint32 type, uint32 id) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
void SetGUID(ObjectGuid const &guid, int32) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MovementInform(uint32 type, uint32 id) override
npc_valkyr_shadowguard(Creature *creature)
void IsSummonedBy(WorldObject *) override