Projekt

Allgemein

Profil

Fehler #4201 » boss_svala.cpp

Melgro, 23.08.2012 23:37

 
1
/*
2
 * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
3
 *
4
 * This program is free software; you can redistribute it and/or modify it
5
 * under the terms of the GNU General Public License as published by the
6
 * Free Software Foundation; either version 2 of the License, or (at your
7
 * option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
 * more details.
13
 *
14
 * You should have received a copy of the GNU General Public License along
15
 * with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17

    
18
#include "ScriptMgr.h"
19
#include "ScriptedCreature.h"
20
#include "SpellScript.h"
21
#include "SpellAuraEffects.h"
22
#include "utgarde_pinnacle.h"
23

    
24
enum Spells
25
{
26
    SPELL_SVALA_TRANSFORMING1                     = 54140,
27
    SPELL_SVALA_TRANSFORMING2                     = 54205,
28
    SPELL_TRANSFORMING_CHANNEL                    = 54142,
29

    
30
    SPELL_CALL_FLAMES                             = 48258, // caster effect only, triggers event 17841
31
    SPELL_SINSTER_STRIKE                          = 15667,
32
    H_SPELL_SINSTER_STRIKE                        = 59409,
33

    
34
    SPELL_RITUAL_PREPARATION                      = 48267,
35
    SPELL_RITUAL_OF_THE_SWORD                     = 48276,
36
    SPELL_RITUAL_STRIKE_TRIGGER                   = 48331, // triggers 48277 & 59930, needs NPC_RITUAL_TARGET as spell_script_target
37
    SPELL_RITUAL_DISARM                           = 54159,
38
    SPELL_RITUAL_STRIKE_EFF_1                     = 48277,
39
    SPELL_RITUAL_STRIKE_EFF_2                     = 59930,
40

    
41
    SPELL_SUMMONED_VIS                            = 64446,
42
    SPELL_RITUAL_CHANNELER_1                      = 48271,
43
    SPELL_RITUAL_CHANNELER_2                      = 48274,
44
    SPELL_RITUAL_CHANNELER_3                      = 48275,
45

    
46
    // Ritual Channeler spells
47
    SPELL_PARALYZE                                = 48278,
48
    SPELL_SHADOWS_IN_THE_DARK                     = 59407,
49

    
50
    // Scourge Hulk spells
51
    SPELL_MIGHTY_BLOW                             = 48697,
52
    SPELL_VOLATILE_INFECTION                      = 56785,
53
    H_SPELL_VOLATILE_INFECTION                    = 59228
54
};
55

    
56
enum Yells
57
{
58
    // Svala
59
    SAY_SVALA_INTRO_0                             = 0,
60

    
61
    // Svala Sorrowgrave
62
    SAY_SVALA_INTRO_1                             = 0,
63
    SAY_SVALA_INTRO_2                             = 1,
64
    SAY_AGGRO                                     = 2,
65
    SAY_SLAY                                      = 3,
66
    SAY_DEATH                                     = 4,
67
    SAY_SACRIFICE_PLAYER                          = 5,
68

    
69
    // Image of Arthas
70
    SAY_DIALOG_OF_ARTHAS_1                        = 0,
71
    SAY_DIALOG_OF_ARTHAS_2                        = 1
72
};
73

    
74
enum Creatures
75
{
76
    CREATURE_ARTHAS                               = 29280, // Image of Arthas
77
    CREATURE_SVALA_SORROWGRAVE                    = 26668, // Svala after transformation
78
    CREATURE_SVALA                                = 29281, // Svala before transformation
79
    CREATURE_RITUAL_CHANNELER                     = 27281,
80
    CREATURE_SPECTATOR                            = 26667,
81
    CREATURE_RITUAL_TARGET                        = 27327,
82
    CREATURE_FLAME_BRAZIER                        = 27273,
83
    CREATURE_SCOURGE_HULK                         = 26555
84
};
85

    
86
enum Objects
87
{
88
    OBJECT_UTGARDE_MIRROR                         = 191745
89
};
90

    
91
enum SvalaPhase
92
{
93
    IDLE,
94
    INTRO,
95
    NORMAL,
96
    SACRIFICING,
97
    SVALADEAD
98
};
99

    
100
#define DATA_INCREDIBLE_HULK 2043
101

    
102
static const float spectatorWP[2][3] =
103
{
104
    {296.95f,-312.76f,86.36f},
105
    {297.69f,-275.81f,86.36f}
106
};
107

    
108
static Position ArthasPos = { 295.81f, -366.16f, 92.57f, 1.58f };
109

    
110
class boss_svala : public CreatureScript
111
{
112
public:
113
    boss_svala() : CreatureScript("boss_svala") { }
114

    
115
    CreatureAI* GetAI(Creature* creature) const
116
    {
117
        return new boss_svalaAI (creature);
118
    }
119

    
120
    struct boss_svalaAI : public ScriptedAI
121
    {
122
        boss_svalaAI(Creature* creature) : ScriptedAI(creature), summons(creature)
123
        {
124
            instance = creature->GetInstanceScript();
125
            Phase = IDLE;
126

    
127
            me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_1, true);
128
            me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_RITUAL_STRIKE_EFF_2, true);
129
        }
130

    
131
        InstanceScript* instance;
132
        SummonList summons;
133
        SvalaPhase Phase;
134

    
135
        Position pos;
136
        float x, y, z;
137

    
138
        uint32 introTimer;
139
        uint8 introPhase;
140
        uint8 sacrePhase;
141

    
142
        TempSummon* arthas;
143
        uint64 arthasGUID;
144

    
145
        uint32 sinsterStrikeTimer;
146
        uint32 callFlamesTimer;
147
        uint32 sacrificeTimer;
148

    
149

    
150
        bool sacrificed75;
151
		bool sacrificed50;
152
		bool sacrificed25;
153
		bool sacrificenow;
154

    
155
        void Reset()
156
        {
157
			sacrificed75 = false;
158
			sacrificed50 = false;
159
			sacrificed25 = false;
160
			sacrificenow = false;
161

    
162

    
163
            SetCombatMovement(true);
164

    
165
            summons.DespawnAll();
166
            me->RemoveAllAuras();
167

    
168
            if (Phase > NORMAL)
169
                Phase = NORMAL;
170

    
171
            me->SetDisableGravity(Phase == NORMAL);
172

    
173
            introTimer = 1 * IN_MILLISECONDS;
174
            introPhase = 0;
175
            arthasGUID = 0;
176

    
177
            if (instance)
178
            {
179
                instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED);
180
                instance->SetData64(DATA_SACRIFICED_PLAYER, 0);
181
            }
182
        }
183

    
184
        void EnterCombat(Unit* /*who*/)
