View difference between Paste ID: UkfSscEy and bYh9fZBM
SHOW: | | - or go back to the newest paste.
1-
/*
1+
//Trinity Based --Untested ICC Final Battle//
2-
 * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
2+
3-
 *
3+
4-
 * This program is free software; you can redistribute it and/or modify it
4+
5-
 * under the terms of the GNU General Public License as published by the
5+
6-
 * Free Software Foundation; either version 2 of the License, or (at your
6+
7-
 * option) any later version.
7+
8-
 *
8+
9-
 * This program is distributed in the hope that it will be useful, but WITHOUT
9+
10-
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
11-
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
12-
 * more details.
12+
13-
 *
13+
14-
 * You should have received a copy of the GNU General Public License along
14+
15-
 * with this program. If not, see <http://www.gnu.org/licenses/>.
15+
16-
 */
16+
17
{
18
    // The Lich King
19
    SAY_LK_INTRO_1                  = 0,
20
    SAY_LK_INTRO_2                  = 1,
21
    SAY_LK_INTRO_3                  = 2,
22
    SAY_LK_REMORSELESS_WINTER       = 4,
23
    SAY_LK_QUAKE                    = 5,
24
    SAY_LK_SUMMON_VALKYR            = 6,
25
    SAY_LK_HARVEST_SOUL             = 7,
26
    SAY_LK_FROSTMOURNE_ESCAPE       = 8,    // not said on heroic
27
    SAY_LK_FROSTMOURNE_KILL         = 9,    // not said on heroic
28
    SAY_LK_KILL                     = 10,
29
    SAY_LK_BERSERK                  = 11,
30
    EMOTE_DEFILE_WARNING            = 12,
31
    EMOTE_NECROTIC_PLAGUE_WARNING   = 13,
32
    SAY_LK_OUTRO_1                  = 14,
33
    SAY_LK_OUTRO_2                  = 15,
34
    SAY_LK_OUTRO_3                  = 16,
35
    SAY_LK_OUTRO_4                  = 17,
36
    SAY_LK_OUTRO_5                  = 18,
37
    SAY_LK_OUTRO_6                  = 19,
38
    SAY_LK_OUTRO_7                  = 20,
39
    SAY_LK_OUTRO_8                  = 21,
40
41
    // Highlord Tirion Fordring
42
    SAY_TIRION_INTRO_1              = 0,
43
    SAY_TIRION_INTRO_2              = 1,
44
    SAY_TIRION_OUTRO_1              = 2,
45
    SAY_TIRION_OUTRO_2              = 3,
46
47
    // Terenas Menethil (outro)
48
    SAY_TERENAS_OUTRO_1             = 0,
49
    SAY_TERENAS_OUTRO_2             = 1,
50
51
    // Terenas Menethil (Frostmourne)
52
    SAY_TERENAS_INTRO_1             = 0,
53
    SAY_TERENAS_INTRO_2             = 1,
54
    SAY_TERENAS_INTRO_3             = 2,
55
};
56
57
enum Spells
58
{
59
    // The Lich King
60
    SPELL_PLAGUE_AVOIDANCE              = 72846,    // raging spirits also get it
61
    SPELL_EMOTE_SIT_NO_SHEATH           = 73220,
62
    SPELL_BOSS_HITTIN_YA                = 73878,
63
    SPELL_EMOTE_SHOUT_NO_SHEATH         = 73213,
64
    SPELL_ICE_LOCK                      = 71614,
65
66
    // Phase 1
67
    SPELL_SUMMON_SHAMBLING_HORROR       = 70372,
68
    SPELL_RISEN_WITCH_DOCTOR_SPAWN      = 69639,
69
    SPELL_SUMMON_DRUDGE_GHOULS          = 70358,
70
    SPELL_INFEST                        = 70541,
71
    SPELL_NECROTIC_PLAGUE               = 70337,
72
    SPELL_NECROTIC_PLAGUE_JUMP          = 70338,
73
    SPELL_PLAGUE_SIPHON                 = 74074,
74
    SPELL_SHADOW_TRAP                   = 73539,
75
    SPELL_SHADOW_TRAP_AURA              = 73525,
76
    SPELL_SHADOW_TRAP_KNOCKBACK         = 73529,
77
78
    // Phase Transition
79
    SPELL_REMORSELESS_WINTER_1          = 68981,
80
    SPELL_REMORSELESS_WINTER_2          = 72259,
81
    SPELL_PAIN_AND_SUFFERING            = 72133,
82
    SPELL_SUMMON_ICE_SPHERE             = 69104,
83
    SPELL_ICE_SPHERE                    = 69090,
84
    SPELL_ICE_BURST_TARGET_SEARCH       = 69109,
85
    SPELL_ICE_PULSE                     = 69091,
86
    SPELL_ICE_BURST                     = 69108,
87
    SPELL_RAGING_SPIRIT                 = 69200,
88
    SPELL_RAGING_SPIRIT_VISUAL          = 69197,
89
    SPELL_RAGING_SPIRIT_VISUAL_CLONE    = 69198,
90
    SPELL_SOUL_SHRIEK                   = 69242,
91
    SPELL_QUAKE                         = 72262,
92
93
    // Phase 2
94
    SPELL_DEFILE                        = 72762,
95
    SPELL_DEFILE_AURA                   = 72743,
96
    SPELL_DEFILE_GROW                   = 72756,
97
    SPELL_SUMMON_VALKYR                 = 69037,
98
    SPELL_SUMMON_VALKYR_PERIODIC        = 74361,
99
    SPELL_HARVEST_SOUL_VALKYR           = 68985,    // Val'kyr Shadowguard vehicle aura
100
    SPELL_SOUL_REAPER                   = 69409,
101
    SPELL_SOUL_REAPER_BUFF              = 69410,
102
    SPELL_WINGS_OF_THE_DAMNED           = 74352,
103
    SPELL_VALKYR_TARGET_SEARCH          = 69030,
104
    SPELL_CHARGE                        = 74399,    // cast on selected target
105
    SPELL_VALKYR_CARRY                  = 74445,    // removes unselectable flag
106
    SPELL_LIFE_SIPHON                   = 73488,
107
    SPELL_LIFE_SIPHON_HEAL              = 73489,
108
    SPELL_EJECT_ALL_PASSENGERS          = 68576,
109
110
    // Phase 3
111
    SPELL_VILE_SPIRITS                  = 70498,
112
    SPELL_VILE_SPIRIT_MOVE_SEARCH       = 70501,
113
    SPELL_VILE_SPIRIT_DAMAGE_SEARCH     = 70502,
114
    SPELL_SPIRIT_BURST                  = 70503,
115
    SPELL_HARVEST_SOUL                  = 68980,
116
    SPELL_HARVEST_SOULS                 = 73654,    // Heroic version, weird because it has all 4 difficulties just like above spell
117
    SPELL_HARVEST_SOUL_VEHICLE          = 68984,
118
    SPELL_HARVEST_SOUL_VISUAL           = 71372,
119
    SPELL_HARVEST_SOUL_TELEPORT         = 72546,
120
    SPELL_HARVEST_SOULS_TELEPORT        = 73655,
121
    SPELL_HARVEST_SOUL_TELEPORT_BACK    = 72597,
122
    SPELL_IN_FROSTMOURNE_ROOM           = 74276,
123
    SPELL_KILL_FROSTMOURNE_PLAYERS      = 75127,
124
    SPELL_HARVESTED_SOUL                = 72679,
125
    SPELL_TRIGGER_VILE_SPIRIT_HEROIC    = 73582,
126
127
    // Frostmourne
128
    SPELL_LIGHTS_FAVOR                  = 69382,
129
    SPELL_RESTORE_SOUL                  = 72595,
130
    SPELL_RESTORE_SOULS                 = 73650,    // Heroic
131
    SPELL_DARK_HUNGER                   = 69383,    // Passive proc healing
132
    SPELL_DESTROY_SOUL                  = 74086,    // Used when Terenas Menethil dies
133
    SPELL_SOUL_RIP                      = 69397,    // Deals increasing damage
134
    SPELL_SOUL_RIP_DAMAGE               = 69398,
135
    SPELL_TERENAS_LOSES_INSIDE          = 72572,
136
    SPELL_SUMMON_SPIRIT_BOMB_1          = 73581,    // (Heroic)
137
    SPELL_SUMMON_SPIRIT_BOMB_2          = 74299,    // (Heroic)
138
    SPELL_EXPLOSION                     = 73576,    // Spirit Bomb (Heroic)
139
140
    // Outro
141
    SPELL_FURY_OF_FROSTMOURNE           = 72350,
142
    SPELL_FURY_OF_FROSTMOURNE_NO_REZ    = 72351,
143
    SPELL_EMOTE_QUESTION_NO_SHEATH      = 73330,
144
    SPELL_RAISE_DEAD                    = 71769,
145
    SPELL_LIGHTS_BLESSING               = 71797,
146
    SPELL_JUMP                          = 71809,
147
    SPELL_JUMP_TRIGGERED                = 71811,
148
    SPELL_JUMP_2                        = 72431,
149
    SPELL_SUMMON_BROKEN_FROSTMOURNE     = 74081,    // visual
150
    SPELL_SUMMON_BROKEN_FROSTMOURNE_2   = 72406,    // animation
151
    SPELL_SUMMON_BROKEN_FROSTMOURNE_3   = 73017,    // real summon
152
    SPELL_BROKEN_FROSTMOURNE            = 72398,
153
    SPELL_BROKEN_FROSTMOURNE_KNOCK      = 72405,
154
    SPELL_SOUL_BARRAGE                  = 72305,
155
    SPELL_SUMMON_TERENAS                = 72420,
156
    SPELL_MASS_RESURRECTION             = 72429,
157
    SPELL_MASS_RESURRECTION_REAL        = 72423,
158
    SPELL_PLAY_MOVIE                    = 73159,
159
160
    // Shambling Horror
161
    SPELL_SHOCKWAVE                     = 72149,
162
    SPELL_ENRAGE                        = 72143,
163
    SPELL_FRENZY                        = 28747,
164
};
165
166
#define NECROTIC_PLAGUE_LK   RAID_MODE<uint32>(70337, 73912, 73913, 73914)
167
#define NECROTIC_PLAGUE_PLR  RAID_MODE<uint32>(70338, 73785, 73786, 73787)
168
#define REMORSELESS_WINTER_1 RAID_MODE<uint32>(68981, 74270, 74271, 74272)
169
#define REMORSELESS_WINTER_2 RAID_MODE<uint32>(72259, 74273, 74274, 74275)
170
#define SUMMON_VALKYR        RAID_MODE<uint32>(69037, 74361, 69037, 74361)
171
#define HARVEST_SOUL         RAID_MODE<uint32>(68980, 74325, 74296, 74297)
172
173
enum Events
174
{
175
    // The Lich King
176
    // intro events
177
    EVENT_INTRO_MOVE_1              = 1,
178
    EVENT_INTRO_MOVE_2              = 2,
179
    EVENT_INTRO_MOVE_3              = 3,
180
    EVENT_INTRO_TALK_1              = 4,
181
    EVENT_EMOTE_CAST_SHOUT          = 5,
182
    EVENT_INTRO_EMOTE_1             = 6,
183
    EVENT_INTRO_CHARGE              = 7,
184
    EVENT_INTRO_CAST_FREEZE         = 8,
185
    EVENT_FINISH_INTRO              = 9,
186
187
    // combat events
188
    EVENT_SUMMON_SHAMBLING_HORROR   = 10,
189
    EVENT_SUMMON_DRUDGE_GHOUL       = 11,
190
    EVENT_INFEST                    = 12,
191
    EVENT_NECROTIC_PLAGUE           = 13,
192
    EVENT_SHADOW_TRAP               = 14,   // heroic only
193
    EVENT_SOUL_REAPER               = 15,
194
    EVENT_DEFILE                    = 16,
195
    EVENT_HARVEST_SOUL              = 17,   // normal mode only
196
    EVENT_PAIN_AND_SUFFERING        = 18,
197
    EVENT_SUMMON_ICE_SPHERE         = 19,
198
    EVENT_SUMMON_RAGING_SPIRIT      = 20,
199
    EVENT_QUAKE                     = 21,
200
    EVENT_SUMMON_VALKYR             = 22,
201
    EVENT_GRAB_PLAYER               = 23,
202
    EVENT_MOVE_TO_DROP_POS          = 24,
203
    EVENT_LIFE_SIPHON               = 25,   // heroic only
204
    EVENT_START_ATTACK              = 26,
205
    EVENT_QUAKE_2                   = 27,
206
    EVENT_VILE_SPIRITS              = 28,
207
    EVENT_HARVEST_SOULS             = 29,   // heroic only
208
    EVENT_WICKED_SPIRITS            = 30,
209
    EVENT_SOUL_RIP                  = 31,
210
    EVENT_DESTROY_SOUL              = 32,
211
    EVENT_FROSTMOURNE_TALK_1        = 33,
212
    EVENT_FROSTMOURNE_TALK_2        = 34,
213
    EVENT_FROSTMOURNE_TALK_3        = 35,
214
    EVENT_TELEPORT_BACK             = 36,
215
    EVENT_FROSTMOURNE_HEROIC        = 37,
216
    EVENT_OUTRO_TALK_1              = 38,
217
    EVENT_OUTRO_TALK_2              = 39,
218
    EVENT_OUTRO_EMOTE_TALK          = 40,
219
    EVENT_OUTRO_TALK_3              = 41,
220
    EVENT_OUTRO_MOVE_CENTER         = 42,
221
    EVENT_OUTRO_TALK_4              = 43,
222
    EVENT_OUTRO_RAISE_DEAD          = 44,
223
    EVENT_OUTRO_TALK_5              = 45,
224
    EVENT_OUTRO_BLESS               = 46,
225
    EVENT_OUTRO_REMOVE_ICE          = 47,
226
    EVENT_OUTRO_MOVE_1              = 48,
227
    EVENT_OUTRO_JUMP                = 49,
228
    EVENT_OUTRO_TALK_6              = 50,
229
    EVENT_OUTRO_KNOCK_BACK          = 51,
230
    EVENT_OUTRO_SOUL_BARRAGE        = 52,
231
    EVENT_OUTRO_SUMMON_TERENAS      = 53,
232
    EVENT_OUTRO_TERENAS_TALK_1      = 54,
233
    EVENT_OUTRO_TERENAS_TALK_2      = 55,
234
    EVENT_OUTRO_TALK_7              = 56,
235
    EVENT_OUTRO_TALK_8              = 57,
236
    EVENT_BERSERK                   = 58,
237
238
    // Shambling Horror
239
    EVENT_SHOCKWAVE                 = 59,
240
    EVENT_ENRAGE                    = 60,
241
242
    // Raging Spirit
243
    EVENT_SOUL_SHRIEK               = 61,
244
245
    // Strangulate Vehicle (Harvest Soul)
246
    EVENT_TELEPORT                  = 62,
247
    EVENT_MOVE_TO_LICH_KING         = 63,
248
    EVENT_DESPAWN_SELF              = 64,
249
};
250
251
enum EventGroups
252
{
253
    EVENT_GROUP_BERSERK         = 1,
254
    EVENT_GROUP_VILE_SPIRITS    = 2,
255
};
256
257
enum Phases
258
{
259
    PHASE_INTRO                 = 1,
260
    PHASE_ONE                   = 2,
261
    PHASE_TWO                   = 3,
262
    PHASE_THREE                 = 4,
263
    PHASE_TRANSITION            = 5,
264
    PHASE_FROSTMOURNE           = 6,    // only set on heroic mode when all players are sent into frostmourne
265
    PHASE_OUTRO                 = 7,
266
267
    PHASE_MASK_INTRO            = 1 << PHASE_INTRO,
268
    PHASE_MASK_ONE              = 1 << PHASE_ONE,
269
    PHASE_MASK_TWO              = 1 << PHASE_TWO,
270
    PHASE_MASK_THREE            = 1 << PHASE_THREE,
271
    PHASE_MASK_TRANSITION       = 1 << PHASE_TRANSITION,
272
    PHASE_MASK_NO_CAST_CHECK    = (1 << PHASE_TRANSITION) | (1 << PHASE_FROSTMOURNE) | (1 << PHASE_OUTRO),
273
    PHASE_MASK_FROSTMOURNE      = 1 << PHASE_FROSTMOURNE,
274
    PHASE_MASK_OUTRO            = 1 << PHASE_OUTRO,
275
    PHASE_MASK_NO_VICTIM        = (1 << PHASE_INTRO) | (1 << PHASE_OUTRO) | (1 << PHASE_FROSTMOURNE),
276
};
277
278
#define PHASE_TWO_THREE  (events.GetPhaseMask() & PHASE_MASK_TWO ? PHASE_TWO : PHASE_THREE)
279
280
Position const CenterPosition     = {503.6282f, -2124.655f, 1040.8602f, 0.0f};
281
Position const TirionIntro        = {489.2970f, -2124.840f, 1040.8602f, 0.0f};
282
Position const TirionCharge       = {482.9019f, -2124.479f, 1040.8602f, 0.0f};
283
Position const LichKingIntro[3]   =
284
{
285
    {432.0851f, -2123.673f, 1064.6615f, 0.0f},
286
    {457.8351f, -2123.423f, 1041.1615f, 0.0f},
287
    {465.0730f, -2123.470f, 1040.8602f, 0.0f},
288
};
289
Position const OutroPosition1     = {493.6286f, -2124.569f, 1040.8602f, 0.0f};
290
Position const OutroFlying        = {508.9897f, -2124.561f, 1045.8598f, 0.0f};
291
Position const TerenasSpawn       = {495.5542f, -2517.012f, 1050.000f, 4.6993f};
292
Position const TerenasSpawnHeroic = {495.7080f, -2523.760f, 1050.000f, 0.0f};
293
Position const SpiritWardenSpawn  = {495.3406f, -2529.983f, 1050.000f, 1.5592f};
294
295
enum MovePoints
296
{
297
    POINT_CENTER_1          = 1,
298
    POINT_CENTER_2          = 2,
299
    POINT_TIRION_INTRO      = 3,
300
    POINT_LK_INTRO_1        = 4,
301
    POINT_LK_INTRO_2        = 5,
302
    POINT_LK_INTRO_3        = 6,
303
    POINT_TIRION_CHARGE     = 7,
304
    POINT_DROP_PLAYER       = 8,
305
    POINT_LK_OUTRO_1        = 9,
306
    POINT_TIRION_OUTRO_1    = 10,
307
    POINT_OUTRO_JUMP        = 11,
308
    POINT_LK_OUTRO_2        = 12,
309
    POINT_GROUND            = 13,
310
    POINT_CHARGE            = 1003, // globally used number for charge spell effects
311
};
312
313
enum EncounterActions
314
{
315
    ACTION_START_ENCOUNTER      = 0,
316
    ACTION_CONTINUE_INTRO       = 1,
317
    ACTION_START_ATTACK         = 2,
318
    ACTION_OUTRO                = 3,
319
    ACTION_PLAY_MUSIC           = 4,
320
    ACTION_BREAK_FROSTMOURNE    = 5,
321
    ACTION_SUMMON_TERENAS       = 6,
322
    ACTION_FINISH_OUTRO         = 7,
323
    ACTION_TELEPORT_BACK        = 8,
324
};
325
326
enum MiscData
327
{
328
    LIGHT_SNOWSTORM             = 2490,
329
    LIGHT_SOULSTORM             = 2508,
330
331
    MUSIC_FROZEN_THRONE         = 17457,
332
    MUSIC_SPECIAL               = 17458,    // Summon Shambling Horror, Remorseless Winter, Quake, Summon Val'kyr Periodic, Harvest Soul, Vile Spirits
333
    MUSIC_FURY_OF_FROSTMOURNE   = 17459,
334
    MUSIC_FINAL                 = 17460,    // Raise Dead, Light's Blessing
335
336
    SOUND_PAIN                  = 17360,    // separate sound, not attached to any text
337
338
    EQUIP_ASHBRINGER_GLOWING    = 50442,
339
    EQUIP_BROKEN_FROSTMOURNE    = 50840,
340
341
    MOVIE_FALL_OF_THE_LICH_KING = 16,
342
};
343
344
#define DATA_PLAGUE_STACK 70337
345
#define DATA_VILE 45814622
346
347
class NecroticPlagueTargetCheck : public std::unary_function<Unit*, bool>
348
{
349
    public:
350
        NecroticPlagueTargetCheck(Unit const* obj, uint32 notAura1 = 0, uint32 notAura2 = 0)
351
            : _sourceObj(obj), _notAura1(notAura1), _notAura2(notAura2)
352
        {
353
        }
354
355
        bool operator()(Unit* unit) const
356
        {
357
            if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->isTotem() || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
358
                return false;
359
            if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
360
                return false;
361
            return true;
362
        }
363
364
    private:
365
        Unit const* _sourceObj;
366
        uint32 _notAura1;
367
        uint32 _notAura2;
368
};
369
370
class HeightDifferenceCheck
371
{
372
    public:
373
        HeightDifferenceCheck(GameObject* go, float diff, bool reverse)
374
            : _baseObject(go), _difference(diff), _reverse(reverse)
375
        {
376
        }
377
378
        bool operator()(Unit* unit) const
379
        {
380
            return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse;
381
        }
382
383
    private:
384
        GameObject* _baseObject;
385
        float _difference;
386
        bool _reverse;
387
};
388
389
class FrozenThroneResetWorker
390
{
391
    public:
392
        FrozenThroneResetWorker() { }
393
394
        bool operator()(GameObject* go)
395
        {
396
            switch (go->GetEntry())
397
            {
398
                case GO_ARTHAS_PLATFORM:
399
                    go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING);
400
                    break;
401
                case GO_DOODAD_ICECROWN_THRONEFROSTYWIND01:
402
                    go->SetGoState(GO_STATE_ACTIVE);
403
                    break;
404
                case GO_DOODAD_ICECROWN_THRONEFROSTYEDGE01:
405
                    go->SetGoState(GO_STATE_READY);
406
                    break;
407
                case GO_DOODAD_ICESHARD_STANDING02:
408
                case GO_DOODAD_ICESHARD_STANDING01:
409
                case GO_DOODAD_ICESHARD_STANDING03:
410
                case GO_DOODAD_ICESHARD_STANDING04:
411
                    go->ResetDoorOrButton();
412
                    break;
413
                default:
414
                    break;
415
            }
416
417
            return false;
418
        }
