root/Trunk/src/InstanceScripts/Raid_Naxxramas.h @ 1114

Revision 1114, 143.1 kB (checked in by Hypersniper, 7 months ago)

REVERT of last commit for now.

Line 
1/*
2 * ArcScripts for ArcEmu MMORPG Server
3 * Copyright (C) 2009 ArcEmu Team <http://www.arcemu.org/>
4 * Copyright (C) 2008-2009 Sun++ Team <http://www.sunscripting.com/>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "StdAfx.h"
21#include "Setup.h"
22#include "../Common/Base.h"
23#include "../Common/Instance_Base.h"
24
25class GrandWidowFaerlinaAI;
26class AnubRekhanAI;
27class DeathchargerSteedAI;
28class PlaguedWarriorAI;
29class PlaguedChampionAI;
30class PlaguedGuardianAI;
31class PlagueFissureGO;
32class SporeAI;
33class PortalOfShadowsAI;
34class DeathKnightUnderstudyAI;
35
36/////////////////////////////////////////////////////////////////////////////////
37////// The Arachnid Quarter
38
39/////////////////////////////////////////////////////////////////////////////////
40////// Carrion Spinner
41#define CN_CARRION_SPINNER                                      15975
42#define CARRION_SPINNER_POISON_BOLT_NORMAL      30043
43#define CARRION_SPINNER_POISON_BOLT_HEROIC      56032
44#define CARRION_SPINNER_WEB_WRAP                        28618 // TODO: PULL EFFECT *FUN*
45
46class CarrionSpinnerAI : public MoonScriptCreatureAI
47{
48        MOONSCRIPT_FACTORY_FUNCTION( CarrionSpinnerAI, MoonScriptCreatureAI );
49        CarrionSpinnerAI( Creature* pCreature );
50
51        void Destroy();
52};
53
54/////////////////////////////////////////////////////////////////////////////////
55////// Dread Creeper
56#define CN_DREAD_CREEPER                                                15974
57#define DREAD_CREEPER_VEIL_OF_SHADOW_NORMAL             53803
58#define DREAD_CREEPER_VEIL_OF_SHADOW_HEROIC             28440
59
60class DreadCreeperAI : public MoonScriptCreatureAI
61{
62        MOONSCRIPT_FACTORY_FUNCTION( DreadCreeperAI, MoonScriptCreatureAI );
63        DreadCreeperAI( Creature* pCreature );
64
65        void Destroy();
66};
67
68/////////////////////////////////////////////////////////////////////////////////
69////// Naxxramas Cultist
70#define CN_NAXXRAMAS_CULTIST                                    15980
71#define NAXXRAMAS_CULTIST_KNOCKBACK_NORMAL              53850
72#define NAXXRAMAS_CULTIST_KNOCKBACK_HEROIC              53851
73
74class NaxxramasCultistAI : public MoonScriptCreatureAI
75{
76        MOONSCRIPT_FACTORY_FUNCTION( NaxxramasCultistAI, MoonScriptCreatureAI );
77        NaxxramasCultistAI( Creature* pCreature );
78
79        void Destroy();
80};
81//Necro Stalker AI - was it removed ?
82/////////////////////////////////////////////////////////////////////////////////
83////// Venom Stalker
84#define CN_VENOM_STALKER                                                15976
85#define VENOM_STALKER_POISON_CHARGE_NORMAL              28431
86#define VENOM_STALKER_POISON_CHARGE_HEROIC              53809
87
88class VenomStalkerAI : public MoonScriptCreatureAI
89{
90        MOONSCRIPT_FACTORY_FUNCTION( VenomStalkerAI, MoonScriptCreatureAI );
91        VenomStalkerAI( Creature* pCreature );
92
93        void Destroy();
94};
95
96/////////////////////////////////////////////////////////////////////////////////
97////// Tomb Horror
98#define CN_TOMB_HORROR                                                  15979
99#define TOMB_HORROR_SPIKE_VOLLEY                                28615
100#define TOMB_HORROR_CRYPT_SCARAB_SWARM_NORMAL   54313
101#define TOMB_HORROR_CRYPT_SCARAB_SWARM_HEROIC   54317
102#define TOMB_HORROR_CRYPT_SCARABS_NORMAL                54311
103#define TOMB_HORROR_CRYPT_SCARABS_HEROIC                54316
104
105class TombHorrorAI : public MoonScriptCreatureAI
106{
107        MOONSCRIPT_FACTORY_FUNCTION( TombHorrorAI, MoonScriptCreatureAI );
108        TombHorrorAI( Creature* pCreature );
109
110        void Destroy();
111};
112
113/////////////////////////////////////////////////////////////////////////////////
114////// Naxxramas Acolyte
115#define CN_NAXXRAMAS_ACOLYTE                                                    16368
116#define NAXXRAMAS_ACOLYTE_SHADOW_BOLT_VOLLEY_NORMAL             56064
117#define NAXXRAMAS_ACOLYTE_SHADOW_BOLT_VOLLEY_HEROIC             56065
118#define NAXXRAMAS_ACOLYTE_ARCANE_EXPLOSION_NORMAL               56063
119#define NAXXRAMAS_ACOLYTE_ARCANE_EXPLOSION_HEROIC               56067
120// To check: "total caster" + Explosion only when players are close ?
121class NaxxramasAcolyteAI : public MoonScriptCreatureAI
122{
123        MOONSCRIPT_FACTORY_FUNCTION( NaxxramasAcolyteAI, MoonScriptCreatureAI );
124        NaxxramasAcolyteAI( Creature* pCreature );
125
126        void Destroy();
127};
128
129/////////////////////////////////////////////////////////////////////////////////
130////// Vigilant Shade
131#define CN_VIGILANT_SHADE                                                               30085
132#define VIGILANT_SHADE_INVISIBILITY                                             55848
133#define VIGILANT_SHADE_SHADOW_BOLT_VOLLEY_NORMAL                55850
134#define VIGILANT_SHADE_SHADOW_BOLT_VOLLEY_HEROIC                55851
135// Invisiblity should be removed OnCombatStart ?
136class VigilantShadeAI : public MoonScriptCreatureAI
137{
138        MOONSCRIPT_FACTORY_FUNCTION( VigilantShadeAI, MoonScriptCreatureAI );
139        VigilantShadeAI( Creature* pCreature );
140
141        void OnCombatStart( Unit* pTarget );
142        void OnCombatStop( Unit* pTarget );
143        void Destroy();
144};
145
146/////////////////////////////////////////////////////////////////////////////////
147////// Crypt Reaver
148#define CN_CRYPT_REAVER                                                 15978
149#define CRYPT_REAVER_CLEAVE                                             40504
150#define CRYPT_REAVER_FRENZY                                             56625
151
152class CryptReaverAI : public MoonScriptCreatureAI
153{
154        MOONSCRIPT_FACTORY_FUNCTION( CryptReaverAI, MoonScriptCreatureAI );
155        CryptReaverAI( Creature* pCreature );
156
157        void Destroy();
158};
159
160/////////////////////////////////////////////////////////////////////////////////
161////// Web Wrap
162#define CN_WEB_WRAP                                                             16486
163
164class WebWrapAI : public MoonScriptCreatureAI
165{
166        MOONSCRIPT_FACTORY_FUNCTION( WebWrapAI, MoonScriptCreatureAI );
167        WebWrapAI( Creature* pCreature );
168
169        void OnCombatStart( Unit* pTarget );
170        void OnCombatStop( Unit* pTarget );
171        void OnDied( Unit* pKiller );
172        void AIUpdate();
173        void Destroy();
174
175        uint64  mPlayerGuid;
176};
177
178/////////////////////////////////////////////////////////////////////////////////
179////// Maexxna Spiderling
180#define CN_MAEXXNA_SPIDERLING                                           17055
181#define MAEXXNA_SPIDERLING_NECROTIC_POISON_NORMAL       54121
182#define MAEXXNA_SPIDERLING_NECROTIC_POISON_HEROIC       28776
183
184class MaexxnaSpiderlingAI : public MoonScriptCreatureAI
185{
186        MOONSCRIPT_FACTORY_FUNCTION( MaexxnaSpiderlingAI, MoonScriptCreatureAI );
187        MaexxnaSpiderlingAI( Creature* pCreature );
188
189        void Destroy();
190};
191
192/////////////////////////////////////////////////////////////////////////////////
193////// Maexxna
194#define CN_MAEXXNA                                                              15952
195#define MAEXXNA_WEB_WRAP                                                28622
196#define MAEXXNA_WEB_SPRAY_NORMAL                                29484
197#define MAEXXNA_WEB_SPRAY_HEROIC                                54125                   
198#define MAEXXNA_POISON_SHOCK_NORMAL                             28741
199#define MAEXXNA_POISON_SHOCK_HEROIC                             54122
200#define MAEXXNA_NECROTIC_POISON_NORMAL                  54121
201#define MAEXXNA_NECROTIC_POISON_HEROIC                  28776
202#define MAEXXNA_FRENZY_NORMAL                                   54123
203#define MAEXXNA_FRENZY_HEROIC                                   54124
204
205static Coords WebWrapPos[] =
206{
207        // Left wall
208        { 3515.307861f, -3837.076172f, 302.671753f, 4.388477f, 0 },
209        { 3529.401123f, -3841.910889f, 300.766174f, 4.335070f, 0 },
210        { 3541.990479f, -3851.308350f, 298.685272f, 3.804141f, 0 },
211        // Right wall
212        { 3497.262939f, -3949.542969f, 308.138916f, 1.433983f, 0 },
213        { 3510.450928f, -3949.871582f, 309.523193f, 1.613839f, 0 },
214        { 3523.486572f, -3946.144287f, 309.651611f, 1.973552f, 0 }
215};
216
217void SpellFunc_MaexxnaWebWrap( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
218
219class MaexxnaAI : public MoonScriptBossAI
220{
221        MOONSCRIPT_FACTORY_FUNCTION( MaexxnaAI, MoonScriptBossAI );
222        MaexxnaAI( Creature* pCreature );
223
224        void OnCombatStart( Unit* pTarget );
225        void OnCombatStop( Unit* pTarget );
226        void AIUpdate();
227        void Destroy();
228
229        SpellDesc*                      mWebWrapProc;
230        bool                            mHasEnraged;
231        bool                            mLeftWall;
232        int32                           mAddsSummonTimer;
233        int32                           mWebSprayTimer;
234        int32                           mWebWrapTimer;
235};
236
237/////////////////////////////////////////////////////////////////////////////////
238////// Naxxramas Worshipper
239#define CN_NAXXRAMAS_WORSHIPPER                                                 16506
240#define NAXXRAMAS_WORSHIPPER_FIREBALL_NORMAL                    54095
241#define NAXXRAMAS_WORSHIPPER_FIREBALL_HEROIC                    54096
242#define NAXXRAMAS_WORSHIPPER_WIDOW_EMBRACE                              28732
243#define NAXXRAMAS_WORSHIPPER_MIND_EXHAUSTION                    28727
244
245class NaxxramasWorshipperAI : public MoonScriptCreatureAI
246{
247        MOONSCRIPT_FACTORY_FUNCTION( NaxxramasWorshipperAI, MoonScriptCreatureAI );
248        NaxxramasWorshipperAI( Creature* pCreature );
249        friend class GrandWidowFaerlinaAI;
250
251        void OnCastSpell( uint32 pSpellId );
252        void OnDied( Unit* pKiller );
253        void AIUpdate();
254        void Destroy();
255
256        GrandWidowFaerlinaAI*   mGrandWidow;
257        bool                                    mPossessed;
258};
259
260/////////////////////////////////////////////////////////////////////////////////
261////// Naxxramas Follower
262#define CN_NAXXRAMAS_FOLLOWER                                                   16505
263#define NAXXRAMAS_FOLLOWER_BERSERKER_CHARGE_HEROIC              56107
264#define NAXXRAMAS_FOLLOWER_SILENCE_HEROIC                               54093
265
266void SpellFunc_NaxxramasFollowerCharge( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
267
268class NaxxramasFollowerAI : public MoonScriptCreatureAI
269{
270        MOONSCRIPT_FACTORY_FUNCTION( NaxxramasFollowerAI, MoonScriptCreatureAI );
271        NaxxramasFollowerAI( Creature* pCreature );
272        friend class GrandWidowFaerlinaAI;
273
274        void Destroy();
275
276        GrandWidowFaerlinaAI*   mGrandWidow;
277        SpellDesc*                              mCharge;
278};
279
280/////////////////////////////////////////////////////////////////////////////////
281////// Grand Widow Faerlina
282#define CN_GRAND_WIDOW_FAERLINA                                                 15953
283#define GRAND_WIDOW_FAERLINA_POISON_VOLLEY_BOLT_NORMAL  28796
284#define GRAND_WIDOW_FAERLINA_POISON_VOLLEY_BOLT_HEROIC  54098
285#define GRAND_WIDOW_FAERLINA_FRENZY_NORMAL                              28798
286#define GRAND_WIDOW_FAERLINA_FRENZY_HEROIC                              54100
287#define GRAND_WIDOW_RAIN_OF_FIRE_NORMAL                                 39024
288#define GRAND_WIDOW_RAIN_OF_FIRE_HEROIC                                 58936
289
290static Coords Worshippers[ 4 ] =
291{
292        { -3.0f, 0, 0, 0, 0 },
293        { -9.0f, 0, 0, 0, 0 },
294        { 3.0f, 0, 0, 0, 0 },
295        { 9.0f, 0, 0, 0, 0 }
296};
297
298static Coords Followers[ 2 ] =
299{
300        { -6.0f, 0, 0, 0, 0 },
301        { 6.0f, 0, 0, 0, 0 }
302};
303
304class GrandWidowFaerlinaAI : public MoonScriptBossAI
305{
306        MOONSCRIPT_FACTORY_FUNCTION( GrandWidowFaerlinaAI, MoonScriptBossAI );
307        GrandWidowFaerlinaAI( Creature* pCreature );
308
309        void OnCombatStart( Unit* pTarget );
310        void OnCombatStop( Unit* pTarget );
311        void AIUpdate();
312        void Destroy();
313
314        set< NaxxramasWorshipperAI* >   mWorshippers;
315        set< NaxxramasFollowerAI* >             mFollowers;
316        SpellDesc*                                              mFrenzy;
317        SpellDesc*                                              mPoisonVolleyBolt;
318        int32                                                   mFrenzyTimer;
319        int32                                                   mPoisonVolleyBoltTimer;
320};
321
322/////////////////////////////////////////////////////////////////////////////////
323////// Crypt Guard
324#define CN_CRYPT_GUARD                                          16573
325#define CRYPT_GUARD_ACID_SPLIT_NORMAL           28969
326#define CRYPT_GUARD_ACID_SPLIT_HEROIC           56098
327#define CRYPT_GUARD_CLEAVE                                      40504
328#define CRYPT_GUARD_FRENZY                                      8269
329
330class CryptGuardAI : public MoonScriptCreatureAI
331{
332        MOONSCRIPT_FACTORY_FUNCTION( CryptGuardAI, MoonScriptCreatureAI );
333        CryptGuardAI( Creature* pCreature );
334        friend class AnubRekhanAI;
335
336        void OnCombatStart( Unit* pTarget );
337        void AIUpdate();
338        void Destroy();
339
340        AnubRekhanAI*   mAnubRekhanAI;
341        bool                    mEnraged;
342};
343
344/////////////////////////////////////////////////////////////////////////////////
345////// Corpse Scarab
346#define CN_CORPSE_SCARAB                                                16698
347
348class CorpseScarabAI : public MoonScriptCreatureAI
349{
350        MOONSCRIPT_FACTORY_FUNCTION( CorpseScarabAI, MoonScriptCreatureAI );
351        CorpseScarabAI( Creature* pCreature );
352        friend class AnubRekhanAI;
353
354        void Destroy();
355
356        AnubRekhanAI*   mAnubRekhanAI;
357};
358
359/////////////////////////////////////////////////////////////////////////////////
360////// Anub'Rekhan
361#define CN_ANUBREKHAN                                                   15956
362#define ANUBREKHAN_IMPALE_NORMAL                                28783
363#define ANUBREKHAN_IMPALE_HEROIC                                56090
364#define ANUBREKHAN_LOCUST_SWARM_NORMAL                  28785
365#define ANUBREKHAN_LOCUST_SWARM_HEROIC                  54021
366#define ANUBREKHAN_SUMMON_CORPSE_SCARABS_5              29105
367#define ANUBREKHAN_SUMMON_CORPSE_SCARABS_10             28864
368#define ANUBREKHAN_BERSERK                                              26662
369
370static Coords CryptGuards[] =
371{
372        { 3300.486572f, -3449.479492f, 287.077850f, 3.883793f, 0 },
373        { 3300.568604f, -3503.060059f, 287.077850f, 2.367975f, 0 },
374        { 3332.591797f, -3476.102539f, 287.073425f, 0.015707f, 0 }
375};
376
377void SpellFunc_AnubRekhanCorpseScarabsPlayer( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
378void SpellFunc_AnubRekhanCorpseScarabsCryptGuard( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
379
380class AnubRekhanAI : public MoonScriptBossAI
381{
382        MOONSCRIPT_FACTORY_FUNCTION( AnubRekhanAI, MoonScriptBossAI );
383        AnubRekhanAI( Creature* pCreature );
384
385        void OnCombatStart( Unit* pTarget );
386        void OnCombatStop( Unit* pTarget );
387        void AIUpdate();
388        void Destroy();
389
390        set< CorpseScarabAI* >  mScarabs;
391        set< CryptGuardAI* >    mCryptGuards;
392        set< uint32 >                   mUsedCorpseGuids;
393        SpellDesc*                              mLocustSwarm;
394        int32                                   mLocustSwarmTimer;
395        int32                                   mCryptSpawnTimer;
396};
397
398/////////////////////////////////////////////////////////////////////////////////
399////// The Plague Quarter
400
401/////////////////////////////////////////////////////////////////////////////////
402////// Infectious Ghoul
403#define CN_INFECTIOUS_GHOUL                                             16244
404#define INFECTIOUS_GHOUL_FLESH_ROT                              54709
405#define INFECTIOUS_GHOUL_REND_NORMAL                    54703
406#define INFECTIOUS_GHOUL_REND_HEROIC                    54708
407#define INFECTIOUS_GHOUL_FRENZY_NORMAL                  54701
408#define INFECTIOUS_GHOUL_FRENZY_HEROIC                  24318
409
410class InfectiousGhoulAI : public MoonScriptCreatureAI
411{
412        MOONSCRIPT_FACTORY_FUNCTION( InfectiousGhoulAI, MoonScriptCreatureAI );
413        InfectiousGhoulAI( Creature* pCreature );
414
415        void OnCombatStart( Unit* pTarget );
416        void AIUpdate();
417        void Destroy();
418
419        bool    mEnraged;
420};
421
422/////////////////////////////////////////////////////////////////////////////////
423////// Stoneskin Gargoyle
424#define CN_STONESKIN_GARGOYLE                                   16168
425#define STONESKIN_GARGOYLE_ACID_VOLLEY_NORMAL   29325
426#define STONESKIN_GARGOYLE_ACID_VOLLEY_HEROIC   54714
427#define STONESKIN_GARGOYLE_STONESKIN_NORMAL             28995
428#define STONESKIN_GARGOYLE_STONESKIN_HEROIC             54722
429
430class StoneskinGargoyleAI : public MoonScriptCreatureAI
431{
432        MOONSCRIPT_FACTORY_FUNCTION( StoneskinGargoyleAI, MoonScriptCreatureAI );
433        StoneskinGargoyleAI( Creature* pCreature );
434
435        bool HasStoneskin();
436        void AIUpdate();
437        void Destroy();
438
439        SpellDesc*      mStoneskin;
440};
441
442/////////////////////////////////////////////////////////////////////////////////
443////// Frenzied Bat
444#define CN_FRENZIED_BAT                                         16036
445#define FRENZIED_BAT_FRENZIED_DIVE                      54781
446
447class FrenziedBatAI : public MoonScriptCreatureAI
448{
449        MOONSCRIPT_FACTORY_FUNCTION( FrenziedBatAI, MoonScriptCreatureAI );
450        FrenziedBatAI( Creature* pCreature );
451
452        void Destroy();
453};
454
455/////////////////////////////////////////////////////////////////////////////////
456////// Plague Beast
457#define CN_PLAGUE_BEAST                                         16034
458#define PLAGUE_BEAST_PLAGUE_SPLASH_NORMAL       54780
459#define PLAGUE_BEAST_PLAGUE_SPLASH_HEROIC       56538
460#define PLAGUE_BEAST_MUTATED_SPORES                     30110
461#define PLAGUE_BEAST_TRAMPLE                            5568
462
463class PlagueBeastAI : public MoonScriptCreatureAI
464{
465        MOONSCRIPT_FACTORY_FUNCTION( PlagueBeastAI, MoonScriptCreatureAI );
466        PlagueBeastAI( Creature* pCreature );
467
468        void OnCombatStart( Unit* pTarget );
469        void OnCombatStop( Unit* pTarget );
470        void Destroy();
471};
472
473/////////////////////////////////////////////////////////////////////////////////
474////// Eye Stalker
475#define CN_EYE_STALKER                                          16236
476#define EYE_STALKER_MIND_FLAY_NORMAL            29407
477#define EYE_STALKER_MIND_FLAY_HEROIC            54805
478
479class EyeStalkerAI : public MoonScriptCreatureAI
480{
481        MOONSCRIPT_FACTORY_FUNCTION( EyeStalkerAI, MoonScriptCreatureAI );
482        EyeStalkerAI( Creature* pCreature );
483
484        void OnCombatStart( Unit* pTarget );
485        void AIUpdate();
486        void Destroy();
487};
488
489/////////////////////////////////////////////////////////////////////////////////
490////// Noth the Plaguebringer
491#define CN_NOTH_THE_PLAGUEBRINGER                                                       15954
492#define NOTH_THE_PLAGUEBRINGER_BLINK_HEROIC                                     29208
493#define NOTH_THE_PLAGUEBRINGER_CRIPLE_HEROIC                            29212
494#define NOTH_THE_PLAGUEBRINGER_CURSE_OF_THE_PLAGUE_NORMAL       29213   // I must check if it's target-limited spell
495#define NOTH_THE_PLAGUEBRINGER_CURSE_OF_THE_PLAGUE_HEROIC       54835   // I must check if it's target-limited spell
496#define NOTH_THE_PLAGUEBRINGER_BERSERK                                          47008   // Guessed
497
498static Coords SkelPosPhase1[] =
499{
500        { 2660.175781f, -3473.315674f, 262.003967f, 5.252077f, 0 },
501        { 2717.336426f, -3463.309326f, 262.044098f, 3.703270f, 0 },
502        { 2718.720215f, -3524.452881f, 261.943176f, 2.760789f, 0 }
503};
504
505static Coords SkelPosPhase2[] =
506{
507        { 2660.932129f, -3474.058105f, 262.004730f, 5.765719f, 0 },
508        { 2706.175537f, -3465.862793f, 262.003510f, 4.488667f, 0 },
509        { 2723.024170f, -3472.919434f, 262.102020f, 3.809298f, 0 },
510        { 2717.878906f, -3518.062988f, 261.905945f, 3.177050f, 0 }
511};
512
513void SpellFunc_NothToBalconyPhaseSwitch( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
514void SpellFunc_NothFromBalconyPhaseSwitch( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
515void SpellFunc_NothCriple( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
516void SpellFunc_NothBlink( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
517
518class NothThePlaguebringerAI : public MoonScriptBossAI
519{
520        MOONSCRIPT_FACTORY_FUNCTION( NothThePlaguebringerAI, MoonScriptBossAI );
521        NothThePlaguebringerAI( Creature* pCreature );
522        friend class PlaguedWarriorAI;
523        friend class PlaguedChampionAI;
524        friend class PlaguedGuardianAI;
525
526        void OnCombatStart( Unit* pTarget );
527        void OnCombatStop( Unit* pTarget );
528        void AIUpdate();
529        void Destroy();
530
531        set< PlaguedWarriorAI*>         mWarriors;
532        set< PlaguedChampionAI*>        mChampions;
533        set< PlaguedGuardianAI* >       mGuardians;
534        SpellDesc*                                      mCriple;
535        SpellDesc*                                      mBlink;
536        SpellDesc*                                      mToBalconySwitch;
537        SpellDesc*                                      mFromBalconySwitch;
538        int32                                           mBlinkTimer;
539        int32                                           mSkeletonTimer;
540        int32                                           mPhaseSwitchTimer;
541        uint32                                          mPhaseCounter;
542};
543
544/////////////////////////////////////////////////////////////////////////////////
545////// Plagued Warrior
546#define CN_PLAGUED_WARRIOR                                              16984
547#define PLAGUED_WARRIOR_STRIKE                                  12057
548#define PLAGUED_WARRIOR_CLEAVE                                  15496
549
550class PlaguedWarriorAI : public MoonScriptCreatureAI
551{
552        MOONSCRIPT_FACTORY_FUNCTION( PlaguedWarriorAI, MoonScriptCreatureAI );
553        PlaguedWarriorAI( Creature* pCreature );
554
555        void Destroy();
556
557        NothThePlaguebringerAI* mNothAI;
558};
559
560/////////////////////////////////////////////////////////////////////////////////
561////// Plagued Champion
562#define CN_PLAGUED_CHAMPION                                             16983
563#define PLAGUED_CHAMPION_MORTAL_STRIKE_NORMAL   32736
564#define PLAGUED_CHAMPION_MORTAL_STRIKE_HEROIC   13737
565#define PLAGUED_CHAMPION_SHADOW_SHOCK_NORMAL    30138
566#define PLAGUED_CHAMPION_SHADOW_SHOCK_HEROIC    54889
567
568class PlaguedChampionAI : public MoonScriptCreatureAI
569{
570        MOONSCRIPT_FACTORY_FUNCTION( PlaguedChampionAI, MoonScriptCreatureAI );
571        PlaguedChampionAI( Creature* pCreature );
572
573        void Destroy();
574
575        NothThePlaguebringerAI* mNothAI;
576};
577
578/////////////////////////////////////////////////////////////////////////////////
579////// Plagued Guardian
580#define CN_PLAGUED_GUARDIAN                                                     16981
581#define PLAGUED_GUARDIAN_ARCANE_EXPLOSION_NORMAL        54890
582#define PLAGUED_GUARDIAN_ARCANE_EXPLOSION_HEROIC        54891
583#define PLAGUED_GUARDIAN_BLINK                                          29208
584
585class PlaguedGuardianAI : public MoonScriptCreatureAI
586{
587        MOONSCRIPT_FACTORY_FUNCTION( PlaguedGuardianAI, MoonScriptCreatureAI );
588        PlaguedGuardianAI( Creature* pCreature );
589
590        void Destroy();
591
592        NothThePlaguebringerAI* mNothAI;
593};
594
595/////////////////////////////////////////////////////////////////////////////////
596////// Heigan the Unclean
597#define CN_HEIGAN_THE_UNCLEAN                                           15936
598#define HEIGAN_THE_UNCLEAN_SPELL_DISRUPTION                     29310
599#define HEIGAN_THE_UNCLEAN_DECREPIT_FEVER_NORMAL        29998
600#define HEIGAN_THE_UNCLEAN_DECREPIT_FEVER_HEROIC        55011
601#define HEIGAN_THE_UNCLEAN_PLAGUE_CLOUD_CHANNEL         29350
602#define HEIGAN_THE_UNCLEAN_PLAGUE_CLOUD_DAMAGE          30122
603#define HEIGAN_THE_UNCLEAN_TELEPORT                                     34673   // Guessed.
604#define FISSURE_TRIGGER_ERUPTION                                29371
605
606float HeiganPos[2] = {2796, -3707};
607const float HeiganEruptionSlope[3] =
608{
609    (-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]),
610    (-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]),
611    (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]),
612};
613
614class HeiganTheUncleanAI : public MoonScriptBossAI
615{
616        MOONSCRIPT_FACTORY_FUNCTION( HeiganTheUncleanAI, MoonScriptBossAI );
617        HeiganTheUncleanAI( Creature* pCreature );
618        friend class PlagueFissureGO;
619
620        uint32  CalculateTriggerArea( float pPosX, float pPosY );
621        void    CallEruptionEvent( int32 pTimerId, int32 pNewTime );
622        void    OnCombatStart( Unit* pTarget );
623        void    OnCombatStop( Unit* pTarget );
624        void    AIUpdate();
625        void    Destroy();
626
627        set< pair< uint32, PlagueFissureGO* > >         mFissures;
628        int32                                                                           mPhaseSwitchTimer;
629        int32                                                                           mEruptionTimer;
630        int32                                                                           mEruptionPhase;
631        bool                                                                            mClockWiseEruption;
632};
633
634/////////////////////////////////////////////////////////////////////////////////
635////// Plague Fissure
636#define GO_PLAGUE_FISSURE               181533         
637
638class PlagueFissureGO : public GameObjectAIScript
639{
640public:
641
642        static GameObjectAIScript* Create( GameObject* pGameObject );
643        PlagueFissureGO( GameObject* pGameObject );
644
645        void DoErrupt();
646
647        // I believe it's nowhere hooked in the core.
648        void SetState( uint32 pState );
649        void Destroy();
650
651        HeiganTheUncleanAI*     mHeiganAI;
652};
653
654/////////////////////////////////////////////////////////////////////////////////
655////// Loatheb
656#define CN_LOATHEB                                                      16011
657#define LOATHEB_NECROTIC_AURA                           55593
658#define LOATHEB_SUMMON_SPORE                            29234
659#define LOATHEB_DEATHBLOOM_NORMAL                       29865
660#define LOATHEB_DEATHBLOOM_HEROIC                       55053
661#define LOATHEB_DEATHBLOOM_DAMAGE_NORMAL        55594
662#define LOATHEB_DEATHBLOOM_DAMAGE_HEROIC        55601
663#define LOATHEB_INEVITABLE_DOOM_NORMAL          29204
664#define LOATHEB_INEVITABLE_DOOM_HEROIC          55052
665#define LOATHEB_BERSERK                                         26662   // Unused
666
667static Coords Spores[] =
668{
669        { 2880.517334f, -4027.450684f, 273.680695f, 0.848522f, 0 },
670        { 2938.914307f, -4027.245850f, 273.617340f, 2.419318f, 0 },
671        { 2938.526611f, -3968.206543f, 273.524963f, 3.829108f, 0 },
672        { 2879.754883f, -3968.288574f, 273.633698f, 5.525566f, 0 }
673};
674
675class LoathebAI : public MoonScriptBossAI
676{
677        MOONSCRIPT_FACTORY_FUNCTION( LoathebAI, MoonScriptBossAI );
678        LoathebAI( Creature* pCreature );
679        friend class SporeAI;
680
681        void OnCombatStart( Unit* pTarget );
682        void OnCombatStop( Unit* pTarget );
683        void AIUpdate();
684        void Destroy();
685
686        set< SporeAI* > mSpores;
687        uint32                  mDoomStaticTimer;
688        int32                   mSporeTimer;
689        int32                   mDoomTimer;
690        int32                   mDeathbloomTimer;
691        bool                    mDeathbloomDamagePhase;
692};
693
694/////////////////////////////////////////////////////////////////////////////////
695////// Spore
696#define CN_SPORE                                                16286
697#define SPORE_FUNGAL_CREEP                              29232
698
699class SporeAI : public MoonScriptCreatureAI
700{
701        MOONSCRIPT_FACTORY_FUNCTION( SporeAI, MoonScriptCreatureAI );
702        SporeAI( Creature* pCreature );
703
704    void OnDied( Unit* pKiller );
705        void Destroy();
706
707        LoathebAI* mLoathebAI;
708};
709
710/////////////////////////////////////////////////////////////////////////////////
711////// The Military Quarter
712
713/////////////////////////////////////////////////////////////////////////////////
714////// Death Knight
715#define CN_DEATH_KNIGHT                                         16146
716#define DEATH_KNIGHT_BLOOD_PRESENCE                     55212
717#define DEATH_KNIGHT_DEATH_COIL_NORMAL          55209
718#define DEATH_KNIGHT_DEATH_COIL_HEROIC          55320
719#define DEATH_KNIGHT_DEATH_COIL_HEAL            55210
720#define DEATH_KNIGHT_HYSTERIA                           55213
721
722class DeathKnightAI : public MoonScriptCreatureAI
723{
724        MOONSCRIPT_FACTORY_FUNCTION( DeathKnightAI, MoonScriptCreatureAI );
725        DeathKnightAI( Creature* pCreature );
726
727        void OnCombatStart( Unit* pTarget );
728        void Destroy();
729};
730
731/////////////////////////////////////////////////////////////////////////////////
732////// Death Knight Captain
733#define CN_DEATH_KNIGHT_CAPTAIN                                         16145
734#define DEATH_KNIGHT_CAPTAIN_UNHOLY_PRESENCE            55222
735#define DEATH_KNIGHT_CAPTAIN_RAISE_DEAD                         28353
736#define DEATH_KNIGHT_CAPTAIN_PLAGUE_STRIKE_NORMAL       55255
737#define DEATH_KNIGHT_CAPTAIN_PLAGUE_STRIKE_HEROIC       55321
738#define DEATH_KNIGHT_CAPTAIN_WHIRLWIND                          28335
739
740class DeathKnightCaptainAI : public MoonScriptCreatureAI
741{
742        MOONSCRIPT_FACTORY_FUNCTION( DeathKnightCaptainAI, MoonScriptCreatureAI );
743        DeathKnightCaptainAI( Creature* pCreature );
744
745        void OnCombatStart( Unit* pTarget );
746        void Destroy();
747};
748
749/////////////////////////////////////////////////////////////////////////////////
750////// Skeletal Construct - wiki says he's in Naxx, but WoWHead claims him to be in Icecrown only
751
752/////////////////////////////////////////////////////////////////////////////////
753////// Ghost of Naxxramas
754#define CN_GHOST_OF_NAXXRAMAS                                                   16419
755
756class GhostOfNaxxramasAI : public MoonScriptCreatureAI
757{
758        MOONSCRIPT_FACTORY_FUNCTION( GhostOfNaxxramasAI, MoonScriptCreatureAI );
759        GhostOfNaxxramasAI( Creature* pCreature );
760
761        void Destroy();
762};
763
764/////////////////////////////////////////////////////////////////////////////////
765////// Shade of Naxxramas
766#define CN_SHADE_OF_NAXXRAMAS                                                   16164
767#define SHADE_OF_NAXXRAMAS_PORTAL_OF_SHADOWS                    28383
768#define SHADE_OF_NAXXRAMAS_SHADOW_BOLT_VOLLEY_NORMAL    28407
769#define SHADE_OF_NAXXRAMAS_SHADOW_BOLT_VOLLEY_HEROIC    55323
770
771class ShadeOfNaxxramasAI : public MoonScriptCreatureAI
772{
773        MOONSCRIPT_FACTORY_FUNCTION( ShadeOfNaxxramasAI, MoonScriptCreatureAI );
774        ShadeOfNaxxramasAI( Creature* pCreature );
775        friend class PortalOfShadowsAI;
776
777        void OnDied( Unit* pKiller );
778        void Destroy();
779
780        set< PortalOfShadowsAI* >       mPortals;
781};
782
783/////////////////////////////////////////////////////////////////////////////////
784////// Portal of Shadows
785#define CN_PORTAL_OF_SHADOWS                                                    16420
786
787class PortalOfShadowsAI : public MoonScriptCreatureAI
788{
789        MOONSCRIPT_FACTORY_FUNCTION( PortalOfShadowsAI, MoonScriptCreatureAI );
790        PortalOfShadowsAI( Creature* pCreature );
791
792        void OnCombatStart( Unit* pTarget );
793        void OnCombatStop( Unit* pTarget );
794        void AIUpdate();
795        void Destroy();
796
797        ShadeOfNaxxramasAI*     mShadeAI;
798        int32                           mSpawnTimer;
799};
800
801/////////////////////////////////////////////////////////////////////////////////
802////// Necro Knight
803#define CN_NECRO_KNIGHT                                                 16165
804#define NECRO_KNIGHT_ARCANE_EXPLOSION                   15453
805#define NECRO_KNIGHT_BLAST_WAVE                                 30092
806#define NECRO_KNIGHT_BLINK                                              28391
807#define NECRO_KNIGHT_CONE_OF_COLD                               30095
808#define NECRO_KNIGHT_FLAMESTRIKE                                30091
809#define NECRO_KNIGHT_FROST_NOVA                                 30094
810
811void SpellFunc_NecroKnightBlink( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
812
813class NecroKnightAI : public MoonScriptCreatureAI
814{
815        MOONSCRIPT_FACTORY_FUNCTION( NecroKnightAI, MoonScriptCreatureAI );
816        NecroKnightAI( Creature* pCreature );
817
818        void Destroy();
819};
820
821/////////////////////////////////////////////////////////////////////////////////
822////// Skeletal Smith
823#define CN_SKELETAL_SMITH                                               16193
824#define SKELETAL_SMITH_CRUSH_ARMOR                              33661
825#define SKELETAL_SMITH_DISARM                                   6713
826#define SKELETAL_SMITH_THUNDERCLAP                              23931
827//#define SKELETAL_SMITH_SUDDER_ARMOR                           24317
828
829class SkeletalSmithAI : public MoonScriptCreatureAI
830{
831        MOONSCRIPT_FACTORY_FUNCTION( SkeletalSmithAI, MoonScriptCreatureAI );
832        SkeletalSmithAI( Creature* pCreature );
833
834        void Destroy();
835};
836
837/////////////////////////////////////////////////////////////////////////////////
838////// Death Knight Cavalier
839#define CN_DEATH_KNIGHT_CAVALIER                                        16163
840#define DEATH_KNIGHT_CAVALIER_BONE_ARMOR_NORMAL         55315
841#define DEATH_KNIGHT_CAVALIER_BONE_ARMOR_HEROIC         55336
842#define DEATH_KNIGHT_CAVALIER_DISMOUNT_DEATHCHARGER     55294
843#define DEATH_KNIGHT_CAVALIER_ICY_TOUCH_NORMAL          55313
844#define DEATH_KNIGHT_CAVALIER_ICY_TOUCH_HEROIC          55331
845#define DEATH_KNIGHT_CAVALIER_STRANGULATE_NORMAL        55314
846#define DEATH_KNIGHT_CAVALIER_STRANGULATE_HEROIC        55334
847#define DEATH_KNIGHT_CAVALIER_AURA_OF_AGONY                     28413
848#define DEATH_KNIGHT_CAVALIER_CLEAVE                            15284
849#define DEATH_KNIGHT_CAVALIER_DEATH_COIL                        28412
850
851class DeathKnightCavalierAI : public MoonScriptCreatureAI
852{
853        MOONSCRIPT_FACTORY_FUNCTION( DeathKnightCavalierAI, MoonScriptCreatureAI );
854        DeathKnightCavalierAI( Creature* pCreature );
855        friend class DeathchargerSteedAI;
856
857        void OnCombatStop( Unit* pTarget );
858        void AIUpdate();
859        void Destroy();
860
861        DeathchargerSteedAI*    mChargerAI;
862        bool                                    mIsMounted;
863};
864
865/////////////////////////////////////////////////////////////////////////////////
866////// Deathcharger Steed
867#define CN_DEATHCHARGER_STEED                                   29818
868#define DEATHCHARGER_STEED_CHARGE                               55317
869
870void SpellFunc_DeathchargerSteedCharge( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
871
872class DeathchargerSteedAI : public MoonScriptCreatureAI
873{
874        MOONSCRIPT_FACTORY_FUNCTION( DeathchargerSteedAI, MoonScriptCreatureAI );
875        DeathchargerSteedAI( Creature* pCreature );
876        friend class DeathKnightCavalierAI;
877
878        void OnCombatStop( Unit* pTarget );
879        void Destroy();
880
881        DeathKnightCavalierAI*  mDeathKnightAI;
882        SpellDesc*                              mCharge;
883};
884
885/////////////////////////////////////////////////////////////////////////////////
886////// Dark Touched Warrior
887#define CN_DARK_TOUCHED_WARRIOR                                 16156
888#define DARK_TOUCHED_WARRIOR_WHIRLWIND                  55267
889//#define DARK_TOUCHED_WARRIOR_WHIRLWIND                        55266   // This one disables mob's melee
890
891class DarkTouchedWarriorAI : public MoonScriptCreatureAI
892{
893        MOONSCRIPT_FACTORY_FUNCTION( DarkTouchedWarriorAI, MoonScriptCreatureAI );
894        DarkTouchedWarriorAI( Creature* pCreature );
895
896        void OnCombatStart( Unit* pTarget );
897        void AIUpdate();
898        void Destroy();
899
900        int32   mResetHateTimer;
901};
902
903/////////////////////////////////////////////////////////////////////////////////
904////// Risen Squire
905#define CN_RISEN_SQUIRE                                         16154
906#define RISEN_SQUIRE_PIERCE_ARMOR                       55318
907
908class RisenSquireAI : public MoonScriptCreatureAI
909{
910        MOONSCRIPT_FACTORY_FUNCTION( RisenSquireAI, MoonScriptCreatureAI );
911        RisenSquireAI( Creature* pCreature );
912
913        void Destroy();
914};
915
916/////////////////////////////////////////////////////////////////////////////////
917////// Unholy Axe
918#define CN_UNHOLY_AXE                                                   16194
919#define UNHOLY_AXE_MORTAL_STRIKE_NORMAL                 16856
920#define UNHOLY_AXE_MORTAL_STRIKE_HEROIC                 15708
921#define UNHOLY_AXE_WHIRLWIND_NORMAL                             55463
922#define UNHOLY_AXE_WHIRLWIND_HEROIC                             24236
923
924class UnholyAxeAI : public MoonScriptCreatureAI
925{
926        MOONSCRIPT_FACTORY_FUNCTION( UnholyAxeAI, MoonScriptCreatureAI );
927        UnholyAxeAI( Creature* pCreature );
928
929        void Destroy();
930};
931
932/////////////////////////////////////////////////////////////////////////////////
933////// Unholy Sword
934#define CN_UNHOLY_SWORD                                                 16216
935#define UNHOLY_SWORD_CLEAVE_NORMAL                              15284
936#define UNHOLY_SWORD_CLEAVE_HEROIC                              19632
937
938class UnholySwordAI : public MoonScriptCreatureAI
939{
940        MOONSCRIPT_FACTORY_FUNCTION( UnholySwordAI, MoonScriptCreatureAI );
941        UnholySwordAI( Creature* pCreature );
942
943        void Destroy();
944};
945
946/////////////////////////////////////////////////////////////////////////////////
947////// Unholy Staff
948#define CN_UNHOLY_STAFF                                                 16215
949#define UNHOLY_STAFF_ARCANE_EXPLOSION_NORMAL    28450
950#define UNHOLY_STAFF_ARCANE_EXPLOSION_HEROIC    55467
951#define UNHOLY_STAFF_FROST_NOVA                                 29849
952#define UNHOLY_STAFF_POLYMORPH                                  29848
953
954class UnholyStaffAI : public MoonScriptCreatureAI
955{
956        MOONSCRIPT_FACTORY_FUNCTION( UnholyStaffAI, MoonScriptCreatureAI );
957        UnholyStaffAI( Creature* pCreature );
958
959        void Destroy();
960};
961
962/////////////////////////////////////////////////////////////////////////////////
963////// Instructor Razuvious
964#define CN_INSTRUCTOR_RAZUVIOUS                                                 16061
965#define INSTRUCTOR_RAZUVIOUS_DISRUPTING_SHOUT_NORMAL    55543
966#define INSTRUCTOR_RAZUVIOUS_DISRUPTING_SHOUT_HEROIC    29107
967#define INSTRUCTOR_RAZUVIOUS_JAGGED_KNIFE                               55550
968#define INSTRUCTOR_RAZUVIOUS_UNBALANCING_STRIKE                 55470
969#define INSTRUCTOR_RAZUVIOUS_HOPELESS                                   29125
970
971class InstructorRazuviousAI : public MoonScriptBossAI
972{
973        MOONSCRIPT_FACTORY_FUNCTION( InstructorRazuviousAI, MoonScriptBossAI );
974        InstructorRazuviousAI( Creature* pCreature );
975        friend class DeathKnightUnderstudyAI;
976
977        void OnCombatStart( Unit* pTarget );
978        void OnCombatStop( Unit* pTarget );
979        void OnDied( Unit* pKiller );
980        void AIUpdate();
981        void Destroy();
982
983        set< DeathKnightUnderstudyAI* > mStudents;
984};
985
986InstructorRazuviousAI::InstructorRazuviousAI( Creature* pCreature ) : MoonScriptBossAI( pCreature )
987{
988};
989
990void InstructorRazuviousAI::OnCombatStart( Unit* pTarget )
991{
992        ParentClass::OnCombatStart( pTarget );
993};
994
995void InstructorRazuviousAI::OnCombatStop( Unit* pTarget )
996{
997        ParentClass::OnCombatStop( pTarget );
998};
999
1000void InstructorRazuviousAI::OnDied( Unit* pKiller )
1001{
1002        ParentClass::OnDied( pKiller );
1003};
1004
1005void InstructorRazuviousAI::AIUpdate()
1006{
1007        ParentClass::AIUpdate();
1008};
1009
1010void InstructorRazuviousAI::Destroy()
1011{
1012        delete this;
1013};
1014
1015/////////////////////////////////////////////////////////////////////////////////
1016////// Death Knight Understudy
1017#define CN_DEATH_KNIGHT_UNDERSTUDY                                      16803
1018#define DEATH_KNIGHT_UNDERSTUDY_BLOOD_STRIKE            61696
1019#define DEATH_KNIGHT_UNDERSTUDY_BONE_BARRIER            29061
1020#define DEATH_KNIGHT_UNDERSTUDY_TAUNT                           29060
1021
1022class DeathKnightUnderstudyAI : public MoonScriptCreatureAI
1023{
1024        MOONSCRIPT_FACTORY_FUNCTION( DeathKnightUnderstudyAI, MoonScriptCreatureAI );
1025        DeathKnightUnderstudyAI( Creature* pCreature );
1026
1027        void Destroy();
1028
1029        InstructorRazuviousAI*  mRazuviousAI;
1030        bool                                    mIsControlled;
1031};
1032
1033DeathKnightUnderstudyAI::DeathKnightUnderstudyAI( Creature* pCreature ) : MoonScriptCreatureAI( pCreature )
1034{
1035        AddSpell( DEATH_KNIGHT_UNDERSTUDY_BLOOD_STRIKE, Target_Current, 10, 0, 4, 0, 8 );
1036        AddSpell( DEATH_KNIGHT_UNDERSTUDY_BONE_BARRIER, Target_Self, 8, 0, 30 );
1037        AddSpell( DEATH_KNIGHT_UNDERSTUDY_TAUNT, Target_Current, 8, 0, 10, 0, 8 );
1038
1039        // Blood Strike
1040        AI_Spell* NewSpell = new AI_Spell;
1041        NewSpell->spell = dbcSpell.LookupEntry( DEATH_KNIGHT_UNDERSTUDY_BLOOD_STRIKE );
1042        NewSpell->agent = AGENT_SPELL;
1043        NewSpell->entryId = _unit->GetEntry();
1044        NewSpell->maxrange = GetMaxRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );
1045        NewSpell->minrange = GetMinRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );
1046        NewSpell->spelltargetType = TTYPE_SINGLETARGET;
1047        NewSpell->spellType = STYPE_DAMAGE;
1048        NewSpell->cooldown = objmgr.GetPetSpellCooldown( NewSpell->spell->Id );
1049        NewSpell->cooldowntime = 0;
1050        NewSpell->autocast_type = AUTOCAST_EVENT_NONE;
1051        NewSpell->floatMisc1 = 0;
1052        NewSpell->Misc2 = 0;
1053        NewSpell->procChance = 0;
1054        NewSpell->procCount=0;
1055        _unit->GetAIInterface()->addSpellToList( NewSpell );
1056        //_unit->GetAIInterface()->m_spells.push_back( NewSpell );
1057
1058        // Bone Barrier
1059        NewSpell = new AI_Spell;
1060        NewSpell->spell = dbcSpell.LookupEntry( DEATH_KNIGHT_UNDERSTUDY_BONE_BARRIER );
1061        NewSpell->agent = AGENT_SPELL;
1062        NewSpell->entryId = _unit->GetEntry();
1063        NewSpell->maxrange = GetMaxRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );
1064        NewSpell->minrange = GetMinRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );
1065        NewSpell->spelltargetType = TTYPE_CASTER;
1066        NewSpell->spellType = STYPE_BUFF;
1067        NewSpell->cooldown = objmgr.GetPetSpellCooldown( NewSpell->spell->Id );
1068        NewSpell->cooldowntime = 0;
1069        NewSpell->autocast_type = AUTOCAST_EVENT_NONE;
1070        NewSpell->floatMisc1 = 0;
1071        NewSpell->Misc2 = 0;
1072        NewSpell->procChance = 0;
1073        NewSpell->procCount=0;
1074        _unit->GetAIInterface()->addSpellToList( NewSpell );
1075                        //_unit->GetAIInterface()->m_spells.push_back( NewSpell );
1076
1077        // Taunt
1078        NewSpell = new AI_Spell;
1079        NewSpell->spell = dbcSpell.LookupEntry( DEATH_KNIGHT_UNDERSTUDY_TAUNT );
1080        NewSpell->agent = AGENT_SPELL;
1081        NewSpell->entryId = _unit->GetEntry();
1082        NewSpell->maxrange = GetMaxRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );           
1083        NewSpell->minrange = GetMinRange( dbcSpellRange.LookupEntry( NewSpell->spell->rangeIndex ) );
1084        NewSpell->spelltargetType = TTYPE_SINGLETARGET;
1085        NewSpell->spellType = STYPE_BUFF;
1086        NewSpell->cooldown = objmgr.GetPetSpellCooldown( NewSpell->spell->Id );
1087        NewSpell->cooldowntime = 0;
1088        NewSpell->autocast_type = AUTOCAST_EVENT_NONE;
1089        NewSpell->floatMisc1 = 0;
1090        NewSpell->Misc2 = 0;
1091        NewSpell->procChance = 0;
1092        NewSpell->procCount=0;
1093        _unit->GetAIInterface()->addSpellToList( NewSpell );
1094        //_unit->GetAIInterface()->m_spells.push_back( NewSpell )
1095
1096        mRazuviousAI = NULL;
1097};
1098
1099void DeathKnightUnderstudyAI::Destroy()
1100{
1101        if ( mRazuviousAI != NULL )
1102        {
1103                set< DeathKnightUnderstudyAI* >::iterator Iter = mRazuviousAI->mStudents.find( this );
1104                if ( Iter != mRazuviousAI->mStudents.end() )
1105                        mRazuviousAI->mStudents.erase( Iter );
1106
1107                mRazuviousAI = NULL;
1108        };
1109
1110        delete this;
1111};
1112
1113/////////////////////////////////////////////////////////////////////////////////
1114////// The Construct Quarter
1115
1116/////////////////////////////////////////////////////////////////////////////////
1117////// Patchwork Golem
1118#define CN_PATCHWORK_GOLEM                                              16017
1119#define PATCHWORK_GOLEM_CLEAVE                                  27794
1120#define PATCHWORK_GOLEM_DISEASE_CLOUD_NORMAL    27793
1121#define PATCHWORK_GOLEM_DISEASE_CLOUD_HEROIC    28362
1122#define PATCHWORK_GOLEM_EXECUTE_NORMAL                  7160
1123#define PATCHWORK_GOLEM_EXECUTE_HEROIC                  56426
1124#define PATCHWORK_GOLEM_WAR_STOMP_NORMAL                27758
1125#define PATCHWORK_GOLEM_WAR_STOMP_HEROIC                56427
1126
1127class PatchworkGolemAI : public MoonScriptCreatureAI
1128{
1129        MOONSCRIPT_FACTORY_FUNCTION( PatchworkGolemAI, MoonScriptCreatureAI );
1130        PatchworkGolemAI( Creature* pCreature );
1131
1132        void OnCombatStart( Unit* pTarget );
1133        void OnCombatStop( Unit* pTarget );
1134        void Destroy();
1135};
1136
1137/////////////////////////////////////////////////////////////////////////////////
1138////// Bile Retcher
1139#define CN_BILE_RETCHER                                                 16018
1140#define BILE_RETCHER_BILE_VOMIT_NORMAL                  27807
1141#define BILE_RETCHER_BILE_VOMIT_HEROIC                  54326
1142#define BILE_RETCHER_BILE_RETCHER_SLAM                  27862
1143
1144class BileRetcherAI : public MoonScriptCreatureAI
1145{
1146        MOONSCRIPT_FACTORY_FUNCTION( BileRetcherAI, MoonScriptCreatureAI );
1147        BileRetcherAI( Creature* pCreature );
1148
1149        void Destroy();
1150};
1151
1152/////////////////////////////////////////////////////////////////////////////////
1153////// Sewage Slime
1154#define CN_SEWAGE_SLIME                                                 16375
1155#define SEWAGE_SLIME_DISEASE_CLOUD                              28156
1156
1157class SewageSlimeAI : public MoonScriptCreatureAI
1158{
1159        MOONSCRIPT_FACTORY_FUNCTION( SewageSlimeAI, MoonScriptCreatureAI );
1160        SewageSlimeAI( Creature* pCreature );
1161
1162        void OnCombatStart( Unit* pTarget );
1163        void OnCombatStop( Unit* pTarget );
1164        void Destroy();
1165};
1166
1167/////////////////////////////////////////////////////////////////////////////////
1168////// Embalming Slime
1169#define CN_EMBALMING_SLIME                                              16375
1170#define EMBALMING_SLIME_EMBALMING_CLOUD                 28322
1171
1172class EmbalmingSlimeAI : public MoonScriptCreatureAI
1173{
1174        MOONSCRIPT_FACTORY_FUNCTION( EmbalmingSlimeAI, MoonScriptCreatureAI );
1175        EmbalmingSlimeAI( Creature* pCreature );
1176
1177        void OnCombatStart( Unit* pTarget );
1178        void OnCombatStop( Unit* pTarget );
1179        void Destroy();
1180};
1181
1182/////////////////////////////////////////////////////////////////////////////////
1183////// Mad Scientist
1184#define CN_MAD_SCIENTIST                                                16020
1185#define MAD_SCIENTIST_GREAT_HEAL_NORMAL                 28306
1186#define MAD_SCIENTIST_GREAT_HEAL_HEROIC                 54337
1187#define MAD_SCIENTIST_MANA_BURN_NORMAL                  28301
1188#define MAD_SCIENTIST_MANA_BURN_HEROIC                  54338
1189
1190class MadScientistAI : public MoonScriptCreatureAI
1191{
1192        MOONSCRIPT_FACTORY_FUNCTION( MadScientistAI, MoonScriptCreatureAI );
1193        MadScientistAI( Creature* pCreature );
1194
1195        void Destroy();
1196};
1197
1198/////////////////////////////////////////////////////////////////////////////////
1199////// Living Monstrosity
1200#define CN_LIVING_MONSTROSITY                                           16021
1201#define LIVING_MONSTROSITY_FEAR                                         27990
1202#define LIVING_MONSTROSITY_LIGHTNING_TOTEM                      28294
1203#define LIVING_MONSTROSITY_CHAIN_LIGHTNING_NORMAL       28293
1204#define LIVING_MONSTROSITY_CHAIN_LIGHTNING_HEROIC       54334
1205
1206class LivingMonstrosityAI : public MoonScriptCreatureAI
1207{
1208        MOONSCRIPT_FACTORY_FUNCTION( LivingMonstrosityAI, MoonScriptCreatureAI );
1209        LivingMonstrosityAI( Creature* pCreature );
1210
1211        void Destroy();
1212};
1213
1214/////////////////////////////////////////////////////////////////////////////////
1215////// Lightning Totem
1216#define CN_LIGHTNING_TOTEM                                                      16385
1217#define LIGHTNING_TOTEM_SHOCK_NORMAL                            28297
1218#define LIGHTNING_TOTEM_SHOCK_HEROIC                            54333
1219
1220class LightningTotemAI : public MoonScriptCreatureAI
1221{
1222        MOONSCRIPT_FACTORY_FUNCTION( LightningTotemAI, MoonScriptCreatureAI );
1223        LightningTotemAI( Creature* pCreature );
1224
1225        void OnCombatStart( Unit* pTarget );
1226        void AIUpdate();
1227        void Destroy();
1228};
1229
1230/////////////////////////////////////////////////////////////////////////////////
1231////// Stitched Colossus
1232#define CN_STITCHED_COLOSSUS                                    30071
1233#define STITCHED_COLOSSUS_MASSIVE_STOMP_NORMAL  55821
1234#define STITCHED_COLOSSUS_MASSIVE_STOMP_HEROIC  55826
1235#define STITCHED_COLOSSUS_UNSTOPPABLE_ENRAGE    54356
1236
1237class StitchedColossusAI : public MoonScriptCreatureAI
1238{
1239        MOONSCRIPT_FACTORY_FUNCTION( StitchedColossusAI, MoonScriptCreatureAI );
1240        StitchedColossusAI( Creature* pCreature );
1241
1242        void OnCombatStart( Unit* pTarget );
1243        void AIUpdate();
1244        void Destroy();
1245
1246        bool    mEnraged;
1247};
1248
1249/////////////////////////////////////////////////////////////////////////////////
1250////// Marauding Geist
1251#define CN_MARAUDING_GEIST                                              30083
1252#define MARAUDING_GEIST_FRENZIED_LEAP                   56729
1253
1254class MaraudingGeistAI : public MoonScriptCreatureAI
1255{
1256        MOONSCRIPT_FACTORY_FUNCTION( MaraudingGeistAI, MoonScriptCreatureAI );
1257        MaraudingGeistAI( Creature* pCreature );
1258
1259        void Destroy();
1260};
1261
1262/////////////////////////////////////////////////////////////////////////////////
1263////// Patchwerk
1264
1265void SpellFunc_PatchwerkHatefulStrike( SpellDesc* pThis, MoonScriptCreatureAI* pCreatureAI, Unit* pTarget, TargetType pType );
1266
1267#define CN_PATCHWERK 16028
1268#define PATCHWERK_FRENZY 28131
1269#define PATCHWERK_BERSERK 26662
1270#define PATCHWERK_HATEFUL_STRIKE_10 41926
1271#define PATCHWERK_HATEFUL_STRIKE_25 59192
1272
1273class PatchwerkAI : public MoonScriptBossAI
1274{
1275        MOONSCRIPT_FACTORY_FUNCTION( PatchwerkAI, MoonScriptBossAI );
1276        PatchwerkAI( Creature* pCreature );
1277
1278        void AIUpdate();
1279        void Destroy();
1280
1281        bool    mEnraged;
1282};
1283
1284// ---- Abomination Wing ----
1285
1286// Stitched Spewer AI
1287#define STICKED_SPEWER 16025
1288
1289#define CN_SLIME_BOLT 32309
1290#define CN_UPPERCUT 26007
1291
1292class StickedSpewerAI : public CreatureAIScript
1293{
1294public:
1295        ADD_CREATURE_FACTORY_FUNCTION(StickedSpewerAI);
1296        SP_AI_Spell spells[2];
1297        bool m_spellcheck[2];
1298
1299    StickedSpewerAI(Creature* pCreature) : CreatureAIScript(pCreature)
1300    {
1301                // -- Number of spells to add --
1302                nrspells = 2;
1303
1304                // --- Initialization ---
1305                for(int i=0;i<nrspells;i++)
1306                {
1307                        m_spellcheck[i] = false;
1308                }
1309                // ----------------------
1310               
1311                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1312        spells[0].info = dbcSpell.LookupEntry(CN_SLIME_BOLT);
1313                spells[0].targettype = TARGET_VARIOUS;
1314                spells[0].instant = false;
1315                spells[0].perctrigger = 10.0f;
1316                spells[0].attackstoptimer = 2000; // 1sec
1317               
1318                spells[1].info = dbcSpell.LookupEntry(CN_UPPERCUT);
1319                spells[1].targettype = TARGET_VARIOUS;
1320                spells[1].instant = false;
1321                spells[1].perctrigger = 10.0f;
1322                spells[1].attackstoptimer = 2000; // 1sec
1323
1324    }
1325   
1326    void OnCombatStart(Unit* mTarget)
1327    {
1328        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1329    }
1330
1331    void OnCombatStop(Unit* mTarget)
1332    {
1333        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1334        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1335        RemoveAIUpdateEvent();
1336    }
1337
1338    void OnDied(Unit* mKiller)
1339    {
1340       RemoveAIUpdateEvent();
1341    }
1342
1343    void AIUpdate()
1344    {
1345                float val = (float)RandomFloat(100.0f);
1346        SpellCast(val);
1347    }
1348
1349    void SpellCast(float val)
1350    {
1351        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1352        {
1353                        float comulativeperc = 0;
1354                    Unit* target = NULL;
1355                        for(int i=0;i<nrspells;i++)
1356                        {
1357                                if(!spells[i].perctrigger) continue;
1358                               
1359                                if(m_spellcheck[i])
1360                                {
1361                                        target = _unit->GetAIInterface()->GetNextTarget();
1362                                        switch(spells[i].targettype)
1363                                        {
1364                                                case TARGET_SELF:
1365                                                case TARGET_VARIOUS:
1366                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1367                                                case TARGET_ATTACKING:
1368                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1369                                                case TARGET_DESTINATION:
1370                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1371                                        }
1372                                        m_spellcheck[i] = false;
1373                                        return;
1374                                }
1375
1376                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1377                                {
1378                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1379                                        m_spellcheck[i] = true;
1380                                }
1381                                comulativeperc += spells[i].perctrigger;
1382                        }
1383        }
1384    }
1385
1386protected:
1387
1388        int nrspells;
1389};
1390
1391
1392
1393//Surgical Assistant AI
1394#define CN_SURGICAL_ASSISTANT 16022
1395
1396#define MIND_FLAY 28310
1397
1398class SurgicalAssistantAI : public CreatureAIScript
1399{
1400public:
1401        ADD_CREATURE_FACTORY_FUNCTION(SurgicalAssistantAI);
1402        SP_AI_Spell spells[1];
1403        bool m_spellcheck[1];
1404
1405    SurgicalAssistantAI(Creature* pCreature) : CreatureAIScript(pCreature)
1406    {
1407                // -- Number of spells to add --
1408                nrspells = 1;
1409
1410                // --- Initialization ---
1411                for(int i=0;i<nrspells;i++)
1412                {
1413                        m_spellcheck[i] = false;
1414                }
1415                // ----------------------
1416               
1417                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1418        spells[0].info = dbcSpell.LookupEntry(MIND_FLAY);
1419                spells[0].targettype = TARGET_ATTACKING;
1420                spells[0].instant = false;
1421                spells[0].perctrigger = 20.0f;
1422                spells[0].attackstoptimer = 6000; // 1sec
1423
1424    }
1425   
1426    void OnCombatStart(Unit* mTarget)
1427    {
1428        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1429    }
1430
1431    void OnCombatStop(Unit* mTarget)
1432    {
1433        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1434        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1435        RemoveAIUpdateEvent();
1436    }
1437
1438    void OnDied(Unit* mKiller)
1439    {
1440       RemoveAIUpdateEvent();
1441    }
1442
1443    void AIUpdate()
1444    {
1445                float val = (float)RandomFloat(100.0f);
1446        SpellCast(val);
1447    }
1448
1449    void SpellCast(float val)
1450    {
1451        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1452        {
1453                        float comulativeperc = 0;
1454                    Unit* target = NULL;
1455                        for(int i=0;i<nrspells;i++)
1456                        {
1457                                if(!spells[i].perctrigger) continue;
1458                               
1459                                if(m_spellcheck[i])
1460                                {
1461                                        target = _unit->GetAIInterface()->GetNextTarget();
1462                                        switch(spells[i].targettype)
1463                                        {
1464                                                case TARGET_SELF:
1465                                                case TARGET_VARIOUS:
1466                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1467                                                case TARGET_ATTACKING:
1468                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1469                                                case TARGET_DESTINATION:
1470                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1471                                        }
1472                                        m_spellcheck[i] = false;
1473                                        return;
1474                                }
1475
1476                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1477                                {
1478                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1479                                        m_spellcheck[i] = true;
1480                                }
1481                                comulativeperc += spells[i].perctrigger;
1482                        }
1483        }
1484    }
1485
1486protected:
1487
1488        int nrspells;
1489};
1490
1491
1492// Sludge Belcher AI
1493#define CN_SLUDGE_BELCHER 16029
1494
1495#define DISEISE_BUFFET 27891
1496#define SUMMON_BILE_SLIMES 27889 // TODO: GAWD :P
1497
1498class SludgeBelcherAI : public CreatureAIScript
1499{
1500public:
1501        ADD_CREATURE_FACTORY_FUNCTION(SludgeBelcherAI);
1502        SP_AI_Spell spells[2];
1503        bool m_spellcheck[2];
1504
1505    SludgeBelcherAI(Creature* pCreature) : CreatureAIScript(pCreature)
1506    {
1507                // -- Number of spells to add --
1508                nrspells = 2;
1509
1510                // --- Initialization ---
1511                for(int i=0;i<nrspells;i++)
1512                {
1513                        m_spellcheck[i] = false;
1514                }
1515                // ----------------------
1516               
1517                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1518        spells[0].info = dbcSpell.LookupEntry(DISEISE_BUFFET);
1519                spells[0].targettype = TARGET_ATTACKING;
1520                spells[0].instant = false;
1521                spells[0].perctrigger = 20.0f;
1522                spells[0].attackstoptimer = 1000; // 1sec
1523               
1524                spells[1].info = dbcSpell.LookupEntry(SUMMON_BILE_SLIMES);
1525                spells[1].targettype = TARGET_SELF;
1526                spells[1].instant = false;
1527                spells[1].perctrigger = 5.0f;
1528                spells[1].attackstoptimer = 3000; // 1sec
1529
1530    }
1531   
1532    void OnCombatStart(Unit* mTarget)
1533    {
1534        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1535    }
1536
1537    void OnCombatStop(Unit* mTarget)
1538    {
1539        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1540        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1541        RemoveAIUpdateEvent();
1542    }
1543
1544    void OnDied(Unit* mKiller)
1545    {
1546       RemoveAIUpdateEvent();
1547    }
1548
1549    void AIUpdate()
1550    {
1551                float val = (float)RandomFloat(100.0f);
1552        SpellCast(val);
1553    }
1554
1555    void SpellCast(float val)
1556    {
1557        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1558        {
1559                        float comulativeperc = 0;
1560                    Unit* target = NULL;
1561                        for(int i=0;i<nrspells;i++)
1562                        {
1563                                if(!spells[i].perctrigger) continue;
1564                               
1565                                if(m_spellcheck[i])
1566                                {
1567                                        target = _unit->GetAIInterface()->GetNextTarget();
1568                                        switch(spells[i].targettype)
1569                                        {
1570                                                case TARGET_SELF:
1571                                                case TARGET_VARIOUS:
1572                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1573                                                case TARGET_ATTACKING:
1574                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1575                                                case TARGET_DESTINATION:
1576                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1577                                        }
1578                                        m_spellcheck[i] = false;
1579                                        return;
1580                                }
1581
1582                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1583                                {
1584                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1585                                        m_spellcheck[i] = true;
1586                                }
1587                                comulativeperc += spells[i].perctrigger;
1588                        }
1589        }
1590    }
1591
1592protected:
1593
1594        int nrspells;
1595};
1596
1597// BOSS'S
1598
1599// Patchwerk AI
1600
1601
1602// Grobbulus AI
1603#define CN_GROBBULUS 15931
1604
1605#define POISON_CLOUD_GROB 31259 // self
1606#define SLIME_SPRAY 28157 // various
1607#define SUMMON_FALLOUT_SLIME 28218 // TODO: cast on slime sprayd targets
1608#define MUTATING_INJECTION 28169 // TODO: DUMMY AURA
1609
1610class GrobbulusAI : public CreatureAIScript
1611{
1612public:
1613        ADD_CREATURE_FACTORY_FUNCTION(GrobbulusAI);
1614        SP_AI_Spell spells[2];
1615        bool m_spellcheck[2];
1616
1617    GrobbulusAI(Creature* pCreature) : CreatureAIScript(pCreature)
1618    {
1619                // -- Number of spells to add --
1620                nrspells = 2;
1621
1622                // --- Initialization ---
1623                for(int i=0;i<nrspells;i++)
1624                {
1625                        m_spellcheck[i] = false;
1626                }
1627                // ----------------------
1628               
1629                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1630        spells[0].info = dbcSpell.LookupEntry(POISON_CLOUD_GROB);
1631                spells[0].targettype = TARGET_SELF;
1632                spells[0].instant = false;
1633                spells[0].perctrigger = 0.0f;
1634                spells[0].attackstoptimer = 1000; // 1sec
1635
1636                spells[1].info = dbcSpell.LookupEntry(SLIME_SPRAY);
1637                spells[1].targettype = TARGET_VARIOUS;
1638                spells[1].instant = false;
1639                spells[1].perctrigger = 15.0f;
1640                spells[1].attackstoptimer = 3000; // 1sec
1641
1642    }
1643   
1644    void OnCombatStart(Unit* mTarget)
1645    {
1646        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1647                _unit->CastSpell(_unit, spells[0].info, spells[0].instant);
1648    }
1649
1650    void OnCombatStop(Unit* mTarget)
1651    {
1652        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1653        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1654        RemoveAIUpdateEvent();
1655    }
1656
1657    void OnDied(Unit* mKiller)
1658    {
1659       RemoveAIUpdateEvent();
1660    }
1661
1662    void AIUpdate()
1663    {
1664                float val = (float)RandomFloat(100.0f);
1665        SpellCast(val);
1666    }
1667
1668    void SpellCast(float val)
1669    {
1670        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1671        {
1672                        float comulativeperc = 0;
1673                    Unit* target = NULL;
1674                        for(int i=0;i<nrspells;i++)
1675                        {
1676                                if(!spells[i].perctrigger) continue;
1677                               
1678                                if(m_spellcheck[i])
1679                                {
1680                                        target = _unit->GetAIInterface()->GetNextTarget();
1681                                        switch(spells[i].targettype)
1682                                        {
1683                                                case TARGET_SELF:
1684                                                case TARGET_VARIOUS:
1685                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1686                                                case TARGET_ATTACKING:
1687                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1688                                                case TARGET_DESTINATION:
1689                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1690                                        }
1691                                        m_spellcheck[i] = false;
1692                                        return;
1693                                }
1694
1695                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1696                                {
1697                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1698                                        m_spellcheck[i] = true;
1699                                }
1700                                comulativeperc += spells[i].perctrigger;
1701                        }
1702        }
1703    }
1704
1705protected:
1706
1707        int nrspells;
1708};
1709
1710
1711// Gluth AI
1712#define CN_GLUTH 15932
1713
1714#define MORTAL_WOUND 28308 // target
1715#define DECIMATE 28374 // TODO: needs to be scripted
1716#define TERRIFYING_ROAR 37939
1717#define FRENZY 38664 // self
1718
1719class GluthAI : public CreatureAIScript
1720{
1721public:
1722        ADD_CREATURE_FACTORY_FUNCTION(GluthAI);
1723        SP_AI_Spell spells[3];
1724        bool m_spellcheck[3];
1725
1726    GluthAI(Creature* pCreature) : CreatureAIScript(pCreature)
1727    {
1728                // -- Number of spells to add --
1729                nrspells = 3;
1730
1731                // --- Initialization ---
1732                for(int i=0;i<nrspells;i++)
1733                {
1734                        m_spellcheck[i] = false;
1735                }
1736                // ----------------------
1737               
1738                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1739        spells[0].info = dbcSpell.LookupEntry(MORTAL_WOUND);
1740                spells[0].targettype = TARGET_ATTACKING;
1741                spells[0].instant = false;
1742                spells[0].perctrigger = 15.0f;
1743                spells[0].attackstoptimer = 2000; // 1sec
1744
1745                spells[1].info = dbcSpell.LookupEntry(TERRIFYING_ROAR);
1746                spells[1].targettype = TARGET_VARIOUS;
1747                spells[1].instant = false;
1748                spells[1].perctrigger = 5.0f;
1749                spells[1].attackstoptimer = 3000; // 1sec
1750
1751                spells[2].info = dbcSpell.LookupEntry(FRENZY);
1752                spells[2].targettype = TARGET_SELF;
1753                spells[2].instant = false;
1754                spells[2].perctrigger = 5.0f;
1755                spells[2].attackstoptimer = 1000; // 1sec
1756
1757    }
1758   
1759    void OnCombatStart(Unit* mTarget)
1760    {
1761        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1762    }
1763
1764    void OnCombatStop(Unit* mTarget)
1765    {
1766        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1767        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1768        RemoveAIUpdateEvent();
1769    }
1770
1771        void OnTargetDied(Unit* mTarget)
1772    { 
1773    }
1774
1775    void OnDied(Unit* mKiller)
1776    {
1777       RemoveAIUpdateEvent();
1778    }
1779
1780    void AIUpdate()
1781    {
1782                float val = (float)RandomFloat(100.0f);
1783        SpellCast(val);
1784    }
1785
1786    void SpellCast(float val)
1787    {
1788        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1789        {
1790                        float comulativeperc = 0;
1791                    Unit* target = NULL;
1792                        for(int i=0;i<nrspells;i++)
1793                        {
1794                                if(!spells[i].perctrigger) continue;
1795                               
1796                                if(m_spellcheck[i])
1797                                {
1798                                        target = _unit->GetAIInterface()->GetNextTarget();
1799                                        switch(spells[i].targettype)
1800                                        {
1801                                                case TARGET_SELF:
1802                                                case TARGET_VARIOUS:
1803                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1804                                                case TARGET_ATTACKING:
1805                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1806                                                case TARGET_DESTINATION:
1807                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1808                                        }
1809                                        m_spellcheck[i] = false;
1810                                        return;
1811                                }
1812
1813                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1814                                {
1815                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1816                                        m_spellcheck[i] = true;
1817                                }
1818                                comulativeperc += spells[i].perctrigger;
1819                        }
1820        }
1821    }
1822
1823protected:
1824
1825        int nrspells;
1826};
1827
1828// ---- Deathknight Wing ----
1829
1830// Bony Construct AI
1831#define CN_BONY_CONSTRUCT 16167
1832
1833#define SWEEPING_SLAM 25322
1834//TODO: Melee Chain Cleave - Strikes enemies in front of the Construct, chaining to anyone in melee range of the targets.
1835
1836class BonyConstructAI : public CreatureAIScript
1837{
1838public:
1839        ADD_CREATURE_FACTORY_FUNCTION(BonyConstructAI);
1840        SP_AI_Spell spells[1];
1841        bool m_spellcheck[1];
1842
1843    BonyConstructAI(Creature* pCreature) : CreatureAIScript(pCreature)
1844    {
1845                // -- Number of spells to add --
1846                nrspells = 1;
1847
1848                // --- Initialization ---
1849                for(int i=0;i<nrspells;i++)
1850                {
1851                        m_spellcheck[i] = false;
1852                }
1853                // ----------------------
1854               
1855                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1856        spells[0].info = dbcSpell.LookupEntry(SWEEPING_SLAM);
1857                spells[0].targettype = TARGET_VARIOUS;
1858                spells[0].instant = false;
1859                spells[0].perctrigger = 15.0f;
1860                spells[0].attackstoptimer = 2000; // 1sec
1861
1862    }
1863   
1864    void OnCombatStart(Unit* mTarget)
1865    {
1866        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1867    }
1868
1869    void OnCombatStop(Unit* mTarget)
1870    {
1871        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1872        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1873        RemoveAIUpdateEvent();
1874    }
1875
1876    void OnDied(Unit* mKiller)
1877    {
1878       RemoveAIUpdateEvent();
1879    }
1880
1881    void AIUpdate()
1882    {
1883                float val = (float)RandomFloat(100.0f);
1884        SpellCast(val);
1885    }
1886
1887    void SpellCast(float val)
1888    {
1889        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1890        {
1891                        float comulativeperc = 0;
1892                    Unit* target = NULL;
1893                        for(int i=0;i<nrspells;i++)
1894                        {
1895                                if(!spells[i].perctrigger) continue;
1896                               
1897                                if(m_spellcheck[i])
1898                                {
1899                                        target = _unit->GetAIInterface()->GetNextTarget();
1900                                        switch(spells[i].targettype)
1901                                        {
1902                                                case TARGET_SELF:
1903                                                case TARGET_VARIOUS:
1904                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
1905                                                case TARGET_ATTACKING:
1906                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
1907                                                case TARGET_DESTINATION:
1908                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
1909                                        }
1910                                        m_spellcheck[i] = false;
1911                                        return;
1912                                }
1913
1914                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
1915                                {
1916                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
1917                                        m_spellcheck[i] = true;
1918                                }
1919                                comulativeperc += spells[i].perctrigger;
1920                        }
1921        }
1922    }
1923
1924protected:
1925
1926        int nrspells;
1927};
1928
1929
1930
1931// Death Lord AI
1932#define CN_DEATH_LORD 16861
1933
1934#define AURA_OF_AGONY 28413
1935
1936class DeathLordAI : public CreatureAIScript
1937{
1938public:
1939        ADD_CREATURE_FACTORY_FUNCTION(DeathLordAI);
1940        SP_AI_Spell spells[1];
1941        bool m_spellcheck[1];
1942
1943    DeathLordAI(Creature* pCreature) : CreatureAIScript(pCreature)
1944    {
1945                // -- Number of spells to add --
1946                nrspells = 1;
1947
1948                // --- Initialization ---
1949                for(int i=0;i<nrspells;i++)
1950                {
1951                        m_spellcheck[i] = false;
1952                }
1953                // ----------------------
1954               
1955                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
1956        spells[0].info = dbcSpell.LookupEntry(AURA_OF_AGONY);
1957                spells[0].targettype = TARGET_VARIOUS;
1958                spells[0].instant = false;
1959                spells[0].perctrigger = 15.0f;
1960                spells[0].attackstoptimer = 2000; // 1sec
1961
1962    }
1963   
1964    void OnCombatStart(Unit* mTarget)
1965    {
1966        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
1967    }
1968
1969    void OnCombatStop(Unit* mTarget)
1970    {
1971        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
1972        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
1973        RemoveAIUpdateEvent();
1974    }
1975
1976    void OnDied(Unit* mKiller)
1977    {
1978       RemoveAIUpdateEvent();
1979    }
1980
1981    void AIUpdate()
1982    {
1983                float val = (float)RandomFloat(100.0f);
1984        SpellCast(val);
1985    }
1986
1987    void SpellCast(float val)
1988    {
1989        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
1990        {
1991                        float comulativeperc = 0;
1992                    Unit* target = NULL;
1993                        for(int i=0;i<nrspells;i++)
1994                        {
1995                                if(!spells[i].perctrigger) continue;
1996                               
1997                                if(m_spellcheck[i])
1998                                {
1999                                        target = _unit->GetAIInterface()->GetNextTarget();
2000                                        switch(spells[i].targettype)
2001                                        {
2002                                                case TARGET_SELF:
2003                                                case TARGET_VARIOUS:
2004                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
2005                                                case TARGET_ATTACKING:
2006                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
2007                                                case TARGET_DESTINATION:
2008                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
2009                                        }
2010                                        m_spellcheck[i] = false;
2011                                        return;
2012                                }
2013
2014                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
2015                                {
2016                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
2017                                        m_spellcheck[i] = true;
2018                                }
2019                                comulativeperc += spells[i].perctrigger;
2020                        }
2021        }
2022    }
2023
2024protected:
2025
2026        int nrspells;
2027};
2028
2029// -- BOSS'S --
2030
2031// Instructor Razuvious AI
2032#define CN_INSTRUCTOR_RAZUVIOUS 16061
2033
2034#define UNBALANCING_STRIKE 26613
2035#define DISRUPTING_SHOUT 29107
2036
2037class RazuviousAI : public CreatureAIScript
2038{
2039public:
2040        ADD_CREATURE_FACTORY_FUNCTION(RazuviousAI);
2041        SP_AI_Spell spells[2];
2042        bool m_spellcheck[2];
2043
2044    RazuviousAI(Creature* pCreature) : CreatureAIScript(pCreature)
2045    {
2046                // -- Number of spells to add --
2047                nrspells = 2;
2048
2049                // --- Initialization ---
2050                for(int i=0;i<nrspells;i++)
2051                {
2052                        m_spellcheck[i] = false;
2053                }
2054                // ----------------------
2055               
2056                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
2057        spells[0].info = dbcSpell.LookupEntry(DISRUPTING_SHOUT);
2058                spells[0].targettype = TARGET_VARIOUS;
2059                spells[0].instant = false;
2060                spells[0].perctrigger = 15.0f;
2061                spells[0].attackstoptimer = 3000; // 1sec
2062
2063                spells[1].info = dbcSpell.LookupEntry(UNBALANCING_STRIKE);
2064                spells[1].targettype = TARGET_ATTACKING;
2065                spells[1].instant = false;
2066                spells[1].perctrigger = 35.0f;
2067                spells[1].attackstoptimer = 1000; // 1sec
2068
2069    }
2070   
2071    void OnCombatStart(Unit* mTarget)
2072    {
2073        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
2074    }
2075
2076    void OnCombatStop(Unit* mTarget)
2077    {
2078        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2079        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2080        RemoveAIUpdateEvent();
2081    }
2082
2083        void OnTargetDied(Unit* mTarget)
2084    { 
2085                if(Rand(50.0f))
2086                {
2087                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You should've stayed home!");
2088                        _unit->PlaySoundToSet(8862);
2089                }
2090                else
2091                {
2092                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You disappoint me, students!");
2093                        _unit->PlaySoundToSet(8863);
2094                }
2095    }
2096
2097    void OnDied(Unit* mKiller)
2098    {
2099                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "An honorable... death...");
2100                _unit->PlaySoundToSet(8860);
2101       RemoveAIUpdateEvent();
2102    }
2103
2104    void AIUpdate()
2105    {
2106                float val = (float)RandomFloat(100.0f);
2107        SpellCast(val);
2108    }
2109
2110    void SpellCast(float val)
2111    {
2112        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
2113        {
2114                        float comulativeperc = 0;
2115                    Unit* target = NULL;
2116                        for(int i=0;i<nrspells;i++)
2117                        {
2118                                if(!spells[i].perctrigger) continue;
2119                               
2120                                if(m_spellcheck[i])
2121                                {
2122                                        target = _unit->GetAIInterface()->GetNextTarget();
2123                                        switch(spells[i].targettype)
2124                                        {
2125                                                case TARGET_SELF:
2126                                                case TARGET_VARIOUS:
2127                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
2128                                                case TARGET_ATTACKING:
2129                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
2130                                                case TARGET_DESTINATION:
2131                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
2132                                        }
2133                                        m_spellcheck[i] = false;
2134                                        return;
2135                                }
2136
2137                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
2138                                {
2139                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
2140                                        m_spellcheck[i] = true;
2141                                }
2142                                comulativeperc += spells[i].perctrigger;
2143                        }
2144        }
2145    }
2146
2147protected:
2148
2149        int nrspells;
2150};
2151// - The Four Horsemen: -
2152
2153// Thane Korth'azz AI
2154#define CN_THANE_KORTHAZZ 16064
2155
2156#define MARK_OF_KORTHAZZ 28832
2157#define METEOR 35181 // 1 target
2158
2159class KorthazzAI : public CreatureAIScript
2160{
2161public:
2162        ADD_CREATURE_FACTORY_FUNCTION(KorthazzAI);
2163        SP_AI_Spell spells[2];
2164        bool m_spellcheck[2];
2165
2166    KorthazzAI(Creature* pCreature) : CreatureAIScript(pCreature)
2167    {
2168                // -- Number of spells to add --
2169                nrspells = 2;
2170
2171                // --- Initialization ---
2172                for(int i=0;i<nrspells;i++)
2173                {
2174                        m_spellcheck[i] = false;
2175                }
2176                // ----------------------
2177
2178                tountcooldown = 6;
2179                tountcont = 0;
2180                m_attackstart = false;
2181               
2182                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
2183        spells[0].info = dbcSpell.LookupEntry(MARK_OF_KORTHAZZ);
2184                spells[0].targettype = TARGET_VARIOUS;
2185                spells[0].instant = false;
2186                spells[0].perctrigger = 5.0f;
2187                spells[0].attackstoptimer = 1000; // 1sec
2188
2189                spells[1].info = dbcSpell.LookupEntry(METEOR);
2190                spells[1].targettype = TARGET_ATTACKING;
2191                spells[1].instant = false;
2192                spells[1].perctrigger = 15.0f;
2193                spells[1].attackstoptimer = 3000; // 1sec
2194
2195    }
2196   
2197    void OnCombatStart(Unit* mTarget)
2198    {
2199                m_attackstart = true;
2200                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Come out and fight ye wee ninny!");
2201                _unit->PlaySoundToSet(8899);
2202
2203        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
2204    }
2205
2206    void OnCombatStop(Unit* mTarget)
2207    {
2208                m_attackstart = false;
2209        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2210        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2211        RemoveAIUpdateEvent();
2212    }
2213
2214        void OnTargetDied(Unit* mTarget)
2215    { 
2216                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Next time, bring more friends!");
2217                _unit->PlaySoundToSet(8901);
2218    }
2219
2220    void OnDied(Unit* mKiller)
2221    {
2222                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "What a bloody waste this is!");
2223                _unit->PlaySoundToSet(8900);
2224                _unit->CastSpell(_unit, spells[1].info, spells[1].instant);
2225                // Chest check
2226                Unit* hrsone = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16065);
2227                Unit* hrstwo = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16063);
2228                Object* chest = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(2520.66f, -2955.36f, 245.634f, 181366);
2229                if( hrsone != NULL && hrstwo != NULL )
2230                {
2231                        if(!hrsone->isAlive() && !hrstwo->isAlive() && !chest)
2232                        {
2233                                _unit->GetMapMgr()->GetInterface()->SpawnGameObject(181366 , 2520.66f, -2955.36f, 245.634f, 5.58505f, true, 0 , 0); 
2234                                RemoveAIUpdateEvent();
2235                        }
2236                        else if(!hrsone->isAlive() && !hrstwo->isAlive() && chest)
2237                        {
2238                                RemoveAIUpdateEvent();
2239                        }
2240                        else if(chest)
2241                        {
2242                                RemoveAIUpdateEvent();
2243                        }
2244                        else
2245                        {
2246                                RemoveAIUpdateEvent();
2247                        }
2248                }
2249                else
2250                {
2251                        RemoveAIUpdateEvent();
2252                }
2253    }
2254
2255    void AIUpdate()
2256    {
2257                if(!m_attackstart)
2258                {
2259                        if(!tountcooldown)
2260                        {
2261                                tountcooldown = 6;
2262                               
2263                                switch(tountcont)
2264                                {
2265                                        case 0:
2266                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "To arms, ye roustabouts! We've got company!");
2267                                                _unit->PlaySoundToSet(8903);
2268                                        case 1:
2269                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I heard about enough of yer sniveling. Shut yer fly trap 'afore I shut it for ye!");
2270                                                _unit->PlaySoundToSet(8904);
2271                                        case 2:
2272                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I'm gonna enjoy killin' these slack-jawed daffodils!");
2273                                                _unit->PlaySoundToSet(8905);
2274
2275                                }
2276                                tountcont++;
2277                                if(tountcont >= 3)
2278                                        tountcont = 0;
2279                        }
2280                        tountcooldown--;
2281                }
2282
2283                if(m_spellcheck[0])
2284                {
2285                        _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I like my meat extra crispy!");
2286                        _unit->PlaySoundToSet(8902);
2287                }
2288
2289                float val = (float)RandomFloat(100.0f);
2290        SpellCast(val);
2291    }
2292
2293    void SpellCast(float val)
2294    {
2295        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
2296        {
2297                        float comulativeperc = 0;
2298                    Unit* target = NULL;
2299                        for(int i=0;i<nrspells;i++)
2300                        {
2301                                if(!spells[i].perctrigger) continue;
2302                               
2303                                if(m_spellcheck[i])
2304                                {
2305                                        target = _unit->GetAIInterface()->GetNextTarget();
2306                                        switch(spells[i].targettype)
2307                                        {
2308                                                case TARGET_SELF:
2309                                                case TARGET_VARIOUS:
2310                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
2311                                                case TARGET_ATTACKING:
2312                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
2313                                                case TARGET_DESTINATION:
2314                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
2315                                        }
2316                                        m_spellcheck[i] = false;
2317                                        return;
2318                                }
2319
2320                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
2321                                {
2322                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
2323                                        m_spellcheck[i] = true;
2324                                }
2325                                comulativeperc += spells[i].perctrigger;
2326                        }
2327        }
2328    }
2329
2330protected:
2331
2332    bool m_attackstart;
2333        uint32 tountcooldown,tountcont;
2334        int nrspells;
2335};
2336
2337/*
23388899 - Come out and fight ye wee ninny!
23398900 - what a bloody waste this is!
23408901 - next time. bring more friend
23418902 - i like my meat extra crispy
23428903 - To arms, ye roustabouts! We've got company!
23438904 - I heard about enough of yer sniveling. Shut yer fly trap 'afore I shut it for ye!
23448905 - I'm gonna enjoy killin' these slack-jawed daffodils!
2345
23468899, 'A_KOR_NAXX_AGGRO'
23478900, 'A_KOR_NAXX_DEATH'
23488901, 'A_KOR_NAXX_SLAY'
23498902, 'A_KOR_NAXX_SPECIAL'
23508903, 'A_KOR_NAXX_TAUNT01'
23518904, 'A_KOR_NAXX_TAUNT02'
23528905, 'A_KOR_NAXX_TAUNT03'
2353*/
2354
2355// Baron Rivendare AI
2356#define CN_Baron_Rivendare_4H 30549 //4H not to confuse with Strat UD Side..
2357//Gief new Strat boss blizz or you make Stab a sad panda
2358
2359
2360// Lady Blaumeux AI
2361#define CN_LADY_BLAUMEUX 16065
2362
2363#define MARK_OF_BLAUMEUX 28833
2364#define VOID_ZONE 28863 // TODO: DUMMY PART
2365
2366class BlaumeuxAI : public CreatureAIScript
2367{
2368public:
2369        ADD_CREATURE_FACTORY_FUNCTION(BlaumeuxAI);
2370        SP_AI_Spell spells[2];
2371        bool m_spellcheck[2];
2372
2373    BlaumeuxAI(Creature* pCreature) : CreatureAIScript(pCreature)
2374    {
2375                // -- Number of spells to add --
2376                nrspells = 2;
2377
2378                // --- Initialization ---
2379                for(int i=0;i<nrspells;i++)
2380                {
2381                        m_spellcheck[i] = false;
2382                }
2383                // ----------------------
2384
2385                tountcooldown = 16;
2386                tountcont = 0;
2387                m_attackstart = false;
2388               
2389                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
2390        spells[0].info = dbcSpell.LookupEntry(MARK_OF_BLAUMEUX);
2391                spells[0].targettype = TARGET_VARIOUS;
2392                spells[0].instant = false;
2393                spells[0].perctrigger = 5.0f;
2394                spells[0].attackstoptimer = 1000; // 1sec
2395
2396                spells[1].info = dbcSpell.LookupEntry(VOID_ZONE);
2397                spells[1].targettype = TARGET_VARIOUS;
2398                spells[1].instant = false;
2399                spells[1].perctrigger = 15.0f;
2400                spells[1].attackstoptimer = 3000; // 1sec
2401
2402    }
2403   
2404    void OnCombatStart(Unit* mTarget)
2405    {
2406                m_attackstart = true;
2407                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Defend yourself!");
2408                _unit->PlaySoundToSet(8892);
2409
2410        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
2411    }
2412
2413    void OnCombatStop(Unit* mTarget)
2414    {
2415                m_attackstart = false;
2416        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2417        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2418        RemoveAIUpdateEvent();
2419    }
2420
2421        void OnTargetDied(Unit* mTarget)
2422    { 
2423                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Who's next?");
2424                _unit->PlaySoundToSet(8894);
2425    }
2426
2427    void OnDied(Unit* mKiller)
2428    {
2429                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Tou...che.");
2430                _unit->PlaySoundToSet(8893);
2431                _unit->CastSpell(_unit, spells[1].info, spells[1].instant);
2432                // Chest check
2433                Unit* hrsone = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16064);
2434                Unit* hrstwo = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16063);
2435                Object* chest = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(2520.66f, -2955.36f, 245.634f, 181366);
2436               
2437                if (hrsone && hrstwo)
2438                        if(!hrsone->isAlive() && !hrstwo->isAlive() && !chest)
2439                        {
2440                                _unit->GetMapMgr()->GetInterface()->SpawnGameObject(181366 , 2520.66f, -2955.36f, 245.634f, 5.58505f, true, 0, 0); 
2441                        }
2442
2443                RemoveAIUpdateEvent();
2444        }
2445       
2446    void AIUpdate()
2447    {
2448                if(!m_attackstart)
2449                {
2450                        if(!tountcooldown)
2451                        {
2452                                tountcooldown = 16;
2453                               
2454                                switch(tountcont)
2455                                {
2456                                        case 0:
2457                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Come, Zeliek, do not drive them out. Not before we've had our fun.");
2458                                                _unit->PlaySoundToSet(8896);
2459                                        case 1:
2460                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "I do hope they stay alive long enough for me to... introduce myself.");
2461                                                _unit->PlaySoundToSet(8897);
2462                                        case 2:
2463                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "The first kill goes to me! Anyone care to wager?");
2464                                                _unit->PlaySoundToSet(8898);
2465
2466                                }
2467                                tountcont++;
2468                                if(tountcont >= 3)
2469                                        tountcont = 0;
2470                        }
2471                        tountcooldown--;
2472                }
2473
2474                if(m_spellcheck[0])
2475                {
2476                        _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Your life is mine!");
2477                        _unit->PlaySoundToSet(8895);
2478                }
2479
2480                float val = (float)RandomFloat(100.0f);
2481        SpellCast(val);
2482    }
2483
2484    void SpellCast(float val)
2485    {
2486        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
2487        {
2488                        float comulativeperc = 0;
2489                    Unit* target = NULL;
2490                        for(int i=0;i<nrspells;i++)
2491                        {
2492                                if(!spells[i].perctrigger) continue;
2493                               
2494                                if(m_spellcheck[i])
2495                                {
2496                                        target = _unit->GetAIInterface()->GetNextTarget();
2497                                        switch(spells[i].targettype)
2498                                        {
2499                                                case TARGET_SELF:
2500                                                case TARGET_VARIOUS:
2501                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
2502                                                case TARGET_ATTACKING:
2503                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
2504                                                case TARGET_DESTINATION:
2505                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
2506                                        }
2507                                        m_spellcheck[i] = false;
2508                                        return;
2509                                }
2510
2511                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
2512                                {
2513                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
2514                                        m_spellcheck[i] = true;
2515                                }
2516                                comulativeperc += spells[i].perctrigger;
2517                        }
2518        }
2519    }
2520
2521protected:
2522
2523    bool m_attackstart;
2524        uint32 tountcooldown,tountcont;
2525        int nrspells;
2526};
2527
2528/*
25298892 - Defend yourself
25308893 - Tou...che
25318894 - Who's next?
25328895 - Your life is mine!
25338896 - Come, Zeliek, do not drive them out. Not before we've had our fun
25348897 - I do hope they stay alive long enough for me to... introduce myself,
25358898 - The first kill goes to me! Anyone care to wager?
2536
25378892, 'A_BLA_NAXX_AGGRO'
25388893, 'A_BLA_NAXX_DEATH'
25398894, 'A_BLA_NAXX_SLAY'
25408895, 'A_BLA_NAXX_SPECIAL'
25418896, 'A_BLA_NAXX_TAUNT01'
25428897, 'A_BLA_NAXX_TAUNT02'
25438898, 'A_BLA_NAXX_TAUNT03'
2544*/
2545
2546// Sir Zeliek AI
2547#define CN_SIR_ZELIEK 16063
2548
2549#define MARK_OF_ZELIEK 28835
2550#define HOLY_WRATH 32445 // 1target
2551
2552class ZeliekAI : public CreatureAIScript
2553{
2554public:
2555        ADD_CREATURE_FACTORY_FUNCTION(ZeliekAI);
2556        SP_AI_Spell spells[2];
2557        bool m_spellcheck[2];
2558
2559    ZeliekAI(Creature* pCreature) : CreatureAIScript(pCreature)
2560    {
2561                // -- Number of spells to add --
2562                nrspells = 2;
2563
2564                // --- Initialization ---
2565                for(int i=0;i<nrspells;i++)
2566                {
2567                        m_spellcheck[i] = false;
2568                }
2569                // ----------------------
2570
2571                tountcooldown = 13;
2572                tountcont = 0;
2573                m_attackstart = false;
2574               
2575                // Create basic info for spells here, and play with it later , fill always the info, targettype and if is instant or not!
2576        spells[0].info = dbcSpell.LookupEntry(MARK_OF_ZELIEK);
2577                spells[0].targettype = TARGET_VARIOUS;
2578                spells[0].instant = false;
2579                spells[0].perctrigger = 5.0f;
2580                spells[0].attackstoptimer = 1000; // 1sec
2581
2582                spells[1].info = dbcSpell.LookupEntry(HOLY_WRATH);
2583                spells[1].targettype = TARGET_ATTACKING;
2584                spells[1].instant = false;
2585                spells[1].perctrigger = 15.0f;
2586                spells[1].attackstoptimer = 1000; // 1sec
2587
2588    }
2589   
2590    void OnCombatStart(Unit* mTarget)
2591    {
2592                m_attackstart = true;
2593                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Flee before its too late!");
2594                _unit->PlaySoundToSet(8913);
2595
2596        RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
2597    }
2598
2599    void OnCombatStop(Unit* mTarget)
2600    {
2601                m_attackstart = false;
2602        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2603        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2604        RemoveAIUpdateEvent();
2605    }
2606
2607        void OnTargetDied(Unit* mTarget)
2608    { 
2609                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Forgive me!");
2610                _unit->PlaySoundToSet(8915);
2611    }
2612
2613    void OnDied(Unit* mKiller)
2614    {
2615                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "It is... as it should be.");
2616                _unit->PlaySoundToSet(8914);
2617                _unit->CastSpell(_unit, spells[1].info, spells[1].instant);
2618                // Chest check
2619                Unit* hrsone = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16064);
2620                Unit* hrstwo = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), 16065);
2621                Object* chest = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(2520.66f, -2955.36f, 245.634f, 181366); 
2622               
2623                if(!hrsone->isAlive() && !hrstwo->isAlive() && !chest)
2624                {
2625                        _unit->GetMapMgr()->GetInterface()->SpawnGameObject(181366 , 2520.66f, -2955.36f, 245.634f, 5.58505f, true, 0, 0); 
2626                        RemoveAIUpdateEvent();
2627                }
2628                else if(!hrsone->isAlive() && !hrstwo->isAlive() && chest)
2629                {
2630                        RemoveAIUpdateEvent();
2631                }
2632                else if(chest)
2633                {
2634                        RemoveAIUpdateEvent();
2635                }
2636                else
2637                {
2638                        RemoveAIUpdateEvent();
2639                }
2640    }
2641
2642    void AIUpdate()
2643    {
2644                if(!m_attackstart)
2645                {
2646                        if(!tountcooldown)
2647                        {
2648                                tountcooldown = 13;
2649                               
2650                                switch(tountcont)
2651                                {
2652                                        case 0:
2653                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Invaders, cease this foolish venture at once! Turn away while you still can!");
2654                                                _unit->PlaySoundToSet(8917);
2655                                        case 1:
2656                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Perhaps they will come to their senses, and run away as fast as they can!");
2657                                                _unit->PlaySoundToSet(8918);
2658                                        case 2:
2659                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "Do not continue! Turn back while there's still time!");
2660                                                _unit->PlaySoundToSet(8919);
2661
2662                                }
2663                                tountcont++;
2664                                if(tountcont >= 3)
2665                                        tountcont = 0;
2666                        }
2667                        tountcooldown--;
2668                }
2669
2670                if(m_spellcheck[0])
2671                {
2672                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "i have no choice but to obey!");
2673                        _unit->PlaySoundToSet(8916);
2674                }
2675
2676                float val = (float)RandomFloat(100.0f);
2677        SpellCast(val);
2678    }
2679
2680    void SpellCast(float val)
2681    {
2682        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
2683        {
2684                        float comulativeperc = 0;
2685                    Unit* target = NULL;
2686                        for(int i=0;i<nrspells;i++)
2687                        {
2688                                if(!spells[i].perctrigger) continue;
2689                               
2690                                if(m_spellcheck[i])
2691                                {
2692                                        target = _unit->GetAIInterface()->GetNextTarget();
2693                                        switch(spells[i].targettype)
2694                                        {
2695                                                case TARGET_SELF:
2696                                                case TARGET_VARIOUS:
2697                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
2698                                                case TARGET_ATTACKING:
2699                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
2700                                                case TARGET_DESTINATION:
2701                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
2702                                        }
2703                                        m_spellcheck[i] = false;
2704                                        return;
2705                                }
2706
2707                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
2708                                {
2709                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
2710                                        m_spellcheck[i] = true;
2711                                }
2712                                comulativeperc += spells[i].perctrigger;
2713                        }
2714        }
2715    }
2716
2717protected:
2718
2719    bool m_attackstart;
2720        uint32 tountcooldown,tountcont;
2721        int nrspells;
2722};
2723
2724// -- Sapphiron Encounter by M4ksiu -- //
2725
2726// Settings
2727
2728#define DISABLE_FROST_BREATH
2729
2730// Frost Breath TrgiggerAI
2731
2732#define CN_FROST_BREATH_TRIGGER         50010   // Flying "ball" of frost energy
2733#define CN_FROST_BREATH_TRIGGER2        50011   // Explosion
2734#define CN_FROST_BREATH_TRIGGER3        50012   // Wing Buffet
2735#define CN_CHILL_TRIGGER                        50013   // Mass chill trigger (used, because we can't cast many aoe triggers on one character >_>)
2736
2737// Air phase spells
2738#define FROST_BREATH            28524
2739#define FROST_BREATH_EFFECT     30101
2740#define FROST_BREATH_DAMAGE     29318
2741
2742// Additional spells
2743#define SAPPHIRONS_WING_BUFFET  29328
2744
2745struct Spawns
2746{
2747        float x;
2748        float y;
2749        float z;
2750        float o;
2751};
2752
2753struct Spawns PhaseTwoWP[]=
2754{
2755        {  },
2756        { 3520.820068f, -5233.799805f, 137.626007f, 4.553010f }
2757};
2758
2759struct Spawns IceBlocks[]=      // Those are not blizzlike pos, because those blocks are spawned randomly
2760{
2761        {  },
2762        { 3580.986084f, -5241.330078f, 137.627304f, 3.006957f },
2763        { 3562.967285f, -5257.952148f, 137.860916f, 2.468959f },
2764        { 3569.620850f, -5276.108398f, 137.582733f, 2.480744f },
2765        { 3551.420410f, -5283.535156f, 137.731903f, 2.009505f },
2766        { 3535.933594f, -5294.710938f, 138.080002f, 1.823366f },
2767        { 3522.235107f, -5286.610352f, 138.115601f, 1.532768f },
2768        { 3503.184814f, -5296.418945f, 138.111252f, 1.222535f },
2769        { 3489.055664f, -5278.863770f, 138.119934f, 0.884814f },
2770        { 3473.002686f, -5277.641602f, 137.733414f, 0.680609f },
2771        { 3472.302734f, -5255.734863f, 137.755569f, 0.331107f },
2772        { 3458.193848f, -5241.013672f, 137.566147f, 0.111195f },
2773        { 3463.324463f, -5221.530273f, 137.634888f, 6.084152f },
2774        { 3467.574219f, -5200.617676f, 137.559662f, 5.860314f },
2775        { 3479.394775f, -5178.301758f, 140.904312f, 5.405583f },
2776        { 3507.219727f, -5180.725098f, 140.625473f, 4.431685f },
2777        { 3518.371338f, -5172.666504f, 142.269135f, 4.694800f },
2778        { 3542.516846f, -5184.699707f, 140.655182f, 4.470973f },
2779        { 3559.013916f, -5183.916016f, 140.899689f, 4.644558f },
2780        { 3559.006592f, -5183.923340f, 140.895554f, 3.952624f },
2781        { 3571.978760f, -5209.633301f, 137.671906f, 3.514374f }
2782};
2783
2784/*struct Spawns IceBlocks[]=    // Those are not blizzlike pos, because those blocks are spawned randomly
2785{
2786        {  },
2787        { 3580.986084f, -5241.330078f, 137.627304f, 3.006957f },
2788        { 3562.967285f, -5257.952148f, 137.860916f, 2.468959f },
2789        { 3569.620850f, -5276.108398f, 137.582733f, 2.480744f },
2790
2791        { 3535.933594f, -5294.710938f, 138.080002f, 1.823366f },
2792        { 3522.235107f, -5286.610352f, 138.115601f, 1.532768f },
2793        { 3503.184814f, -5296.418945f, 138.111252f, 1.222535f },
2794       
2795        { 3473.002686f, -5277.641602f, 137.733414f, 0.680609f },
2796        { 3472.302734f, -5255.734863f, 137.755569f, 0.331107f },
2797        { 3458.193848f, -5241.013672f, 137.566147f, 0.111195f },
2798
2799        { 3467.574219f, -5200.617676f, 137.559662f, 5.860314f },
2800        { 3479.394775f, -5178.301758f, 140.904312f, 5.405583f },
2801        { 3507.219727f, -5180.725098f, 140.625473f, 4.431685f },
2802
2803        { 3542.516846f, -5184.699707f, 140.655182f, 4.470973f },
2804        { 3559.013916f, -5183.916016f, 140.899689f, 4.644558f },
2805        { 3559.006592f, -5183.923340f, 140.895554f, 3.952624f },
2806
2807        { 3551.420410f, -5283.535156f, 137.731903f, 2.009505f },
2808        { 3489.055664f, -5278.863770f, 138.119934f, 0.884814f },
2809        { 3463.324463f, -5221.530273f, 137.634888f, 6.084152f },
2810        { 3518.371338f, -5172.666504f, 142.269135f, 4.694800f },
2811        { 3571.978760f, -5209.633301f, 137.671906f, 3.514374f }
2812};*/
2813
2814class FrostBreathTriggerAI : public CreatureAIScript
2815{
2816public:
2817        ADD_CREATURE_FACTORY_FUNCTION(FrostBreathTriggerAI);
2818
2819    FrostBreathTriggerAI(Creature* pCreature) : CreatureAIScript(pCreature)
2820    {
2821                _unit->GetAIInterface()->MoveTo(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z + 10.5f, PhaseTwoWP[1].o);
2822                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
2823                _unit->GetAIInterface()->m_moveFly = true;
2824                _unit->m_noRespawn = true;
2825                _unit->Despawn(7000, 0);
2826
2827                RegisterAIUpdateEvent(1000);
2828
2829                AICounter = 7;
2830    }
2831   
2832    void OnCombatStart(Unit* mTarget) {}
2833
2834    void OnCombatStop(Unit* mTarget)
2835    {
2836        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2837        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2838    }
2839
2840    void OnDied(Unit* mKiller)
2841    {
2842       RemoveAIUpdateEvent();
2843    }
2844
2845    void AIUpdate()
2846    {
2847                _unit->CastSpell(_unit, FROST_BREATH_EFFECT, true);
2848
2849                AICounter--;
2850                if (AICounter == 6)
2851                        _unit->GetAIInterface()->MoveTo(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z + AICounter * 1.5f, PhaseTwoWP[1].o);
2852                else
2853                        _unit->GetAIInterface()->MoveTo(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, PhaseTwoWP[1].o);
2854        }
2855       
2856protected:
2857
2858        int AICounter;
2859};
2860
2861class FrostBreathTrigger2AI : public CreatureAIScript
2862{
2863public:
2864        ADD_CREATURE_FACTORY_FUNCTION(FrostBreathTrigger2AI);
2865
2866    FrostBreathTrigger2AI(Creature* pCreature) : CreatureAIScript(pCreature)
2867    {
2868#ifdef DISABLE_FROST_BREATH
2869                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
2870#else
2871                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
2872#endif
2873                _unit->GetAIInterface()->disable_melee = true;
2874                _unit->GetAIInterface()->m_canMove = false;
2875                _unit->m_noRespawn = true;
2876                _unit->Despawn(8000, 0);
2877
2878                _unit->CastSpell(_unit, FROST_BREATH, false);
2879        }
2880
2881        void OnCombatStop(Unit* mTarget)
2882        {
2883        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2884        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2885    }
2886
2887    void OnDied(Unit* mKiller)
2888    {
2889       RemoveAIUpdateEvent();
2890    }
2891};
2892
2893class FrostBreathTrigger3AI : public CreatureAIScript
2894{
2895public:
2896        ADD_CREATURE_FACTORY_FUNCTION(FrostBreathTrigger3AI);
2897
2898    FrostBreathTrigger3AI(Creature* pCreature) : CreatureAIScript(pCreature)
2899    {
2900                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
2901                _unit->CastSpell(_unit, SAPPHIRONS_WING_BUFFET, true);
2902                _unit->GetAIInterface()->disable_melee = true;
2903                _unit->GetAIInterface()->m_canMove = false;
2904                _unit->m_noRespawn = true;
2905
2906                RegisterAIUpdateEvent(1000);
2907    }
2908
2909    void OnCombatStop(Unit* mTarget)
2910    {
2911        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2912        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2913    }
2914
2915    void OnDied(Unit* mKiller)
2916    {
2917       RemoveAIUpdateEvent();
2918    }
2919
2920    void AIUpdate()
2921    {
2922                _unit->CastSpell(_unit, SAPPHIRONS_WING_BUFFET, true);
2923        }
2924};
2925
2926class ChillTriggerAI : public CreatureAIScript
2927{
2928public:
2929        ADD_CREATURE_FACTORY_FUNCTION(ChillTriggerAI);
2930
2931    ChillTriggerAI(Creature* pCreature) : CreatureAIScript(pCreature)
2932    {
2933                _unit->CastSpellAoF(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), dbcSpell.LookupEntry(28547), true);
2934                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
2935                _unit->GetAIInterface()->disable_melee = true;
2936                _unit->GetAIInterface()->m_canMove = false;
2937                _unit->m_noRespawn = true;
2938                _unit->Despawn(15000, 0);
2939    }
2940
2941    void OnCombatStop(Unit* mTarget)
2942    {
2943        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
2944        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
2945    }
2946};
2947
2948// SapphironAI
2949// Missing spawning effect with building skeleton of Sappiron
2950#define CN_SAPPHIRON    15989
2951
2952// Land phase spells
2953#define LIFE_DRAIN                                      28542
2954#define CHILL                                           28547
2955#define FROST_AURA                                      28531
2956
2957// Air phase spells
2958#define ICEBOLT                                         28522
2959
2960// Additional spells
2961#define SAPPHIRON_DIES                          29357
2962#define BERSERK                                         26662   // 28498 - casts frostbolt (would be cool for Sapphiron), but every 2 sec for 5 min (~16k dmg per hit);
2963                                                                                        // 27680 - 10 mins instead 5 mins
2964// Researches
2965#define SAPPHIRON_BIRTH                         181356
2966#define FROSTWYRM_WATERFALL_DOOR        181225
2967#define ICE_BLOCK_GO                            181247
2968
2969// Move types
2970#define WALK    0
2971#define RUN             256
2972#define FLY             768
2973
2974// Immunities
2975#define IMMUNITY_DISEASE                        6681
2976#define IMMUNITY_SHADOW                         7743
2977#define IMMUNITY_FROST                          7940
2978#define IMMUNITY_NATURE                         7941
2979#define IMMUNITY_FIRE                           7942
2980#define IMMUNITY_HOLY                           34182
2981#define IMMUNITY_ARCANE                         34184
2982#define IMMUNITY_PHYSICAL                       34310
2983
2984class SapphironAI : public CreatureAIScript
2985{
2986public:
2987        ADD_CREATURE_FACTORY_FUNCTION(SapphironAI);
2988        SP_AI_Spell spells[4];
2989        bool m_spellcheck[4];
2990
2991    SapphironAI(Creature* pCreature) : CreatureAIScript(pCreature)
2992    {
2993                _unit->GetAIInterface()->addWayPoint(CreateWaypoint(1, 3000, RUN));
2994
2995                nrspells = 2;
2996                for(int i = 0; i < nrspells; i++)
2997                {
2998                        m_spellcheck[i] = false;
2999                        spells[i].casttime = 0;
3000                }
3001               
3002        spells[0].info = dbcSpell.LookupEntry(LIFE_DRAIN);
3003                spells[0].targettype = TARGET_VARIOUS;
3004                spells[0].instant = true;
3005                spells[0].perctrigger = 8.0f;
3006                spells[0].cooldown = 20;
3007                spells[0].attackstoptimer = 2000;
3008
3009                spells[1].info = dbcSpell.LookupEntry(CHILL);
3010                spells[1].targettype = TARGET_RANDOM_DESTINATION;
3011                spells[1].instant = true;
3012                spells[1].perctrigger = 10.0f;
3013                spells[1].cooldown = 15;
3014                spells[1].attackstoptimer = 1000;
3015                spells[1].mindist2cast = 0.0f;
3016                spells[1].maxdist2cast = 40.0f;
3017                spells[1].minhp2cast = 0;
3018                spells[1].maxhp2cast = 100;
3019
3020                spells[2].info = dbcSpell.LookupEntry(ICEBOLT);
3021                spells[2].targettype = TARGET_RANDOM_SINGLE;
3022                spells[2].instant = true;
3023                spells[2].perctrigger = 0.0f;
3024                spells[2].cooldown = 0;
3025                spells[2].attackstoptimer = 1000;
3026                spells[2].mindist2cast = 0.0f;
3027                spells[2].maxdist2cast = 70.0f;
3028                spells[2].minhp2cast = 0;
3029                spells[2].maxhp2cast = 100;
3030               
3031                spells[3].info = dbcSpell.LookupEntry(BERSERK);
3032                spells[3].targettype = TARGET_SELF;
3033                spells[3].instant = true;
3034                spells[3].perctrigger = 0.0f;
3035                spells[3].cooldown = 900;
3036                spells[3].attackstoptimer = 1000;
3037
3038                _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
3039                _unit->GetAIInterface()->SetAllowedToEnterCombat(true);
3040                _unit->GetAIInterface()->m_moveFly = false;
3041                _unit->GetAIInterface()->m_canMove = true;
3042                _unit->CastSpell(_unit, IMMUNITY_FROST, true);
3043
3044                WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
3045                data << _unit->GetNewGUID();
3046                data << uint32(0);
3047                _unit->SendMessageToSet(&data, false);
3048
3049                ChillCounter = NULL;
3050                FlightActions = 0;
3051                ChillCounter = 0;
3052                PhaseTimer = 0;
3053                m_phase = 1;
3054    }
3055   
3056    void OnCombatStart(Unit* mTarget)
3057    {
3058                for(int i = 0; i < nrspells; i++)
3059                        spells[i].casttime = 0;
3060
3061                spells[3].casttime = (uint32)time(NULL) + spells[3].cooldown;
3062
3063                _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
3064                _unit->GetAIInterface()->SetAllowedToEnterCombat(true);
3065                _unit->GetAIInterface()->m_moveFly = false;
3066                _unit->GetAIInterface()->m_canMove = true;
3067
3068                WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
3069                data << _unit->GetNewGUID();
3070                data << uint32(0);
3071                _unit->SendMessageToSet(&data, false);
3072
3073                GameObject* Waterfall = NULL;
3074                Waterfall = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(3536.852783f, -5159.951172f, 143.636139f, FROSTWYRM_WATERFALL_DOOR);
3075                if (Waterfall != NULL)
3076                {
3077                        Waterfall->SetState(1);
3078                }
3079
3080                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
3081
3082                PhaseTimer = (uint32)time(NULL) + 35;
3083                ChillCounter = NULL;
3084                FlightActions = 0;
3085                ChillCounter = 0;
3086                m_phase = 1;
3087    }
3088
3089    void OnCombatStop(Unit* mTarget)
3090    {
3091                Creature* BreathTrigger = NULL;
3092                BreathTrigger = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, CN_FROST_BREATH_TRIGGER3);
3093                if (BreathTrigger != NULL)
3094                        BreathTrigger->Despawn(0,0);
3095
3096                for (int i = 1; i < 21; i++)
3097                {
3098                        GameObject* IceBlock = NULL;
3099                        IceBlock = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(IceBlocks[i].x, IceBlocks[i].y, IceBlocks[i].z, ICE_BLOCK_GO);
3100                        if (IceBlock != NULL)
3101                        {
3102                                IceBlock->Delete();
3103                        }
3104                }
3105
3106                GameObject* Waterfall = NULL;
3107                Waterfall = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(3536.852783f, -5159.951172f, 143.636139f, FROSTWYRM_WATERFALL_DOOR);
3108                if (Waterfall != NULL)
3109                {
3110                        Waterfall->SetState(0);
3111                }
3112
3113                _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
3114                _unit->GetAIInterface()->SetAllowedToEnterCombat(true);
3115                _unit->GetAIInterface()->m_moveFly = false;
3116                _unit->GetAIInterface()->m_canMove = true;
3117
3118                WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
3119                data << _unit->GetNewGUID();
3120                data << uint32(0);
3121                _unit->SendMessageToSet(&data, false);
3122
3123                _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
3124                _unit->GetAIInterface()->SetAIState(STATE_IDLE);
3125
3126                RemoveAIUpdateEvent();
3127    }
3128
3129        void OnTargetDied(Unit* mTarget)
3130        {
3131        }
3132
3133    void OnDied(Unit* mKiller)
3134    {
3135                _unit->CastSpell(_unit, SAPPHIRON_DIES, true);
3136
3137                RemoveAIUpdateEvent();
3138    }
3139
3140    void AIUpdate()
3141    {
3142                uint32 t = (uint32)time(NULL);
3143                if (t > spells[3].casttime && _unit->GetCurrentSpell() == NULL)
3144                {
3145                        _unit->CastSpell(_unit, spells[3].info, spells[3].instant);
3146
3147                        spells[3].casttime = t + spells[3].cooldown;
3148                }
3149
3150                switch (m_phase)
3151                {
3152                case 1:
3153                        PhaseOne();
3154                        break;
3155                case 2:
3156                        PhaseTwo();
3157                        break;
3158                default:
3159                        {
3160                        }
3161                }
3162    }
3163
3164        void PhaseOne()
3165        {
3166                _unit->CastSpell(_unit, FROST_AURA, true);
3167
3168                if (_unit->GetAIInterface()->getMoveType() == MOVEMENTTYPE_WANTEDWP)
3169                        return;
3170
3171                if (_unit->GetHealthPct() > 10)
3172                {
3173                        uint32 t = (uint32)time(NULL);
3174                        if (t > PhaseTimer)
3175                        {
3176                                if (_unit->GetCurrentSpell() != NULL)
3177                                        _unit->GetCurrentSpell()->cancel();
3178
3179                                _unit->GetAIInterface()->SetAllowedToEnterCombat(false);
3180                                _unit->GetAIInterface()->StopMovement(0);
3181                                _unit->GetAIInterface()->SetAIState(STATE_SCRIPTMOVE);
3182                                _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_WANTEDWP);
3183                                _unit->GetAIInterface()->setWaypointToMove(1);
3184
3185                                return;
3186                        }
3187                }
3188
3189                if (ChillCounter > 0)
3190                {
3191                        ChillCounter--;
3192                        if (ChillTarget != NULL)
3193                        {
3194                                _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_CHILL_TRIGGER, ChillTarget->GetPositionX(), ChillTarget->GetPositionY(), ChillTarget->GetPositionZ(), ChillTarget->GetOrientation(), true, false, 0, 0);
3195                        }
3196
3197                        if (ChillCounter == 0)
3198                        {
3199                                ChillTarget = NULL;
3200                        }
3201                }
3202
3203                float val = (float)RandomFloat(100.0f);
3204        SpellCast(val);
3205        }
3206
3207        void PhaseTwo()
3208        {
3209                if (FlightActions == 0)
3210                {
3211                        _unit->GetAIInterface()->m_canMove = false;
3212                        _unit->GetAIInterface()->SetAllowedToEnterCombat(true);
3213                        _unit->GetAIInterface()->setCurrentAgent(AGENT_SPELL);
3214                        _unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
3215                        _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
3216                        _unit->GetAIInterface()->setWaypointToMove(0);
3217                }
3218
3219                if (FlightActions < 5)
3220                {
3221                        if (_unit->GetCurrentSpell() == NULL)
3222                        {
3223                                if (_unit->GetAIInterface()->GetNextTarget() != NULL)
3224                                {
3225                                        CastSpellOnRandomTarget(2, 0.0f, 40.0f, 0, 100);
3226
3227                                        FlightActions++;
3228                                        if (FlightActions >= 5)
3229                                        {
3230                                                uint32 LastOne = 0;
3231                                                for (int i = 0; i < 2; i++)
3232                                                {
3233                                                        uint32 Block = 0;
3234                                                        while (LastOne == Block)
3235                                                        {
3236                                                                Block = RandomUInt(5) + 15;
3237                                                        }
3238
3239                                                        LastOne = Block;
3240
3241                                                        GameObject* IceBlock = NULL;
3242                                                        IceBlock = _unit->GetMapMgr()->GetInterface()->SpawnGameObject(ICE_BLOCK_GO, IceBlocks[Block].x, IceBlocks[Block].y, IceBlocks[Block].z, IceBlocks[Block].o, true, 0, 0);
3243                                                        if (IceBlock != NULL)
3244                                                        {
3245                                                                IceBlock->SetUInt32Value(GAMEOBJECT_FLAGS, 1);
3246                                                        }
3247                                                }
3248
3249                                                RemoveAIUpdateEvent();
3250                                                RegisterAIUpdateEvent(3000);
3251
3252                                                FlightActions = 5;
3253                                        }
3254
3255                                        if (FlightActions == 2)
3256                                        {
3257                                                for (int i = 0; i < 2; i++)
3258                                                {
3259                                                        uint32 Block = 0;
3260                                                        if (i == 0)
3261                                                                Block = RandomUInt(3) + 1;
3262                                                        else
3263                                                                Block = RandomUInt(3) + 10;
3264
3265                                                        GameObject* IceBlock = NULL;
3266                                                        IceBlock = _unit->GetMapMgr()->GetInterface()->SpawnGameObject(ICE_BLOCK_GO, IceBlocks[Block].x, IceBlocks[Block].y, IceBlocks[Block].z, IceBlocks[Block].o, true, 0, 0);
3267                                                        if (IceBlock != NULL)
3268                                                        {
3269                                                                IceBlock->SetUInt32Value(GAMEOBJECT_FLAGS, 1);
3270                                                        }
3271                                                }
3272                                        }
3273
3274                                        if (FlightActions == 4)
3275                                        {
3276                                                for (int i = 0; i < 2; i++)
3277                                                {
3278                                                        uint32 Block = 0;
3279                                                        if (i == 0)
3280                                                                Block = RandomUInt(3) + 7;
3281                                                        else
3282                                                                Block = RandomUInt(9) + 13;
3283
3284                                                        GameObject* IceBlock = NULL;
3285                                                        IceBlock = _unit->GetMapMgr()->GetInterface()->SpawnGameObject(ICE_BLOCK_GO, IceBlocks[Block].x, IceBlocks[Block].y, IceBlocks[Block].z, IceBlocks[Block].o, true, 0, 0);
3286                                                        if (IceBlock != NULL)
3287                                                        {
3288                                                                IceBlock->SetUInt32Value(GAMEOBJECT_FLAGS, 1);
3289                                                        }
3290                                                }
3291                                        }
3292                                }
3293                        }
3294                }
3295
3296                else
3297                {
3298                        if (FlightActions == 5)
3299                        {
3300                                Unit* FlyingFrostBreath = NULL;
3301                                FlyingFrostBreath =_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FROST_BREATH_TRIGGER, PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z + 18.0f, _unit->GetOrientation(), true, false, 0, 0);
3302                                if (FlyingFrostBreath != NULL)
3303                                {
3304                                        FlyingFrostBreath->GetAIInterface()->MoveTo(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, PhaseTwoWP[1].o);
3305                                }
3306
3307                                _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FROST_BREATH_TRIGGER2, PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, _unit->GetOrientation(), true, false, 0, 0);
3308
3309                                RemoveAIUpdateEvent();
3310                                RegisterAIUpdateEvent(10000);
3311
3312                                Creature* BreathTrigger = NULL;
3313                                BreathTrigger = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, CN_FROST_BREATH_TRIGGER3);
3314                                if (BreathTrigger != NULL)
3315                                        BreathTrigger->Despawn(0,0);
3316                        }
3317
3318                        if (FlightActions == 6)
3319                        {
3320                                for (int i = 1; i < 21; i++)
3321                                {
3322                                        GameObject* IceBlock = NULL;
3323                                        IceBlock = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(IceBlocks[i].x, IceBlocks[i].y, IceBlocks[i].z, ICE_BLOCK_GO);
3324                                        if (IceBlock != NULL)
3325                                        {
3326                                                IceBlock->Delete();
3327                                        }
3328                                }
3329
3330                                _unit->GetAIInterface()->m_moveFly = false;
3331                                _unit->Emote(EMOTE_ONESHOT_LAND);
3332
3333                                WorldPacket data(SMSG_MOVE_UNSET_HOVER, 13);
3334                                data << _unit->GetNewGUID();
3335                                data << uint32(0);
3336                                _unit->SendMessageToSet(&data, false);
3337
3338                                RemoveAIUpdateEvent();
3339                                RegisterAIUpdateEvent(3000);
3340                        }
3341
3342                        if (FlightActions == 7)
3343                        {
3344                                _unit->GetAIInterface()->m_canMove = true;
3345                                _unit->GetAIInterface()->SetAllowedToEnterCombat(true);
3346                _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
3347                _unit->GetAIInterface()->SetAIState(STATE_SCRIPTIDLE);
3348                _unit->GetAIInterface()->setMoveType(MOVEMENTTYPE_DONTMOVEWP);
3349                _unit->GetAIInterface()->setWaypointToMove(0);
3350
3351                                RemoveAIUpdateEvent();
3352                                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
3353
3354                                PhaseTimer = (uint32)time(NULL) + 67;
3355                                ChillTarget = NULL;
3356                                FlightActions = 0;
3357                                ChillCounter = 0;
3358                                m_phase = 1;
3359                        }
3360
3361                        FlightActions++;
3362                }
3363        }
3364
3365        void SpellCast(float val)
3366    {
3367        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget() != NULL)
3368        {
3369                        float comulativeperc = 0;
3370                    Unit* target = NULL;
3371                        for (int i = 0; i < nrspells; i++)
3372                        {
3373                                if(!spells[i].perctrigger) continue;
3374                               
3375                                if(m_spellcheck[i])
3376                                {
3377                                        target = _unit->GetAIInterface()->GetNextTarget();
3378                                        switch(spells[i].targettype)
3379                                        {
3380                                                case TARGET_SELF:
3381                                                case TARGET_VARIOUS:
3382                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
3383                                                case TARGET_ATTACKING:
3384                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
3385                                                case TARGET_DESTINATION:
3386                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
3387                                                case TARGET_RANDOM_FRIEND:
3388                                                case TARGET_RANDOM_SINGLE:
3389                                                case TARGET_RANDOM_DESTINATION:
3390                                                        CastSpellOnRandomTarget(i, spells[i].mindist2cast, spells[i].maxdist2cast, spells[i].minhp2cast, spells[i].maxhp2cast); break;
3391                                        }
3392
3393                                        if (spells[i].speech != "")
3394                                        {
3395                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
3396                                                _unit->PlaySoundToSet(spells[i].soundid); 
3397                                        }
3398
3399                                        m_spellcheck[i] = false;
3400                                        return;
3401                                }
3402
3403                                uint32 t = (uint32)time(NULL);
3404                                if((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) && t > spells[i].casttime)
3405                                {
3406                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
3407                                        spells[i].casttime = t + spells[i].cooldown;
3408                                        m_spellcheck[i] = true;
3409                                }
3410
3411                                comulativeperc += spells[i].perctrigger;
3412                        }
3413        }
3414    }
3415
3416        void CastSpellOnRandomTarget(uint32 i, float mindist2cast, float maxdist2cast, int minhp2cast, int maxhp2cast)
3417        {
3418                if (!maxdist2cast) maxdist2cast = 100.0f;
3419                if (!maxhp2cast) maxhp2cast = 100;
3420
3421                if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget() != NULL)
3422        {
3423                        std::vector<Unit*> TargetTable;         /* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
3424                                                                                                /* If anyone wants to use this function, then leave this note!                                                                           */
3425                        for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr) 
3426                        { 
3427                                if (isHostile(_unit, (*itr)) && (*itr) != _unit && ((*itr)->GetTypeId()== TYPEID_UNIT || (*itr)->GetTypeId() == TYPEID_PLAYER) && (*itr)->GetInstanceID() == _unit->GetInstanceID())
3428                                {
3429                                        Unit* RandomTarget = NULL;
3430                                        RandomTarget = TO_UNIT(*itr);
3431
3432                                        if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) >= mindist2cast*mindist2cast && _unit->GetDistance2dSq(RandomTarget) <= maxdist2cast*maxdist2cast && _unit->GetAIInterface()->getThreatByPtr(RandomTarget) > 0 && isHostile(_unit, RandomTarget))
3433                                        {
3434                                                TargetTable.push_back(RandomTarget);
3435                                        } 
3436                                } 
3437                        }
3438
3439                        if (!TargetTable.size())
3440                                return;
3441
3442                        size_t RandTarget = rand()%TargetTable.size();
3443
3444                        Unit*  RTarget = TargetTable[RandTarget];
3445
3446                        if (RTarget == NULL)
3447                                return;
3448
3449                        if (i == 1)
3450                        {
3451                                ChillCounter = RandomUInt(3) + 3;
3452                                ChillTarget = RTarget;
3453                        }
3454
3455                        else
3456                        {
3457                                switch (spells[i].targettype)
3458                                {
3459                                case TARGET_RANDOM_FRIEND:
3460                                case TARGET_RANDOM_SINGLE:
3461                                        _unit->CastSpell(RTarget, spells[i].info, spells[i].instant); break;
3462                                case TARGET_RANDOM_DESTINATION:
3463                                        _unit->CastSpellAoF(RTarget->GetPositionX(), RTarget->GetPositionY(), RTarget->GetPositionZ(), spells[i].info, spells[i].instant); break;
3464                                }
3465                        }
3466
3467                        TargetTable.clear();
3468                }
3469        }
3470
3471        void OnReachWP(uint32 iWaypointId, bool bForwards)
3472    {
3473                if (iWaypointId == 1)
3474                {
3475                        _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_FROST_BREATH_TRIGGER3, PhaseTwoWP[1].x, PhaseTwoWP[1].y, PhaseTwoWP[1].z, _unit->GetOrientation(), true, false, 0, 0);
3476                        _unit->GetAIInterface()->m_moveFly = true;
3477                        _unit->Emote(EMOTE_ONESHOT_LIFTOFF);
3478
3479                        WorldPacket data(SMSG_MOVE_SET_HOVER, 13);
3480                        data << _unit->GetNewGUID();
3481                        data << uint32(0);
3482                        _unit->SendMessageToSet(&data, false);
3483
3484                        RemoveAIUpdateEvent();
3485                        RegisterAIUpdateEvent(3500);
3486
3487                        ChillTarget = NULL;
3488                        FlightActions = 0;
3489                        ChillCounter = 0;
3490                        m_phase = 2;
3491                }
3492        }
3493
3494        inline WayPoint* CreateWaypoint(int id, uint32 waittime, uint32 flags)
3495    {
3496        WayPoint * wp = _unit->CreateWaypointStruct();
3497        wp->id = id;
3498        wp->x = PhaseTwoWP[id].x;
3499        wp->y = PhaseTwoWP[id].y;
3500        wp->z = PhaseTwoWP[id].z;
3501        wp->o = PhaseTwoWP[id].o;
3502        wp->waittime = waittime;
3503        wp->flags = flags;
3504        wp->forwardemoteoneshot = 0;
3505        wp->forwardemoteid = 0;
3506        wp->backwardemoteoneshot = 0;
3507        wp->backwardemoteid = 0;
3508        wp->forwardskinid = 0;
3509        wp->backwardskinid = 0;
3510        return wp;
3511    }
3512
3513protected:
3514
3515        Unit* ChillTarget;      // I don't like it >_>
3516
3517        uint32 FlightActions;
3518        uint32 ChillCounter;
3519        uint32 PhaseTimer;
3520        uint32 m_phase;
3521        int nrspells;
3522};
3523
3524// -- Kel'thuzad Encounter by M4ksiu -- //
3525
3526// Encounter mobs
3527
3528#define CN_THE_LICH_KING 16980
3529#define CN_SOLDIER_OF_THE_FROZEN_WASTES 16427
3530#define CN_UNSTOPPABLE_ABOMINATION 16428
3531#define CN_SOUL_WEAVER 16429
3532#define CN_GUARDIAN_OF_ICECROWN 16441
3533
3534/*
3535  _____
3536 /  K  \
3537/1     4\
3538|       |
3539|2     5|
3540|       |
3541\3     6/
3542 \_ 7 _/
3543   | |
3544
3545*/
3546
3547static Spawns SFrozenWastes[] = // Soldier of the Frozen Wastes (no idea about those :| )
3548{
3549        { 3759.149902f, -5074.879883f, 143.175003f, 1.203640f },        // 1
3550        { 3762.959961f, -5067.399902f, 143.453003f, 0.893413f },
3551        { 3772.419922f, -5076.379883f, 143.466995f, 3.606970f },
3552        { 3779.699951f, -5078.180176f, 143.764008f, 4.038940f },
3553        { 3770.219971f, -5065.740234f, 143.477005f, 0.630304f },
3554        { 3765.709961f, -5060.799805f, 143.748001f, 1.608120f },
3555        { 3776.909912f, -5066.100098f, 143.550003f, 5.130640f },
3556        { 3782.659912f, -5069.529785f, 143.757004f, 5.150280f },
3557        { 3773.909912f, -5059.589844f, 143.774002f, 6.257680f },
3558        { 3780.260010f, -5061.580078f, 143.742996f, 5.169910f },
3559        { 3721.429932f, -5052.759766f, 143.442993f, 1.457330f },        // 2
3560        { 3732.149902f, -5051.589844f, 143.444000f, 1.017500f },
3561        { 3741.889893f, -5047.439941f, 143.886002f, 3.075250f },
3562        { 3726.229980f, -5043.410156f, 143.455994f, 6.150070f },
3563        { 3718.679932f, -5042.520020f, 143.768005f, 1.614410f },
3564        { 3733.060059f, -5040.979980f, 143.557007f, 1.669380f },
3565        { 3741.860107f, -5038.410156f, 143.917999f, 4.410420f },
3566        { 3736.189941f, -5032.810059f, 143.847000f, 5.026970f },
3567        { 3723.219971f, -5035.770020f, 143.764999f, 4.701020f },
3568        { 3728.760010f, -5031.759766f, 143.785995f, 3.723200f },
3569        { 3683.189941f, -5062.419922f, 143.175995f, 0.559623f },        // 3
3570        { 3687.739990f, -5057.779785f, 143.175995f, 1.345020f },
3571        { 3674.040039f, -5067.899902f, 143.524994f, 0.005909f },
3572        { 3688.340088f, -5052.009766f, 143.473007f, 2.299280f },
3573        { 3681.659912f, -5052.549805f, 143.263000f, 3.343860f },
3574        { 3678.840080f, -5055.529785f, 143.332993f, 3.512720f },
3575        { 3685.800049f, -5045.779785f, 143.615997f, 6.253750f },
3576        { 3673.479980f, -5053.350098f, 143.554993f, 1.945840f },
3577        { 3670.649902f, -5061.149902f, 143.820007f, 4.266700f },
3578        { 3688.018311f, -5061.541992f, 143.178223f, 0.512497f },
3579        { 3742.659912f, -5157.009766f, 143.171005f, 0.773261f },        // 4
3580        { 3750.310059f, -5153.779785f, 143.179993f, 5.603460f },
3581        { 3739.770020f, -5163.000000f, 143.662994f, 1.095270f },
3582        { 3746.649902f, -5164.560059f, 143.520004f, 1.970990f },
3583        { 3748.479980f, -5169.109863f, 143.649002f, 2.591460f },
3584        { 3744.560059f, -5173.520020f, 143.895996f, 1.370160f },
3585        { 3758.260010f, -5156.299805f, 143.570999f, 6.192510f },
3586        { 3762.620117f, -5159.149902f, 143.712997f, 4.433220f },
3587        { 3760.840088f, -5162.959961f, 143.649002f, 4.280060f },
3588        { 3756.580078f, -5170.060059f, 143.623001f, 3.031280f },
3589        { 3705.229980f, -5163.189941f, 143.266998f, 5.692200f },        // 5
3590        { 3696.949951f, -5163.370117f, 143.608002f, 0.901274f },
3591        { 3710.080078f, -5168.709961f, 143.585999f, 4.675110f },
3592        { 3697.030029f, -5170.220215f, 143.606003f, 0.343642f },
3593        { 3692.030029f, -5170.020020f, 143.815994f, 0.932691f },
3594        { 3710.320068f, -5175.319824f, 143.705002f, 4.639770f },
3595        { 3694.550049f, -5177.540039f, 143.839005f, 1.549230f },
3596        { 3705.830078f, -5179.120117f, 143.729996f, 3.956480f },
3597        { 3712.800049f, -5179.109863f, 143.891006f, 3.855950f },
3598        { 3701.669922f, -5181.859863f, 143.804001f, 1.380370f },
3599        { 3676.590088f, -5144.899902f, 143.186005f, 3.575550f },        // 6
3600        { 3670.649902f, -5142.629883f, 143.173996f, 4.313820f },
3601        { 3665.689941f, -5136.279785f, 143.177994f, 1.176150f },
3602        { 3664.870117f, -5132.330078f, 143.205002f, 3.249600f },
3603        { 3662.120117f, -5144.299805f, 143.320007f, 2.256080f },
3604        { 3658.979980f, -5139.490234f, 143.421997f, 6.077040f },
3605        { 3651.850098f, -5137.140137f, 143.764999f, 0.799161f },
3606        { 3654.689941f, -5144.009766f, 143.546997f, 2.519180f },
3607        { 3666.020020f, -5149.500000f, 143.587006f, 3.359560f },
3608        { 3667.959961f, -5153.120117f, 143.791000f, 4.015380f },
3609        { 3659.979980f, -5100.450195f, 143.453003f, 5.168254f },        // 7
3610        { 3662.800049f, -5088.189941f, 143.557999f, 4.409650f },
3611        { 3658.439941f, -5090.649902f, 143.470001f, 5.528840f },
3612        { 3652.810059f, -5090.450195f, 143.475998f, 1.362310f },
3613        { 3651.780029f, -5095.339844f, 143.388000f, 0.981387f },
3614        { 3652.629883f, -5098.970215f, 143.544998f, 2.799580f },
3615        { 3652.679932f, -5083.479980f, 143.774994f, 0.482659f },
3616        { 3647.189941f, -5085.490234f, 143.570999f, 1.919940f },
3617        { 3645.120117f, -5097.240234f, 143.487000f, 0.765403f },
3618        { 3646.360107f, -5101.200195f, 143.681000f, 2.909540f }
3619};
3620
3621static Spawns Abomination[] =   // Unstoppable Abomination
3622{
3623        { 3776.229980f, -5081.439941f, 143.779999f, 4.043730f },        // 1
3624        { 3774.419922f, -5071.490234f, 143.423996f, 4.214940f },
3625        { 3759.850098f, -5064.479980f, 143.636002f, 6.255410f },
3626        { 3740.899902f, -5052.740234f, 143.785995f, 1.836760f },        // 2
3627        { 3726.919922f, -5040.020020f, 143.535995f, 2.481570f },
3628        { 3715.010010f, -5049.259766f, 143.632004f, 5.071810f },
3629        { 3695.060059f, -5052.160156f, 143.548004f, 3.792400f },        // 3
3630        { 3678.129883f, -5048.060059f, 143.436996f, 5.363980f },
3631        { 3676.120117f, -5061.359863f, 143.492004f, 5.726840f },
3632        { 3756.780029f, -5149.419922f, 143.460007f, 2.774530f },        // 4
3633        { 3752.262695f, -5164.782227f, 143.409119f, 0.383768f },
3634        { 3740.669922f, -5168.600098f, 143.873993f, 1.051360f },
3635        { 3714.020020f, -5171.129883f, 143.776993f, 1.742510f },        // 5
3636        { 3702.185303f, -5174.303711f, 143.532303f, 5.443298f },
3637        { 3693.739990f, -5162.149902f, 143.748001f, 5.696990f },
3638        { 3673.189941f, -5150.500000f, 143.751999f, 3.030570f },        // 6
3639        { 3658.570068f, -5147.799805f, 143.494003f, 1.230440f },
3640        { 3659.560059f, -5132.129883f, 143.677002f, 5.988380f },
3641        { 3651.130859f, -5104.800293f, 143.798248f, 5.374194f },        // 7
3642        { 3646.947021f, -5092.266113f, 143.305878f, 5.005841f },
3643        { 3658.618408f, -5083.832031f, 143.778641f, 5.951464f }
3644};
3645
3646static Spawns SoulWeaver[] =    // Soul Weaver
3647{
3648        { 3768.540039f, -5075.140137f, 143.203995f, 5.096160f },
3649        { 3728.030029f, -5047.359863f, 143.306000f, 5.230460f },
3650        { 3682.929932f, -5055.819824f, 143.184006f, 5.368690f },
3651        { 3749.429932f, -5160.419922f, 143.283997f, 4.723090f },
3652        { 3706.120117f, -5169.250000f, 143.436996f, 2.682630f },
3653        { 3665.310059f, -5142.339844f, 143.220001f, 1.147180f },
3654        { 3656.365234f, -5094.724121f, 143.306641f, 6.203571f }
3655};
3656
3657static Spawns Guardians[] =             // Guardians of Icecrown
3658{
3659        { 3778.371582f, -5065.141113f, 143.614639f, 3.700061f },
3660        { 3731.733398f, -5032.681152f, 143.775040f, 4.485459f },
3661        { 3758.592285f, -5170.157715f, 143.667297f, 2.144972f },
3662        { 3700.936279f, -5183.230469f, 143.858582f, 1.314648f }
3663};
3664
3665static Spawns Waves[] =                 // Spawn positions of units that attack circle
3666{
3667        { 3756.380615f, -5080.560059f, 142.906921f, 3.762599f },
3668        { 3726.448242f, -5058.546387f, 142.467331f, 4.262112f },
3669        { 3690.084229f, -5066.993164f, 142.705917f, 5.245427f },
3670        { 3742.711670f, -5146.786133f, 142.964890f, 2.178441f },
3671        { 3706.024902f, -5155.362793f, 142.655304f, 1.294868f },
3672        { 3676.363281f, -5133.007324f, 142.806168f, 0.615499f },
3673        { 3668.310303f, -5096.927246f, 142.307312f, 6.128994f }
3674};
3675
3676// Kel'thuzad AI
3677// each ~10-20 sec new mob
3678
3679#define CN_KELTHUZAD 15990
3680
3681#define SFROSTBOLT 28478
3682#define MFROSTBOLT 28479
3683#define CHAINS_OF_KELTHUZAD 28410
3684#define DETONATE_MANA 27819
3685#define SHADOW_FISSURE 27810
3686#define FROST_BLAST 27808
3687
3688#define KELTHUZAD_CHANNEL 29423
3689
3690class KelthuzadAI : public CreatureAIScript
3691{
3692public:
3693        ADD_CREATURE_FACTORY_FUNCTION(KelthuzadAI);
3694        SP_AI_Spell spells[7];
3695        bool m_spellcheck[7];
3696        bool FrozenWastes[7];
3697        bool Abominations[7];
3698        bool SoulWeavers[7];
3699
3700    KelthuzadAI(Creature* pCreature) : CreatureAIScript(pCreature)
3701    {
3702                nrspells = 6;
3703
3704                for(int i=0;i<nrspells;i++)
3705                {
3706                        m_spellcheck[i] = false;
3707                        spells[i].casttime = 0;
3708                }
3709
3710                for (int i = 0; i < 7; i++)
3711                {
3712                        FrozenWastes[i] = false;
3713                        Abominations[i] = false;
3714                        SoulWeavers[i] = false;
3715                }
3716               
3717        spells[0].info = dbcSpell.LookupEntry(SFROSTBOLT);
3718                spells[0].targettype = TARGET_ATTACKING;
3719                spells[0].instant = false;
3720                spells[0].perctrigger = 7.0f;
3721                spells[0].cooldown = 0;
3722                spells[0].attackstoptimer = 2000;
3723
3724                spells[1].info = dbcSpell.LookupEntry(MFROSTBOLT);
3725                spells[1].targettype = TARGET_VARIOUS;
3726                spells[1].instant = true;
3727                spells[1].perctrigger = 0.1f;
3728                spells[1].cooldown = 15;                        // it's casted after 15 sec anyway, so it does need additional perctrigger
3729                spells[1].attackstoptimer = 1000;
3730
3731                spells[2].info = dbcSpell.LookupEntry(CHAINS_OF_KELTHUZAD);
3732                spells[2].targettype = TARGET_RANDOM_SINGLE;
3733                spells[2].instant = true;
3734                spells[2].perctrigger = 5.0f;
3735                spells[2].cooldown = 20;
3736                spells[2].attackstoptimer = 1000;
3737                spells[2].mindist2cast = 0.0f;
3738                spells[2].maxdist2cast = 40.0f;
3739                spells[2].minhp2cast = 0;
3740                spells[2].maxhp2cast = 100;
3741
3742                spells[3].info = dbcSpell.LookupEntry(DETONATE_MANA);
3743                spells[3].targettype = TARGET_RANDOM_SINGLE;
3744                spells[3].instant = true;
3745                spells[3].perctrigger = 6.0f;
3746                spells[3].cooldown = 7;
3747                spells[3].attackstoptimer = 2000;
3748                spells[3].mindist2cast = 0.0f;
3749                spells[3].maxdist2cast = 40.0f;
3750                spells[3].minhp2cast = 0;
3751                spells[3].maxhp2cast = 100;
3752
3753                spells[4].info = dbcSpell.LookupEntry(SHADOW_FISSURE);
3754                spells[4].targettype = TARGET_ATTACKING;
3755                spells[4].instant = true;
3756                spells[4].perctrigger = 5.0f;
3757                spells[4].cooldown = 10;
3758                spells[4].attackstoptimer = 2000;
3759
3760                spells[5].info = dbcSpell.LookupEntry(FROST_BLAST);
3761                spells[5].targettype = TARGET_RANDOM_SINGLE;
3762                spells[5].instant = true;
3763                spells[5].perctrigger = 6.0f;
3764                spells[5].cooldown = 10;
3765                spells[5].attackstoptimer = 2000;
3766                spells[5].soundid = 8815;
3767                spells[5].speech = "I shall freeze the blood in your veins!";   // not sure if it's to this one or to one of bolt spells
3768                spells[5].mindist2cast = 0.0f;
3769                spells[5].maxdist2cast = 40.0f;
3770                spells[5].minhp2cast = 0;
3771                spells[5].maxhp2cast = 100;
3772
3773                spells[6].info = dbcSpell.LookupEntry(KELTHUZAD_CHANNEL);
3774                spells[6].targettype = TARGET_SELF;
3775                spells[6].instant = false;
3776                spells[6].perctrigger = 0.0f;
3777                spells[6].cooldown = 0;
3778                spells[6].attackstoptimer = 1000;
3779
3780                _unit->GetAIInterface()->disable_melee = false;
3781                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
3782                _unit->GetAIInterface()->m_canMove = true;
3783
3784                DespawnTrash = false;
3785                EventStart = false;
3786                SpawnCounter = 0;
3787                PhaseTimer = 310;
3788                SpawnTimer = 0;
3789                GCounter = 0;
3790                m_phase = 0;
3791    }
3792   
3793    void OnCombatStart(Unit* mTarget)
3794    {
3795                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Minions, servants, soldiers of the cold dark, obey the call of Kel'Thuzad!");
3796                _unit->PlaySoundToSet(8819);
3797
3798                Unit* TheLichKing = NULL;
3799                TheLichKing = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3767.58f, -5117.15f, 174.49f, CN_THE_LICH_KING);
3800                if (TheLichKing != NULL)
3801                {
3802                        _unit->SetChannelSpellTargetGUID(TheLichKing->GetGUID());
3803                        _unit->SetChannelSpellId(29423);
3804                }
3805
3806                GameObject*  KelGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(3635.44f, -5090.33f, 143.205f, 181228);
3807                                       
3808                if (KelGate)
3809                        KelGate->SetState(1);
3810
3811                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
3812                _unit->GetAIInterface()->disable_melee = true;
3813                _unit->GetAIInterface()->m_canMove = false;
3814               
3815        RegisterAIUpdateEvent(1000);
3816                CastTime();
3817
3818                DespawnTrash = false;
3819                EventStart = true;
3820                SpawnCounter = 0;
3821                PhaseTimer = 310;
3822                SpawnTimer = 0;
3823                GCounter = 0;
3824                m_phase = 1;
3825    }
3826
3827    void OnCombatStop(Unit* mTarget)
3828    {
3829                GameObject*  KelGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(3635.44f, -5090.33f, 143.205f, 181228);
3830                if (KelGate != NULL)
3831                        KelGate->SetState(0);
3832
3833                for (int i = 0; i < 4; i++)
3834                {
3835                        GameObject*  WindowGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(Guardians[i].x, Guardians[i].y, Guardians[i].z, 200002);             
3836                        if (WindowGate != NULL)
3837                                WindowGate->SetState(1);
3838                }
3839
3840                _unit->SetChannelSpellTargetGUID(0);
3841                _unit->SetChannelSpellId(0);
3842        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
3843        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
3844                _unit->GetAIInterface()->disable_melee = false;
3845                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
3846                _unit->GetAIInterface()->m_canMove = true;
3847        RemoveAIUpdateEvent();
3848
3849                DespawnTrash = true;
3850                EventStart = false;
3851                SpawnCounter = 0;
3852                PhaseTimer = 310;
3853                SpawnTimer = 0;
3854                GCounter = 0;
3855                m_phase = 0;
3856    }
3857
3858        void CastTime()
3859        {
3860                for(int i=0;i<nrspells;i++)
3861                        spells[i].casttime = 0;
3862        }
3863
3864        void OnTargetDied(Unit* mTarget)
3865        {
3866                if (_unit->GetHealthPct() == 0) return;
3867
3868                uint32 RandomSpeach = rand()%2;
3869                switch (RandomSpeach)
3870                {
3871                case 0:
3872                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The dark void awaits you!");
3873                        _unit->PlaySoundToSet(8817);
3874                        break;
3875                case 1:
3876                        //_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "");    // no text?
3877                        _unit->PlaySoundToSet(8818);
3878                        break;
3879                }
3880        }
3881
3882    void OnDied(Unit* mKiller)
3883    {
3884                GameObject*  KelGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(3635.44f, -5090.33f, 143.205f, 181228); 
3885                if (KelGate != NULL)
3886                        KelGate->SetState(0);
3887
3888                for (int i = 0; i < 4; i++)
3889                {
3890                        GameObject*  WindowGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(Guardians[i].x, Guardians[i].y, Guardians[i].z, 200002);
3891                        if (WindowGate != NULL)
3892                                WindowGate->SetState(1);
3893                }
3894
3895                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Do not rejoice... your victory is a hollow one... for I shall return with powers beyond your imagining!");
3896                _unit->PlaySoundToSet(8814);
3897
3898                _unit->GetAIInterface()->disable_melee = false;
3899                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
3900                _unit->GetAIInterface()->m_canMove = true;
3901                RemoveAIUpdateEvent();
3902
3903                EventStart = false;
3904                SpawnCounter = 0;
3905                PhaseTimer = 310;
3906                SpawnTimer = 0;
3907                GCounter = 0;
3908                m_phase = 0;
3909    }
3910
3911    void AIUpdate()
3912    {
3913                switch (m_phase)
3914                {
3915                case 1:
3916                        PhaseOne();
3917                        break;
3918                case 2:
3919                        PhaseTwo();
3920                        break;
3921                case 3:
3922                        PhaseThree();
3923                        break;
3924                default:
3925                        {
3926                        }
3927                }
3928    }
3929
3930        void PhaseOne()
3931        {
3932                if (EventStart == true)
3933                {
3934                        SpawnTimer++;
3935                        if (SpawnTimer == 5 || SpawnTimer == 10)
3936                        {
3937                                for (int i = 0; i < 7; i++)
3938                                {
3939                                        int Counter = 0;
3940
3941                                        while (Counter == 0)
3942                                        {
3943                                                if (FrozenWastes[i] == false && (rand()%3 == 0 || SpawnCounter > 0))
3944                                                {
3945                                                        for (int x = 0; x < 10; x++)
3946                                                        {
3947                                                                uint32 SpawnID = 10*i + x;
3948                                                                _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_SOLDIER_OF_THE_FROZEN_WASTES, SFrozenWastes[SpawnID].x, SFrozenWastes[SpawnID].y, SFrozenWastes[SpawnID].z, SFrozenWastes[SpawnID].o, true, false, 0, 0);
3949                                                        }
3950
3951                                                        FrozenWastes[i] = true;
3952                                                        Counter++;
3953                                                }
3954
3955                                                if (Abominations[i] == false && (rand()%3 == 0 || SpawnCounter > 0))
3956                                                {
3957                                                        for (int x = 0; x < 3; x++)
3958                                                        {
3959                                                                uint32 SpawnID = 3*i + x;
3960                                                                _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_UNSTOPPABLE_ABOMINATION, Abomination[SpawnID].x, Abomination[SpawnID].y, Abomination[SpawnID].z, Abomination[SpawnID].o, true, false, 0, 0);
3961                                                        }
3962
3963                                                        Abominations[i] = true;
3964                                                        Counter++;
3965                                                }
3966
3967                                                if (SoulWeavers[i] == false && ((rand()%3 == 0 && Counter < 2) || Counter == 0 || SpawnCounter > 0))
3968                                                {
3969                                                        uint32 SpawnID = i;
3970                                                        _unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_SOUL_WEAVER, SoulWeaver[SpawnID].x, SoulWeaver[SpawnID].y, SoulWeaver[SpawnID].z, SoulWeaver[SpawnID].o, true, false, 0, 0);
3971                                               
3972                                                        SoulWeavers[i] = true;
3973                                                        Counter++;
3974                                                }
3975
3976                                                if (SoulWeavers[i] == true && Abominations[i] == true && FrozenWastes[i] == true)
3977                                                        Counter = 1;
3978                                        }
3979                                }
3980
3981                                SpawnCounter++;
3982                        }
3983
3984                        if (SpawnCounter == 2)
3985                        {
3986                                for (int i = 0; i < 7; i++)
3987                                {
3988                                        FrozenWastes[i] = false;
3989                                        Abominations[i] = false;
3990                                        SoulWeavers[i] = false;
3991                                }
3992
3993                                WaveTimer = rand()%6+10;
3994                                EventStart = false;
3995                                SpawnCounter = 0;
3996                                PhaseTimer = 310;
3997                                SpawnTimer = 0;
3998                        }
3999                }
4000
4001                else
4002                {
4003                        PhaseTimer--;
4004                        WaveTimer--;
4005
4006                        if (PhaseTimer == 5)
4007                        {
4008                                uint32 RandomSpeach = rand()%3;
4009                                switch (RandomSpeach)
4010                                {
4011                                case 0:
4012                                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Pray for mercy!");
4013                                        _unit->PlaySoundToSet(8809);
4014                                        break;
4015                                case 1:
4016                                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Scream your dying breath!");
4017                                        _unit->PlaySoundToSet(8810);
4018                                        break;
4019                                case 2:
4020                                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "The end is upon you!");
4021                                        _unit->PlaySoundToSet(8811);
4022                                        break;
4023                                }
4024                        }
4025
4026                        if (PhaseTimer == 3)
4027                                DespawnTrash = true;
4028
4029                        if (!PhaseTimer)
4030                        {
4031                                _unit->SetChannelSpellTargetGUID(0);
4032                                _unit->SetChannelSpellId(0);
4033                                _unit->GetAIInterface()->disable_melee = false;
4034                                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, 0);
4035                                _unit->GetAIInterface()->m_canMove = true;
4036                               
4037                                DespawnTrash = false;
4038                                HelpDialog = 0;
4039                                GCounter = 0;
4040                                m_phase = 2;
4041                                return;
4042                        }
4043
4044                        else if (!WaveTimer && PhaseTimer > 5)
4045                        {
4046                                uint32 SpawnPoint = RandomUInt(7);
4047                                uint32 RandomSU = 0;
4048                                if (PhaseTimer > 250)
4049                                        RandomSU = RandomUInt(4);
4050                                if (PhaseTimer <= 250 && PhaseTimer >= 150)
4051                                        RandomSU = RandomUInt(5);
4052                                if (PhaseTimer <= 150 && PhaseTimer > 100)
4053                                        RandomSU = RandomUInt(6);
4054                                if (PhaseTimer <= 100)
4055                                        RandomSU = RandomUInt(7);
4056
4057                                uint32 UnitType;
4058
4059                                switch (RandomSU)
4060                                {
4061                                        case 0:
4062                                        case 1: UnitType = CN_SOLDIER_OF_THE_FROZEN_WASTES; break;
4063                                        case 2:
4064                                        case 4: UnitType = CN_SOUL_WEAVER; break;
4065                                        case 3:
4066                                        case 5:
4067                                        case 6: UnitType = CN_UNSTOPPABLE_ABOMINATION; break;
4068                                        default:
4069                                                {
4070                                                        UnitType = CN_UNSTOPPABLE_ABOMINATION;
4071                                                }
4072                                }
4073
4074                                _unit->GetMapMgr()->GetInterface()->SpawnCreature(UnitType, Waves[SpawnPoint].x, Waves[SpawnPoint].y, Waves[SpawnPoint].z, Waves[SpawnPoint].o, true, false, 0, 0);
4075                                WaveTimer = rand()%11+10;
4076                        }
4077                }
4078        }
4079
4080        void PhaseTwo()
4081        {
4082                if (_unit->GetHealthPct() <= 40)
4083                {
4084                        HelpDialog++;
4085                        if (HelpDialog == 1)
4086                        {
4087                                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Master! I require aid!");
4088                                _unit->PlaySoundToSet(8816);
4089                        }
4090
4091                        if (HelpDialog == 4)
4092                        {
4093                                Unit* TheLichKing = NULL;
4094                                TheLichKing = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3767.58f, -5117.15f, 174.49f, CN_THE_LICH_KING);
4095                                if (TheLichKing != NULL)
4096                                {
4097                                        TheLichKing->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Very well... warriors of the frozen wastes, rise up, I command you to fight, kill, and die for your master. Let none survive...");
4098                                        TheLichKing->PlaySoundToSet(8824);
4099                                }
4100
4101                                else
4102                                {
4103                                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Very well... warriors of the frozen wastes, rise up, I command you to fight, kill, and die for your master. Let none survive...");
4104                                        _unit->PlaySoundToSet(8824);
4105                                }
4106
4107                                for (int i = 0; i < 4; i++)
4108                                {
4109                                        GameObject*  WindowGate  = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(Guardians[i].x, Guardians[i].y, Guardians[i].z, 200002);
4110                                        if (WindowGate)
4111                                                WindowGate->SetState(0);
4112                                }
4113                        }
4114
4115                        if (HelpDialog == 10 || HelpDialog == 12 || HelpDialog == 14 || HelpDialog == 16 || HelpDialog == 18)
4116                        {
4117                                Unit* Guardian = NULL;
4118                                uint32 i = RandomUInt(4);
4119                                Guardian =_unit->GetMapMgr()->GetInterface()->SpawnCreature(CN_GUARDIAN_OF_ICECROWN, Guardians[i].x, Guardians[i].y, Guardians[i].z, Guardians[i].o, true, false, 0, 0);
4120                                if (Guardian  != NULL)
4121                                {
4122                                        if (Guardian->GetAIInterface()->GetNextTarget() != NULL)
4123                                                Guardian->GetAIInterface()->AttackReaction(Guardian->GetAIInterface()->GetNextTarget(), 1, 0);
4124                                }
4125
4126                                GCounter++;
4127                                if (GCounter == 5)
4128                                {
4129                                        GCounter = 0;
4130                                        m_phase = 3;
4131                                }
4132                        }
4133                }
4134
4135                float val = (float)RandomFloat(100.0f);
4136        SpellCast(val);
4137        }
4138
4139        void PhaseThree()
4140        {
4141                float val = (float)RandomFloat(100.0f);
4142        SpellCast(val);
4143        }
4144
4145        void SpellCast(float val)
4146    {
4147        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
4148        {
4149                        float comulativeperc = 0;
4150                    Unit* target = NULL;
4151                        for(int i=0;i<nrspells;i++)
4152                        {
4153                                if(!spells[i].perctrigger) continue;
4154                               
4155                                if(m_spellcheck[i])
4156                                {
4157                                        target = _unit->GetAIInterface()->GetNextTarget();
4158                                        switch(spells[i].targettype)
4159                                        {
4160                                                case TARGET_SELF:
4161                                                case TARGET_VARIOUS:
4162                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
4163                                                case TARGET_ATTACKING:
4164                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
4165                                                case TARGET_DESTINATION:
4166                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
4167                                                case TARGET_RANDOM_FRIEND:
4168                                                case TARGET_RANDOM_SINGLE:
4169                                                case TARGET_RANDOM_DESTINATION:
4170                                                        CastSpellOnRandomTarget(i, spells[i].mindist2cast, spells[i].maxdist2cast, spells[i].minhp2cast, spells[i].maxhp2cast); break;
4171                                        }
4172
4173                                        if (i == 2)
4174                                                ChainSound();
4175
4176                                        if (spells[i].speech != "")
4177                                        {
4178                                                _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, spells[i].speech.c_str());
4179                                                _unit->PlaySoundToSet(spells[i].soundid); 
4180                                        }
4181
4182                                        m_spellcheck[i] = false;
4183                                        return;
4184                                }
4185
4186                                uint32 t = (uint32)time(NULL);
4187                                if(((val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger)) || i == 1) && t > spells[i].casttime)
4188                                {
4189                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
4190                                        spells[i].casttime = t + spells[i].cooldown;
4191                                        m_spellcheck[i] = true;
4192                                }
4193                                comulativeperc += spells[i].perctrigger;
4194                        }
4195        }
4196    }
4197
4198        void CastSpellOnRandomTarget(uint32 i, float mindist2cast, float maxdist2cast, int minhp2cast, int maxhp2cast)
4199        {
4200                if (!maxdist2cast) maxdist2cast = 100.0f;
4201                if (!maxhp2cast) maxhp2cast = 100;
4202
4203                if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
4204        {
4205                        std::vector<Unit*> TargetTable;         /* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
4206                                                                                                /* If anyone wants to use this function, then leave this note!                                                                           */
4207                        for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr) 
4208                        { 
4209                                if (((spells[i].targettype == TARGET_RANDOM_FRIEND && isFriendly(_unit, (*itr))) || (spells[i].targettype != TARGET_RANDOM_FRIEND && isHostile(_unit, (*itr)) && (*itr) != _unit)) && ((*itr)->GetTypeId()== TYPEID_UNIT || (*itr)->GetTypeId() == TYPEID_PLAYER) && (*itr)->GetInstanceID() == _unit->GetInstanceID()) // isAttackable(_unit, (*itr)) &&
4210                                {
4211                                        Unit* RandomTarget = NULL;
4212                                        RandomTarget = TO_UNIT(*itr);
4213
4214                                        if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) >= mindist2cast*mindist2cast && _unit->GetDistance2dSq(RandomTarget) <= maxdist2cast*maxdist2cast && ((RandomTarget->GetHealthPct() >= minhp2cast && RandomTarget->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND) || (_unit->GetAIInterface()->getThreatByPtr(RandomTarget) > 0 && isHostile(_unit, RandomTarget))))
4215                                        {
4216                                                TargetTable.push_back(RandomTarget);
4217                                        } 
4218                                } 
4219                        }
4220
4221                        if (_unit->GetHealthPct() >= minhp2cast && _unit->GetHealthPct() <= maxhp2cast && spells[i].targettype == TARGET_RANDOM_FRIEND)
4222                                TargetTable.push_back(_unit);
4223
4224                        if (!TargetTable.size())
4225                                return;
4226
4227                        size_t RandTarget = rand()%TargetTable.size();
4228
4229                        Unit*  RTarget = TargetTable[RandTarget];
4230
4231                        if (!RTarget)
4232                                return;
4233
4234                        switch (spells[i].targettype)
4235                        {
4236                        case TARGET_RANDOM_FRIEND:
4237                        case TARGET_RANDOM_SINGLE:
4238                                _unit->CastSpell(RTarget, spells[i].info, spells[i].instant); break;
4239                        case TARGET_RANDOM_DESTINATION:
4240                                _unit->CastSpellAoF(RTarget->GetPositionX(), RTarget->GetPositionY(), RTarget->GetPositionZ(), spells[i].info, spells[i].instant); break;
4241                        }
4242
4243                        TargetTable.clear();
4244                }
4245        }
4246
4247        void ChainSound()
4248        {
4249                uint32 RandomSpeach = rand()%2;
4250                switch (RandomSpeach)
4251                {
4252                case 0:
4253                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Your soul is bound to me now!");
4254                        _unit->PlaySoundToSet(8812);
4255                        break;
4256                case 1:
4257                        _unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "There will be no escape!");
4258                        _unit->PlaySoundToSet(8813);
4259                        break;
4260                }
4261        }
4262
4263        bool GetDespawnTrash() { return DespawnTrash; }
4264
4265protected:
4266
4267        bool DespawnTrash, EventStart;
4268        uint32 SpawnCounter;
4269        uint32 HelpDialog;
4270        uint32 SpawnTimer;
4271        uint32 PhaseTimer;
4272        uint32 WaveTimer;
4273        uint32 GCounter;
4274        uint32 m_phase;
4275        int nrspells;
4276};
4277
4278// The Lich KingAI
4279
4280class TheLichKingAI : public CreatureAIScript
4281{
4282public:
4283    ADD_CREATURE_FACTORY_FUNCTION(TheLichKingAI);
4284
4285    TheLichKingAI(Creature* pCreature) : CreatureAIScript(pCreature)
4286    {
4287                _unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
4288    }
4289};
4290
4291// Soldier of the Frozen WastesAI
4292
4293#define DARK_BLAST 28457 // 28458
4294
4295class SoldierOfTheFrozenWastesAI : public CreatureAIScript
4296{
4297public:
4298    ADD_CREATURE_FACTORY_FUNCTION(SoldierOfTheFrozenWastesAI);
4299    SoldierOfTheFrozenWastesAI(Creature* pCreature) : CreatureAIScript(pCreature)
4300    {
4301                _unit->m_noRespawn = true;
4302
4303                OnStart = false;
4304
4305                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4306    }
4307   
4308    void OnCombatStart(Unit* mTarget)
4309    {
4310                LastPosX = _unit->GetPositionX();
4311                LastPosY = _unit->GetPositionY();
4312                LastPosZ = _unit->GetPositionZ();
4313
4314                //RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4315    }
4316
4317    void OnCombatStop(Unit* mTarget)
4318    {
4319        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
4320        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
4321
4322                //RemoveAIUpdateEvent();
4323    }
4324
4325    void OnDied(Unit* mKiller)
4326    {
4327       RemoveAIUpdateEvent();
4328    }
4329
4330    void AIUpdate()
4331    {
4332                Creature* Kelthuzad = NULL;
4333                Kelthuzad = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3749.950195f, -5113.451660f, 141.288635f, 15990);
4334                if (Kelthuzad == NULL || !Kelthuzad->isAlive())
4335                {
4336                        _unit->Despawn(0,0);
4337                        return;
4338                }
4339                else if (Kelthuzad->GetScript())
4340                {
4341                        CreatureAIScript *pScript = Kelthuzad->GetScript();
4342                        if (static_cast<KelthuzadAI*>(pScript)->GetDespawnTrash())
4343                        {
4344                                _unit->Despawn(0,0);
4345                                return;
4346                        }
4347                }
4348                if (_unit->GetPositionX() == LastPosX && _unit->GetPositionY() == LastPosY && _unit->GetPositionZ() == LastPosZ)
4349                {
4350                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4351                }
4352                if (OnStart == false)
4353                {
4354                        for (int i = 0; i < 7; i++)
4355                        {
4356                                if (_unit->GetPositionX() == Waves[i].x && _unit->GetPositionY() == Waves[i].y && _unit->GetPositionZ() == Waves[i].z)
4357                                {
4358                                        float xchange  = (float)RandomFloat(10.0f);
4359                                        float distance = 10.0f;
4360
4361                                        float ychange = sqrt(distance*distance - xchange*xchange);
4362
4363                                        if (rand()%2 == 1)
4364                                                xchange *= -1;
4365                                        if (rand()%2 == 1)
4366                                                ychange *= -1;
4367
4368                                        newposx = 3715.845703f + xchange;
4369                                        newposy = -5106.928223f + ychange;
4370
4371                                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4372                                }
4373                        }
4374
4375                        OnStart = true;
4376                }
4377
4378                if (_unit->GetAIInterface()->GetNextTarget() != NULL)
4379                {
4380                        Unit* target = _unit->GetAIInterface()->GetNextTarget();
4381                        if (_unit->GetDistance2dSq(target) <= 49.0f)
4382                                _unit->CastSpell(_unit, DARK_BLAST, true);
4383                }
4384    }
4385
4386protected:
4387
4388        float LastPosX, LastPosY, LastPosZ;
4389        float newposx;
4390        float newposy;
4391        bool OnStart;
4392};
4393
4394// Unstoppable Abomination AI
4395
4396#define UA_MORTAL_WOUND 25646   // 36814
4397
4398class UnstoppableAbominationAI : public CreatureAIScript
4399{
4400public:
4401    ADD_CREATURE_FACTORY_FUNCTION(UnstoppableAbominationAI);
4402        SP_AI_Spell spells[1];
4403        bool m_spellcheck[1];
4404
4405    UnstoppableAbominationAI(Creature* pCreature) : CreatureAIScript(pCreature)
4406    {
4407                nrspells = 1;
4408                for(int i=0;i<nrspells;i++)
4409                {
4410                        m_spellcheck[i] = false;
4411                        spells[i].casttime = 0;
4412                }
4413
4414                spells[0].info = dbcSpell.LookupEntry(UA_MORTAL_WOUND);
4415                spells[0].targettype = TARGET_ATTACKING;
4416                spells[0].instant = true;
4417                spells[0].cooldown = 10;
4418                spells[0].perctrigger = 15.0f;
4419                spells[0].attackstoptimer = 1000;
4420
4421                _unit->m_noRespawn = true;
4422
4423                OnStart = false;
4424
4425                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4426    }
4427   
4428    void OnCombatStart(Unit* mTarget)
4429    {
4430                LastPosX = _unit->GetPositionX();
4431                LastPosY = _unit->GetPositionY();
4432                LastPosZ = _unit->GetPositionZ();
4433
4434                //RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4435
4436                for (int i = 0; i < nrspells; i++)
4437                        spells[i].casttime = 0;
4438    }
4439
4440    void OnCombatStop(Unit* mTarget)
4441    {
4442        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
4443        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
4444
4445                //RemoveAIUpdateEvent();
4446    }
4447
4448    void OnDied(Unit* mKiller)
4449    {
4450       RemoveAIUpdateEvent();
4451    }
4452
4453    void AIUpdate()
4454    {
4455                Creature* Kelthuzad = NULL;
4456                Kelthuzad = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3749.950195f, -5113.451660f, 141.288635f, 15990);
4457                if (Kelthuzad == NULL || !Kelthuzad->isAlive())
4458                {
4459                        _unit->Despawn(0,0);
4460                        return;
4461                }
4462                else if (Kelthuzad->GetScript())
4463                {
4464                        CreatureAIScript *pScript = Kelthuzad->GetScript();
4465                        if (static_cast<KelthuzadAI*>(pScript)->GetDespawnTrash())
4466                        {
4467                                _unit->Despawn(0,0);
4468                                return;
4469                        }
4470                }
4471                if (_unit->GetPositionX() == LastPosX && _unit->GetPositionY() == LastPosY && _unit->GetPositionZ() == LastPosZ)
4472                {
4473                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4474                }
4475                if (OnStart == false)
4476                {
4477                        for (int i = 0; i < 7; i++)
4478                        {
4479                                if (_unit->GetPositionX() == Waves[i].x && _unit->GetPositionY() == Waves[i].y && _unit->GetPositionZ() == Waves[i].z)
4480                                {
4481                                        float xchange  = (float)RandomFloat(10.0f);
4482                                        float distance = 10.0f;
4483
4484                                        float ychange = sqrt(distance*distance - xchange*xchange);
4485
4486                                        if (rand()%2 == 1)
4487                                                xchange *= -1;
4488                                        if (rand()%2 == 1)
4489                                                ychange *= -1;
4490
4491                                        newposx = 3715.845703f + xchange;
4492                                        newposy = -5106.928223f + ychange;
4493
4494                                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4495                                }
4496                        }
4497
4498                        OnStart = true;
4499                }
4500
4501                float val = (float)RandomFloat(100.0f);
4502                SpellCast(val);
4503    }
4504
4505        void SpellCast(float val)
4506    {
4507        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
4508        {
4509                        float comulativeperc = 0;
4510                    Unit* target = NULL;
4511                        for(int i=0;i<nrspells;i++)
4512                        {
4513                                if(!spells[i].perctrigger) continue;
4514                               
4515                                if(m_spellcheck[i])
4516                                {
4517                                        target = _unit->GetAIInterface()->GetNextTarget();
4518
4519                                        if (i == 0 && _unit->GetDistance2dSq(target) > 25.0f) return;
4520
4521                                        switch(spells[i].targettype)
4522                                        {
4523                                                case TARGET_SELF:
4524                                                case TARGET_VARIOUS:
4525                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
4526                                                case TARGET_ATTACKING:
4527                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
4528                                                case TARGET_DESTINATION:
4529                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
4530                                        }
4531                                        m_spellcheck[i] = false;
4532                                        return;
4533                                }
4534
4535                                uint32 t = (uint32)time(NULL);
4536                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
4537                                {
4538                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
4539                                        spells[i].casttime = t + spells[i].cooldown;
4540                                        m_spellcheck[i] = true;
4541                                }
4542                                comulativeperc += spells[i].perctrigger;
4543                        }
4544        }
4545    }
4546
4547protected:
4548
4549        float LastPosX, LastPosY, LastPosZ;
4550        float newposx;
4551        float newposy;
4552        bool OnStart;
4553        int nrspells;
4554};
4555
4556// Soul Weaver AI
4557
4558#define WAIL_OF_SOULS 28459
4559
4560class SoulWeaverAI : public CreatureAIScript
4561{
4562public:
4563    ADD_CREATURE_FACTORY_FUNCTION(SoulWeaverAI);
4564        SP_AI_Spell spells[1];
4565        bool m_spellcheck[1];
4566
4567    SoulWeaverAI(Creature* pCreature) : CreatureAIScript(pCreature)
4568    {
4569                nrspells = 1;
4570                for(int i=0;i<nrspells;i++)
4571                {
4572                        m_spellcheck[i] = false;
4573                        spells[i].casttime = 0;
4574                }
4575
4576                spells[0].info = dbcSpell.LookupEntry(WAIL_OF_SOULS);
4577                spells[0].targettype = TARGET_VARIOUS;
4578                spells[0].instant = true;
4579                spells[0].cooldown = 10;
4580                spells[0].perctrigger = 15.0f;
4581                spells[0].attackstoptimer = 1000;
4582
4583                _unit->m_noRespawn = true;
4584
4585                OnStart = false;
4586
4587                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4588    }
4589   
4590    void OnCombatStart(Unit* mTarget)
4591    {
4592                LastPosX = _unit->GetPositionX();
4593                LastPosY = _unit->GetPositionY();
4594                LastPosZ = _unit->GetPositionZ();
4595
4596                //RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4597
4598                for (int i = 0; i < nrspells; i++)
4599                        spells[i].casttime = 0;
4600    }
4601
4602    void OnCombatStop(Unit* mTarget)
4603    {
4604        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
4605        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
4606
4607                //RemoveAIUpdateEvent();
4608    }
4609
4610    void OnDied(Unit* mKiller)
4611    {
4612       RemoveAIUpdateEvent();
4613    }
4614
4615    void AIUpdate()
4616    {
4617                Creature* Kelthuzad = NULL;
4618                Kelthuzad = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3749.950195f, -5113.451660f, 141.288635f, 15990);
4619                if (Kelthuzad == NULL || !Kelthuzad->isAlive())
4620                {
4621                        _unit->Despawn(0,0);
4622                        return;
4623                }
4624                else if (Kelthuzad->GetScript())
4625                {
4626                        CreatureAIScript *pScript = Kelthuzad->GetScript();
4627                        if (static_cast<KelthuzadAI*>(pScript)->GetDespawnTrash())
4628                        {
4629                                _unit->Despawn(0,0);
4630                                return;
4631                        }
4632                }
4633                if (_unit->GetPositionX() == LastPosX && _unit->GetPositionY() == LastPosY && _unit->GetPositionZ() == LastPosZ)
4634                {
4635                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4636                }
4637                if (OnStart == false)
4638                {
4639                        for (int i = 0; i < 7; i++)
4640                        {
4641                                if (_unit->GetPositionX() == Waves[i].x && _unit->GetPositionY() == Waves[i].y && _unit->GetPositionZ() == Waves[i].z)
4642                                {
4643                                        float xchange  = (float)RandomFloat(10.0f);
4644                                        float distance = 10.0f;
4645
4646                                        float ychange = sqrt(distance*distance - xchange*xchange);
4647
4648                                        if (rand()%2 == 1)
4649                                                xchange *= -1;
4650                                        if (rand()%2 == 1)
4651                                                ychange *= -1;
4652
4653                                        newposx = 3715.845703f + xchange;
4654                                        newposy = -5106.928223f + ychange;
4655
4656                                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4657                                }
4658                        }
4659
4660                        OnStart = true;
4661                }
4662
4663                float val = (float)RandomFloat(100.0f);
4664                SpellCast(val);
4665    }
4666
4667        void SpellCast(float val)
4668    {
4669        if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
4670        {
4671                        float comulativeperc = 0;
4672                    Unit* target = NULL;
4673                        for(int i=0;i<nrspells;i++)
4674                        {
4675                                if(!spells[i].perctrigger) continue;
4676                               
4677                                if(m_spellcheck[i])
4678                                {
4679                                        target = _unit->GetAIInterface()->GetNextTarget();
4680
4681                                        if (i == 0 && _unit->GetDistance2dSq(target) > 64.0f) return;   // 8yards
4682
4683                                        switch(spells[i].targettype)
4684                                        {
4685                                                case TARGET_SELF:
4686                                                case TARGET_VARIOUS:
4687                                                        _unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
4688                                                case TARGET_ATTACKING:
4689                                                        _unit->CastSpell(target, spells[i].info, spells[i].instant); break;
4690                                                case TARGET_DESTINATION:
4691                                                        _unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
4692                                        }
4693                                        m_spellcheck[i] = false;
4694                                        return;
4695                                }
4696
4697                                uint32 t = (uint32)time(NULL);
4698                                if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
4699                                {
4700                                        _unit->setAttackTimer(spells[i].attackstoptimer, false);
4701                                        spells[i].casttime = t + spells[i].cooldown;
4702                                        m_spellcheck[i] = true;
4703                                }
4704                                comulativeperc += spells[i].perctrigger;
4705                        }
4706        }
4707    }
4708
4709protected:
4710
4711        float LastPosX, LastPosY, LastPosZ;
4712        float newposx;
4713        float newposy;
4714        bool OnStart;
4715        int nrspells;
4716};
4717
4718// Guardian of Icecrown AI
4719
4720#define BLOOD_TAP 28459
4721
4722class GuardianOfIcecrownAI : public CreatureAIScript
4723{
4724public:
4725    ADD_CREATURE_FACTORY_FUNCTION(GuardianOfIcecrownAI);
4726        SP_AI_Spell spells[1];
4727        bool m_spellcheck[1];
4728
4729    GuardianOfIcecrownAI(Creature* pCreature) : CreatureAIScript(pCreature)
4730    {
4731                nrspells = 1;
4732                for(int i=0;i<nrspells;i++)
4733                {
4734                        m_spellcheck[i] = false;
4735                }
4736
4737                spells[0].info = dbcSpell.LookupEntry(BLOOD_TAP);
4738                spells[0].targettype = TARGET_SELF;
4739                spells[0].instant = true;
4740                spells[0].cooldown = 0;
4741                spells[0].perctrigger = 0.0f;
4742                spells[0].attackstoptimer = 1000;
4743
4744                _unit->GetAIInterface()->m_moveRun = true;
4745                _unit->m_noRespawn = true;
4746
4747                OnStart = false;
4748
4749                RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4750    }
4751   
4752    void OnCombatStart(Unit* mTarget)
4753    {
4754                if (_unit->GetAIInterface()->GetNextTarget())
4755                        LastTarget = _unit->GetAIInterface()->GetNextTarget();
4756
4757                LastPosX = _unit->GetPositionX();
4758                LastPosY = _unit->GetPositionY();
4759                LastPosZ = _unit->GetPositionZ();
4760               
4761                //RegisterAIUpdateEvent(_unit->GetBaseAttackTime(MELEE));
4762    }
4763
4764    void OnCombatStop(Unit* mTarget)
4765    {
4766        _unit->GetAIInterface()->setCurrentAgent(AGENT_NULL);
4767        _unit->GetAIInterface()->SetAIState(STATE_IDLE);
4768
4769                //RemoveAIUpdateEvent();
4770    }
4771
4772    void OnDied(Unit* mKiller)
4773    {
4774       RemoveAIUpdateEvent();
4775    }
4776
4777    void AIUpdate()
4778    {
4779                Unit* Kelthuzad = NULL;
4780                Kelthuzad = _unit->GetMapMgr()->GetInterface()->GetCreatureNearestCoords(3715.950195f, -5106.451660f, 141.288635f, 15990);
4781                if (Kelthuzad && !Kelthuzad->isAlive())
4782                {
4783                        _unit->Despawn(0,0);
4784                }
4785                if (_unit->GetPositionX() == LastPosX && _unit->GetPositionY() == LastPosY && _unit->GetPositionZ() == LastPosZ)
4786                {
4787                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4788                }
4789                if (OnStart == false)
4790                {
4791                        for (int i = 0; i < 7; i++)
4792                        {
4793                                if (_unit->GetPositionX() == Guardians[i].x && _unit->GetPositionY() == Guardians[i].y && _unit->GetPositionZ() == Guardians[i].z)
4794                                {
4795                                        float xchange  = (float)RandomFloat(10.0f);
4796                                        float distance = 10.0f;
4797
4798                                        float ychange = sqrt(distance*distance - xchange*xchange);
4799
4800                                        if (rand()%2 == 1)
4801                                                xchange *= -1;
4802                                        if (rand()%2 == 1)
4803                                                ychange *= -1;
4804
4805                                        newposx = 3715.845703f + xchange;
4806                                        newposy = -5106.928223f + ychange;
4807
4808                                        _unit->GetAIInterface()->MoveTo(newposx, newposy, 141.290451f, _unit->GetOrientation());
4809                                }
4810                        }
4811
4812                        OnStart = true;
4813                }
4814
4815                if (_unit->GetAIInterface()->GetNextTarget())
4816                {
4817                        Unit* target = NULL;
4818                        target = _unit->GetAIInterface()->GetNextTarget();
4819
4820                        if (!LastTarget) { LastTarget = target; return; }
4821
4822                        if (LastTarget != target)
4823                                _unit->CastSpell(_unit, spells[0].info, spells[0].instant);
4824
4825                        LastTarget = target;
4826                }
4827    }
4828
4829protected:
4830
4831        float LastPosX, LastPosY, LastPosZ;
4832        Unit* LastTarget;
4833        float newposx;
4834        float newposy;
4835        bool OnStart;
4836        int nrspells;
4837};
4838
4839void SetupNaxxramas( ScriptMgr* pScriptMgr );
Note: See TracBrowser for help on using the browser.