185
        {
186
            Talk(SAY_AGGRO);
187

    
188
            sinsterStrikeTimer = 7 * IN_MILLISECONDS;
189
            callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
190

    
191
            if (instance)
192
                instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS);
193
        }
194

    
195
        void JustSummoned(Creature* summon)
196
        {
197
            if (summon->GetEntry() == CREATURE_RITUAL_CHANNELER)
198
                summon->CastSpell(summon, SPELL_SUMMONED_VIS, true);
199

    
200
            summons.Summon(summon);
201
        }
202

    
203
        void SummonedCreatureDespawn(Creature* summon)
204
        {
205
            summons.Despawn(summon);
206
        }
207

    
208
        void MoveInLineOfSight(Unit* who)
209
        {
210
            if (!who)
211
                return;
212

    
213
            if (Phase == IDLE && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40))
214
            {
215
                Phase = INTRO;
216
                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
217

    
218
                if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f))
219
                    mirror->SetGoState(GO_STATE_READY);
220

    
221
                if (Creature* arthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN))
222
                {
223
                    arthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
224
                    arthasGUID = arthas->GetGUID();
225
                }
226
            }
227
        }
228

    
229
        void KilledUnit(Unit* victim)
230
        {
231
            if (victim != me)
232
                Talk(SAY_SLAY);
233
        }
234

    
235
        void JustDied(Unit* /*killer*/)
236
        {
237
            if (Phase == SACRIFICING)
238
                SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
239

    
240
            me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
241

    
242
            summons.DespawnAll();
243

    
244
            if (instance)
245
                instance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE);
246

    
247
            Talk(SAY_DEATH);
248
        }
249

    
250
        void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell)
251
        {
252
            if (spell->Id == SPELL_RITUAL_STRIKE_EFF_1 && Phase != NORMAL && Phase != SVALADEAD)
253
            {
254
                Phase = NORMAL;
255
                SetCombatMovement(true);
256

    
257
                if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f, true))
258
                    me->GetMotionMaster()->MoveChase(target);
259
            }
260
        }
261

    
262
        void UpdateAI(const uint32 diff)