419
};
420
421
class StartMovementEvent : public BasicEvent
422
{
423
    public:
424
        StartMovementEvent(Creature* summoner, Creature* owner)
425
            : _summoner(summoner), _owner(owner)
426
        {
427
        }
428
429
        bool Execute(uint64 /*time*/, uint32 /*diff*/)
430
        {
431
            _owner->SetReactState(REACT_AGGRESSIVE);
432
            if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(_summoner)))
433
                _owner->AI()->AttackStart(target);
434
            return true;
435
        }
436
437
    private:
438
        Creature* _summoner;
439
        Creature* _owner;
440
};
441
442
class VileSpiritActivateEvent : public BasicEvent
443
{
444
    public:
445
        explicit VileSpiritActivateEvent(Creature* owner)
446
            : _owner(owner)
447
        {
448
        }
449
450
        bool Execute(uint64 /*time*/, uint32 /*diff*/)
451
        {
452
            _owner->SetReactState(REACT_AGGRESSIVE);
453
            _owner->CastSpell(_owner, SPELL_VILE_SPIRIT_MOVE_SEARCH, true);
454
            _owner->CastSpell((Unit*)NULL, SPELL_VILE_SPIRIT_DAMAGE_SEARCH, true);
455
            return true;
456
        }
457
458
    private:
459
        Creature* _owner;
460
};
461
462
class boss_the_lich_king : public CreatureScript
463
{
464
    public:
465
        boss_the_lich_king() : CreatureScript("boss_the_lich_king") { }
466
467
        struct boss_the_lich_kingAI : public BossAI
468
        {
469
            boss_the_lich_kingAI(Creature* creature) : BossAI(creature, DATA_THE_LICH_KING)
470
            {
471
            }
472
473
            void Reset()
474
            {
475
                _Reset();
476
                events.SetPhase(PHASE_INTRO);
477
                _necroticPlagueStack = 0;
478
                _vileSpiritExplosions = 0;
479
                SetEquipmentSlots(true);
480
            }
481
482
            void JustDied(Unit* /*killer*/)
483
            {
484
                _JustDied();
485
                DoCastAOE(SPELL_PLAY_MOVIE, false);
486
                me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
487
                me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x03);
488
489
                //me->GetMotionMaster()->MoveFall();
490
            }
491
492
            void EnterCombat(Unit* target)
493
            {
494
                if (!instance->CheckRequiredBosses(DATA_THE_LICH_KING, target->ToPlayer()))
495
                {
496
                    EnterEvadeMode();
497
                    instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
498
                    return;
499
                }
500
501
                me->setActive(true);
502
                DoZoneInCombat();
503
504
                events.SetPhase(PHASE_ONE);
505
                events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 20000, 0, PHASE_ONE);
506
                events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 10000, 0, PHASE_ONE);
507
                events.ScheduleEvent(EVENT_INFEST, 5000, 0, PHASE_ONE);
508
                events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, urand(30000, 33000), 0, PHASE_ONE);
509
                events.ScheduleEvent(EVENT_BERSERK, 900000, EVENT_GROUP_BERSERK);
510
                if (IsHeroic())
511
                    events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500, 0, PHASE_ONE);
512
            }
513
514
            void JustReachedHome()
515
            {
516
                _JustReachedHome();
517
                instance->SetBossState(DATA_THE_LICH_KING, NOT_STARTED);
518
519
                // Reset The Frozen Throne gameobjects
520
                FrozenThroneResetWorker reset;
521
                Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset);
522
                me->VisitNearbyGridObject(333.0f, worker);
523
524
                // Reset any light override
525
                SendLightOverride(0, 5000);
526
            }
527
528
            bool CanAIAttack(Unit const* target) const
529
            {
530
                // The Lich King must not select targets in frostmourne room if he killed everyone outside
531
                return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM);
532
            }
533
534
            void EnterEvadeMode()
535
            {
536
                instance->SetBossState(DATA_THE_LICH_KING, FAIL);
537
                BossAI::EnterEvadeMode();
538
                if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
539
                    tirion->AI()->EnterEvadeMode();
540
                DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS);
541
                summons.DoAction(NPC_STRANGULATE_VEHICLE, ACTION_TELEPORT_BACK);
542
            }
543
544
            void KilledUnit(Unit* victim)
545
            {
546
                if (victim->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode() && !(events.GetPhaseMask() & PHASE_MASK_OUTRO))
547
                    Talk(SAY_LK_KILL);
548
            }
549
550
            void DoAction(int32 const action)
551
            {
552
                switch (action)
553
                {
554
                    case ACTION_START_ENCOUNTER:
555
                        instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS);
556
                        Talk(SAY_LK_INTRO_1);
557
                        SendMusicToPlayers(MUSIC_FROZEN_THRONE);
558
                        // schedule talks
559
                        me->SetStandState(UNIT_STAND_STATE_STAND);
560
                        events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4000);
561
                        break;
562
                    case ACTION_START_ATTACK:
563
                        events.ScheduleEvent(EVENT_START_ATTACK, 5000);
564
                        break;
565
                    case ACTION_PLAY_MUSIC:
566
                        SendMusicToPlayers(MUSIC_FINAL);
567
                        break;
568
                    case ACTION_RESTORE_LIGHT:
569
                        SendLightOverride(0, 5000);
570
                        break;
571
                    case ACTION_BREAK_FROSTMOURNE:
572
                        DoCastAOE(SPELL_SUMMON_BROKEN_FROSTMOURNE);
573
                        DoCastAOE(SPELL_SUMMON_BROKEN_FROSTMOURNE_2);
574
                        SetEquipmentSlots(false, EQUIP_BROKEN_FROSTMOURNE);
575
                        events.ScheduleEvent(EVENT_OUTRO_TALK_6, 2500, 0, PHASE_OUTRO);
576
                        break;
577
                    case ACTION_FINISH_OUTRO:
578
                        events.ScheduleEvent(EVENT_OUTRO_TALK_7, 7000, 0, PHASE_OUTRO);
579
                        events.ScheduleEvent(EVENT_OUTRO_TALK_8, 17000, 0, PHASE_OUTRO);
580
                        break;
581
                    case ACTION_TELEPORT_BACK:
582
                        summons.DoAction(NPC_STRANGULATE_VEHICLE, ACTION_TELEPORT_BACK);
583
                        if (!IsHeroic())
584
                            Talk(SAY_LK_FROSTMOURNE_ESCAPE);
585
                        else
586
                            DoCastAOE(SPELL_TRIGGER_VILE_SPIRIT_HEROIC);
587
                        break;
588
                    default:
589
                        break;
590
                }
591
            }
592
593
            uint32 GetData(uint32 type)
594
            {
595
                switch (type)
596
                {
597
                    case DATA_PLAGUE_STACK:
598
                        return _necroticPlagueStack;
599
                    case DATA_VILE:
600
                        return _vileSpiritExplosions;
601
                    default:
602
                        break;
603
                }
604
605
                return 0;
606
            }
607
608
            void SetData(uint32 type, uint32 value)
609
            {
610
                switch (type)
611
                {
612
                    case DATA_PLAGUE_STACK:
613
                        _necroticPlagueStack = std::max(value, _necroticPlagueStack);
614
                        break;
615
                    case DATA_VILE:
616
                        _vileSpiritExplosions += value;
617
                        break;
618
                    default:
619
                        break;
620
                }
621
            }
622
623
            void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/)
624
            {
625
                if (events.GetPhaseMask() & PHASE_MASK_ONE && !HealthAbovePct(70))
626
                {
627
                    events.SetPhase(PHASE_TRANSITION);
628
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
629
                    me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition);
630
                    return;
631
                }
632
633
                if (events.GetPhaseMask() & PHASE_MASK_TWO && !HealthAbovePct(40))
634
                {
635
                    events.SetPhase(PHASE_TRANSITION);
636
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
637
                    me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition);
638
                    return;
639
                }
640
641
                if (events.GetPhaseMask() & PHASE_MASK_THREE && !HealthAbovePct(10))
642
                {
643
                    me->SetReactState(REACT_PASSIVE);
644
                    me->AttackStop();
645
                    events.Reset();
646
                    events.SetPhase(PHASE_OUTRO);
647
                    summons.DespawnAll();
648
                    SendMusicToPlayers(MUSIC_FURY_OF_FROSTMOURNE);
649
                    DoCastAOE(SPELL_FURY_OF_FROSTMOURNE);
650
                    me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
651
                    events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600, 0, PHASE_OUTRO);
652
                    events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600, 0, PHASE_OUTRO);
653
                    events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 17600, 0, PHASE_OUTRO);
654
                    events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 27600, 0, PHASE_OUTRO);
655
                    events.ScheduleEvent(EVENT_OUTRO_TALK_2, 34600, 0, PHASE_OUTRO);
656
                    events.ScheduleEvent(EVENT_OUTRO_TALK_3, 43600, 0, PHASE_OUTRO);
657
                    events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 54600, 0, PHASE_OUTRO);
658
                    events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 58600, 0, PHASE_OUTRO);
659
                    events.ScheduleEvent(EVENT_OUTRO_MOVE_CENTER, 69600, 0, PHASE_OUTRO);
660
                    // stop here. rest will get scheduled from MovementInform
661
                    return;
662
                }
663
            }
664
665
            void JustSummoned(Creature* summon)
666
            {
667
                switch (summon->GetEntry())
668
                {
669
                    case NPC_SHAMBLING_HORROR:
670
                    case NPC_DRUDGE_GHOUL:
671
                        summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
672
                        summon->SetReactState(REACT_PASSIVE);
673
                        summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
674
                        summon->m_Events.AddEvent(new StartMovementEvent(me, summon), summon->m_Events.CalculateTime(5000));
675
                        break;
676
                    case NPC_ICE_SPHERE:
677
                    {
678
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
679
                        {
680
                            summon->SetReactState(REACT_PASSIVE);
681
                            summon->CastSpell(summon, SPELL_ICE_SPHERE, false);
682
                            summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false);
683
                            summon->CastSpell(target, SPELL_ICE_PULSE, false);
684
                            summon->ClearUnitState(UNIT_STAT_CASTING);
685
                            summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
686
                        }
687
                        else
688
                            summon->DespawnOrUnsummon();
689
                        break;
690
                    }
691
                    case NPC_DEFILE:
692
                        summon->SetReactState(REACT_PASSIVE);
693
                        summon->CastSpell(summon, SPELL_DEFILE_AURA, false);
694
                        break;
695
                    case NPC_FROSTMOURNE_TRIGGER:
696
                    {
697
                        summons.Summon(summon);
698
                        summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true);
699
700
                        SendLightOverride(LIGHT_SOULSTORM, 10000);
701
                        SendWeather(WEATHER_STATE_BLACKSNOW);
702
703
                        events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5000, 0, PHASE_OUTRO);
704
                        return;
705
                    }
706
                    case NPC_VILE_SPIRIT:
707
                    {
708
                        summons.Summon(summon);
709
                        if (events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE)
710
                        {
711
                            TeleportSpirit(summon);
712
                            return;
713
                        }
714
715
                        summon->SetReactState(REACT_PASSIVE);
716
                        summon->SetSpeed(MOVE_FLIGHT, 0.5f);
717
                        summon->GetMotionMaster()->MoveRandom(10.0f);
718
                        summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000));
719
                        return;
720
                    }
721
                    case NPC_STRANGULATE_VEHICLE:
722
                        summons.Summon(summon);
723
                        return;
724
                    default:
725
                        break;
726
                }
727
728
                BossAI::JustSummoned(summon);
729
            }
730
731
            void SummonedCreatureDies(Creature* summon, Unit* /*killer*/)
732
            {
733
                switch (summon->GetEntry())
734
                {
735
                    case NPC_SHAMBLING_HORROR:
736
                    case NPC_DRUDGE_GHOUL:
737
                    case NPC_ICE_SPHERE:
738
                    case NPC_VALKYR_SHADOWGUARD:
739
                    case NPC_RAGING_SPIRIT:
740
                    case NPC_VILE_SPIRIT:
741
                    case NPC_WICKED_SPIRIT:
742
                        summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
743
                        break;
744
                    default:
745
                        break;
746
                }
747
            }
748
749
            void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
750
            {
751
                if (spell->Id == SPELL_HARVESTED_SOUL && me->isInCombat() && !IsHeroic())
752
                    Talk(SAY_LK_FROSTMOURNE_KILL);
753
            }
754
755
            void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
756
            {
757
                if (spell->Id == REMORSELESS_WINTER_1 || spell->Id == REMORSELESS_WINTER_2)
758
                {
759
                    SendLightOverride(LIGHT_SNOWSTORM, 5000);
760
                    SendWeather(WEATHER_STATE_LIGHT_SNOW);
761
                }
762
            }
763
764
            void MovementInform(uint32 type, uint32 pointId)
765
            {
766
                if (type != POINT_MOTION_TYPE)
767
                    return;
768
769
                switch (pointId)
770
                {
771
                    case POINT_LK_INTRO_1:
772
                        // schedule for next update cycle, current update must finalize movement
773
                        events.ScheduleEvent(EVENT_INTRO_MOVE_2, 1, 0, PHASE_INTRO);
774
                        break;
775
                    case POINT_LK_INTRO_2:
776
                        events.ScheduleEvent(EVENT_INTRO_MOVE_3, 1, 0, PHASE_INTRO);
777
                        break;
778
                    case POINT_LK_INTRO_3:
779
                        if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
780
                            tirion->AI()->DoAction(ACTION_CONTINUE_INTRO);
781
                        events.ScheduleEvent(EVENT_INTRO_TALK_1, 9000, 0, PHASE_INTRO);
782
                        break;
783
                    case POINT_CENTER_1:
784
                        me->SetFacing(0.0f);
785
                        Talk(SAY_LK_REMORSELESS_WINTER);
786
                        SendMusicToPlayers(MUSIC_SPECIAL);
787
                        me->SetReactState(REACT_PASSIVE);
788
                        me->AttackStop();
789
                        DoCast(me, SPELL_REMORSELESS_WINTER_1);
790
                        events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
791
                        events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION);
792
                        events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4000, 0, PHASE_TRANSITION);
793
                        events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
794
                        events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 3000, 0, PHASE_TRANSITION);
795
                        events.ScheduleEvent(EVENT_SUMMON_VALKYR, 78000, 0, PHASE_TWO);
796
                        events.ScheduleEvent(EVENT_INFEST, 70000, 0, PHASE_TWO);
797
                        events.ScheduleEvent(EVENT_DEFILE, 97000, 0, PHASE_TWO);
798
                        events.ScheduleEvent(EVENT_SOUL_REAPER, 94000, 0, PHASE_TWO);
799
                        me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
800
                        break;
801
                    case POINT_CENTER_2:
802
                        me->SetFacing(0.0f);
803
                        Talk(SAY_LK_REMORSELESS_WINTER);
804
                        SendMusicToPlayers(MUSIC_SPECIAL);
805
                        me->SetReactState(REACT_PASSIVE);
806
                        me->AttackStop();
807
                        DoCast(me, SPELL_REMORSELESS_WINTER_2);
808
                        summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD);
809
                        events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
810
                        events.ScheduleEvent(EVENT_QUAKE_2, 62500, 0, PHASE_TRANSITION);
811
                        events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6000, 0, PHASE_TRANSITION);
812
                        events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
813
                        events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 5000, 0, PHASE_TRANSITION);
814
                        events.ScheduleEvent(EVENT_DEFILE, 95500, 0, PHASE_THREE);
815
                        events.ScheduleEvent(EVENT_SOUL_REAPER, 99500, 0, PHASE_THREE);
816
                        events.ScheduleEvent(EVENT_VILE_SPIRITS, 79500, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE);
817
                        events.ScheduleEvent(IsHeroic() ? EVENT_HARVEST_SOULS : EVENT_HARVEST_SOUL, 73500, 0, PHASE_THREE);
818
                        me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
819
                        break;
820
                    case POINT_LK_OUTRO_1:
821
                        events.ScheduleEvent(EVENT_OUTRO_TALK_4, 1, 0, PHASE_OUTRO);
822
                        events.ScheduleEvent(EVENT_OUTRO_RAISE_DEAD, 1000, 0, PHASE_OUTRO);
823
                        events.ScheduleEvent(EVENT_OUTRO_TALK_5, 29000, 0, PHASE_OUTRO);
824
                        break;
825
                    case POINT_LK_OUTRO_2:
826
                        if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
827
                            tirion->AI()->Talk(SAY_TIRION_OUTRO_2);
828
                        if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
829
                            frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS);
830
                        break;
831
                    default:
832
                        break;
833
                }
834
            }
835
836
            void UpdateAI(uint32 const diff)
837
            {
838
                // check phase first to prevent updating victim and entering evade mode when not wanted
839
                if (!(events.GetPhaseMask() & PHASE_MASK_NO_VICTIM))
840
                    if (!UpdateVictim())
841
                        return;
842
843
                events.Update(diff);
844
845
                // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells
846
                if (me->HasUnitState(UNIT_STAT_CASTING) && !(events.GetPhaseMask() & PHASE_MASK_NO_CAST_CHECK))
847
                    return;
848
849
                while (uint32 eventId = events.ExecuteEvent())
850
                {
851
                    switch (eventId)
852
                    {
853
                        case EVENT_INTRO_MOVE_1:
854
                            me->SetSheath(SHEATH_STATE_MELEE);
855
                            me->RemoveAurasDueToSpell(SPELL_EMOTE_SIT_NO_SHEATH);
856
                            me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
857
                            me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_1, LichKingIntro[0]);
858
                            break;
859
                        case EVENT_INTRO_MOVE_2:
860
                            me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_2, LichKingIntro[1]);
861
                            break;
862
                        case EVENT_INTRO_MOVE_3:
863
                            me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_3, LichKingIntro[2]);
864
                            break;
865
                        case EVENT_INTRO_TALK_1:
866
                            Talk(SAY_LK_INTRO_2);
867
                            // for some reason blizz sends 2 emotes in row here so (we handle one in Talk)
868
                            me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NOSHEATHE);
869
                            events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 7000, 0, PHASE_INTRO);
870
                            events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 13000, 0, PHASE_INTRO);
871
                            events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 18000, 0, PHASE_INTRO);
872
                            events.ScheduleEvent(EVENT_INTRO_CAST_FREEZE, 31000, 0, PHASE_INTRO);
873
                            break;
874
                        case EVENT_EMOTE_CAST_SHOUT:
875
                            DoCast(me, SPELL_EMOTE_SHOUT_NO_SHEATH, false);
876
                            break;
877
                        case EVENT_INTRO_EMOTE_1:
878
                            me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NOSHEATHE);
879
                            break;
880
                        case EVENT_INTRO_CAST_FREEZE:
881
                            Talk(SAY_LK_INTRO_3);
882
                            DoCastAOE(SPELL_ICE_LOCK, false);
883
                            events.ScheduleEvent(EVENT_FINISH_INTRO, 1000, 0, PHASE_INTRO);
884
                            break;
885
                        case EVENT_FINISH_INTRO:
886
                            me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
887
                            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
888
                            me->SetReactState(REACT_AGGRESSIVE);
889
                            events.SetPhase(PHASE_ONE);
890
                            me->SetInCombatWithZone();
891
                            break;
892
                        case EVENT_SUMMON_SHAMBLING_HORROR:
893
                            DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR);
894
                            SendMusicToPlayers(MUSIC_SPECIAL);
895
                            events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 60000, 0, PHASE_ONE);
896
                            break;
897
                        case EVENT_SUMMON_DRUDGE_GHOUL:
898
                            DoCast(me, SPELL_SUMMON_DRUDGE_GHOULS);
899
                            events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 30000, 0, PHASE_ONE);
900
                            break;
901
                        case EVENT_INFEST:
902
                            DoCast(me, SPELL_INFEST);
903
                            events.ScheduleEvent(EVENT_INFEST, urand(21000, 24000), 0, (events.GetPhaseMask() & PHASE_MASK_ONE) ? PHASE_ONE : PHASE_TWO);
904
                            break;
905
                        case EVENT_NECROTIC_PLAGUE:
906
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, NecroticPlagueTargetCheck(me, NECROTIC_PLAGUE_LK, NECROTIC_PLAGUE_PLR)))
907
                            {
908
                                Talk(EMOTE_NECROTIC_PLAGUE_WARNING, target->GetGUID());
909
                                DoCast(target, SPELL_NECROTIC_PLAGUE);
910
                            }
911
                            events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, urand(30000, 33000), 0, PHASE_ONE);
912
                            break;
913
                        case EVENT_SHADOW_TRAP:
914
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
915
                                DoCast(target, SPELL_SHADOW_TRAP);
916
                            events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500, 0, PHASE_ONE);
917
                            break;
918
                        case EVENT_SOUL_REAPER:
919
                            DoCastVictim(SPELL_SOUL_REAPER);
920
                            events.ScheduleEvent(EVENT_SOUL_REAPER, urand(33000, 35000), 0, PHASE_TWO_THREE);
921
                            break;
922
                        case EVENT_DEFILE:
923
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_HARVEST_SOUL_VALKYR))
924
                            {
925
                                Talk(EMOTE_DEFILE_WARNING);
926
                                DoCast(target, SPELL_DEFILE);
927
                            }
928
                            events.ScheduleEvent(EVENT_DEFILE, urand(32000, 35000), 0, PHASE_TWO_THREE);
929
                            break;
930
                        case EVENT_HARVEST_SOUL:
931
                            Talk(SAY_LK_HARVEST_SOUL);
932
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SpellTargetSelector(me, SPELL_HARVEST_SOUL)))
933
                                DoCast(target, SPELL_HARVEST_SOUL);
934
                            events.ScheduleEvent(EVENT_HARVEST_SOUL, 75000, 0, PHASE_THREE);
935
                            break;
936
                        case EVENT_PAIN_AND_SUFFERING:
937
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
938
                                me->CastSpell(target, SPELL_PAIN_AND_SUFFERING, TRIGGERED_NONE);
939
                            events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, urand(1500, 4000), 0, PHASE_TRANSITION);
940
                            break;
941
                        case EVENT_SUMMON_ICE_SPHERE:
942
                            DoCastAOE(SPELL_SUMMON_ICE_SPHERE);
943
                            events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, urand(7500, 8500), 0, PHASE_TRANSITION);
944
                            break;
945
                        case EVENT_SUMMON_RAGING_SPIRIT:
946
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
947
                                me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE);
948
                            events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, urand(22000, 23000), 0, PHASE_TRANSITION);
949
                            break;
950
                        case EVENT_QUAKE:
951
                            events.SetPhase(PHASE_TWO);
952
                            me->ClearUnitState(UNIT_STAT_CASTING);  // clear state to ensure check in DoCastAOE passes
953
                            DoCastAOE(SPELL_QUAKE);
954
                            SendMusicToPlayers(MUSIC_SPECIAL);
955
                            Talk(SAY_LK_QUAKE);
956
                            break;
957
                        case EVENT_QUAKE_2:
958
                            events.SetPhase(PHASE_THREE);
959
                            me->ClearUnitState(UNIT_STAT_CASTING);  // clear state to ensure check in DoCastAOE passes
960
                            DoCastAOE(SPELL_QUAKE);
961
                            SendMusicToPlayers(MUSIC_SPECIAL);
962
                            Talk(SAY_LK_QUAKE);
963
                            break;
964
                        case EVENT_SUMMON_VALKYR:
965
                            SendMusicToPlayers(MUSIC_SPECIAL);
966
                            Talk(SAY_LK_SUMMON_VALKYR);
967
                            DoCastAOE(SUMMON_VALKYR);
968
                            events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 50000), 0, PHASE_TWO);
969
                            break;
970
                        case EVENT_START_ATTACK:
971
                            me->SetReactState(REACT_AGGRESSIVE);
972
                            if (events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE)
973
                                events.SetPhase(PHASE_THREE);
974
                            break;
975
                        case EVENT_VILE_SPIRITS:
976
                            SendMusicToPlayers(MUSIC_SPECIAL);
977
                            DoCastAOE(SPELL_VILE_SPIRITS);
978
                            events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE);
979
                            break;
980
                        case EVENT_WICKED_SPIRITS:
981
                            DoCastAOE(SPELL_VILE_SPIRITS);
982
                            events.ScheduleEvent(EVENT_WICKED_SPIRITS, urand(35000, 40000), 0, PHASE_FROSTMOURNE);
983
                            break;
984
                        case EVENT_HARVEST_SOULS:
985
                            Talk(SAY_LK_HARVEST_SOUL);
986
                            DoCastAOE(SPELL_HARVEST_SOULS);
987
                            events.ScheduleEvent(EVENT_HARVEST_SOULS, urand(100000, 110000), 0, PHASE_THREE);
988
                            events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading)
989
                            me->SetReactState(REACT_PASSIVE);
990
                            me->AttackStop();
991
                            events.ScheduleEvent(EVENT_WICKED_SPIRITS, events.GetNextEventTime(EVENT_VILE_SPIRITS) - events.GetTimer(), 0, PHASE_FROSTMOURNE);
992
                            events.DelayEvents(50000, EVENT_GROUP_VILE_SPIRITS);
993
                            events.RescheduleEvent(EVENT_DEFILE, 50000, 0, PHASE_THREE);
994
                            events.RescheduleEvent(EVENT_SOUL_REAPER, urand(57000, 62000), 0, PHASE_THREE);
995
                            events.ScheduleEvent(EVENT_START_ATTACK, 49000);
996
                            events.ScheduleEvent(EVENT_FROSTMOURNE_HEROIC, 6500);
997
                            break;
998
                        case EVENT_FROSTMOURNE_HEROIC:
999
                            if (TempSummon* terenas = me->GetMap()->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE_H, TerenasSpawnHeroic, NULL, 50000))