263
        {
264
			switch (Phase)
265
			{
266
				case IDLE:
267
					return;
268
				case INTRO:
269
					if (introTimer <= diff)
270
					{
271
						Creature* arthas = Unit::GetCreature(*me, arthasGUID);
272
						if (!arthas)
273
							return;
274

    
275
						switch (introPhase)
276
						{
277
							case 0:
278
								Talk(SAY_SVALA_INTRO_0);
279
								++introPhase;
280
								introTimer = 8100;
281
								break;
282
							case 1:
283
								arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_1);
284
								++introPhase;
285
								introTimer = 10000;
286
								break;
287
							case 2:
288
								arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false);
289
								pos.Relocate(me);
290
								pos.m_positionZ += 8.0f;
291
								me->GetMotionMaster()->MoveTakeoff(0, pos);
292
								// spectators flee event
293
								if (instance)
294
								{
295
									std::list<Creature*> lspectatorList;
296
									GetCreatureListWithEntryInGrid(lspectatorList, me, CREATURE_SPECTATOR, 100.0f);
297
									for (std::list<Creature*>::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr)
298
									{
299
										if ((*itr)->isAlive())
300
										{
301
											(*itr)->SetStandState(UNIT_STAND_STATE_STAND);
302
											(*itr)->SetWalk(false);
303
											(*itr)->GetMotionMaster()->MovePoint(1, spectatorWP[0][0], spectatorWP[0][1], spectatorWP[0][2]);
304
										}
305
									}
306
								}
307
								++introPhase;
308
								introTimer = 4200;
309
								break;
310
							case 3:
311
								me->CastSpell(me, SPELL_SVALA_TRANSFORMING1, false);
312
								++introPhase;
313
								introTimer = 6200;
314
								break;
315
							case 4:
316
								me->CastSpell(me, SPELL_SVALA_TRANSFORMING2, false);
317
								arthas->InterruptNonMeleeSpells(true);
318
								me->RemoveAllAuras();
319
								me->UpdateEntry(CREATURE_SVALA_SORROWGRAVE);
320
								me->SetFacingToObject(arthas);
321
								me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
322
								++introPhase;
323
								introTimer = 3200;
324
								break;
325
							case 5:
326
								Talk(SAY_SVALA_INTRO_1);
327
								++introPhase;
328
								introTimer = 10000;
329
								break;
330
							case 6:
331
								arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_2);
332
								++introPhase;
333
								introTimer = 7200;
334
								break;
335
							case 7:
336
								Talk(SAY_SVALA_INTRO_2);
337
								me->SetOrientation(1.58f);
338
								me->SendMovementFlagUpdate();
339
								arthas->SetVisible(false);
340
								++introPhase;
341
								introTimer = 13800;
342
								break;
343
							case 8:
344
								pos.Relocate(me);
345
								pos.m_positionX = me->GetHomePosition().GetPositionX();
346
								pos.m_positionY = me->GetHomePosition().GetPositionY();
347
								pos.m_positionZ = 90.6065f;
348
								me->GetMotionMaster()->MoveLand(0, pos);
349
								me->SetDisableGravity(false, true);
350
								me->SetHover(true);
351
								++introPhase;
352
								introTimer = 3000;
353
								break;
354
							case 9:
355
								if (GameObject* mirror = GetClosestGameObjectWithEntry(me, OBJECT_UTGARDE_MIRROR, 100.0f))
356
									mirror->SetGoState(GO_STATE_ACTIVE);
357
								me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
358
								arthas->DespawnOrUnsummon();
359
								arthasGUID = 0;
360
								Phase = NORMAL;
361
								break;
362
						}
363
					}
364
					else
365
						introTimer -= diff;
366
					return;
367
				case NORMAL:
368
					//Return since we have no target
369
					if (!UpdateVictim())
370
						return;
371
					if (sinsterStrikeTimer <= diff)
372
					{
373
						DoCast(me->getVictim(), SPELL_SINSTER_STRIKE);
374
						sinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS);
375
					}
376
					else
377
						sinsterStrikeTimer -= diff;
378
					if (callFlamesTimer <= diff)
379
					{
380
						if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
381
						{
382
							DoCast(target, SPELL_CALL_FLAMES);
383
							callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
384
						}
385
					}
386
						else callFlamesTimer -= diff;
387

    
388
				//RITUAL_OF_THE_SWORD at 75%, 50% and 25%
389
				 if ( (!sacrificed75 && HealthBelowPct(75)))
390
				 {
391
					 sacrificenow = true;
392
					 sacrificed75 = true;
393
				 }
394
				 if ( (!sacrificed50 && HealthBelowPct(50)))
395
				 {
396
					sacrificenow = true;
397
					sacrificed50 = true;
398
				 }
399
				 if ( (!sacrificed25 && HealthBelowPct(25)))
400
				 {
401
					 sacrificenow = true;
402
					 sacrificed25 = true;
403
				 }