1000
                            {
1001
                                terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO);
1002
                                std::list<Creature*> triggers;
1003
                                GetCreatureListWithEntryInGrid(triggers, terenas, NPC_WORLD_TRIGGER_INFINITE_AOI, 100.0f);
1004
                                if (!triggers.empty())
1005
                                {
1006
                                    triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true));
1007
                                    Unit* spawner = triggers.front();
1008
                                    spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true);  // summons bombs randomly
1009
                                    spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true);  // summons bombs on players
1010
                                }
1011
1012
                                for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i)
1013
                                {
1014
                                    Creature* summon = ObjectAccessor::GetCreature(*me, *i);
1015
                                    if (summon && summon->GetEntry() == NPC_VILE_SPIRIT)
1016
                                        TeleportSpirit(summon);
1017
                                }
1018
                            }
1019
                            break;
1020
                        case EVENT_OUTRO_TALK_1:
1021
                            Talk(SAY_LK_OUTRO_1);
1022
                            DoCastAOE(SPELL_FURY_OF_FROSTMOURNE_NO_REZ, true);
1023
                            break;
1024
                        case EVENT_OUTRO_TALK_2:
1025
                            Talk(SAY_LK_OUTRO_2);
1026
                            DoCastAOE(SPELL_EMOTE_QUESTION_NO_SHEATH);
1027
                            break;
1028
                        case EVENT_OUTRO_EMOTE_TALK:
1029
                            me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NOSHEATHE);
1030
                            break;
1031
                        case EVENT_OUTRO_TALK_3:
1032
                            if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
1033
                                me->SetFacing(0.0f, tirion);
1034
                            Talk(SAY_LK_OUTRO_3);
1035
                            break;
1036
                        case EVENT_OUTRO_MOVE_CENTER:
1037
                            me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_1, CenterPosition);
1038
                            break;
1039
                        case EVENT_OUTRO_TALK_4:
1040
                            me->SetFacing(0.01745329f);
1041
                            Talk(SAY_LK_OUTRO_4);
1042
                            break;
1043
                        case EVENT_OUTRO_RAISE_DEAD:
1044
                            DoCastAOE(SPELL_RAISE_DEAD);
1045
                            me->ClearUnitState(UNIT_STAT_CASTING);
1046
                            SendMusicToPlayers(MUSIC_FINAL);
1047
                            break;
1048
                        case EVENT_OUTRO_TALK_5:
1049
                            Talk(SAY_LK_OUTRO_5);
1050
                            if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
1051
                                tirion->AI()->DoAction(ACTION_OUTRO);
1052
                            break;
1053
                        case EVENT_OUTRO_TALK_6:
1054
                            Talk(SAY_LK_OUTRO_6);
1055
                            if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
1056
                                tirion->SetFacing(0.0f, me);
1057
                            me->ClearUnitState(UNIT_STAT_CASTING);
1058
                            DoCastAOE(SPELL_SUMMON_BROKEN_FROSTMOURNE_3);
1059
                            SetEquipmentSlots(false, EQUIP_UNEQUIP);
1060
                            break;
1061
                        case EVENT_OUTRO_SOUL_BARRAGE:
1062
                            DoCastAOE(SPELL_SOUL_BARRAGE);
1063
                            sCreatureTextMgr->SendSound(me, SOUND_PAIN, CHAT_MSG_MONSTER_YELL, 0, TEXT_RANGE_NORMAL, TEAM_OTHER, false);
1064
                            // set flight
1065
                            me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
1066
                            me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x03);
1067
                            me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_2, OutroFlying);
1068
                            break;
1069
                        case EVENT_OUTRO_TALK_7:
1070
                            Talk(SAY_LK_OUTRO_7);
1071
                            break;
1072
                        case EVENT_OUTRO_TALK_8:
1073
                            Talk(SAY_LK_OUTRO_8);
1074
                            break;
1075
                        case EVENT_BERSERK:
1076
                            Talk(SAY_LK_BERSERK);
1077
                            DoCast(me, SPELL_BERSERK2);
1078
                            break;
1079
                        default:
1080
                            break;
1081
                    }
1082
                }
1083
1084
                DoMeleeAttackIfReady();
1085
            }
1086
1087
        private:
1088
1089
            void TeleportSpirit(Creature* summon)
1090
            {
1091
                float dist = me->GetObjectSize() + (15.0f - me->GetObjectSize()) * float(rand_norm());
1092
                float angle = float(rand_norm()) * float(2.0f * M_PI);
1093
                Position dest = TerenasSpawnHeroic;
1094
                me->MovePosition(dest, dist, angle);
1095
                dest.m_positionZ += 15.0f;
1096
                summon->UpdateEntry(NPC_WICKED_SPIRIT);
1097
                summon->SetReactState(REACT_PASSIVE);
1098
                summon->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation());
1099
                summon->SetSpeed(MOVE_FLIGHT, 0.5f);
1100
                summon->m_Events.KillAllEvents(true);
1101
                summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(1000));
1102
            }
1103
1104
            void SendMusicToPlayers(uint32 musicId) const
1105
            {
1106
                WorldPacket data(SMSG_PLAY_MUSIC, 4);
1107
                data << uint32(musicId);
1108
                SendPacketToPlayers(&data);
1109
            }
1110
1111
            void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const
1112
            {
1113
                WorldPacket data(SMSG_OVERRIDE_LIGHT, 12);
1114
                data << uint32(2488);       // Light.dbc entry (map default)
1115
                data << uint32(overrideId); // Light.dbc entry (override)
1116
                data << uint32(fadeInTime);
1117
                SendPacketToPlayers(&data);
1118
            }
1119
1120
            void SendWeather(WeatherState weather) const
1121
            {
1122
                WorldPacket data(SMSG_WEATHER, 9);
1123
                data << uint32(weather);
1124
                data << float(0.5f);
1125
                data << uint8(0);
1126
                SendPacketToPlayers(&data);
1127
            }
1128
1129
            // Send packet to all players in The Frozen Throne
1130
            void SendPacketToPlayers(WorldPacket const* data) const
1131
            {
1132
                Map::PlayerList const& players = me->GetMap()->GetPlayers();
1133
                if (!players.isEmpty())
1134
                    for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
1135
                        if (Player* player = itr->getSource())
1136
                            if (player->GetAreaId() == AREA_THE_FROZEN_THRONE)
1137
                                player->GetSession()->SendPacket(data);
1138
            }
1139
1140
            uint32 _necroticPlagueStack;
1141
            uint32 _vileSpiritExplosions;
1142
        };
1143
1144
        CreatureAI* GetAI(Creature* creature) const
1145
        {
1146
            return GetIcecrownCitadelAI<boss_the_lich_kingAI>(creature);
1147
        }
1148
};
1149
1150
class npc_tirion_fordring_tft : public CreatureScript
1151
{
1152
    public:
1153
        npc_tirion_fordring_tft() : CreatureScript("npc_tirion_fordring_tft") { }
1154
1155
        struct npc_tirion_fordringAI : public ScriptedAI
1156
        {
1157
            npc_tirion_fordringAI(Creature* creature) : ScriptedAI(creature),
1158
                _instance(creature->GetInstanceScript())
1159
            {
1160
            }
1161
1162
            void Reset()
1163
            {
1164
                _events.Reset();
1165
                if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE)
1166
                    me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
1167
            }
1168
1169
            void MovementInform(uint32 type, uint32 id)
1170
            {
1171
                if (type != POINT_MOTION_TYPE)
1172
                    return;
1173
1174
                switch (id)
1175
                {
1176
                    case POINT_TIRION_INTRO:
1177
                        me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
1178
                        if (Creature* theLichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1179
                            theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER);
1180
                        break;
1181
                    case POINT_TIRION_OUTRO_1:
1182
                        _events.ScheduleEvent(EVENT_OUTRO_JUMP, 1, 0, PHASE_OUTRO);
1183
                        break;
1184
                }
1185
            }
1186
1187
            void DoAction(int32 const action)
1188
            {
1189
                switch (action)
1190
                {
1191
                    case ACTION_CONTINUE_INTRO:
1192
                        Talk(SAY_TIRION_INTRO_1);
1193
                        _events.ScheduleEvent(EVENT_INTRO_TALK_1, 34000, 0, PHASE_INTRO);
1194
                        break;
1195
                    case ACTION_OUTRO:
1196
                        _events.SetPhase(PHASE_OUTRO);
1197
                        _events.ScheduleEvent(EVENT_OUTRO_TALK_1, 7000, 0, PHASE_OUTRO);
1198
                        _events.ScheduleEvent(EVENT_OUTRO_BLESS, 18000, 0, PHASE_OUTRO);
1199
                        _events.ScheduleEvent(EVENT_OUTRO_REMOVE_ICE, 23000, 0, PHASE_OUTRO);
1200
                        _events.ScheduleEvent(EVENT_OUTRO_MOVE_1, 25000, 0, PHASE_OUTRO);
1201
                        break;
1202
                }
1203
            }
1204
1205
            void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
1206
            {
1207
                if (spell->Id == SPELL_ICE_LOCK)
1208
                    me->SetFacing(3.085098f);
1209
                else if (spell->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
1210
                    SetEquipmentSlots(true);    // remove glow on ashbringer
1211
            }
1212
1213
            void sGossipSelect(Player* /*player*/, uint32 sender, uint32 action)
1214
            {
1215
                if (me->GetCreatureInfo()->GossipMenuId == sender && !action)
1216
                {
1217
                    _events.SetPhase(PHASE_INTRO);
1218
                    me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
1219
                    me->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
1220
                    me->GetMotionMaster()->MovePoint(POINT_TIRION_INTRO, TirionIntro);
1221
                }
1222
            }
1223
1224
            void JustReachedHome()
1225
            {
1226
                me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
1227
1228
                if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE)
1229
                    return;
1230
1231
                me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
1232
            }
1233
1234
            void UpdateAI(uint32 const diff)
1235
            {
1236
                if (!UpdateVictim() && !(_events.GetPhaseMask() & (PHASE_MASK_INTRO | PHASE_MASK_OUTRO)))
1237
                    return;
1238
1239
                _events.Update(diff);
1240
1241
                if (me->HasUnitState(UNIT_STAT_CASTING))
1242
                    return;
1243
1244
                while (uint32 eventId = _events.ExecuteEvent())
1245
                {
1246
                    switch (eventId)
1247
                    {
1248
                        case EVENT_INTRO_TALK_1:
1249
                            Talk(SAY_TIRION_INTRO_2);
1250
                            _events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 2000, 0, PHASE_INTRO);
1251
                            _events.ScheduleEvent(EVENT_INTRO_CHARGE, 5000, 0, PHASE_INTRO);
1252
                            break;
1253
                        case EVENT_INTRO_EMOTE_1:
1254
                            me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NOSHEATHE);
1255
                            break;
1256
                        case EVENT_INTRO_CHARGE:
1257
                            me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
1258
                            me->GetMotionMaster()->MovePoint(POINT_TIRION_CHARGE, TirionCharge);
1259
                            break;
1260
                        case EVENT_OUTRO_TALK_1:
1261
                            Talk(SAY_TIRION_OUTRO_1);
1262
                            break;
1263
                        case EVENT_OUTRO_BLESS:
1264
                            DoCast(me, SPELL_LIGHTS_BLESSING);
1265
                            break;
1266
                        case EVENT_OUTRO_REMOVE_ICE:
1267
                            me->RemoveAurasDueToSpell(SPELL_ICE_LOCK);
1268
                            SetEquipmentSlots(false, EQUIP_ASHBRINGER_GLOWING);
1269
                            if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1270
                            {
1271
                                me->SetFacing(0.0f, lichKing);
1272
                                lichKing->AI()->DoAction(ACTION_PLAY_MUSIC);
1273
                            }
1274
                            break;
1275
                        case EVENT_OUTRO_MOVE_1:
1276
                            me->GetMotionMaster()->MovePoint(POINT_TIRION_OUTRO_1, OutroPosition1);
1277
                            break;
1278
                        case EVENT_OUTRO_JUMP:
1279
                            DoCastAOE(SPELL_JUMP);
1280
                            break;
1281
                        default:
1282
                            break;
1283
                    }
1284
                }
1285
1286
                DoMeleeAttackIfReady();
1287
            }
1288
1289
        private:
1290
            EventMap _events;
1291
            InstanceScript* _instance;
1292
        };
1293
1294
        CreatureAI* GetAI(Creature* creature) const
1295
        {
1296
            return GetIcecrownCitadelAI<npc_tirion_fordringAI>(creature);
1297
        }
1298
};
1299
1300
class npc_shambling_horror_icc : public CreatureScript
1301
{
1302
    public:
1303
        npc_shambling_horror_icc() :  CreatureScript("npc_shambling_horror_icc") { }
1304
1305
        struct npc_shambling_horror_iccAI : public ScriptedAI
1306
        {
1307
            npc_shambling_horror_iccAI(Creature* creature) : ScriptedAI(creature)
1308
            {
1309
                _frenzied = false;
1310
            }
1311
1312
            void Reset()
1313
            {
1314
                _events.Reset();
1315
                _events.ScheduleEvent(EVENT_SHOCKWAVE, urand(20000, 25000));
1316
                _events.ScheduleEvent(EVENT_ENRAGE, urand(11000, 14000));
1317
            }
1318
1319
            void DamageTaken(Unit* /*attacker*/, uint32& damage)
1320
            {
1321
                if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage))
1322
                {
1323
                    _frenzied = true;
1324
                    DoCast(me, SPELL_FRENZY, true);
1325
                }
1326
            }
1327
1328
            void UpdateAI(uint32 const diff)
1329
            {
1330
                if (!UpdateVictim())
1331
                    return;
1332
1333
                _events.Update(diff);
1334
1335
                if (me->HasUnitState(UNIT_STAT_CASTING))
1336
                    return;
1337
1338
                while (uint32 eventId = _events.ExecuteEvent())
1339
                {
1340
                    switch (eventId)
1341
                    {
1342
                        case EVENT_SHOCKWAVE:
1343
                            DoCast(me, SPELL_SHOCKWAVE);
1344
                            _events.ScheduleEvent(EVENT_SHOCKWAVE, urand(20000, 25000));
1345
                            break;
1346
                        case EVENT_ENRAGE:
1347
                            DoCast(me, SPELL_ENRAGE);
1348
                            _events.ScheduleEvent(EVENT_ENRAGE, urand(20000, 25000));
1349
                            break;
1350
                        default:
1351
                            break;
1352
                    }
1353
                }
1354
1355
                DoMeleeAttackIfReady();
1356
            }
1357
1358
        private:
1359
            EventMap _events;
1360
            bool _frenzied;
1361
        };
1362
1363
        CreatureAI* GetAI(Creature* creature) const
1364
        {
1365
            return GetIcecrownCitadelAI<npc_shambling_horror_iccAI>(creature);
1366
        }
1367
};
1368
1369
class npc_raging_spirit : public CreatureScript
1370
{
1371
    public:
1372
        npc_raging_spirit() : CreatureScript("npc_raging_spirit") { }
1373
1374
        struct npc_raging_spiritAI : public ScriptedAI
1375
        {
1376
            npc_raging_spiritAI(Creature* creature) : ScriptedAI(creature),
1377
                _instance(creature->GetInstanceScript())
1378
            {
1379
            }
1380
1381
            void Reset()
1382
            {
1383
                _events.Reset();
1384
                _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000));
1385
                DoCast(me, SPELL_PLAGUE_AVOIDANCE, true);
1386
                DoCast(me, SPELL_RAGING_SPIRIT_VISUAL, true);
1387
                if (TempSummon* summon = me->ToTempSummon())
1388
                    if (Unit* summoner = summon->GetSummoner())
1389
                        summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true);
1390
                DoCast(me, SPELL_BOSS_HITTIN_YA, true);
1391
            }
1392
1393
            void IsSummonedBy(Unit* /*summoner*/)
1394
            {
1395
                // player is the spellcaster so register summon manually
1396
                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1397
                    lichKing->AI()->JustSummoned(me);
1398
            }
1399
1400
            void JustDied(Unit* /*killer*/)
1401
            {
1402
                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1403
                    lichKing->AI()->SummonedCreatureDespawn(me);
1404
                if (TempSummon* summon = me->ToTempSummon())
1405
                    summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN);
1406
            }
1407
1408
            void UpdateAI(uint32 const diff)
1409
            {
1410
                if (!UpdateVictim())
1411
                    return;
1412
1413
                _events.Update(diff);
1414
1415
                if (me->HasUnitState(UNIT_STAT_CASTING))
1416
                    return;
1417
1418
                while (uint32 eventId = _events.ExecuteEvent())
1419
                {
1420
                    switch (eventId)
1421
                    {
1422
                        case EVENT_SOUL_SHRIEK:
1423
                            DoCastAOE(SPELL_SOUL_SHRIEK);
1424
                            _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000));
1425
                            break;
1426
                        default:
1427
                            break;
1428
                    }
1429
                }
1430
1431
                DoMeleeAttackIfReady();
1432
            }
1433
1434
        private:
1435
            EventMap _events;
1436
            InstanceScript* _instance;
1437
        };
1438
1439
        CreatureAI* GetAI(Creature* creature) const
1440
        {
1441
            return GetIcecrownCitadelAI<npc_raging_spiritAI>(creature);
1442
        }
1443
};
1444
1445
class npc_valkyr_shadowguard : public CreatureScript
1446
{
1447
    public:
1448
        npc_valkyr_shadowguard() : CreatureScript("npc_valkyr_shadowguard") { }
1449
1450
        struct npc_valkyr_shadowguardAI : public ScriptedAI
1451
        {
1452
            npc_valkyr_shadowguardAI(Creature* creature) : ScriptedAI(creature),
1453
                _grabbedPlayer(0), _instance(creature->GetInstanceScript())
1454
            {
1455
            }
1456
1457
            void Reset()
1458
            {
1459
                _events.Reset();
1460
                me->SetReactState(REACT_PASSIVE);
1461
                DoCast(me, SPELL_WINGS_OF_THE_DAMNED, false);
1462
                me->SetSpeed(MOVE_FLIGHT, 0.642857f, true);
1463
            }
1464
1465
            void IsSummonedBy(Unit* /*summoner*/)
1466
            {
1467
                _events.Reset();
1468
                _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2500);
1469
            }
1470
1471
            void DamageTaken(Unit* /*attacker*/, uint32& damage)
1472
            {
1473
                if (!IsHeroic())
1474
                    return;
1475
1476
                if (!me->HasAuraType(SPELL_AURA_CONTROL_VEHICLE))
1477
                    return;
1478
1479
                if (me->HealthBelowPctDamaged(50, damage))
1480
                {
1481
                    _events.Reset();
1482
                    DoCastAOE(SPELL_EJECT_ALL_PASSENGERS);
1483
                    me->GetMotionMaster()->MoveTargetedHome();
1484
                    me->ClearUnitState(UNIT_STAT_EVADE);
1485
                }
1486
            }
1487
1488
            void JustReachedHome()
1489
            {
1490
                // schedule siphon life event (heroic only)
1491
                DoZoneInCombat();
1492
                _events.Reset();
1493
                _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2000);
1494
            }
1495
1496
            void AttackStart(Unit* /*target*/)
1497
            {
1498
            }
1499
1500
            void MovementInform(uint32 type, uint32 id)
1501
            {
1502
                if (type != POINT_MOTION_TYPE)
1503
                    return;
1504
1505
                switch (id)
1506
                {
1507
                    case POINT_DROP_PLAYER:
1508
                        DoCastAOE(SPELL_EJECT_ALL_PASSENGERS);
1509
                        me->DespawnOrUnsummon(1000);
1510
                        break;
1511
                    case POINT_CHARGE:
1512
                        if (Player* target = ObjectAccessor::GetPlayer(*me, _grabbedPlayer))
1513
                        {
1514
                            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
1515
                            if (GameObject* platform = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_ARTHAS_PLATFORM)))
1516
                            {
1517
                                std::list<Creature*> triggers;
1518
                                GetCreatureListWithEntryInGrid(triggers, me, NPC_WORLD_TRIGGER, 150.0f);
1519
                                triggers.remove_if(HeightDifferenceCheck(platform, 5.0f, true));
1520
                                if (triggers.empty())
1521
                                    return;
1522
1523
                                triggers.sort(Trinity::ObjectDistanceOrderPred(me));
1524
                                DoCast(target, SPELL_VALKYR_CARRY);
1525
                                _dropPoint.Relocate(triggers.front());
1526
                                _events.ScheduleEvent(EVENT_MOVE_TO_DROP_POS, 1500);
1527
1528
                            }
1529
                        }
1530
                        else
1531
                            me->DespawnOrUnsummon();
1532
                        break;
1533
                    default:
1534
                        break;
1535
                }
1536
            }
1537
1538
            void SetGUID(uint64 guid, int32 /* = 0*/)
1539
            {
1540
                _grabbedPlayer = guid;
1541
            }
1542
1543
            void UpdateAI(uint32 const diff)
1544
            {
1545
                if (!UpdateVictim())
1546
                    return;
1547
1548
                _events.Update(diff);
1549
1550
                if (me->HasUnitState(UNIT_STAT_CASTING))
1551
                    return;
1552
1553
                while (uint32 eventId = _events.ExecuteEvent())
1554
                {
1555
                    switch (eventId)
1556
                    {
1557
                        case EVENT_GRAB_PLAYER:
1558
                            if (!_grabbedPlayer)
1559
                            {
1560
                                DoCastAOE(SPELL_VALKYR_TARGET_SEARCH);
1561
                                _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2000);
1562
                            }
1563
                            break;
1564
                        case EVENT_MOVE_TO_DROP_POS:
1565
                            me->GetMotionMaster()->MovePoint(POINT_DROP_PLAYER, _dropPoint);
1566
                            break;
1567
                        case EVENT_LIFE_SIPHON:
1568
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
1569
                                DoCast(target, SPELL_LIFE_SIPHON);
1570
                            _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2500);
1571
                            break;
1572
                        default:
1573
                            break;
1574
                    }
1575
                }
1576
1577
                // no melee attacks
1578
            }
1579
1580
        private:
1581
            EventMap _events;
1582
            Position _dropPoint;
1583
            uint64 _grabbedPlayer;
1584
            InstanceScript* _instance;
1585
        };
1586
1587
        CreatureAI* GetAI(Creature* creature) const
1588
        {
1589
            return GetIcecrownCitadelAI<npc_valkyr_shadowguardAI>(creature);
1590
        }
1591
};
1592
1593
class npc_strangulate_vehicle : public CreatureScript
1594
{
1595
    public:
1596
        npc_strangulate_vehicle() : CreatureScript("npc_strangulate_vehicle") { }
1597
1598
        struct npc_strangulate_vehicleAI : public ScriptedAI
1599
        {
1600
            npc_strangulate_vehicleAI(Creature* creature) : ScriptedAI(creature),
1601
                _instance(creature->GetInstanceScript())
1602
            {
1603
            }
1604
1605
            void IsSummonedBy(Unit* summoner)
1606
            {
1607
                me->SetFacing(0.0f, summoner);
1608
                DoCast(summoner, SPELL_HARVEST_SOUL_VEHICLE);
1609
                _events.Reset();
1610
                _events.ScheduleEvent(EVENT_MOVE_TO_LICH_KING, 2000);
1611
                _events.ScheduleEvent(EVENT_TELEPORT, 6000);
1612
1613
                // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back
1614
                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1615
                    lichKing->AI()->JustSummoned(me);
1616
            }
1617
1618
            void DoAction(int32 const action)
1619
            {
1620
                if (action != ACTION_TELEPORT_BACK)
1621
                    return;
1622
1623
                if (TempSummon* summ = me->ToTempSummon())
1624
                    if (Unit* summoner = summ->GetSummoner())
1625
                        DoCast(summoner, SPELL_HARVEST_SOUL_TELEPORT_BACK);
1626
1627
                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1628
                    lichKing->AI()->SummonedCreatureDespawn(me);
1629
            }
1630
1631
            void UpdateAI(uint32 const diff)
1632
            {
1633
                UpdateVictim();
1634
1635
                _events.Update(diff);
1636
1637
                while (uint32 eventId = _events.ExecuteEvent())
1638
                {
1639
                    switch (eventId)
1640
                    {
1641
                        case EVENT_TELEPORT:
1642
                            me->GetMotionMaster()->Clear(false);
1643
                            me->GetMotionMaster()->MoveIdle();
1644
                            if (TempSummon* summ = me->ToTempSummon())
1645
                            {
1646
                                if (Unit* summoner = summ->GetSummoner())
1647
                                {
1648
                                    summoner->CastSpell((Unit*)NULL, SPELL_HARVEST_SOUL_VISUAL, true);
1649
                                    summoner->ExitVehicle(summoner);
1650
                                    if (!IsHeroic())
1651
                                        summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true);
1652
                                    else
1653
                                    {
1654
                                        summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true);
1655
                                        summoner->RemoveAurasDueToSpell(HARVEST_SOUL, 0, 0, AURA_REMOVE_BY_EXPIRE);
1656
                                    }
1657
                                }
1658
                            }
1659
1660
                            _events.ScheduleEvent(EVENT_DESPAWN_SELF, 65000);
1661
                            break;
1662
                        case EVENT_MOVE_TO_LICH_KING:
1663
                            if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1664
                            {
1665
                                if (me->GetExactDist(lichKing) > 10.0f)
1666
                                {
1667
                                    Position pos;
1668
                                    lichKing->GetNearPosition(pos, float(rand_norm()) * 5.0f  + 7.5f, lichKing->GetAngle(me));
1669
                                    me->GetMotionMaster()->MovePoint(0, pos);
1670
                                }
1671
                            }
1672
                            break;
1673
                        case EVENT_DESPAWN_SELF:
1674
                            if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1675
                                lichKing->AI()->SummonedCreatureDespawn(me);
1676
                            me->DespawnOrUnsummon(1);
1677
                            break;
1678
                        default:
1679
                            break;
1680
                    }
1681
                }
1682
            }
1683
1684
        private:
1685
            EventMap _events;
1686
            InstanceScript* _instance;
1687
        };
1688
1689
        CreatureAI* GetAI(Creature* creature) const
1690
        {
1691
            return GetIcecrownCitadelAI<npc_strangulate_vehicleAI>(creature);
1692
        }
1693
};
1694
1695
class npc_terenas_menethil : public CreatureScript
1696
{
1697
    public:
1698
        npc_terenas_menethil() : CreatureScript("npc_terenas_menethil") { }
1699
1700
        struct npc_terenas_menethilAI : public ScriptedAI
1701
        {
1702
            npc_terenas_menethilAI(Creature* creature) : ScriptedAI(creature),
1703
                _instance(creature->GetInstanceScript())
1704
            {
1705
            }
1706
1707
            bool CanAIAttack(Unit const* target) const
1708
            {
1709
                return target->GetEntry() != NPC_THE_LICH_KING;
1710
            }
1711
1712
            void DoAction(int32 const action)
1713
            {
1714
                switch (action)
1715
                {
1716
                    case ACTION_FROSTMOURNE_INTRO:
1717
                        me->setActive(true);
1718
                        if (!IsHeroic())
1719
                            me->SetHealth(me->GetMaxHealth() / 2);
1720
                        DoCast(me, SPELL_LIGHTS_FAVOR);
1721
                        _events.Reset();
1722
                        _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_1, 2000, PHASE_FROSTMOURNE);
1723
                        _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_2, 11000, PHASE_FROSTMOURNE);
1724
                        if (!IsHeroic())
1725
                        {
1726
                            _events.ScheduleEvent(EVENT_DESTROY_SOUL, 60000, PHASE_FROSTMOURNE);
1727
                            _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_3, 25000);
1728
                        }
1729
                        break;
1730
                    case ACTION_TELEPORT_BACK:
1731
                        me->CastSpell((Unit*)NULL, SPELL_RESTORE_SOUL, TRIGGERED_NONE);
1732
                        me->DespawnOrUnsummon(3000);
1733
                        break;
1734
                    default:
1735
                        break;
1736
                }
1737
            }
1738
1739
            void EnterEvadeMode()
1740
            {
1741
                // no running back home
1742
                if (!me->isAlive())
1743
                    return;
1744
1745
                me->DeleteThreatList();
1746
                me->CombatStop(false);
1747
            }
1748
1749
            void DamageTaken(Unit* /*attacker*/, uint32& damage)
1750
            {
1751
                if (damage >= me->GetHealth())
1752
                {
1753
                    damage = me->GetHealth() - 1;
1754
                    if (!me->HasAura(SPELL_TERENAS_LOSES_INSIDE) && !IsHeroic())
1755
                    {
1756
                        me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
1757
                        DoCast(SPELL_TERENAS_LOSES_INSIDE);
1758
                        _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1000);
1759
                        if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1760
                        {
1761
                            warden->CastSpell((Unit*)NULL, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1762
                            warden->DespawnOrUnsummon(2000);
1763
                        }
1764
1765
                        me->DespawnOrUnsummon(2000);
1766
                    }
1767
                }
1768
            }
1769
1770
            void IsSummonedBy(Unit* /*summoner*/)
1771
            {
1772
                _events.Reset();
1773
                _events.SetPhase(PHASE_OUTRO);
1774
                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1775
                    me->SetFacing(0.0f, lichKing);
1776
1777
                _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_1, 2000, 0, PHASE_OUTRO);
1778
                _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_2, 14000, 0, PHASE_OUTRO);
1779
            }
1780
1781
            void UpdateAI(uint32 const diff)
1782
            {
1783
                UpdateVictim();
1784
1785
                _events.Update(diff);
1786
1787
                while (uint32 eventId = _events.ExecuteEvent())
1788
                {
1789
                    switch (eventId)
1790
                    {
1791
                        case EVENT_FROSTMOURNE_TALK_1:
1792
                            Talk(SAY_TERENAS_INTRO_1);
1793
                            if (IsHeroic())
1794
                                DoCastAOE(SPELL_RESTORE_SOULS);
1795
                            break;
1796
                        case EVENT_FROSTMOURNE_TALK_2:
1797
                            Talk(SAY_TERENAS_INTRO_2);
1798
                            break;
1799
                        case EVENT_FROSTMOURNE_TALK_3:
1800
                            Talk(SAY_TERENAS_INTRO_3);
1801
                            break;
1802
                        case EVENT_OUTRO_TERENAS_TALK_1:
1803
                            Talk(SAY_TERENAS_OUTRO_1);
1804
                            break;
1805
                        case EVENT_OUTRO_TERENAS_TALK_2:
1806
                            Talk(SAY_TERENAS_OUTRO_2);
1807
                            DoCastAOE(SPELL_MASS_RESURRECTION);
1808
                            if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1809
                            {
1810
                                lichKing->AI()->DoAction(ACTION_FINISH_OUTRO);
1811
                                lichKing->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
1812
                                if (Creature* tirion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HIGHLORD_TIRION_FORDRING)))
1813
                                    tirion->AI()->AttackStart(lichKing);
1814
                            }
1815
                            break;
1816
                        case EVENT_DESTROY_SOUL:
1817
                            me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
1818
                            if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f))
1819
                                warden->CastSpell((Unit*)NULL, SPELL_DESTROY_SOUL, TRIGGERED_NONE);
1820
                            DoCast(SPELL_TERENAS_LOSES_INSIDE);
1821
                            _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1000);
1822
                            break;
1823
                        case EVENT_TELEPORT_BACK:
1824
                            if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING)))
1825
                                lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
1826
                            break;
1827
                        default:
1828
                            break;
1829
                    }
1830
                }
1831
1832
                // fighting Spirit Warden
1833
                if (me->isInCombat())
1834
                    DoMeleeAttackIfReady();
1835
            }
1836
1837
        private:
1838
            EventMap _events;
1839
            InstanceScript* _instance;
1840
        };
1841
1842
        CreatureAI* GetAI(Creature* creature) const
1843
        {
1844
            return GetIcecrownCitadelAI<npc_terenas_menethilAI>(creature);
1845
        }