404
				  //PREPARING for SACRIFICING_PHASE
405
					if (sacrificenow)
406
					{
407
						if (Unit* sacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true))
408
							{
409
								if (instance)
410
									instance->SetData64(DATA_SACRIFICED_PLAYER, sacrificeTarget->GetGUID());
411

    
412
								Talk(SAY_SACRIFICE_PLAYER);
413

    
414
								DoCast(sacrificeTarget, SPELL_RITUAL_PREPARATION);
415

    
416
								SetCombatMovement(false);
417

    
418
								Phase = SACRIFICING;
419
								sacrePhase = 0;
420
								sacrificeTimer = 1 * IN_MILLISECONDS;
421

    
422
								DoCast(me, SPELL_RITUAL_OF_THE_SWORD);
423
						}
424
					}
425

    
426
					DoMeleeAttackIfReady();
427
					break;
428
				case SACRIFICING: 
429
				    if (sacrificeTimer <= diff)
430
					{
431
						switch (sacrePhase)
432
						{
433
							case 0:
434
								// spawn ritual channelers
435
								if (instance)
436
								{
437
									DoCast(me, SPELL_RITUAL_CHANNELER_1, true);
438
									DoCast(me, SPELL_RITUAL_CHANNELER_2, true);
439
									DoCast(me, SPELL_RITUAL_CHANNELER_3, true);
440
								}
441
								++sacrePhase;
442
								sacrificeTimer = 2 * IN_MILLISECONDS;
443
								break;
444
							case 1:
445
								me->StopMoving();
446
								me->GetMotionMaster()->MoveIdle();
447
								me->InterruptNonMeleeSpells(true);
448
								DoCast(me, SPELL_RITUAL_STRIKE_TRIGGER, true);
449
								++sacrePhase;
450
								sacrificeTimer = 200;
451
								break;
452
							case 2:
453
								DoCast(me, SPELL_RITUAL_DISARM);
454
								++sacrePhase;
455
								break;
456
							case 3:
457
								//resetting sacrificenow after the SACRIFICE Phase is over
458
								sacrificenow = false;
459
								break;
460
						}
461
					}
462
					else
463
					{
464
						sacrificeTimer -= diff;
465
					}
466
					break;
467
				default:
468
				break;
469
			}
470
		}
471
    };
472

    
473
};
474

    
475
class npc_ritual_channeler : public CreatureScript
476
{
477
public:
478
    npc_ritual_channeler() : CreatureScript("npc_ritual_channeler") { }
479

    
480
    CreatureAI* GetAI(Creature* creature) const
481
    {
482
        return new npc_ritual_channelerAI(creature);
483
    }
484

    
485
    struct npc_ritual_channelerAI : public Scripted_NoMovementAI
486
    {
487
        npc_ritual_channelerAI(Creature* creature) :Scripted_NoMovementAI(creature)
488
        {
489
            instance = creature->GetInstanceScript();
490
        }
491

    
492
        InstanceScript* instance;
493
        uint32 paralyzeTimer;
494

    
495
        void Reset()
496
        {
497
            paralyzeTimer = 1600;
498
            if (instance)
499
                if (IsHeroic())
500
                    DoCast(me, SPELL_SHADOWS_IN_THE_DARK);
501
        }
502

    
503
        void UpdateAI(const uint32 diff)
504
        {
505
            if (me->HasUnitState(UNIT_STATE_CASTING))
506
                return;
507

    
508
            if (paralyzeTimer <= diff)
509
            {
510
                if (instance)
511
                    if (Unit* victim = me->GetUnit(*me, instance->GetData64(DATA_SACRIFICED_PLAYER)))
512
                        DoCast(victim, SPELL_PARALYZE, false);
513

    
514
                paralyzeTimer = 200;
515
            }
516
            else
517
                paralyzeTimer -= diff;
518
        }
519
    };
520
};
521

    
522
class npc_spectator : public CreatureScript
523
{
524
public:
525
    npc_spectator() : CreatureScript("npc_spectator") { }
526

    
527
    CreatureAI* GetAI(Creature* creature) const
528
    {
529
        return new npc_spectatorAI(creature);
530
    }
531

    
532
    struct npc_spectatorAI : public ScriptedAI
533
    {
534
        npc_spectatorAI(Creature* creature) : ScriptedAI(creature) { }
535

    
536
        void Reset() { }
537

    
538
        void MovementInform(uint32 motionType, uint32 pointId)
539
        {
540
            if (motionType == POINT_MOTION_TYPE)
541
            {
542
                if (pointId == 1)
543
                    me->GetMotionMaster()->MovePoint(2,spectatorWP[1][0],spectatorWP[1][1],spectatorWP[1][2]);
544
                else if (pointId == 2)
545
                    me->DespawnOrUnsummon(1000);
546
            }
547
        }
548
    };
549
};
550

    
551
class RitualTargetCheck
552
{
553
    public:
554
        explicit RitualTargetCheck(Unit* _caster) : caster(_caster) { }
555

    
556
        bool operator() (WorldObject* unit) const
557
        {
558
            if (InstanceScript* instance = caster->GetInstanceScript())
559
                if (instance->GetData64(DATA_SACRIFICED_PLAYER) == unit->GetGUID())
560
                    return false;
561

    
562
            return true;
563
        }
564

    
565
    private:
566
        Unit* caster;
567
};
568

    
569
class spell_paralyze_pinnacle : public SpellScriptLoader
570
{
571
    public:
572
        spell_paralyze_pinnacle() : SpellScriptLoader("spell_paralyze_pinnacle") { }
573

    
574
        class spell_paralyze_pinnacle_SpellScript : public SpellScript
575
        {
576
            PrepareSpellScript(spell_paralyze_pinnacle_SpellScript);
577

    
578
            void FilterTargets(std::list<WorldObject*>& unitList)
579
            {
580
                unitList.remove_if(RitualTargetCheck(GetCaster()));
581
            }
582

    
583
            void Register()
584
            {
585
                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
586
            }
587
        };
588

    
589
        SpellScript* GetSpellScript() const
590
        {
591
            return new spell_paralyze_pinnacle_SpellScript();
592
        }
593
};
594

    
595
class npc_scourge_hulk : public CreatureScript
596
{
597
    public:
598
        npc_scourge_hulk() : CreatureScript("npc_scourge_hulk") { }
599

    
600
        struct npc_scourge_hulkAI : public ScriptedAI
601
        {
602
            npc_scourge_hulkAI(Creature* creature) : ScriptedAI(creature) { }
603

    
604
            uint32 mightyBlow;
605
            uint32 volatileInfection;
606

    
607
            void Reset()
608
            {
609
                mightyBlow = urand(4000, 9000);
610
                volatileInfection = urand(10000, 14000);
611
                killedByRitualStrike = false;
612
            }
613

    
614
            uint32 GetData(uint32 type)
615
            {
616
                return type == DATA_INCREDIBLE_HULK ? killedByRitualStrike : 0;
617
            }
618

    
619
            void DamageTaken(Unit* attacker, uint32 &damage)
620
            {
621
                if (damage >= me->GetHealth() && attacker->GetEntry() == CREATURE_SVALA_SORROWGRAVE)
622
                    killedByRitualStrike = true;
623
            }
624

    
625
            void UpdateAI(uint32 const diff)
626
            {
627
                if (!UpdateVictim())
628
                    return;
629

    
630
                if (mightyBlow <= diff)
631
                {
632
                    if (Unit* victim = me->getVictim())
633
                        if (!victim->HasUnitState(UNIT_STATE_STUNNED))    // Prevent knocking back a ritual player
634
                            DoCast(victim, SPELL_MIGHTY_BLOW);
635
                    mightyBlow = urand(12000, 17000);
636
                }
637
                else
638
                    mightyBlow -= diff;
639

    
640
                if (volatileInfection <= diff)
641
                {
642
                    DoCastVictim(SPELL_VOLATILE_INFECTION);
643
                    volatileInfection = urand(13000, 17000);
644
                }
645
                else
646
                    volatileInfection -= diff;
647

    
648
                DoMeleeAttackIfReady();
649
            }
650

    
651
        private:
652
            bool killedByRitualStrike;
653
        };
654

    
655
        CreatureAI* GetAI(Creature* creature) const
656
        {
657
            return new npc_scourge_hulkAI(creature);
658
        }
659
};
660

    
661
class achievement_incredible_hulk : public AchievementCriteriaScript
662
{
663
    public:
664
        achievement_incredible_hulk() : AchievementCriteriaScript("achievement_incredible_hulk") { }
665

    
666
        bool OnCheck(Player* /*player*/, Unit* target)
667
        {
668
            return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_INCREDIBLE_HULK);
669
        }
670
};
671

    
672
void AddSC_boss_svala()
673
{
674
    new boss_svala();
675
    new npc_ritual_channeler();
676
    new npc_spectator();
677
    new spell_paralyze_pinnacle();
678
    new npc_scourge_hulk();
679
    new achievement_incredible_hulk();
680
}
    (1-1/1)