1846
};
1847
1848
class npc_spirit_warden : public CreatureScript
1849
{
1850
    public:
1851
        npc_spirit_warden() : CreatureScript("npc_spirit_warden") { }
1852
1853
        struct npc_spirit_wardenAI : public ScriptedAI
1854
        {
1855
            npc_spirit_wardenAI(Creature* creature) : ScriptedAI(creature),
1856
                _instance(creature->GetInstanceScript())
1857
            {
1858
            }
1859
1860
            void Reset()
1861
            {
1862
                _events.Reset();
1863
                _events.ScheduleEvent(EVENT_SOUL_RIP, urand(12000, 15000));
1864
                DoCast(SPELL_DARK_HUNGER);
1865
            }
1866
1867
            void JustDied(Unit* /*killer*/)
1868
            {
1869
                if (Creature* terenas = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_TERENAS_MENETHIL)))
1870
                    terenas->AI()->DoAction(ACTION_TELEPORT_BACK);
1871
            }
1872
1873
            void UpdateAI(uint32 const diff)
1874
            {
1875
                if (!UpdateVictim())
1876
                    return;
1877
1878
                _events.Update(diff);
1879
1880
                while (uint32 eventId = _events.ExecuteEvent())
1881
                {
1882
                    switch (eventId)
1883
                    {
1884
                        case EVENT_SOUL_RIP:
1885
                            DoCastVictim(SPELL_SOUL_RIP);
1886
                            _events.ScheduleEvent(EVENT_SOUL_RIP, urand(23000, 27000));
1887
                            break;
1888
                        default:
1889
                            break;
1890
                    }
1891
                }
1892
1893
                DoMeleeAttackIfReady();
1894
            }
1895
1896
        private:
1897
            EventMap _events;
1898
            InstanceScript* _instance;
1899
        };
1900
1901
        CreatureAI* GetAI(Creature* creature) const
1902
        {
1903
            return GetIcecrownCitadelAI<npc_spirit_wardenAI>(creature);
1904
        }
1905
};
1906
1907
class npc_spirit_bomb : public CreatureScript
1908
{
1909
    public:
1910
        npc_spirit_bomb() : CreatureScript("npc_spirit_bomb") { }
1911
1912
        struct npc_spirit_bombAI : public CreatureAI
1913
        {
1914
            npc_spirit_bombAI(Creature* creature) : CreatureAI(creature)
1915
            {
1916
            }
1917
1918
            void IsSummonedBy(Unit* /*summoner*/)
1919
            {
1920
                float destX, destY, destZ;
1921
                me->GetPosition(destX, destY);
1922
                destZ = 1055.0f;    // approximation, gets more precise later
1923
                me->UpdateGroundPositionZ(destX, destY, destZ);
1924
                me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ);
1925
            }
1926
1927
            void MovementInform(uint32 type, uint32 point)
1928
            {
1929
                if (type != POINT_MOTION_TYPE || point != POINT_GROUND)
1930
                    return;
1931
1932
                me->RemoveAllAuras();
1933
                DoCastAOE(SPELL_EXPLOSION);
1934
                me->DespawnOrUnsummon(1000);
1935
            }
1936
1937
            void AttackStart(Unit* /*victim*/)
1938
            {
1939
            }
1940
1941
            void UpdateAI(uint32 const /*diff*/)
1942
            {
1943
                UpdateVictim();
1944
                // no melee attacks
1945
            }
1946
        };
1947
1948
        CreatureAI* GetAI(Creature* creature) const
1949
        {
1950
            return GetIcecrownCitadelAI<npc_spirit_bombAI>(creature);
1951
        }
1952
};
1953
1954
class npc_broken_frostmourne : public CreatureScript
1955
{
1956
    public:
1957
        npc_broken_frostmourne() : CreatureScript("npc_broken_frostmourne") { }
1958
1959
        struct npc_broken_frostmourneAI : public CreatureAI
1960
        {
1961
            npc_broken_frostmourneAI(Creature* creature) : CreatureAI(creature)
1962
            {
1963
            }
1964
1965
            void Reset()
1966
            {
1967
                _events.Reset();
1968
            }
1969
1970
            void IsSummonedBy(Unit* /*summoner*/)
1971
            {
1972
                _events.SetPhase(PHASE_OUTRO);
1973
                _events.ScheduleEvent(EVENT_OUTRO_KNOCK_BACK, 3000, 0, PHASE_OUTRO);
1974
            }
1975
1976
            void DoAction(int32 const action)
1977
            {
1978
                if (action == ACTION_SUMMON_TERENAS)
1979
                    _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6000, 0, PHASE_OUTRO);
1980
            }
1981
1982
            void UpdateAI(uint32 const diff)
1983
            {
1984
                UpdateVictim();
1985
1986
                _events.Update(diff);
1987
1988
                while (uint32 eventId = _events.ExecuteEvent())
1989
                {
1990
                    switch (eventId)
1991
                    {
1992
                        case EVENT_OUTRO_KNOCK_BACK:
1993
                            DoCastAOE(SPELL_BROKEN_FROSTMOURNE_KNOCK);
1994
                            break;
1995
                        case EVENT_OUTRO_SUMMON_TERENAS:
1996
                            DoCastAOE(SPELL_SUMMON_TERENAS);
1997
                            break;
1998
                        default:
1999
                            break;
2000
                    }
2001
                }
2002
2003
                // no melee attacks
2004
            }
2005
2006
        private:
2007
            EventMap _events;
2008
        };
2009
2010
        CreatureAI* GetAI(Creature* creature) const
2011
        {
2012
            return GetIcecrownCitadelAI<npc_broken_frostmourneAI>(creature);
2013
        }
2014
};
2015
2016
class spell_the_lich_king_infest : public SpellScriptLoader
2017
{
2018
    public:
2019
        spell_the_lich_king_infest() :  SpellScriptLoader("spell_the_lich_king_infest") { }
2020
2021
        class spell_the_lich_king_infest_AuraScript : public AuraScript
2022
        {
2023
            PrepareAuraScript(spell_the_lich_king_infest_AuraScript);
2024
2025
            void OnPeriodic(AuraEffect const* /*aurEff*/)
2026
            {
2027
                if (GetUnitOwner()->HealthAbovePct(90))
2028
                {
2029
                    PreventDefaultAction();
2030
                    Remove(AURA_REMOVE_BY_ENEMY_SPELL);
2031
                }
2032
            }
2033
2034
            void OnUpdate(AuraEffect* aurEff)
2035
            {
2036
                // multiply, starting from 2nd tick
2037
                if (aurEff->GetTickNumber() == 1)
2038
                    return;
2039
2040
                aurEff->SetAmount(int32(aurEff->GetAmount() * 1.15f));
2041
            }
2042
2043
            void Register()
2044
            {
2045
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_infest_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
2046
                OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_the_lich_king_infest_AuraScript::OnUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
2047
            }
2048
        };
2049
2050
        AuraScript* GetAuraScript() const
2051
        {
2052
            return new spell_the_lich_king_infest_AuraScript();
2053
        }
2054
};
2055
2056
class spell_the_lich_king_necrotic_plague : public SpellScriptLoader
2057
{
2058
    public:
2059
        spell_the_lich_king_necrotic_plague() :  SpellScriptLoader("spell_the_lich_king_necrotic_plague") { }
2060
2061
        class spell_the_lich_king_necrotic_plague_AuraScript : public AuraScript
2062
        {
2063
            PrepareAuraScript(spell_the_lich_king_necrotic_plague_AuraScript);
2064
2065
            bool Validate(SpellInfo const* /*spell*/)
2066
            {
2067
                if (!sSpellMgr->GetSpellInfo(SPELL_NECROTIC_PLAGUE_JUMP))
2068
                    return false;
2069
                return true;
2070
            }
2071
2072
            void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2073
            {
2074
                switch (GetTargetApplication()->GetRemoveMode())
2075
                {
2076
                    case AURA_REMOVE_BY_ENEMY_SPELL:
2077
                    case AURA_REMOVE_BY_EXPIRE:
2078
                    case AURA_REMOVE_BY_DEATH:
2079
                        break;
2080
                    default:
2081
                        return;
2082
                }
2083
2084
                CustomSpellValues values;
2085
                //values.AddSpellMod(SPELLVALUE_AURA_STACK, 2);
2086
                values.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1);
2087
                GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID());
2088
                if (Unit* caster = GetCaster())
2089
                    caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2090
            }
2091
2092
            void Register()
2093
            {
2094
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
2095
            }
2096
        };
2097
2098
        AuraScript* GetAuraScript() const
2099
        {
2100
            return new spell_the_lich_king_necrotic_plague_AuraScript();
2101
        }
2102
};
2103
2104
class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader
2105
{
2106
    public:
2107
        spell_the_lich_king_necrotic_plague_jump() :  SpellScriptLoader("spell_the_lich_king_necrotic_plague_jump") { }
2108
2109
        class spell_the_lich_king_necrotic_plague_SpellScript : public SpellScript
2110
        {
2111
            PrepareSpellScript(spell_the_lich_king_necrotic_plague_SpellScript);
2112
2113
            bool Load()
2114
            {
2115
                _hadAura = false;
2116
                return true;
2117
            }
2118
2119
            void SelectTarget(std::list<Unit*>& targets)
2120
            {
2121
                targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
2122
                if (targets.size() < 2)
2123
                    return;
2124
2125
                targets.resize(1);
2126
            }
2127
2128
            void CheckAura()
2129
            {
2130
                if (GetHitUnit()->HasAura(GetSpellInfo()->Id))
2131
                    _hadAura = true;
2132
            }
2133
2134
            void AddMissingStack()
2135
            {
2136
                if (GetHitAura() && !_hadAura && GetSpellValue()->EffectBasePoints[EFFECT_1] != AURA_REMOVE_BY_ENEMY_SPELL)
2137
                    GetHitAura()->ModStackAmount(1);
2138
            }
2139
2140
            void Register()
2141
            {
2142
                BeforeHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura);
2143
                OnHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::AddMissingStack);
2144
            }
2145
2146
            bool _hadAura;
2147
        };
2148
2149
        class spell_the_lich_king_necrotic_plague_AuraScript : public AuraScript
2150
        {
2151
            PrepareAuraScript(spell_the_lich_king_necrotic_plague_AuraScript);
2152
2153
            bool Load()
2154
            {
2155
                _lastAmount = 0;
2156
                return true;
2157
            }
2158
2159
            void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2160
            {
2161
                if (Unit* caster = GetCaster())
2162
                    caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount());
2163
            }
2164
2165
            void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2166
            {
2167
                _lastAmount = aurEff->GetAmount();
2168
                switch (GetTargetApplication()->GetRemoveMode())
2169
                {
2170
                    case AURA_REMOVE_BY_EXPIRE:
2171
                    case AURA_REMOVE_BY_DEATH:
2172
                        break;
2173
                    default:
2174
                        return;
2175
                }
2176
2177
                CustomSpellValues values;
2178
                values.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount());
2179
                GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID());
2180
                if (Unit* caster = GetCaster())
2181
                    caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2182
            }
2183
2184
            void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2185
            {
2186
                _lastAmount = aurEff->GetAmount();
2187
            }
2188
2189
            void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
2190
            {
2191
                // this means the stack increased so don't process as if dispelled
2192
                if (aurEff->GetAmount() > _lastAmount)
2193
                    return;
2194
2195
                CustomSpellValues values;
2196
                values.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount());
2197
                values.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1)
2198
                GetTarget()->CastCustomSpell(SPELL_NECROTIC_PLAGUE_JUMP, values, NULL, true, NULL, NULL, GetCasterGUID());
2199
                if (Unit* caster = GetCaster())
2200
                    caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true);
2201
2202
                Remove(AURA_REMOVE_BY_ENEMY_SPELL);
2203
            }
2204
2205
            void Register()
2206
            {
2207
                OnEffectApply += AuraEffectApplyFn(spell_the_lich_king_necrotic_plague_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
2208
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
2209
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY);
2210
                AfterEffectApply += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::AfterDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY);
2211
            }
2212
2213
            int32 _lastAmount;
2214
        };
2215
2216
        SpellScript* GetSpellScript() const
2217
        {
2218
            return new spell_the_lich_king_necrotic_plague_SpellScript();
2219
        }
2220
2221
        AuraScript* GetAuraScript() const
2222
        {
2223
            return new spell_the_lich_king_necrotic_plague_AuraScript();
2224
        }
2225
};
2226
2227
class spell_the_lich_king_shadow_trap_visual : public SpellScriptLoader
2228
{
2229
    public:
2230
        spell_the_lich_king_shadow_trap_visual() : SpellScriptLoader("spell_the_lich_king_shadow_trap_visual") { }
2231
2232
        class spell_the_lich_king_shadow_trap_visual_AuraScript : public AuraScript
2233
        {
2234
            PrepareAuraScript(spell_the_lich_king_shadow_trap_visual_AuraScript);
2235
2236
            void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2237
            {
2238
                if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
2239
                    GetTarget()->CastSpell(GetTarget(), SPELL_SHADOW_TRAP_AURA, TRIGGERED_NONE);
2240
            }
2241
2242
            void Register()
2243
            {
2244
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_shadow_trap_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
2245
            }
2246
        };
2247
2248
        AuraScript* GetAuraScript() const
2249
        {
2250
            return new spell_the_lich_king_shadow_trap_visual_AuraScript();
2251
        }
2252
};
2253
2254
class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader
2255
{
2256
    public:
2257
        spell_the_lich_king_shadow_trap_periodic() : SpellScriptLoader("spell_the_lich_king_shadow_trap_periodic") { }
2258
2259
        class spell_the_lich_king_shadow_trap_periodic_SpellScript : public SpellScript
2260
        {
2261
            PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic_SpellScript);
2262
2263
            void CheckTargetCount(std::list<Unit*>& targets)
2264
            {
2265
                if (targets.empty())
2266
                    return;
2267
2268
                GetCaster()->CastSpell((Unit*)NULL, SPELL_SHADOW_TRAP_KNOCKBACK, true);
2269
            }
2270
2271
            void Register()
2272
            {
2273
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2274
            }
2275
        };
2276
2277
        SpellScript* GetSpellScript() const
2278
        {
2279
            return new spell_the_lich_king_shadow_trap_periodic_SpellScript();
2280
        }
2281
};
2282
2283
class spell_the_lich_king_quake : public SpellScriptLoader
2284
{
2285
    public:
2286
        spell_the_lich_king_quake() : SpellScriptLoader("spell_the_lich_king_quake") { }
2287
2288
        class spell_the_lich_king_quake_SpellScript : public SpellScript
2289
        {
2290
            PrepareSpellScript(spell_the_lich_king_quake_SpellScript);
2291
2292
            bool Load()
2293
            {
2294
                return GetCaster()->GetInstanceScript() != NULL;
2295
            }
2296
2297
            void FilterTargets(std::list<Unit*>& unitList)
2298
            {
2299
                if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetData64(DATA_ARTHAS_PLATFORM)))
2300
                    unitList.remove_if(HeightDifferenceCheck(platform, 5.0f, false));
2301
            }
2302
2303
            void HandleSendEvent(SpellEffIndex /*effIndex*/)
2304
            {
2305
                if (GetCaster()->IsAIEnabled)
2306
                    GetCaster()->GetAI()->DoAction(ACTION_START_ATTACK);
2307
            }
2308
2309
            void Register()
2310
            {
2311
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
2312
                OnEffectHit += SpellEffectFn(spell_the_lich_king_quake_SpellScript::HandleSendEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT);
2313
            }
2314
        };
2315
2316
        SpellScript* GetSpellScript() const
2317
        {
2318
            return new spell_the_lich_king_quake_SpellScript();
2319
        }
2320
};
2321
2322
class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader
2323
{
2324
    public:
2325
        spell_the_lich_king_ice_burst_target_search() : SpellScriptLoader("spell_the_lich_king_ice_burst_target_search") { }
2326
2327
        class spell_the_lich_king_ice_burst_target_search_SpellScript : public SpellScript
2328
        {
2329
            PrepareSpellScript(spell_the_lich_king_ice_burst_target_search_SpellScript);
2330
2331
            bool Validate(SpellInfo const* /*spell*/)
2332
            {
2333
                if (!sSpellMgr->GetSpellInfo(SPELL_ICE_BURST))
2334
                    return false;
2335
                return true;
2336
            }
2337
2338
            void CheckTargetCount(std::list<Unit*>& unitList)
2339
            {
2340
                if (unitList.empty())
2341
                    return;
2342
2343
                // if there is at least one affected target cast the explosion
2344
                GetCaster()->CastSpell(GetCaster(), SPELL_ICE_BURST, true);
2345
                if (GetCaster()->GetTypeId() == TYPEID_UNIT)
2346
                    GetCaster()->ToCreature()->DespawnOrUnsummon(500);
2347
            }
2348
2349
            void Register()
2350
            {
2351
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2352
            }
2353
        };
2354
2355
        SpellScript* GetSpellScript() const
2356
        {
2357
            return new spell_the_lich_king_ice_burst_target_search_SpellScript();
2358
        }
2359
};
2360
2361
class spell_the_lich_king_raging_spirit : public SpellScriptLoader
2362
{
2363
    public:
2364
        spell_the_lich_king_raging_spirit() : SpellScriptLoader("spell_the_lich_king_raging_spirit") { }
2365
2366
        class spell_the_lich_king_raging_spirit_SpellScript : public SpellScript
2367
        {
2368
            PrepareSpellScript(spell_the_lich_king_raging_spirit_SpellScript);
2369
2370
            bool Validate(SpellInfo const* /*spell*/)
2371
            {
2372
                if (!sSpellMgr->GetSpellInfo(SPELL_LIFE_SIPHON_HEAL))
2373
                    return false;
2374
                return true;
2375
            }
2376
2377
            void HandleScript(SpellEffIndex effIndex)
2378
            {
2379
                PreventHitDefaultEffect(effIndex);
2380
                GetHitUnit()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
2381
            }
2382
2383
            void Register()
2384
            {
2385
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_raging_spirit_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
2386
            }
2387
        };
2388
2389
        SpellScript* GetSpellScript() const
2390
        {
2391
            return new spell_the_lich_king_raging_spirit_SpellScript();
2392
        }
2393
};
2394
2395
class ExactDistanceCheck
2396
{
2397
    public:
2398
        ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) {}
2399
2400
        bool operator()(Unit* unit)
2401
        {
2402
            return _source->GetExactDist2d(unit) > _dist;
2403
        }
2404
2405
    private:
2406
        Unit* _source;
2407
        float _dist;
2408
};
2409
2410
class spell_the_lich_king_defile : public SpellScriptLoader
2411
{
2412
    public:
2413
        spell_the_lich_king_defile() : SpellScriptLoader("spell_the_lich_king_defile") { }
2414
2415
        class spell_the_lich_king_defile_SpellScript : public SpellScript
2416
        {
2417
            PrepareSpellScript(spell_the_lich_king_defile_SpellScript);
2418
2419
            void CorrectRange(std::list<Unit*>& targets)
2420
            {
2421
                targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X)));
2422
            }
2423
2424
            void ChangeDamageAndGrow()
2425
            {
2426
                SetHitDamage(int32(GetHitDamage() * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X)));
2427
                // HACK: target player should cast this spell on defile
2428
                // however with current aura handling auras cast by different units
2429
                // cannot stack on the same aura object increasing the stack count
2430
                GetCaster()->CastSpell(GetCaster(), SPELL_DEFILE_GROW, true);
2431
            }
2432
2433
            void Register()
2434
            {
2435
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2436
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
2437
                OnHit += SpellHitFn(spell_the_lich_king_defile_SpellScript::ChangeDamageAndGrow);
2438
            }
2439
        };
2440
2441
        SpellScript* GetSpellScript() const
2442
        {
2443
            return new spell_the_lich_king_defile_SpellScript();
2444
        }
2445
};
2446
2447
class spell_the_lich_king_summon_into_air : public SpellScriptLoader
2448
{
2449
    public:
2450
        spell_the_lich_king_summon_into_air() : SpellScriptLoader("spell_the_lich_king_summon_into_air") { }
2451
2452
        class spell_the_lich_king_summon_into_air_SpellScript : public SpellScript
2453
        {
2454
            PrepareSpellScript(spell_the_lich_king_summon_into_air_SpellScript);
2455
2456
            void ModDestHeight(SpellEffIndex effIndex)
2457
            {
2458
                static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f};
2459
                WorldLocation* dest = const_cast<WorldLocation*>(GetTargetDest());
2460
                dest->RelocateOffset(offset);
2461
                // spirit bombs get higher
2462
                if (GetSpellInfo()->Effects[effIndex].MiscValue == NPC_SPIRIT_BOMB)
2463
                    dest->RelocateOffset(offset);
2464
            }
2465
2466
            void Register()
2467
            {
2468
                OnEffectLaunch += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON);
2469
            }
2470
        };
2471
2472
        SpellScript* GetSpellScript() const
2473
        {
2474
            return new spell_the_lich_king_summon_into_air_SpellScript();
2475
        }
2476
};
2477
2478
class spell_the_lich_king_soul_reaper : public SpellScriptLoader
2479
{
2480
    public:
2481
        spell_the_lich_king_soul_reaper() :  SpellScriptLoader("spell_the_lich_king_soul_reaper") { }
2482
2483
        class spell_the_lich_king_soul_reaper_AuraScript : public AuraScript
2484
        {
2485
            PrepareAuraScript(spell_the_lich_king_soul_reaper_AuraScript);
2486
2487
            bool Validate(SpellInfo const* /*spell*/)
2488
            {
2489
                if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_REAPER_BUFF))
2490
                    return false;
2491
                return true;
2492
            }
2493
2494
            void OnPeriodic(AuraEffect const* /*aurEff*/)
2495
            {
2496
                if (Unit* caster = GetCaster())
2497
                    GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true);
2498
            }
2499
2500
            void Register()
2501
            {
2502
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_reaper_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
2503
            }
2504
        };
2505
2506
        AuraScript* GetAuraScript() const
2507
        {
2508
            return new spell_the_lich_king_soul_reaper_AuraScript();
2509
        }
2510
};
2511
2512
class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader
2513
{
2514
    public:
2515
        spell_the_lich_king_valkyr_target_search() : SpellScriptLoader("spell_the_lich_king_valkyr_target_search") { }
2516
2517
        class spell_the_lich_king_valkyr_target_search_SpellScript : public SpellScript
2518
        {
2519
            PrepareSpellScript(spell_the_lich_king_valkyr_target_search_SpellScript);
2520
2521
            bool Validate(SpellInfo const* /*spell*/)
2522
            {
2523
                if (!sSpellMgr->GetSpellInfo(SPELL_ICE_BURST))
2524
                    return false;
2525
                return true;
2526
            }
2527
2528
            bool Load()
2529
            {
2530
                _target = NULL;
2531
                return true;
2532
            }
2533
2534
            void SelectTarget(std::list<Unit*>& unitList)
2535
            {
2536
                if (unitList.empty())
2537
                    return;
2538
2539
                unitList.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id));
2540
                if (unitList.empty())
2541
                    return;
2542
2543
                _target = SelectRandomContainerElement(unitList);
2544
                unitList.clear();
2545
                unitList.push_back(_target);
2546
                GetCaster()->GetAI()->SetGUID(_target->GetGUID());
2547
            }
2548
2549
            void ReplaceTarget(std::list<Unit*>& unitList)
2550
            {
2551
                unitList.clear();
2552
                if (_target)
2553
                    unitList.push_back(_target);
2554
            }
2555
2556
            void HandleScript(SpellEffIndex effIndex)
2557
            {
2558
                PreventHitDefaultEffect(effIndex);
2559
                GetCaster()->CastSpell(GetHitUnit(), SPELL_CHARGE, true);
2560
            }
2561
2562
            void Register()
2563
            {
2564
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2565
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
2566
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_valkyr_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
2567
            }
2568
2569
            Unit* _target;
2570
        };
2571
2572
        SpellScript* GetSpellScript() const
2573
        {
2574
            return new spell_the_lich_king_valkyr_target_search_SpellScript();
2575
        }
2576
};
2577
2578
class spell_the_lich_king_eject_all_passengers : public SpellScriptLoader
2579
{
2580
    public:
2581
        spell_the_lich_king_eject_all_passengers() : SpellScriptLoader("spell_the_lich_king_eject_all_passengers") { }
2582
2583
        class spell_the_lich_king_eject_all_passengers_SpellScript : public SpellScript
2584
        {
2585
            PrepareSpellScript(spell_the_lich_king_eject_all_passengers_SpellScript);
2586
2587
            bool Load()
2588
            {
2589
                return GetCaster()->IsVehicle();
2590
            }
2591
2592
            void HandleDummy(SpellEffIndex effIndex)
2593
            {
2594
                PreventHitDefaultEffect(effIndex);
2595
                GetCaster()->GetVehicleKit()->RemoveAllPassengers();
2596
            }
2597
2598
            void Register()
2599
            {
2600
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_eject_all_passengers_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
2601
            }
2602
        };
2603
2604
        SpellScript* GetSpellScript() const
2605
        {
2606
            return new spell_the_lich_king_eject_all_passengers_SpellScript();
2607
        }
2608
};
2609
2610
class spell_the_lich_king_cast_back_to_caster : public SpellScriptLoader
2611
{
2612
    public:
2613
        spell_the_lich_king_cast_back_to_caster() :  SpellScriptLoader("spell_the_lich_king_cast_back_to_caster") { }
2614
2615
        class spell_the_lich_king_cast_back_to_caster_SpellScript : public SpellScript
2616
        {
2617
            PrepareSpellScript(spell_the_lich_king_cast_back_to_caster_SpellScript);
2618
2619
            void HandleScript(SpellEffIndex /*effIndex*/)
2620
            {
2621
                GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
2622
            }
2623
2624
            void Register()
2625
            {
2626
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_cast_back_to_caster_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
2627
            }
2628
        };
2629
2630
        SpellScript* GetSpellScript() const
2631
        {
2632
            return new spell_the_lich_king_cast_back_to_caster_SpellScript();
2633
        }
2634
};
2635
2636
class spell_the_lich_king_life_siphon : public SpellScriptLoader
2637
{
2638
    public:
2639
        spell_the_lich_king_life_siphon() : SpellScriptLoader("spell_the_lich_king_life_siphon") { }
2640
2641
        class spell_the_lich_king_life_siphon_SpellScript : public SpellScript
2642
        {
2643
            PrepareSpellScript(spell_the_lich_king_life_siphon_SpellScript);
2644
2645
            bool Validate(SpellInfo const* /*spell*/)
2646
            {
2647
                if (!sSpellMgr->GetSpellInfo(SPELL_LIFE_SIPHON_HEAL))
2648
                    return false;
2649
                return true;
2650
            }
2651
2652
            void TriggerHeal()
2653
            {
2654
                GetHitUnit()->CastCustomSpell(SPELL_LIFE_SIPHON_HEAL, SPELLVALUE_BASE_POINT0, GetHitDamage() * 10, GetCaster(), true);
2655
            }
2656
2657
            void Register()
2658
            {
2659
                AfterHit += SpellHitFn(spell_the_lich_king_life_siphon_SpellScript::TriggerHeal);
2660
            }
2661
        };
2662
2663
        SpellScript* GetSpellScript() const
2664
        {
2665
            return new spell_the_lich_king_life_siphon_SpellScript();
2666
        }
2667
};
2668
2669
class spell_the_lich_king_vile_spirits : public SpellScriptLoader
2670
{
2671
    public:
2672
        spell_the_lich_king_vile_spirits() : SpellScriptLoader("spell_the_lich_king_vile_spirits") { }
2673
2674
        class spell_the_lich_king_vile_spirits_AuraScript : public AuraScript
2675
        {
2676
            PrepareAuraScript(spell_the_lich_king_vile_spirits_AuraScript);
2677
2678
            bool Load()
2679
            {
2680
                _is25Man = GetUnitOwner()->GetMap()->Is25ManRaid();
2681
                return true;
2682
            }
2683
2684
            void OnPeriodic(AuraEffect const* aurEff)
2685
            {
2686
                if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5))
2687
                    GetTarget()->CastSpell((Unit*)NULL, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, NULL, aurEff, GetCasterGUID());
2688
            }
2689
2690
            void Register()
2691
            {
2692
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_vile_spirits_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
2693
            }
2694
2695
            bool _is25Man;
2696
        };
2697
2698
        AuraScript* GetAuraScript() const
2699
        {
2700
            return new spell_the_lich_king_vile_spirits_AuraScript();
2701
        }
2702
};
2703
2704
class spell_the_lich_king_vile_spirits_visual : public SpellScriptLoader
2705
{
2706
    public:
2707
        spell_the_lich_king_vile_spirits_visual() : SpellScriptLoader("spell_the_lich_king_vile_spirits_visual") { }
2708
2709
        class spell_the_lich_king_vile_spirits_visual_SpellScript : public SpellScript
2710
        {
2711
            PrepareSpellScript(spell_the_lich_king_vile_spirits_visual_SpellScript);
2712
2713
            void ModDestHeight(SpellEffIndex /*effIndex*/)
2714
            {
2715
                Position offset = {0.0f, 0.0f, 15.0f, 0.0f};
2716
                const_cast<WorldLocation*>(GetTargetDest())->RelocateOffset(offset);
2717
            }
2718
2719
            void Register()
2720
            {
2721
                OnEffectLaunch += SpellEffectFn(spell_the_lich_king_vile_spirits_visual_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_DUMMY);
2722
            }
2723
        };
2724
2725
        SpellScript* GetSpellScript() const
2726
        {
2727
            return new spell_the_lich_king_vile_spirits_visual_SpellScript();
2728
        }
2729
};
2730
2731
class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoader
2732
{
2733
    public:
2734
        spell_the_lich_king_vile_spirit_move_target_search() : SpellScriptLoader("spell_the_lich_king_vile_spirit_move_target_search") { }
2735
2736
        class spell_the_lich_king_vile_spirit_move_target_search_SpellScript : public SpellScript
2737
        {
2738
            PrepareSpellScript(spell_the_lich_king_vile_spirit_move_target_search_SpellScript);
2739
2740
            bool Load()
2741
            {
2742
                _target = NULL;
2743
                return GetCaster()->GetTypeId() == TYPEID_UNIT;
2744
            }
2745
2746
            void SelectTarget(std::list<Unit*>& targets)
2747
            {
2748
                if (targets.empty())
2749
                    return;
2750
2751
                _target = SelectRandomContainerElement(targets);
2752
            }
2753
2754
            void HandleScript(SpellEffIndex effIndex)
2755
            {
2756
                PreventHitDefaultEffect(effIndex);
2757
                // for this spell, all units are in target map, however it should select one to attack
2758
                if (GetHitUnit() != _target)
2759
                    return;
2760
2761
                GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit());
2762
                GetCaster()->AddThreat(GetHitUnit(), 100000.0f);
2763
            }
2764
2765
            void Register()
2766
            {
2767
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2768
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
2769
            }
2770
2771
            Unit* _target;
2772
        };
2773
2774
        SpellScript* GetSpellScript() const
2775
        {
2776
            return new spell_the_lich_king_vile_spirit_move_target_search_SpellScript();
2777
        }
2778
};
2779
2780
class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptLoader
2781
{
2782
    public:
2783
        spell_the_lich_king_vile_spirit_damage_target_search() : SpellScriptLoader("spell_the_lich_king_vile_spirit_damage_target_search") { }
2784
2785
        class spell_the_lich_king_vile_spirit_damage_target_search_SpellScript : public SpellScript
2786
        {
2787
            PrepareSpellScript(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript);
2788
2789
            bool Load()
2790
            {
2791
                return GetCaster()->GetTypeId() == TYPEID_UNIT;
2792
            }
2793
2794
            void CheckTargetCount(std::list<Unit*>& targets)
2795
            {
2796
                if (targets.empty())
2797
                    return;
2798
2799
                // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this
2800
                // searcher spell will be blocked
2801
                if (TempSummon* summon = GetCaster()->ToTempSummon())
2802
                    if (Unit* summoner = summon->GetSummoner())
2803
                        summoner->GetAI()->SetData(DATA_VILE, 1);
2804
                GetCaster()->CastSpell((Unit*)NULL, SPELL_SPIRIT_BURST, true);
2805
                GetCaster()->ToCreature()->DespawnOrUnsummon(3000);
2806
                GetCaster()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
2807
            }
2808
2809
            void Register()
2810
            {
2811
                OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
2812
            }
2813
2814
            Unit* _target;
2815
        };
2816
2817
        SpellScript* GetSpellScript() const
2818
        {
2819
            return new spell_the_lich_king_vile_spirit_damage_target_search_SpellScript();
2820
        }
2821
};
2822
2823
class spell_the_lich_king_harvest_soul : public SpellScriptLoader
2824
{
2825
    public:
2826
        spell_the_lich_king_harvest_soul() : SpellScriptLoader("spell_the_lich_king_harvest_soul") { }
2827
2828
        class spell_the_lich_king_harvest_soul_AuraScript : public AuraScript
2829
        {
2830
            PrepareAuraScript(spell_the_lich_king_harvest_soul_AuraScript);
2831
2832
            bool Load()
2833
            {
2834
                return GetOwner()->GetInstanceScript() != NULL;
2835
            }
2836
2837
            void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2838
            {
2839
                // m_originalCaster to allow stacking from different casters, meh
2840
                if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2841
                    GetTarget()->CastSpell((Unit*)NULL, SPELL_HARVESTED_SOUL, true, NULL, NULL, GetTarget()->GetInstanceScript()->GetData64(DATA_THE_LICH_KING));
2842
            }
2843
2844
            void Register()
2845
            {
2846
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_harvest_soul_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
2847
            }
2848
        };
2849
2850
        AuraScript* GetAuraScript() const
2851
        {
2852
            return new spell_the_lich_king_harvest_soul_AuraScript();
2853
        }
2854
};
2855
2856
class spell_the_lich_king_lights_favor : public SpellScriptLoader
2857
{
2858
    public:
2859
        spell_the_lich_king_lights_favor() : SpellScriptLoader("spell_the_lich_king_lights_favor") { }
2860
2861
        class spell_the_lich_king_lights_favor_AuraScript : public AuraScript
2862
        {
2863
            PrepareAuraScript(spell_the_lich_king_lights_favor_AuraScript);
2864
2865
            void OnPeriodic(AuraEffect const* /*aurEff*/)
2866
            {
2867
                if (Unit* caster = GetCaster())
2868
                    if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
2869
                        effect->RecalculateAmount(caster);
2870
            }
2871
2872
            void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
2873
            {
2874
                canBeRecalculated = true;
2875
                amount = 0;
2876
                if (Unit* caster = GetCaster())
2877
                    amount = int32(caster->GetHealthPct());
2878
            }
2879
2880
            void Register()
2881
            {
2882
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_lights_favor_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_HEAL);
2883
                DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_the_lich_king_lights_favor_AuraScript::CalculateBonus, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
2884
            }
2885
        };
2886
2887
        AuraScript* GetAuraScript() const
2888
        {
2889
            return new spell_the_lich_king_lights_favor_AuraScript();
2890
        }
2891
};
2892
2893
class spell_the_lich_king_soul_rip : public SpellScriptLoader
2894
{
2895
    public:
2896
        spell_the_lich_king_soul_rip() : SpellScriptLoader("spell_the_lich_king_soul_rip") { }
2897
2898
        class spell_the_lich_king_soul_rip_AuraScript : public AuraScript
2899
        {
2900
            PrepareAuraScript(spell_the_lich_king_soul_rip_AuraScript);
2901
2902
            void OnPeriodic(AuraEffect const* aurEff)
2903
            {
2904
                PreventDefaultAction();
2905
                // shouldn't be needed, this is channeled
2906
                if (Unit* caster = GetCaster())
2907
                    caster->CastCustomSpell(SPELL_SOUL_RIP_DAMAGE, SPELLVALUE_BASE_POINT0, 5000 * aurEff->GetTickNumber(), GetTarget(), true, NULL, aurEff, GetCasterGUID());
2908
            }
2909
2910
            void Register()
2911
            {
2912
                OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_rip_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
2913
            }
2914
        };
2915
2916
        AuraScript* GetAuraScript() const
2917
        {
2918
            return new spell_the_lich_king_soul_rip_AuraScript();
2919
        }
2920
};
2921
2922
class spell_the_lich_king_restore_soul : public SpellScriptLoader
2923
{
2924
    public:
2925
        spell_the_lich_king_restore_soul() : SpellScriptLoader("spell_the_lich_king_restore_soul") { }
2926
2927
        class spell_the_lich_king_restore_soul_SpellScript : public SpellScript
2928
        {
2929
            PrepareSpellScript(spell_the_lich_king_restore_soul_SpellScript);
2930
2931
            bool Load()
2932
            {
2933
                _instance = GetCaster()->GetInstanceScript();
2934
                return _instance != NULL;
2935
            }
2936
2937
            void HandleScript(SpellEffIndex /*effIndex*/)
2938
            {
2939
                if (Creature* lichKing = ObjectAccessor::GetCreature(*GetCaster(), _instance->GetData64(DATA_THE_LICH_KING)))
2940
                    lichKing->AI()->DoAction(ACTION_TELEPORT_BACK);
2941
                if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f))
2942
                    spawner->RemoveAllAuras();
2943
            }
2944
2945
            void RemoveAura()
2946
            {
2947
                if (Unit* target = GetHitUnit())
2948
                    target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT);
2949
            }
2950
2951
            void Register()
2952
            {
2953
                OnEffectHit += SpellEffectFn(spell_the_lich_king_restore_soul_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
2954
                BeforeHit += SpellHitFn(spell_the_lich_king_restore_soul_SpellScript::RemoveAura);
2955
            }
2956
2957
            InstanceScript* _instance;
2958
        };
2959
2960
        SpellScript* GetSpellScript() const
2961
        {
2962
            return new spell_the_lich_king_restore_soul_SpellScript();
2963
        }
2964
};
2965
2966
class spell_the_lich_king_in_frostmourne_room : public SpellScriptLoader
2967
{
2968
    public:
2969
        spell_the_lich_king_in_frostmourne_room() : SpellScriptLoader("spell_the_lich_king_in_frostmourne_room") { }
2970
2971
        class spell_the_lich_king_in_frostmourne_room_AuraScript : public AuraScript
2972
        {
2973
            PrepareAuraScript(spell_the_lich_king_in_frostmourne_room_AuraScript);
2974
2975
            bool Load()
2976
            {
2977
                return GetOwner()->GetInstanceScript() != NULL;
2978
            }
2979
2980
            void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2981
            {
2982
                // m_originalCaster to allow stacking from different casters, meh
2983
                if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH)
2984
                    GetTarget()->CastSpell((Unit*)NULL, SPELL_HARVESTED_SOUL, true, NULL, NULL, GetTarget()->GetInstanceScript()->GetData64(DATA_THE_LICH_KING));
2985
            }
2986
2987
            void Register()
2988
            {
2989
                AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_in_frostmourne_room_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
2990
            }
2991
        };
2992
2993
        AuraScript* GetAuraScript() const
2994
        {
2995
            return new spell_the_lich_king_in_frostmourne_room_AuraScript();
2996
        }
2997
};
2998
2999
class spell_the_lich_king_summon_spirit_bomb : public SpellScriptLoader
3000
{
3001
    public:
3002
        spell_the_lich_king_summon_spirit_bomb() : SpellScriptLoader("spell_the_lich_king_summon_spirit_bomb") { }
3003
3004
        class spell_the_lich_king_summon_spirit_bomb_SpellScript : public SpellScript
3005
        {
3006
            PrepareSpellScript(spell_the_lich_king_summon_spirit_bomb_SpellScript);
3007
3008
            void HandleScript(SpellEffIndex effIndex)
3009
            {
3010
                PreventHitDefaultEffect(effIndex);
3011
                GetHitUnit()->CastSpell((Unit*)NULL, uint32(GetEffectValue()), true);
3012
            }
3013
3014
            void Register()
3015
            {
3016
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_summon_spirit_bomb_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
3017
            }
3018
        };
3019
3020
        SpellScript* GetSpellScript() const
3021
        {
3022
            return new spell_the_lich_king_summon_spirit_bomb_SpellScript();
3023
        }
3024
};
3025
3026
class spell_the_lich_king_trigger_vile_spirit : public SpellScriptLoader
3027
{
3028
    public:
3029
        spell_the_lich_king_trigger_vile_spirit() : SpellScriptLoader("spell_the_lich_king_trigger_vile_spirit") { }
3030
3031
        class spell_the_lich_king_trigger_vile_spirit_SpellScript : public SpellScript
3032
        {
3033
            PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit_SpellScript);
3034
3035
            void TeleportOutside()
3036
            {
3037
                Creature* target = GetHitCreature();
3038
                if (!target)
3039
                    return;
3040
3041
                Position dest;
3042
                Position offset;
3043
                TerenasSpawnHeroic.GetPositionOffsetTo(*target, offset);
3044
                GetCaster()->GetPosition(&dest);
3045
                dest.RelocateOffset(offset);
3046
                target->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation());
3047
            }
3048
3049
            void Register()
3050
            {
3051
                OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::TeleportOutside);
3052
            }
3053
        };
3054
3055
        SpellScript* GetSpellScript() const
3056
        {
3057
            return new spell_the_lich_king_trigger_vile_spirit_SpellScript();
3058
        }
3059
};
3060
3061
class spell_the_lich_king_jump : public SpellScriptLoader
3062
{
3063
    public:
3064
        spell_the_lich_king_jump() : SpellScriptLoader("spell_the_lich_king_jump") { }
3065
3066
        class spell_the_lich_king_jump_SpellScript : public SpellScript
3067
        {
3068
            PrepareSpellScript(spell_the_lich_king_jump_SpellScript);
3069
3070
            void HandleScript(SpellEffIndex effIndex)
3071
            {
3072
                PreventHitDefaultEffect(effIndex);
3073
                GetHitUnit()->RemoveAurasDueToSpell(SPELL_RAISE_DEAD);
3074
                GetHitUnit()->CastSpell((Unit*)NULL, SPELL_JUMP_2, true);
3075
                if (Creature* creature = GetHitCreature())
3076
                    creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE);
3077
            }
3078
3079
            void Register()
3080
            {
3081
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
3082
            }
3083
        };
3084
3085
        SpellScript* GetSpellScript() const
3086
        {
3087
            return new spell_the_lich_king_jump_SpellScript();
3088
        }
3089
};
3090
3091
class spell_the_lich_king_jump_remove_aura : public SpellScriptLoader
3092
{
3093
    public:
3094
        spell_the_lich_king_jump_remove_aura() : SpellScriptLoader("spell_the_lich_king_jump_remove_aura") { }
3095
3096
        class spell_the_lich_king_jump_SpellScript : public SpellScript
3097
        {
3098
            PrepareSpellScript(spell_the_lich_king_jump_SpellScript);
3099
3100
            void HandleScript(SpellEffIndex effIndex)
3101
            {
3102
                PreventHitDefaultEffect(effIndex);
3103
                GetHitUnit()->RemoveAurasDueToSpell(uint32(GetEffectValue()));
3104
            }
3105
3106
            void Register()
3107
            {
3108
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
3109
            }
3110
        };
3111
3112
        SpellScript* GetSpellScript() const
3113
        {
3114
            return new spell_the_lich_king_jump_SpellScript();
3115
        }
3116
};
3117
3118
class spell_the_lich_king_play_movie : public SpellScriptLoader
3119
{
3120
    public:
3121
        spell_the_lich_king_play_movie() : SpellScriptLoader("spell_the_lich_king_play_movie") { }
3122
3123
        class spell_the_lich_king_play_movie_SpellScript : public SpellScript
3124
        {
3125
            PrepareSpellScript(spell_the_lich_king_play_movie_SpellScript);
3126
3127
            bool Validate(SpellInfo const* /*spell*/)
3128
            {
3129
                if (!sMovieStore.LookupEntry(MOVIE_FALL_OF_THE_LICH_KING))
3130
                    return false;
3131
                return true;
3132
            }
3133
3134
            void HandleScript(SpellEffIndex effIndex)
3135
            {
3136
                PreventHitDefaultEffect(effIndex);
3137
                if (Player* player = GetHitPlayer())
3138
                    player->SendMovieStart(MOVIE_FALL_OF_THE_LICH_KING);
3139
            }
3140
3141
            void Register()
3142
            {
3143
                OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_play_movie_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
3144
            }
3145
        };
3146
3147
        SpellScript* GetSpellScript() const
3148
        {
3149
            return new spell_the_lich_king_play_movie_SpellScript();
3150
        }
3151
};
3152
3153
class achievement_been_waiting_long_time : public AchievementCriteriaScript
3154
{
3155
    public:
3156
        achievement_been_waiting_long_time() : AchievementCriteriaScript("achievement_been_waiting_long_time") { }
3157
3158
        bool OnCheck(Player* /*source*/, Unit* target)
3159
        {
3160
            if (!target)
3161
                return false;
3162
3163
            return target->GetAI()->GetData(DATA_PLAGUE_STACK) >= 30;
3164
        }
3165
};
3166
3167
class achievement_neck_deep_in_vile : public AchievementCriteriaScript
3168
{
3169
    public:
3170
        achievement_neck_deep_in_vile() : AchievementCriteriaScript("achievement_neck_deep_in_vile") { }
3171
3172
        bool OnCheck(Player* /*source*/, Unit* target)
3173
        {
3174
            if (!target)
3175
                return false;
3176
3177
            return !target->GetAI()->GetData(DATA_VILE);
3178
        }
3179
};
3180
3181
void AddSC_boss_the_lich_king()
3182
{
3183
    new boss_the_lich_king();
3184
    new npc_tirion_fordring_tft();
3185
    new npc_shambling_horror_icc();
3186
    new npc_raging_spirit();
3187
    new npc_valkyr_shadowguard();
3188
    new npc_strangulate_vehicle();
3189
    new npc_terenas_menethil();
3190
    new npc_spirit_warden();
3191
    new npc_spirit_bomb();
3192
    new npc_broken_frostmourne();
3193
    new spell_the_lich_king_infest();
3194
    new spell_the_lich_king_necrotic_plague();
3195
    new spell_the_lich_king_necrotic_plague_jump();
3196
    new spell_the_lich_king_shadow_trap_visual();
3197
    new spell_the_lich_king_shadow_trap_periodic();
3198
    new spell_the_lich_king_quake();
3199
    new spell_the_lich_king_ice_burst_target_search();
3200
    new spell_the_lich_king_raging_spirit();
3201
    new spell_the_lich_king_defile();
3202
    new spell_the_lich_king_summon_into_air();
3203
    new spell_the_lich_king_soul_reaper();
3204
    new spell_the_lich_king_valkyr_target_search();
3205
    new spell_the_lich_king_eject_all_passengers();
3206
    new spell_the_lich_king_cast_back_to_caster();
3207
    new spell_the_lich_king_life_siphon();
3208
    new spell_the_lich_king_vile_spirits();
3209
    new spell_the_lich_king_vile_spirits_visual();
3210
    new spell_the_lich_king_vile_spirit_move_target_search();
3211
    new spell_the_lich_king_vile_spirit_damage_target_search();
3212
    new spell_the_lich_king_harvest_soul();
3213
    new spell_the_lich_king_lights_favor();
3214
    new spell_the_lich_king_soul_rip();
3215
    new spell_the_lich_king_restore_soul();
3216
    new spell_the_lich_king_in_frostmourne_room();
3217
    new spell_the_lich_king_summon_spirit_bomb();
3218
    new spell_the_lich_king_trigger_vile_spirit();
3219
    new spell_the_lich_king_jump();
3220
    new spell_the_lich_king_jump_remove_aura();
3221
    new spell_trigger_spell_from_caster("spell_the_lich_king_mass_resurrection", SPELL_MASS_RESURRECTION_REAL);
3222
    new spell_the_lich_king_play_movie();
3223
    new achievement_been_waiting_long_time();
3224
    new achievement_neck_deep_in_vile();
3225
}