Advertisement
Guest User

Untitled

a guest
Aug 24th, 2013
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 82.11 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /* ScriptData
  20. SDName: boss_illidan_stormrage
  21. SD%Complete: 90
  22. SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap.
  23. SDCategory: Black Temple
  24. EndScriptData */
  25.  
  26. #include "ScriptMgr.h"
  27. #include "ScriptedCreature.h"
  28. #include "ScriptedGossip.h"
  29. #include "PassiveAI.h"
  30. #include "black_temple.h"
  31. #include "Player.h"
  32. #include "SpellInfo.h"
  33.  
  34. #define EMOTE_UNABLE_TO_SUMMON "%s is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter."
  35.  
  36. // Other defines
  37. #define CENTER_X 676.740f
  38. #define CENTER_Y 305.297f
  39. #define CENTER_Z 353.192f
  40.  
  41. enum Say
  42. {
  43. // Akama
  44. SAY_AKAMA_BEWARE = 0,
  45. SAY_AKAMA_LEAVE = 1,
  46. // Illidan
  47. SAY_ILLIDAN_MINION = 0,
  48. SAY_ILLIDAN_KILL = 1,
  49. SAY_ILLIDAN_TAKEOFF = 2,
  50. SAY_ILLIDAN_SUMMONFLAMES = 3,
  51. SAY_ILLIDAN_EYE_BLAST = 4,
  52. SAY_ILLIDAN_MORPH = 5,
  53. SAY_ILLIDAN_ENRAGE = 6,
  54. SAY_ILLIDAN_TAUNT = 7,
  55. // Maiev Shadowsong
  56. SAY_MAIEV_SHADOWSONG_TAUNT = 0,
  57. // Flame of Azzinoth
  58. EMOTE_AZZINOTH_GAZE = 0
  59. };
  60.  
  61. enum Spells
  62. // Normal Form
  63. {
  64. SPELL_SHEAR = 37335, // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5f second cast
  65. SPELL_FLAME_CRASH = 40832,
  66. SPELL_DRAW_SOUL = 40904,
  67. SPELL_PARASITIC_SHADOWFIEND = 41917,
  68. SPELL_PARASITIC_SHADOWFIEND2 = 41914,
  69. SPELL_SUMMON_PARASITICS = 41915,
  70. SPELL_AGONIZING_FLAMES = 40932,
  71. SPELL_ENRAGE = 40683,
  72. // Flying (Phase 2)
  73. SPELL_THROW_GLAIVE = 39635,
  74. SPELL_THROW_GLAIVE2 = 39849, // Animation for the spell above
  75. SPELL_GLAIVE_RETURNS = 39873,
  76. SPELL_FIREBALL = 40598,
  77. SPELL_DARK_BARRAGE = 40585,
  78. // Demon Form
  79. SPELL_DEMON_TRANSFORM_1 = 40511,
  80. SPELL_DEMON_TRANSFORM_2 = 40398,
  81. SPELL_DEMON_TRANSFORM_3 = 40510,
  82. SPELL_DEMON_FORM = 40506,
  83. SPELL_SHADOW_BLAST = 41078,
  84. SPELL_FLAME_BURST = 41126,
  85. SPELL_FLAME_BURST_EFFECT = 41131, // The actual damage. Have each player cast it on itself (workaround)
  86. // Other Illidan spells
  87. SPELL_KNEEL = 39656, // Before beginning encounter, this is how he appears (talking to skully).
  88. SPELL_SHADOW_PRISON = 40647,
  89. SPELL_DEATH = 41220,
  90. SPELL_BERSERK = 45078,
  91. SPELL_DUAL_WIELD = 42459,
  92. SPELL_SUMMON_MAIEV = 40403,
  93. // Phase Normal spells
  94. SPELL_FLAME_CRASH_EFFECT = 40836,
  95. SPELL_SUMMON_SHADOWDEMON = 41117,
  96. SPELL_SHADOWFIEND_PASSIVE = 41913,
  97. SPELL_SHADOW_DEMON_PASSIVE = 41079,
  98. SPELL_CONSUME_SOUL = 41080,
  99. SPELL_PARALYZE = 41083,
  100. SPELL_PURPLE_BEAM = 39123,
  101. // Phase Flight spells
  102. SPELL_AZZINOTH_CHANNEL = 39857, // Glaives cast it on Flames. Not sure if this is the right spell.
  103. SPELL_EYE_BLAST_TRIGGER = 40017,
  104. SPELL_EYE_BLAST = 39908,
  105. SPELL_BLAZE_EFFECT = 40610,
  106. SPELL_BLAZE_SUMMON = 40637,
  107. SPELL_DEMON_FIRE = 40029,
  108. SPELL_FLAME_BLAST = 40631,
  109. SPELL_CHARGE = 41581,
  110. SPELL_FLAME_ENRAGE = 45078,
  111. // Akama spells
  112. SPELL_AKAMA_DOOR_CHANNEL = 41268,
  113. SPELL_DEATHSWORN_DOOR_CHANNEL = 41269,
  114. SPELL_AKAMA_DOOR_FAIL = 41271, // Not sure where this is really used...
  115. SPELL_HEALING_POTION = 40535,
  116. SPELL_CHAIN_LIGHTNING = 40536,
  117. // Maiev spells
  118. SPELL_CAGE_TRAP_DUMMY = 40761, // Put this in DB for cage trap GO.
  119. SPELL_CAGED = 40695,
  120. SPELL_CAGE_TRAP_SUMMON = 40694, // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working)
  121. SPELL_CAGE_TRAP_BEAM = 40713,
  122. SPELL_TELEPORT_VISUAL = 41232,
  123. SPELL_SHADOW_STRIKE = 40685,
  124. SPELL_THROW_DAGGER = 41152,
  125. SPELL_FAN_BLADES = 39954 // bugged visual
  126. };
  127.  
  128. enum Misc
  129. {
  130. FLAME_ENRAGE_DISTANCE = 30,
  131. FLAME_CHARGE_DISTANCE = 50,
  132.  
  133. EQUIP_ID_MAIN_HAND = 32837,
  134. EQUIP_ID_OFF_HAND = 32838,
  135. EQUIP_ID_MAIN_HAND_MAIEV = 44850,
  136.  
  137. MODEL_INVISIBLE = 11686,
  138. MODEL_ILLIDAN = 21135,
  139. MODEL_BLADE = 21431
  140. };
  141.  
  142. /**** Creature Summon and Recognition IDs ****/
  143. enum CreatureEntry
  144. {
  145. EMPTY = 0,
  146. AKAMA = 22990,
  147. ILLIDAN_STORMRAGE = 22917,
  148. BLADE_OF_AZZINOTH = 22996,
  149. FLAME_OF_AZZINOTH = 22997,
  150. MAIEV_SHADOWSONG = 23197,
  151. SHADOW_DEMON = 23375,
  152. DEMON_FIRE = 23069,
  153. FLAME_CRASH = 23336,
  154. ILLIDAN_DOOR_TRIGGER = 23412,
  155. SPIRIT_OF_OLUM = 23411,
  156. SPIRIT_OF_UDALO = 23410,
  157. ILLIDARI_ELITE = 23226,
  158. PARASITIC_SHADOWFIEND = 23498,
  159. CAGE_TRAP_TRIGGER = 23292
  160. };
  161.  
  162. /*** Phase Names ***/
  163. enum PhaseIllidan
  164. {
  165. PHASE_ILLIDAN_NULL = 0,
  166. PHASE_NORMAL = 1,
  167. PHASE_FLIGHT = 2,
  168. PHASE_NORMAL_2 = 3,
  169. PHASE_DEMON = 4,
  170. PHASE_NORMAL_MAIEV = 5,
  171. PHASE_TALK_SEQUENCE = 6,
  172. PHASE_FLIGHT_SEQUENCE = 7,
  173. PHASE_TRANSFORM_SEQUENCE = 8,
  174. PHASE_ILLIDAN_MAX = 9
  175. }; // Maiev uses the same phase
  176.  
  177. enum PhaseAkama
  178. {
  179. PHASE_AKAMA_NULL = 0,
  180. PHASE_CHANNEL = 1,
  181. PHASE_WALK = 2,
  182. PHASE_TALK = 3,
  183. PHASE_FIGHT_ILLIDAN = 4,
  184. PHASE_FIGHT_MINIONS = 5,
  185. PHASE_RETURN = 6
  186. };
  187.  
  188. enum EventIllidan
  189. {
  190. EVENT_NULL = 0,
  191. EVENT_BERSERK = 1,
  192. // normal phase
  193. EVENT_TAUNT = 2,
  194. EVENT_SHEAR = 3,
  195. EVENT_FLAME_CRASH = 4,
  196. EVENT_PARASITIC_SHADOWFIEND = 5,
  197. EVENT_PARASITE_CHECK = 6,
  198. EVENT_DRAW_SOUL = 7,
  199. EVENT_AGONIZING_FLAMES = 8,
  200. EVENT_TRANSFORM_NORMAL = 9,
  201. EVENT_ENRAGE = 10,
  202. // flight phase
  203. EVENT_FIREBALL = 2,
  204. EVENT_DARK_BARRAGE = 3,
  205. EVENT_EYE_BLAST = 4,
  206. EVENT_MOVE_POINT = 5,
  207. // demon phase
  208. EVENT_SHADOW_BLAST = 2,
  209. EVENT_FLAME_BURST = 3,
  210. EVENT_SHADOWDEMON = 4,
  211. EVENT_TRANSFORM_DEMON = 5,
  212. // sequence phase
  213. EVENT_TALK_SEQUENCE = 2,
  214. EVENT_FLIGHT_SEQUENCE = 2,
  215. EVENT_TRANSFORM_SEQUENCE = 2
  216. };
  217.  
  218. enum EventMaiev
  219. {
  220. EVENT_MAIEV_NULL = 0,
  221. EVENT_MAIEV_STEALTH = 1,
  222. EVENT_MAIEV_TAUNT = 2,
  223. EVENT_MAIEV_SHADOW_STRIKE = 3,
  224. EVENT_MAIEV_THROW_DAGGER = 4,
  225. EVENT_MAIEV_TRAP = 4
  226. };
  227.  
  228. static const EventIllidan MaxTimer[9] =
  229. {
  230. EVENT_NULL,
  231. EVENT_DRAW_SOUL,
  232. EVENT_MOVE_POINT,
  233. EVENT_TRANSFORM_NORMAL,
  234. EVENT_TRANSFORM_DEMON,
  235. EVENT_ENRAGE,
  236. EVENT_TALK_SEQUENCE,
  237. EVENT_FLIGHT_SEQUENCE,
  238. EVENT_TRANSFORM_SEQUENCE
  239. };
  240.  
  241.  
  242. /* ################## TO DO CONVERT THIS UGLINESS TO CREATURE TEXT ##################
  243.  
  244. SET @AKAMA := 23089;
  245. SET @ILLIDAN := 22917;
  246. SET @MAIEV := 23197;
  247. DELETE FROM `creature_text` WHERE `entry`=@AKAMA AND `groupid` IN (2,3,4);
  248. DELETE FROM `creature_text` WHERE `entry`=@ILLIDAN AND `groupid` IN (8,9,10,11,12,13,14);
  249. DELETE FROM `creature_text` WHERE `entry`=@MAIEV AND `groupid` IN (1,2,3,4);
  250. INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
  251. (@ILLIDAN,8,0, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.",14,0,100,0,0,11463, 'Illidan SAY_XXXXXXXXXXX'),
  252. (@AKAMA,2,0, "We've come to end your reign, Illidan. My people and all of Outland shall be free!",14,0,100,25,0,11389, 'Akama SAY_XXXXXXXXXXX'),
  253. (@ILLIDAN,9,0, "Boldly said. But I remain unconvinced.",14,0,100,396,0,11464, 'Illidan SAY_XXXXXXXXXXX'),
  254. (@AKAMA,3,0, "The time has come! The moment is at hand!",14,0,100,22,0,11380, 'Akama SAY_XXXXXXXXXXX'),
  255. (@ILLIDAN,10,0, "You are not prepared!",14,0,100,406,0,11466, 'Illidan SAY_XXXXXXXXXXX'),
  256. (@ILLIDAN,11,0, "Is this it, mortals? Is this all the fury you can muster?",14,0,100,0,0,11476, 'Illidan SAY_XXXXXXXXXXX'),
  257. (@MAIEV,1,0, "Their fury pales before mine, Illidan. We have some unsettled business between us.",14,0,100,5,0,11491, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
  258. (@ILLIDAN,12,0, "Maiev... How is this even possible?",14,0,100,1,0,11477, 'Illidan SAY_XXXXXXXXXXX'),
  259. (@MAIEV,2,0, "Ah... my long hunt is finally over. Today, Justice will be done!",14,0,100,15,0,11492, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
  260. (@ILLIDAN,13,0, "Feel the hatred of ten thousand years!",14,0,100,396,0,11470, 'Illidan SAY_XXXXXXXXXXX'),
  261. (@MAIEV,3,0, "Ahh... It is finished. You are beaten.",14,0,100,0,0,11496, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
  262. (@ILLIDAN,14,0, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..",14,0,100,65,0,11478, 'Illidan SAY_XXXXXXXXXXX'),
  263. (@MAIEV,4,0, "He is right. I feel nothing... I am nothing... Farewell, champions.",14,0,100,0,0,11497, 'Maiev Shadowsong SAY_XXXXXXXXXXX'),
  264. (@AKAMA,4,0, "The Light will fill these dismal halls once again. I swear it.",14,0,100,0,0,11387, 'Akama SAY_XXXXXXXXXXX');
  265.  
  266. */
  267.  
  268. struct Yells
  269. {
  270. uint32 sound;
  271. std::string text;
  272. uint32 creature, timer, emote;
  273. bool Talk;
  274. };
  275.  
  276. static const Yells Conversation[22] =
  277. {
  278. {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true},
  279. {0, "", ILLIDAN_STORMRAGE, 5000, 396, true},
  280. {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true},
  281. {0, "", AKAMA, 5000, 66, true},
  282. {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true},
  283. {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true},
  284. {0, "", AKAMA, 2000, 15, true},
  285. {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true},
  286. {0, "", EMPTY, 1000, 0, true},
  287. {0, "", EMPTY, 0, 0, false}, // 9
  288. {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true},
  289. {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true},
  290. {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true},
  291. {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true},
  292. {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false}, // 14
  293. {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true}, // 15
  294.  
  295. {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later
  296. {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true},
  297. {11498, "", MAIEV_SHADOWSONG, 5000, 0, true},
  298. {11498, "", EMPTY, 1000, 0, true}, // 19 Maiev disappear
  299. {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true},
  300. {0, "", EMPTY, 1000, 0, false} // 21
  301. };
  302.  
  303. struct Locations
  304. {
  305. float x, y, z;
  306. };
  307.  
  308. static const Locations HoverPosition[4]=
  309. {
  310. {657.0f, 340.0f, 355.0f},
  311. {657.0f, 275.0f, 355.0f},
  312. {705.0f, 275.0f, 355.0f},
  313. {705.0f, 340.0f, 355.0f}
  314. };
  315.  
  316. static const Locations GlaivePosition[4]=
  317. {
  318. {695.105f, 305.303f, 354.256f},
  319. {659.338f, 305.303f, 354.256f}, // the distance between two glaives is 36
  320. {700.105f, 305.303f, 354.256f},
  321. {664.338f, 305.303f, 354.256f}
  322. };
  323.  
  324. static const Locations EyeBlast[2]=
  325. {
  326. {677.0f, 350.0f, 354.0f}, // start point, pass through glaive point
  327. {677.0f, 260.0f, 354.0f}
  328. };
  329.  
  330. static const Locations AkamaWP[13]=
  331. {
  332. {770.01f, 304.50f, 312.29f}, // Bottom of the first stairs, at the doors
  333. {780.66f, 304.50f, 319.74f}, // Top of the first stairs
  334. {790.13f, 319.68f, 319.76f}, // Bottom of the second stairs (left from the entrance)
  335. {787.17f, 347.38f, 341.42f}, // Top of the second stairs
  336. {781.34f, 350.31f, 341.44f}, // Bottom of the third stairs
  337. {762.60f, 361.06f, 353.60f}, // Top of the third stairs
  338. {756.35f, 360.52f, 353.27f}, // Before the door-thingy
  339. {743.82f, 342.21f, 353.00f}, // Somewhere further
  340. {732.69f, 305.13f, 353.00f}, // In front of Illidan - (8)
  341. {738.11f, 365.44f, 353.00f}, // in front of the door-thingy (the other one!)
  342. {792.18f, 366.62f, 341.42f}, // Down the first flight of stairs
  343. {796.84f, 304.89f, 319.76f}, // Down the second flight of stairs
  344. {782.01f, 304.55f, 319.76f} // Final location - back at the initial gates. This is where he will fight the minions! (12)
  345. };
  346. // 755.762f, 304.0747f, 312.1769f -- This is where Akama should be spawned
  347. static const Locations SpiritSpawns[2]=
  348. {
  349. {755.5426f, 309.9156f, 312.2129f},
  350. {755.5426f, 298.7923f, 312.0834f}
  351. };
  352.  
  353. struct Animation // For the demon transformation
  354. {
  355. uint32 aura, unaura, timer, size, displayid, phase;
  356. bool equip;
  357. };
  358.  
  359. static const Animation DemonTransformation[10]=
  360. {
  361. {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true},
  362. {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true},
  363. {0, 0, 3000, 1073741824, 21322, 6, false}, // stunned, cannot cast demon form
  364. {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false},
  365. {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false},
  366. {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false},
  367. {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false},
  368. {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false},
  369. {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true},
  370. {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true}
  371. };
  372.  
  373. class npc_flame_of_azzinoth : public CreatureScript
  374. {
  375. public:
  376. npc_flame_of_azzinoth() : CreatureScript("npc_flame_of_azzinoth") { }
  377.  
  378. struct flame_of_azzinothAI : public ScriptedAI
  379. {
  380. flame_of_azzinothAI(Creature* creature) : ScriptedAI(creature) {}
  381.  
  382. void Reset() OVERRIDE
  383. {
  384. FlameBlastTimer = 15000;
  385. CheckTimer = 5000;
  386. GlaiveGUID = 0;
  387. }
  388.  
  389. void EnterCombat(Unit* /*who*/) OVERRIDE
  390. {
  391. DoZoneInCombat();
  392. }
  393.  
  394. void ChargeCheck()
  395. {
  396. Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false);
  397. if (target && (!me->IsWithinCombatRange(target, FLAME_CHARGE_DISTANCE)))
  398. {
  399. me->AddThreat(target, 5000000.0f);
  400. AttackStart(target);
  401. DoCast(target, SPELL_CHARGE);
  402. Talk(EMOTE_AZZINOTH_GAZE);
  403. }
  404. }
  405.  
  406. void EnrageCheck()
  407. {
  408. if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID))
  409. {
  410. if (!me->IsWithinDistInMap(glaive, FLAME_ENRAGE_DISTANCE))
  411. {
  412. glaive->InterruptNonMeleeSpells(true);
  413. DoCast(me, SPELL_FLAME_ENRAGE, true);
  414. DoResetThreat();
  415. if (SelectTarget(SELECT_TARGET_RANDOM, 0))
  416. {
  417. me->AddThreat(me->GetVictim(), 5000000.0f);
  418. AttackStart(me->GetVictim());
  419. }
  420. }
  421. else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL))
  422. {
  423. glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false);
  424. me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE);
  425. }
  426. }
  427. }
  428.  
  429. void SetGlaiveGUID(uint64 guid)
  430. {
  431. GlaiveGUID = guid;
  432. }
  433.  
  434. void UpdateAI(uint32 diff) OVERRIDE
  435. {
  436. if (!UpdateVictim())
  437. return;
  438.  
  439. if (FlameBlastTimer <= diff)
  440. {
  441. DoCastVictim(SPELL_BLAZE_SUMMON, true); // appear at victim
  442. DoCastVictim(SPELL_FLAME_BLAST);
  443. FlameBlastTimer = 15000; // 10000 is official-like?
  444. DoZoneInCombat(); // in case someone is revived
  445. } else FlameBlastTimer -= diff;
  446.  
  447. if (CheckTimer <= diff)
  448. {
  449. ChargeCheck();
  450. EnrageCheck();
  451. CheckTimer = 1000;
  452. } else CheckTimer -= diff;
  453.  
  454. DoMeleeAttackIfReady();
  455. }
  456.  
  457. private:
  458. uint32 FlameBlastTimer;
  459. uint32 CheckTimer;
  460. uint64 GlaiveGUID;
  461. };
  462.  
  463. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  464. {
  465. return new flame_of_azzinothAI(creature);
  466. }
  467. };
  468.  
  469. /************************************** Illidan's AI* **************************************/
  470. class boss_illidan_stormrage : public CreatureScript
  471. {
  472. public:
  473. boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { }
  474.  
  475. struct boss_illidan_stormrageAI : public ScriptedAI
  476. {
  477. boss_illidan_stormrageAI(Creature* creature) : ScriptedAI(creature), Summons(me)
  478. {
  479. instance = creature->GetInstanceScript();
  480. DoCast(me, SPELL_DUAL_WIELD, true);
  481. }
  482.  
  483. void Reset() OVERRIDE;
  484.  
  485. void JustSummoned(Creature* summon) OVERRIDE;
  486.  
  487. void SummonedCreatureDespawn(Creature* summon) OVERRIDE
  488. {
  489. if (summon->GetCreatureTemplate()->Entry == FLAME_OF_AZZINOTH)
  490. {
  491. for (uint8 i = 0; i < 2; ++i)
  492. if (summon->GetGUID() == FlameGUID[i])
  493. FlameGUID[i] = 0;
  494.  
  495. if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL)
  496. {
  497. me->InterruptNonMeleeSpells(true);
  498. EnterPhase(PHASE_FLIGHT_SEQUENCE);
  499. }
  500. }
  501. Summons.Despawn(summon);
  502. }
  503.  
  504. void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) OVERRIDE
  505. {
  506. if (FlightCount == 7) // change hover point
  507. {
  508. if (me->GetVictim())
  509. {
  510. me->SetInFront(me->GetVictim());
  511. me->StopMoving();
  512. }
  513. EnterPhase(PHASE_FLIGHT);
  514. }
  515. else // handle flight sequence
  516. Timer[EVENT_FLIGHT_SEQUENCE] = 1000;
  517. }
  518.  
  519. void EnterCombat(Unit* /*who*/) OVERRIDE
  520. {
  521. me->setActive(true);
  522. DoZoneInCombat();
  523. }
  524.  
  525. void AttackStart(Unit* who) OVERRIDE
  526. {
  527. if (!who || Phase >= PHASE_TALK_SEQUENCE)
  528. return;
  529.  
  530. if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON)
  531. AttackStartNoMove(who);
  532. else
  533. ScriptedAI::AttackStart(who);
  534. }
  535.  
  536. void MoveInLineOfSight(Unit*) OVERRIDE {}
  537.  
  538.  
  539. void JustDied(Unit* /*killer*/) OVERRIDE
  540. {
  541. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  542.  
  543. if (!instance)
  544. return;
  545.  
  546. instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE);
  547.  
  548. for (uint8 i = DATA_GO_ILLIDAN_DOOR_R; i < DATA_GO_ILLIDAN_DOOR_L + 1; ++i)
  549. instance->HandleGameObject(instance->GetData64(i), true);
  550. }
  551.  
  552. void KilledUnit(Unit* victim) OVERRIDE
  553. {
  554. if (victim->GetTypeId() != TYPEID_PLAYER)
  555. return;
  556.  
  557. Talk(SAY_ILLIDAN_KILL);
  558. }
  559.  
  560. void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
  561. {
  562. if (damage >= me->GetHealth() && done_by != me)
  563. damage = 0;
  564. if (done_by->GetGUID() == MaievGUID)
  565. done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him
  566. }
  567.  
  568. void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
  569. {
  570. if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades!
  571. {
  572. if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
  573. SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
  574. else
  575. SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE);
  576. me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
  577. }
  578. }
  579.  
  580. void DeleteFromThreatList(uint64 TargetGUID)
  581. {
  582. ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
  583. for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
  584. {
  585. if ((*itr)->getUnitGuid() == TargetGUID)
  586. {
  587. (*itr)->removeReference();
  588. break;
  589. }
  590. }
  591. }
  592.  
  593. void Talk(uint32 count)
  594. {
  595. Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer;
  596.  
  597. Creature* creature = NULL;
  598. if (Conversation[count].creature == ILLIDAN_STORMRAGE)
  599. creature = me;
  600. else if (Conversation[count].creature == AKAMA)
  601. creature = (Unit::GetCreature((*me), AkamaGUID));
  602. else if (Conversation[count].creature == MAIEV_SHADOWSONG)
  603. creature = (Unit::GetCreature((*me), MaievGUID));
  604.  
  605. if (creature)
  606. {
  607. if (Conversation[count].emote)
  608. creature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation!
  609. if (Conversation[count].text.size())
  610. creature->MonsterYell(Conversation[count].text.c_str(), LANG_UNIVERSAL, 0); // Have the Creature yell out some text
  611. if (Conversation[count].sound)
  612. DoPlaySoundToSet(creature, Conversation[count].sound); // Play some sound on the creature
  613. }
  614. }
  615.  
  616. void EnterPhase(PhaseIllidan NextPhase)
  617. {
  618. DoZoneInCombat();
  619.  
  620. switch (NextPhase)
  621. {
  622. case PHASE_NORMAL:
  623. case PHASE_NORMAL_2:
  624. case PHASE_NORMAL_MAIEV:
  625. AttackStart(me->GetVictim());
  626. Timer[EVENT_TAUNT] = 32000;
  627. Timer[EVENT_SHEAR] = urand(10, 25) * 1000;
  628. Timer[EVENT_FLAME_CRASH] = 20000;
  629. Timer[EVENT_PARASITIC_SHADOWFIEND] = 25000;
  630. Timer[EVENT_PARASITE_CHECK] = 0;
  631. Timer[EVENT_DRAW_SOUL] = 30000;
  632. if (NextPhase == PHASE_NORMAL)
  633. break;
  634. Timer[EVENT_AGONIZING_FLAMES] = 35000;
  635. Timer[EVENT_TRANSFORM_NORMAL] = 60000;
  636. if (NextPhase == PHASE_NORMAL_2)
  637. break;
  638. Timer[EVENT_ENRAGE] = urand(30, 40) * 1000;
  639. break;
  640. case PHASE_FLIGHT:
  641. Timer[EVENT_FIREBALL] = 1000;
  642. if (!(rand()%4))
  643. Timer[EVENT_DARK_BARRAGE] = 10000;
  644. Timer[EVENT_EYE_BLAST] = urand(10, 25) * 1000;
  645. Timer[EVENT_MOVE_POINT] = urand(20, 40) * 1000;
  646. break;
  647. case PHASE_DEMON:
  648. Timer[EVENT_SHADOW_BLAST] = 1000;
  649. Timer[EVENT_FLAME_BURST] = 10000;
  650. Timer[EVENT_SHADOWDEMON] = 30000;
  651. Timer[EVENT_TRANSFORM_DEMON] = 60000;
  652. AttackStart(me->GetVictim());
  653. break;
  654. case PHASE_TALK_SEQUENCE:
  655. Timer[EVENT_TALK_SEQUENCE] = 100;
  656. me->RemoveAllAuras();
  657. me->InterruptNonMeleeSpells(false);
  658. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
  659. me->GetMotionMaster()->Clear(false);
  660. me->AttackStop();
  661. break;
  662. case PHASE_FLIGHT_SEQUENCE:
  663. if (Phase == PHASE_NORMAL) // lift off
  664. {
  665. FlightCount = 1;
  666. Timer[EVENT_FLIGHT_SEQUENCE] = 1;
  667. me->RemoveAllAuras();
  668. me->InterruptNonMeleeSpells(false);
  669. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  670. me->GetMotionMaster()->Clear(false);
  671. me->AttackStop();
  672. }
  673. else // land
  674. Timer[EVENT_FLIGHT_SEQUENCE] = 2000;
  675. break;
  676. case PHASE_TRANSFORM_SEQUENCE:
  677. if (Phase == PHASE_DEMON)
  678. Timer[EVENT_TRANSFORM_SEQUENCE] = 500;
  679. else
  680. {
  681. TransformCount = 0;
  682. Timer[EVENT_TRANSFORM_SEQUENCE] = 500;
  683. Talk(SAY_ILLIDAN_MORPH);
  684. }
  685. me->GetMotionMaster()->Clear();
  686. me->AttackStop();
  687. break;
  688. default:
  689. break;
  690. }
  691. if (MaievGUID)
  692. {
  693. if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID))
  694. if (maiev->IsAlive())
  695. maiev->AI()->DoAction(NextPhase);
  696. }
  697. Phase = NextPhase;
  698. Event = EVENT_NULL;
  699. }
  700.  
  701. void CastEyeBlast()
  702. {
  703. me->InterruptNonMeleeSpells(false);
  704.  
  705. Talk(SAY_ILLIDAN_EYE_BLAST);
  706.  
  707. float distx, disty, dist[2];
  708. for (uint8 i = 0; i < 2; ++i)
  709. {
  710. distx = EyeBlast[i].x - HoverPosition[HoverPoint].x;
  711. disty = EyeBlast[i].y - HoverPosition[HoverPoint].y;
  712. dist[i] = distx * distx + disty * disty;
  713. }
  714. Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1];
  715. for (uint8 i = 0; i < 2; ++i)
  716. {
  717. distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x;
  718. disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y;
  719. dist[i] = distx * distx + disty * disty;
  720. }
  721. Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1];
  722.  
  723. final.x = 2 * final.x - initial.x;
  724. final.y = 2 * final.y - initial.y;
  725.  
  726. Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000);
  727. if (!Trigger)
  728. return;
  729.  
  730. Trigger->SetSpeed(MOVE_WALK, 3);
  731. Trigger->SetWalk(true);
  732. Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z);
  733.  
  734. // Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  735. me->SetTarget(Trigger->GetGUID());
  736. DoCast(Trigger, SPELL_EYE_BLAST);
  737. }
  738.  
  739. void SummonFlamesOfAzzinoth()
  740. {
  741. Talk(SAY_ILLIDAN_SUMMONFLAMES);
  742.  
  743. for (uint8 i = 0; i < 2; ++i)
  744. {
  745. if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i]))
  746. {
  747. if (Creature* flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000))
  748. {
  749. flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction
  750. flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE);
  751. FlameGUID[i] = flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase
  752. CAST_AI(npc_flame_of_azzinoth::flame_of_azzinothAI, flame->AI())->SetGlaiveGUID(GlaiveGUID[i]);
  753. glaive->CastSpell(flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it.
  754. }
  755. }
  756. }
  757. }
  758.  
  759. void SummonMaiev()
  760. {
  761. DoCast(me, SPELL_SHADOW_PRISON, true);
  762. DoCast(me, SPELL_SUMMON_MAIEV, true);
  763. if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console.
  764. {
  765. EnterEvadeMode();
  766. me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0);
  767. TC_LOG_ERROR(LOG_FILTER_TSCR, "SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)");
  768. }
  769. }
  770.  
  771. void HandleTalkSequence();
  772.  
  773. void HandleFlightSequence()
  774. {
  775. switch (FlightCount)
  776. {
  777. case 1: // lift off
  778. me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
  779. me->SetDisableGravity(true);
  780. me->StopMoving();
  781. Talk(SAY_ILLIDAN_TAKEOFF);
  782. Timer[EVENT_FLIGHT_SEQUENCE] = 3000;
  783. break;
  784. case 2: // move to center
  785. me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); // +5, for SPELL_THROW_GLAIVE bug
  786. Timer[EVENT_FLIGHT_SEQUENCE] = 0;
  787. break;
  788. case 3: // throw one glaive
  789. {
  790. uint8 i=1;
  791. Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
  792. if (Glaive)
  793. {
  794. GlaiveGUID[i] = Glaive->GetGUID();
  795. Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  796. Glaive->SetDisplayId(MODEL_INVISIBLE);
  797. Glaive->setFaction(me->getFaction());
  798. DoCast(Glaive, SPELL_THROW_GLAIVE2);
  799. }
  800. }
  801. Timer[EVENT_FLIGHT_SEQUENCE] = 700;
  802. break;
  803. case 4: // throw another
  804. SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
  805. {
  806. uint8 i=0;
  807. Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
  808. if (Glaive)
  809. {
  810. GlaiveGUID[i] = Glaive->GetGUID();
  811. Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  812. Glaive->SetDisplayId(MODEL_INVISIBLE);
  813. Glaive->setFaction(me->getFaction());
  814. DoCast(Glaive, SPELL_THROW_GLAIVE, true);
  815. }
  816. }
  817. Timer[EVENT_FLIGHT_SEQUENCE] = 5000;
  818. break;
  819. case 5: // summon flames
  820. SummonFlamesOfAzzinoth();
  821. Timer[EVENT_FLIGHT_SEQUENCE] = 3000;
  822. break;
  823. case 6: // fly to hover point
  824. me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
  825. Timer[EVENT_FLIGHT_SEQUENCE] = 0;
  826. break;
  827. case 7: // return to center
  828. me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z);
  829. Timer[EVENT_FLIGHT_SEQUENCE] = 0;
  830. break;
  831. case 8: // glaive return
  832. for (uint8 i = 0; i < 2; ++i)
  833. {
  834. if (GlaiveGUID[i])
  835. {
  836. Unit* Glaive = Unit::GetUnit(*me, GlaiveGUID[i]);
  837. if (Glaive)
  838. {
  839. Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us
  840. Glaive->SetDisplayId(MODEL_INVISIBLE); // disappear but not die for now
  841. }
  842. }
  843. }
  844. Timer[EVENT_FLIGHT_SEQUENCE] = 2000;
  845. break;
  846. case 9: // land
  847. me->SetDisableGravity(false);
  848. me->StopMoving();
  849. me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
  850. for (uint8 i = 0; i < 2; ++i)
  851. {
  852. if (GlaiveGUID[i])
  853. {
  854. if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i]))
  855. glaive->DespawnOrUnsummon();
  856.  
  857. GlaiveGUID[i] = 0;
  858. }
  859. }
  860. Timer[EVENT_FLIGHT_SEQUENCE] = 2000;
  861. break;
  862. case 10: // attack
  863. DoResetThreat();
  864. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
  865. me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
  866. EnterPhase(PHASE_NORMAL_2);
  867. break;
  868. default:
  869. break;
  870. }
  871. ++FlightCount;
  872. }
  873.  
  874. void HandleTransformSequence()
  875. {
  876. if (DemonTransformation[TransformCount].unaura)
  877. me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura);
  878.  
  879. if (DemonTransformation[TransformCount].aura)
  880. DoCast(me, DemonTransformation[TransformCount].aura, true);
  881.  
  882. if (DemonTransformation[TransformCount].displayid)
  883. me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time!
  884.  
  885. if (DemonTransformation[TransformCount].equip)
  886. {
  887. // Requip warglaives if needed
  888. SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE);
  889. me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
  890. }
  891. else
  892. {
  893. // Unequip warglaives if needed
  894. SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
  895. }
  896.  
  897. switch (TransformCount)
  898. {
  899. case 2:
  900. DoResetThreat();
  901. break;
  902. case 4:
  903. EnterPhase(PHASE_DEMON);
  904. break;
  905. case 7:
  906. DoResetThreat();
  907. break;
  908. case 9:
  909. if (MaievGUID)
  910. EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3
  911. else
  912. EnterPhase(PHASE_NORMAL_2);
  913. break;
  914. default:
  915. break;
  916. }
  917. if (Phase == PHASE_TRANSFORM_SEQUENCE)
  918. Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer;
  919. ++TransformCount;
  920. }
  921.  
  922. void UpdateAI(uint32 diff) OVERRIDE
  923. {
  924. if ((!UpdateVictim()) && Phase < PHASE_TALK_SEQUENCE)
  925. return;
  926.  
  927. Event = EVENT_NULL;
  928. for (int32 i = 1; i <= MaxTimer[Phase]; ++i)
  929. {
  930. if (Timer[i]) // Event is enabled
  931. {
  932. if (Timer[i] <= diff)
  933. {
  934. if (!Event) // No event with higher priority
  935. Event = (EventIllidan)i;
  936. }
  937. else Timer[i] -= diff;
  938. }
  939. }
  940.  
  941. switch (Phase)
  942. {
  943. case PHASE_NORMAL:
  944. if (HealthBelowPct(65))
  945. EnterPhase(PHASE_FLIGHT_SEQUENCE);
  946. break;
  947.  
  948. case PHASE_NORMAL_2:
  949. if (HealthBelowPct(30))
  950. EnterPhase(PHASE_TALK_SEQUENCE);
  951. break;
  952.  
  953. case PHASE_NORMAL_MAIEV:
  954. if (HealthBelowPct(1))
  955. EnterPhase(PHASE_TALK_SEQUENCE);
  956. break;
  957.  
  958. case PHASE_TALK_SEQUENCE:
  959. if (Event == EVENT_TALK_SEQUENCE)
  960. HandleTalkSequence();
  961. break;
  962.  
  963. case PHASE_FLIGHT_SEQUENCE:
  964. if (Event == EVENT_FLIGHT_SEQUENCE)
  965. HandleFlightSequence();
  966. break;
  967.  
  968. case PHASE_TRANSFORM_SEQUENCE:
  969. if (Event == EVENT_TRANSFORM_SEQUENCE)
  970. HandleTransformSequence();
  971. break;
  972. default:
  973. break;
  974. }
  975.  
  976. if (me->IsNonMeleeSpellCasted(false))
  977. return;
  978.  
  979. if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || (Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)))
  980. {
  981. switch (Event)
  982. {
  983. // PHASE_NORMAL
  984. case EVENT_BERSERK:
  985. Talk(SAY_ILLIDAN_ENRAGE);
  986. DoCast(me, SPELL_BERSERK, true);
  987. Timer[EVENT_BERSERK] = 5000; // The buff actually lasts forever.
  988. break;
  989.  
  990. case EVENT_TAUNT:
  991. Talk(SAY_ILLIDAN_TAUNT);
  992. Timer[EVENT_TAUNT] = urand(25000, 35000);
  993. break;
  994.  
  995. case EVENT_SHEAR:
  996. // no longer exists in 3.0f.2
  997. // DoCastVictim(SPELL_SHEAR);
  998. Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000);
  999. break;
  1000.  
  1001. case EVENT_FLAME_CRASH:
  1002. DoCastVictim(SPELL_FLAME_CRASH);
  1003. Timer[EVENT_FLAME_CRASH] = urand(30000, 40000);
  1004. break;
  1005.  
  1006. case EVENT_PARASITIC_SHADOWFIEND:
  1007. {
  1008. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true))
  1009. DoCast(target, SPELL_PARASITIC_SHADOWFIEND, true);
  1010. Timer[EVENT_PARASITIC_SHADOWFIEND] = urand(35000, 45000);
  1011. }
  1012. break;
  1013.  
  1014. case EVENT_PARASITE_CHECK:
  1015. Timer[EVENT_PARASITE_CHECK] = 0;
  1016. break;
  1017.  
  1018. case EVENT_DRAW_SOUL:
  1019. DoCastVictim(SPELL_DRAW_SOUL);
  1020. Timer[EVENT_DRAW_SOUL] = urand(50000, 60000);
  1021. break;
  1022.  
  1023. // PHASE_NORMAL_2
  1024. case EVENT_AGONIZING_FLAMES:
  1025. DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES);
  1026. Timer[EVENT_AGONIZING_FLAMES] = 0;
  1027. break;
  1028.  
  1029. case EVENT_TRANSFORM_NORMAL:
  1030. EnterPhase(PHASE_TRANSFORM_SEQUENCE);
  1031. break;
  1032.  
  1033. // PHASE_NORMAL_MAIEV
  1034. case EVENT_ENRAGE:
  1035. DoCast(me, SPELL_ENRAGE);
  1036. Timer[EVENT_ENRAGE] = 0;
  1037. break;
  1038.  
  1039. default:
  1040. break;
  1041. }
  1042. DoMeleeAttackIfReady();
  1043. }
  1044.  
  1045. if (Phase == PHASE_FLIGHT)
  1046. {
  1047. switch (Event)
  1048. {
  1049. case EVENT_FIREBALL:
  1050. DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);
  1051. Timer[EVENT_FIREBALL] = 3000;
  1052. break;
  1053.  
  1054. case EVENT_DARK_BARRAGE:
  1055. DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE);
  1056. Timer[EVENT_DARK_BARRAGE] = 0;
  1057. break;
  1058.  
  1059. case EVENT_EYE_BLAST:
  1060. CastEyeBlast();
  1061. Timer[EVENT_EYE_BLAST] = 0;
  1062. break;
  1063.  
  1064. case EVENT_MOVE_POINT:
  1065. Phase = PHASE_FLIGHT_SEQUENCE;
  1066. Timer[EVENT_FLIGHT_SEQUENCE] = 0; // do not start Event when changing hover point
  1067. HoverPoint += (rand()%3 + 1);
  1068. if (HoverPoint > 3)
  1069. HoverPoint -= 4;
  1070. me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
  1071. break;
  1072.  
  1073. default:
  1074. break;
  1075. }
  1076. }
  1077.  
  1078. if (Phase == PHASE_DEMON)
  1079. {
  1080. switch (Event)
  1081. {
  1082. case EVENT_SHADOW_BLAST:
  1083. me->GetMotionMaster()->Clear(false);
  1084. if (!me->IsWithinDistInMap(me->GetVictim(), 50)||!me->IsWithinLOSInMap(me->GetVictim()))
  1085. me->GetMotionMaster()->MoveChase(me->GetVictim(), 30);
  1086. else
  1087. me->GetMotionMaster()->MoveIdle();
  1088. DoCastVictim(SPELL_SHADOW_BLAST);
  1089. Timer[EVENT_SHADOW_BLAST] = 4000;
  1090. break;
  1091. case EVENT_SHADOWDEMON:
  1092. DoCast(me, SPELL_SUMMON_SHADOWDEMON);
  1093. Timer[EVENT_SHADOWDEMON] = 0;
  1094. Timer[EVENT_FLAME_BURST] += 10000;
  1095. break;
  1096. case EVENT_FLAME_BURST:
  1097. DoCast(me, SPELL_FLAME_BURST);
  1098. Timer[EVENT_FLAME_BURST] = 15000;
  1099. break;
  1100. case EVENT_TRANSFORM_DEMON:
  1101. EnterPhase(PHASE_TRANSFORM_SEQUENCE);
  1102. break;
  1103. default:
  1104. break;
  1105. }
  1106. }
  1107. }
  1108.  
  1109. public:
  1110. uint64 AkamaGUID;
  1111. uint32 Timer[EVENT_ENRAGE + 1];
  1112. PhaseIllidan Phase;
  1113. private:
  1114. InstanceScript* instance;
  1115. EventIllidan Event;
  1116. uint32 TalkCount;
  1117. uint32 TransformCount;
  1118. uint32 FlightCount;
  1119. uint32 HoverPoint;
  1120. uint64 MaievGUID;
  1121. uint64 FlameGUID[2];
  1122. uint64 GlaiveGUID[2];
  1123. SummonList Summons;
  1124. };
  1125.  
  1126. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  1127. {
  1128. return new boss_illidan_stormrageAI(creature);
  1129. }
  1130. };
  1131.  
  1132. /********************************** End of Illidan AI* *****************************************/
  1133.  
  1134. /******* Functions and vars for Akama's AI* *****/
  1135. class boss_maiev_shadowsong : public CreatureScript
  1136. {
  1137. public:
  1138. boss_maiev_shadowsong() : CreatureScript("boss_maiev_shadowsong") { }
  1139.  
  1140. struct boss_maievAI : public ScriptedAI
  1141. {
  1142. boss_maievAI(Creature* creature) : ScriptedAI(creature) {};
  1143.  
  1144. void Reset() OVERRIDE
  1145. {
  1146. MaxTimer = 0;
  1147. Phase = PHASE_NORMAL_MAIEV;
  1148. IllidanGUID = 0;
  1149. Timer[EVENT_MAIEV_STEALTH] = 0;
  1150. Timer[EVENT_MAIEV_TAUNT] = urand(22, 43) * 1000;
  1151. Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000;
  1152. SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND_MAIEV, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
  1153. me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738);
  1154. }
  1155.  
  1156. void EnterCombat(Unit* /*who*/) OVERRIDE {}
  1157. void MoveInLineOfSight(Unit* /*who*/) OVERRIDE {}
  1158.  
  1159. void EnterEvadeMode() OVERRIDE {}
  1160.  
  1161. void GetIllidanGUID(uint64 guid)
  1162. {
  1163. IllidanGUID = guid;
  1164. }
  1165.  
  1166. void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
  1167. {
  1168. if (done_by->GetGUID() != IllidanGUID)
  1169. damage = 0;
  1170. else
  1171. {
  1172. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1173. if (illidan->GetVictim() == me)
  1174. damage = me->CountPctFromMaxHealth(10);
  1175.  
  1176. if (damage >= me->GetHealth())
  1177. damage = 0;
  1178. }
  1179. }
  1180.  
  1181. void AttackStart(Unit* who) OVERRIDE
  1182. {
  1183. if (!who || Timer[EVENT_MAIEV_STEALTH])
  1184. return;
  1185.  
  1186. if (Phase == PHASE_TALK_SEQUENCE)
  1187. AttackStartNoMove(who);
  1188. else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE)
  1189. {
  1190. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1191. if (me->IsWithinDistInMap(illidan, 25))
  1192. BlinkToPlayer(); // Do not let dread aura hurt her.
  1193. AttackStartNoMove(who);
  1194. }
  1195. else
  1196. ScriptedAI::AttackStart(who);
  1197. }
  1198.  
  1199. void DoAction(int32 param) OVERRIDE
  1200. {
  1201. if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX)
  1202. EnterPhase(PhaseIllidan(param));
  1203. }
  1204.  
  1205. void EnterPhase(PhaseIllidan NextPhase) // This is in fact Illidan's phase.
  1206. {
  1207. switch (NextPhase)
  1208. {
  1209. case PHASE_TALK_SEQUENCE:
  1210. if (Timer[EVENT_MAIEV_STEALTH])
  1211. {
  1212. me->SetFullHealth();
  1213. me->SetVisible(true);
  1214. Timer[EVENT_MAIEV_STEALTH] = 0;
  1215. }
  1216. me->InterruptNonMeleeSpells(false);
  1217. me->GetMotionMaster()->Clear(false);
  1218. me->AttackStop();
  1219. me->SetTarget(IllidanGUID);
  1220. MaxTimer = 0;
  1221. break;
  1222. case PHASE_TRANSFORM_SEQUENCE:
  1223. MaxTimer = 4;
  1224. Timer[EVENT_MAIEV_TAUNT] += 10000;
  1225. Timer[EVENT_MAIEV_THROW_DAGGER] = 2000;
  1226. break;
  1227. case PHASE_DEMON:
  1228. break;
  1229. case PHASE_NORMAL_MAIEV:
  1230. MaxTimer = 4;
  1231. Timer[EVENT_MAIEV_TAUNT] += 10000;
  1232. Timer[EVENT_MAIEV_TRAP] = 22000;
  1233. break;
  1234. default:
  1235. break;
  1236. }
  1237. if (Timer[EVENT_MAIEV_STEALTH])
  1238. MaxTimer = 1;
  1239. Phase = NextPhase;
  1240. }
  1241.  
  1242. void BlinkTo(float x, float y, float z)
  1243. {
  1244. me->AttackStop();
  1245. me->InterruptNonMeleeSpells(false);
  1246. me->GetMotionMaster()->Clear(false);
  1247. DoTeleportTo(x, y, z);
  1248. DoCast(me, SPELL_TELEPORT_VISUAL, true);
  1249. }
  1250.  
  1251. void BlinkToPlayer()
  1252. {
  1253. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1254. {
  1255. Unit* target = illidan->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0);
  1256.  
  1257. if (!target || !me->IsWithinDistInMap(target, 80) || illidan->IsWithinDistInMap(target, 20))
  1258. {
  1259. uint8 pos = rand()%4;
  1260. BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z);
  1261. }
  1262. else
  1263. {
  1264. float x, y, z;
  1265. target->GetPosition(x, y, z);
  1266. BlinkTo(x, y, z);
  1267. }
  1268. }
  1269. }
  1270.  
  1271. void UpdateAI(uint32 diff) OVERRIDE
  1272. {
  1273. if ((!UpdateVictim())
  1274. && !Timer[EVENT_MAIEV_STEALTH])
  1275. return;
  1276.  
  1277. Event = EVENT_MAIEV_NULL;
  1278. for (uint8 i = 1; i <= MaxTimer; ++i)
  1279. if (Timer[i])
  1280. {
  1281. if (Timer[i] <= diff)
  1282. Event = (EventMaiev)i;
  1283. else Timer[i] -= diff;
  1284. }
  1285.  
  1286. switch (Event)
  1287. {
  1288. case EVENT_MAIEV_STEALTH:
  1289. {
  1290. me->SetFullHealth();
  1291. me->SetVisible(true);
  1292. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1293. Timer[EVENT_MAIEV_STEALTH] = 0;
  1294. BlinkToPlayer();
  1295. EnterPhase(Phase);
  1296. }
  1297. break;
  1298. case EVENT_MAIEV_TAUNT:
  1299. Talk(SAY_MAIEV_SHADOWSONG_TAUNT);
  1300. Timer[EVENT_MAIEV_TAUNT] = urand(22, 43) * 1000;
  1301. break;
  1302. case EVENT_MAIEV_SHADOW_STRIKE:
  1303. DoCastVictim(SPELL_SHADOW_STRIKE);
  1304. Timer[EVENT_MAIEV_SHADOW_STRIKE] = 60000;
  1305. break;
  1306. case EVENT_MAIEV_TRAP:
  1307. if (Phase == PHASE_NORMAL_MAIEV)
  1308. {
  1309. BlinkToPlayer();
  1310. DoCast(me, SPELL_CAGE_TRAP_SUMMON);
  1311. Timer[EVENT_MAIEV_TRAP] = 22000;
  1312. }
  1313. else
  1314. {
  1315. if (!me->IsWithinDistInMap(me->GetVictim(), 40))
  1316. me->GetMotionMaster()->MoveChase(me->GetVictim(), 30);
  1317. DoCastVictim(SPELL_THROW_DAGGER);
  1318. Timer[EVENT_MAIEV_THROW_DAGGER] = 2000;
  1319. }
  1320. break;
  1321. default:
  1322. break;
  1323. }
  1324.  
  1325. if (HealthBelowPct(50))
  1326. {
  1327. me->SetVisible(false);
  1328. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1329. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1330. CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
  1331. me->AttackStop();
  1332. Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute
  1333. MaxTimer = 1;
  1334. }
  1335.  
  1336. if (Phase == PHASE_NORMAL_MAIEV)
  1337. DoMeleeAttackIfReady();
  1338. }
  1339.  
  1340. private:
  1341. uint64 IllidanGUID;
  1342. PhaseIllidan Phase;
  1343. EventMaiev Event;
  1344. uint32 Timer[5];
  1345. uint32 MaxTimer;
  1346. };
  1347.  
  1348. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  1349. {
  1350. return new boss_maievAI(creature);
  1351. }
  1352. };
  1353.  
  1354. class npc_akama_illidan : public CreatureScript
  1355. {
  1356. public:
  1357. npc_akama_illidan() : CreatureScript("npc_akama_illidan") { }
  1358.  
  1359. struct npc_akama_illidanAI : public ScriptedAI
  1360. {
  1361. npc_akama_illidanAI(Creature* creature) : ScriptedAI(creature)
  1362. {
  1363. instance = creature->GetInstanceScript();
  1364. JustCreated = true;
  1365. }
  1366.  
  1367. void Reset() OVERRIDE
  1368. {
  1369. WalkCount = 0;
  1370. if (instance)
  1371. {
  1372. instance->SetBossState(DATA_ILLIDAN_STORMRAGE, NOT_STARTED);
  1373.  
  1374. IllidanGUID = instance->GetData64(DATA_ILLIDAN_STORMRAGE);
  1375. GateGUID = instance->GetData64(DATA_GO_ILLIDAN_GATE);
  1376. DoorGUID[0] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_R);
  1377. DoorGUID[1] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_L);
  1378.  
  1379. if (JustCreated) // close all doors at create
  1380. {
  1381. instance->HandleGameObject(GateGUID, false);
  1382.  
  1383. for (uint8 i = 0; i < 2; ++i)
  1384. instance->HandleGameObject(DoorGUID[i], false);
  1385. }
  1386. else // open all doors, raid wiped
  1387. {
  1388. instance->HandleGameObject(GateGUID, true);
  1389. WalkCount = 1; // skip first wp
  1390.  
  1391. for (uint8 i = 0; i < 2; ++i)
  1392. instance->HandleGameObject(DoorGUID[i], true);
  1393. }
  1394. }
  1395. else
  1396. {
  1397. IllidanGUID = 0;
  1398. GateGUID = 0;
  1399. DoorGUID[0] = 0;
  1400. DoorGUID[1] = 0;
  1401. }
  1402.  
  1403. ChannelGUID = 0;
  1404. SpiritGUID[0] = 0;
  1405. SpiritGUID[1] = 0;
  1406.  
  1407. Phase = PHASE_AKAMA_NULL;
  1408. Timer = 0;
  1409.  
  1410. ChannelCount = 0;
  1411. TalkCount = 0;
  1412. Check_Timer = 5000;
  1413.  
  1414. KillAllElites();
  1415.  
  1416. me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values..
  1417. me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
  1418. me->setActive(false);
  1419. me->SetVisible(false);
  1420. }
  1421.  
  1422. // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit
  1423. void EnterEvadeMode() OVERRIDE
  1424. {
  1425. me->RemoveAllAuras();
  1426. me->DeleteThreatList();
  1427. me->CombatStop(true);
  1428. }
  1429.  
  1430. void EnterCombat(Unit* /*who*/) OVERRIDE {}
  1431. void MoveInLineOfSight(Unit* /*who*/) OVERRIDE {}
  1432.  
  1433.  
  1434. void MovementInform(uint32 MovementType, uint32 /*Data*/) OVERRIDE
  1435. {
  1436. if (MovementType == POINT_MOTION_TYPE)
  1437. Timer = 1;
  1438. }
  1439.  
  1440. void DamageTaken(Unit* done_by, uint32 &damage) OVERRIDE
  1441. {
  1442. if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID)
  1443. damage = 0;
  1444. }
  1445.  
  1446. void KillAllElites()
  1447. {
  1448. ThreatContainer::StorageType const &threatList = me->getThreatManager().getThreatList();
  1449. std::vector<Unit*> eliteList;
  1450. for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
  1451. {
  1452. Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid());
  1453. if (unit && unit->GetEntry() == ILLIDARI_ELITE)
  1454. eliteList.push_back(unit);
  1455. }
  1456. for (std::vector<Unit*>::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr)
  1457. (*itr)->setDeathState(JUST_DIED);
  1458. EnterEvadeMode();
  1459. }
  1460.  
  1461. void BeginTalk()
  1462. {
  1463. if (!instance)
  1464. return;
  1465.  
  1466. instance->SetBossState(DATA_ILLIDAN_STORMRAGE, IN_PROGRESS);
  1467. for (uint8 i = 0; i < 2; ++i)
  1468. instance->HandleGameObject(DoorGUID[i], false);
  1469. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1470. {
  1471. illidan->RemoveAurasDueToSpell(SPELL_KNEEL);
  1472. me->SetInFront(illidan);
  1473. illidan->SetInFront(me);
  1474. me->GetMotionMaster()->MoveIdle();
  1475. illidan->GetMotionMaster()->MoveIdle();
  1476. CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->AkamaGUID = me->GetGUID();
  1477. CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE);
  1478. }
  1479. }
  1480.  
  1481. void BeginChannel()
  1482. {
  1483. me->setActive(true);
  1484. me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
  1485. if (!JustCreated)
  1486. return;
  1487. float x, y, z;
  1488. if (GameObject* gate = ObjectAccessor::GetGameObject(*me, GateGUID))
  1489. gate->GetPosition(x, y, z);
  1490. else
  1491. return; // if door not spawned, don't crash server
  1492.  
  1493. if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000))
  1494. {
  1495. ChannelGUID = Channel->GetGUID();
  1496. Channel->SetDisplayId(MODEL_INVISIBLE); // Invisible but spell visuals can still be seen.
  1497. DoCast(Channel, SPELL_AKAMA_DOOR_FAIL);
  1498. }
  1499.  
  1500. for (uint8 i = 0; i < 2; ++i)
  1501. if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000))
  1502. {
  1503. Spirit->SetVisible(false);
  1504. SpiritGUID[i] = Spirit->GetGUID();
  1505. }
  1506. }
  1507.  
  1508. void BeginWalk()
  1509. {
  1510. me->SetWalk(false);
  1511. me->SetSpeed(MOVE_RUN, 1.0f);
  1512. me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z);
  1513. }
  1514.  
  1515. void EnterPhase(PhaseAkama NextPhase)
  1516. {
  1517. if (!instance)
  1518. return;
  1519. switch (NextPhase)
  1520. {
  1521. case PHASE_CHANNEL:
  1522. BeginChannel();
  1523. Timer = 5000;
  1524. ChannelCount = 0;
  1525. break;
  1526. case PHASE_WALK:
  1527. if (Phase == PHASE_CHANNEL)
  1528. WalkCount = 0;
  1529. else if (Phase == PHASE_TALK)
  1530. {
  1531. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1532. CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
  1533. EnterEvadeMode();
  1534. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1535. ++WalkCount;
  1536. }
  1537. JustCreated = false;
  1538. BeginWalk();
  1539. Timer = 0;
  1540. break;
  1541. case PHASE_TALK:
  1542. if (Phase == PHASE_WALK)
  1543. {
  1544. BeginTalk();
  1545. Timer = 0;
  1546. }
  1547. else if (Phase == PHASE_FIGHT_ILLIDAN)
  1548. {
  1549. Timer = 1;
  1550. TalkCount = 0;
  1551. }
  1552. break;
  1553. case PHASE_FIGHT_ILLIDAN:
  1554. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1555. {
  1556. me->AddThreat(illidan, 10000000.0f);
  1557. me->GetMotionMaster()->MoveChase(illidan);
  1558. }
  1559. Timer = 30000; // chain lightning
  1560. break;
  1561. case PHASE_FIGHT_MINIONS:
  1562. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1563. Timer = urand(10000, 16000); // summon minion
  1564. break;
  1565. case PHASE_RETURN:
  1566. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1567. KillAllElites();
  1568. WalkCount = 0;
  1569. BeginWalk();
  1570. Timer = 1;
  1571. break;
  1572. default:
  1573. break;
  1574. }
  1575. Phase = NextPhase;
  1576. Event = false;
  1577. }
  1578.  
  1579. void HandleTalkSequence()
  1580. {
  1581. switch (TalkCount)
  1582. {
  1583. case 0:
  1584. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1585. {
  1586. CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->Timer[EVENT_TAUNT] += 30000;
  1587. illidan->AI()->Talk(SAY_ILLIDAN_MINION);
  1588. }
  1589. Timer = 8000;
  1590. break;
  1591. case 1:
  1592. Talk(SAY_AKAMA_LEAVE);
  1593. Timer = 3000;
  1594. break;
  1595. case 2:
  1596. EnterPhase(PHASE_WALK);
  1597. break;
  1598. }
  1599. ++TalkCount;
  1600. }
  1601.  
  1602. void HandleChannelSequence()
  1603. {
  1604. Unit* Channel = NULL;
  1605. Unit* Spirit[2] = { NULL, NULL };
  1606. if (ChannelCount <= 5)
  1607. {
  1608. Channel = Unit::GetUnit(*me, ChannelGUID);
  1609. Spirit[0] = Unit::GetUnit(*me, SpiritGUID[0]);
  1610. Spirit[1] = Unit::GetUnit(*me, SpiritGUID[1]);
  1611. if (!Channel || !Spirit[0] || !Spirit[1])
  1612. return;
  1613. }
  1614.  
  1615. switch (ChannelCount)
  1616. {
  1617. case 0: // channel failed
  1618. me->InterruptNonMeleeSpells(true);
  1619. Timer = 2000;
  1620. break;
  1621. case 1: // spirit appear
  1622. Spirit[0]->SetVisible(true);
  1623. Spirit[1]->SetVisible(true);
  1624. Timer = 2000;
  1625. break;
  1626. case 2: // spirit help
  1627. DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL);
  1628. Spirit[0]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL, false);
  1629. Spirit[1]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL, false);
  1630. Timer = 5000;
  1631. break;
  1632. case 3: // open the gate
  1633. me->InterruptNonMeleeSpells(true);
  1634. Spirit[0]->InterruptNonMeleeSpells(true);
  1635. Spirit[1]->InterruptNonMeleeSpells(true);
  1636. if (instance)
  1637. instance->HandleGameObject(GateGUID, true);
  1638. Timer = 2000;
  1639. break;
  1640. case 4:
  1641. me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
  1642. Timer = 2000;
  1643. break;
  1644. case 5:
  1645. Talk(SAY_AKAMA_BEWARE);
  1646. Channel->setDeathState(JUST_DIED);
  1647. Spirit[0]->SetVisible(false);
  1648. Spirit[1]->SetVisible(false);
  1649. Timer = 3000;
  1650. break;
  1651. case 6:
  1652. EnterPhase(PHASE_WALK);
  1653. break;
  1654. default:
  1655. break;
  1656. }
  1657. ++ChannelCount;
  1658. }
  1659.  
  1660. void HandleWalkSequence()
  1661. {
  1662. switch (WalkCount)
  1663. {
  1664. case 6:
  1665. for (uint8 i = 0; i < 2; ++i)
  1666. if (instance)
  1667. instance->HandleGameObject(DoorGUID[i], true);
  1668. break;
  1669. case 8:
  1670. if (Phase == PHASE_WALK)
  1671. EnterPhase(PHASE_TALK);
  1672. else
  1673. EnterPhase(PHASE_FIGHT_ILLIDAN);
  1674. break;
  1675. case 12:
  1676. EnterPhase(PHASE_FIGHT_MINIONS);
  1677. break;
  1678. }
  1679.  
  1680. if (Phase == PHASE_WALK)
  1681. {
  1682. Timer = 0;
  1683. ++WalkCount;
  1684. me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z);
  1685. }
  1686. }
  1687.  
  1688. void UpdateAI(uint32 diff) OVERRIDE
  1689. {
  1690. if (!me->IsVisible())
  1691. {
  1692. if (Check_Timer <= diff)
  1693. {
  1694. if (instance && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE)
  1695. me->SetVisible(true);
  1696.  
  1697. Check_Timer = 5000;
  1698. } else Check_Timer -= diff;
  1699. }
  1700. Event = false;
  1701. if (Timer)
  1702. {
  1703. if (Timer <= diff)
  1704. Event = true;
  1705. else Timer -= diff;
  1706. }
  1707.  
  1708. if (Event)
  1709. {
  1710. switch (Phase)
  1711. {
  1712. case PHASE_CHANNEL:
  1713. if (JustCreated)
  1714. HandleChannelSequence();
  1715. else{
  1716. EnterPhase(PHASE_WALK);
  1717. }
  1718. break;
  1719. case PHASE_TALK:
  1720. HandleTalkSequence();
  1721. break;
  1722. case PHASE_WALK:
  1723. case PHASE_RETURN:
  1724. HandleWalkSequence();
  1725. break;
  1726. case PHASE_FIGHT_ILLIDAN:
  1727. {
  1728. Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID);
  1729. if (illidan && illidan->HealthBelowPct(90))
  1730. EnterPhase(PHASE_TALK);
  1731. else
  1732. {
  1733. DoCastVictim(SPELL_CHAIN_LIGHTNING);
  1734. Timer = 30000;
  1735. }
  1736. }
  1737. break;
  1738. case PHASE_FIGHT_MINIONS:
  1739. {
  1740. float x, y, z;
  1741. me->GetPosition(x, y, z);
  1742. Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
  1743. // Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
  1744. if (Elite)
  1745. {
  1746. Elite->AI()->AttackStart(me);
  1747. Elite->AddThreat(me, 1000000.0f);
  1748. AttackStart(Elite);
  1749. me->AddThreat(Elite, 1000000.0f);
  1750. }
  1751. Timer = urand(10000, 16000);
  1752. if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
  1753. if (illidan->HealthBelowPct(10))
  1754. EnterPhase(PHASE_RETURN);
  1755. }
  1756. break;
  1757. default:
  1758. break;
  1759. }
  1760. }
  1761.  
  1762. if (!UpdateVictim())
  1763. return;
  1764.  
  1765. if (HealthBelowPct(20))
  1766. DoCast(me, SPELL_HEALING_POTION);
  1767.  
  1768. DoMeleeAttackIfReady();
  1769. }
  1770.  
  1771. void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
  1772. {
  1773. player->CLOSE_GOSSIP_MENU();
  1774. EnterPhase(PHASE_CHANNEL);
  1775. }
  1776.  
  1777. private:
  1778. bool JustCreated;
  1779. InstanceScript* instance;
  1780. PhaseAkama Phase;
  1781. bool Event;
  1782. uint32 Timer;
  1783. uint64 IllidanGUID;
  1784. uint64 ChannelGUID;
  1785. uint64 SpiritGUID[2];
  1786. uint64 GateGUID;
  1787. uint64 DoorGUID[2];
  1788. uint32 ChannelCount;
  1789. uint32 WalkCount;
  1790. uint32 TalkCount;
  1791. uint32 Check_Timer;
  1792. };
  1793.  
  1794. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  1795. {
  1796. return new npc_akama_illidanAI(creature);
  1797. }
  1798. };
  1799.  
  1800. void boss_illidan_stormrage::boss_illidan_stormrageAI::Reset()
  1801. {
  1802. if (instance)
  1803. instance->SetBossState(DATA_ILLIDAN_STORMRAGE, NOT_STARTED);
  1804.  
  1805. if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID))
  1806. {
  1807. if (!akama->IsAlive())
  1808. akama->Respawn();
  1809. else
  1810. akama->AI()->EnterEvadeMode();
  1811. }
  1812.  
  1813. MaievGUID = 0;
  1814. for (uint8 i = 0; i < 2; ++i)
  1815. {
  1816. FlameGUID[i] = 0;
  1817. GlaiveGUID[i] = 0;
  1818. }
  1819.  
  1820. Phase = PHASE_ILLIDAN_NULL;
  1821. Event = EVENT_NULL;
  1822. Timer[EVENT_BERSERK] = 1500000;
  1823.  
  1824. HoverPoint = 0;
  1825. TalkCount = 0;
  1826. FlightCount = 0;
  1827. TransformCount = 0;
  1828.  
  1829. me->SetDisplayId(MODEL_ILLIDAN);
  1830. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
  1831. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1832. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  1833. SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
  1834. me->SetDisableGravity(false);
  1835. me->setActive(false);
  1836. Summons.DespawnAll();
  1837. }
  1838.  
  1839. void boss_illidan_stormrage::boss_illidan_stormrageAI::JustSummoned(Creature* summon)
  1840. {
  1841. Summons.Summon(summon);
  1842. switch (summon->GetEntry())
  1843. {
  1844. case PARASITIC_SHADOWFIEND:
  1845. {
  1846. if (Phase == PHASE_TALK_SEQUENCE)
  1847. {
  1848. summon->SetVisible(false);
  1849. summon->setDeathState(JUST_DIED);
  1850. return;
  1851. }
  1852. Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true);
  1853. if (!target || target->HasAura(SPELL_PARASITIC_SHADOWFIEND)
  1854. || target->HasAura(SPELL_PARASITIC_SHADOWFIEND2))
  1855. target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true);
  1856. if (target)
  1857. summon->AI()->AttackStart(target);
  1858. }
  1859. break;
  1860. case SHADOW_DEMON:
  1861. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players.
  1862. {
  1863. summon->AddThreat(target, 5000000.0f);
  1864. summon->AI()->AttackStart(target);
  1865. }
  1866. break;
  1867. case MAIEV_SHADOWSONG:
  1868. {
  1869. summon->SetVisible(false); // Leave her invisible until she has to talk
  1870. summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  1871. MaievGUID = summon->GetGUID();
  1872. CAST_AI(boss_maiev_shadowsong::boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID());
  1873. summon->AI()->DoAction(PHASE_TALK_SEQUENCE);
  1874. }
  1875. break;
  1876. case FLAME_OF_AZZINOTH:
  1877. {
  1878. summon->AI()->AttackStart(summon->SelectNearestTarget(999));
  1879. }
  1880. break;
  1881. default:
  1882. break;
  1883. }
  1884. }
  1885.  
  1886. void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence()
  1887. {
  1888. switch (TalkCount)
  1889. {
  1890. case 0:
  1891. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  1892. break;
  1893. case 8:
  1894. // Equip our warglaives!
  1895. SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE);
  1896. me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
  1897. me->SetWalk(false);
  1898. break;
  1899. case 9:
  1900. if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID))
  1901. {
  1902. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
  1903. me->AddThreat(akama, 100.0f);
  1904. CAST_AI(npc_akama_illidan::npc_akama_illidanAI, akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN);
  1905. EnterPhase(PHASE_NORMAL);
  1906. }
  1907. break;
  1908. case 10:
  1909. SummonMaiev();
  1910. break;
  1911. case 11:
  1912. if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID))
  1913. {
  1914. maiev->SetVisible(true); // Maiev is now visible
  1915. maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported!
  1916. maiev->SetInFront(me); // Have her face us
  1917. me->SetInFront(maiev); // Face her, so it's not rude =P
  1918. maiev->GetMotionMaster()->MoveIdle();
  1919. me->GetMotionMaster()->MoveIdle();
  1920. }
  1921. break;
  1922. case 14:
  1923. if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID))
  1924. {
  1925. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
  1926. maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
  1927. maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE
  1928. maiev->AI()->AttackStart(me); // Force Maiev to attack us.
  1929. EnterPhase(PHASE_NORMAL_MAIEV);
  1930. }
  1931. break;
  1932. case 15:
  1933. DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him
  1934. Summons.DespawnAll();
  1935. break;
  1936. case 17:
  1937. if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID))
  1938. {
  1939. if (!me->IsWithinDistInMap(akama, 15))
  1940. {
  1941. float x, y, z;
  1942. me->GetPosition(x, y, z);
  1943. x += 10; y += 10;
  1944. akama->GetMotionMaster()->Clear(false);
  1945. // Akama->GetMotionMaster()->MoveIdle();
  1946. akama->SetPosition(x, y, z, 0.0f);
  1947. akama->MonsterMoveWithSpeed(x, y, z, 0); // Illidan must not die until Akama arrives.
  1948. akama->GetMotionMaster()->MoveChase(me);
  1949. }
  1950. }
  1951. break;
  1952. case 19: // Make Maiev leave
  1953. if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID))
  1954. {
  1955. maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true);
  1956. maiev->setDeathState(JUST_DIED);
  1957. me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
  1958. }
  1959. break;
  1960. case 21: // Kill ourself.
  1961. me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
  1962. break;
  1963. default:
  1964. break;
  1965. }
  1966. if (Phase == PHASE_TALK_SEQUENCE)
  1967. Talk(TalkCount); // This function does most of the talking
  1968. ++TalkCount;
  1969. }
  1970.  
  1971. class npc_cage_trap_trigger : public CreatureScript
  1972. {
  1973. public:
  1974. npc_cage_trap_trigger() : CreatureScript("npc_cage_trap_trigger") { }
  1975.  
  1976. struct cage_trap_triggerAI : public ScriptedAI
  1977. {
  1978. cage_trap_triggerAI(Creature* creature) : ScriptedAI(creature) {}
  1979.  
  1980. void Reset() OVERRIDE
  1981. {
  1982. IllidanGUID = 0;
  1983.  
  1984. Active = false;
  1985. SummonedBeams = false;
  1986.  
  1987. DespawnTimer = 0;
  1988.  
  1989. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  1990. }
  1991.  
  1992. void EnterCombat(Unit* /*who*/)OVERRIDE {}
  1993.  
  1994. void MoveInLineOfSight(Unit* who) OVERRIDE
  1995.  
  1996. {
  1997. if (!Active)
  1998. return;
  1999.  
  2000. if (who && (who->GetTypeId() != TYPEID_PLAYER))
  2001. {
  2002. if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan
  2003. {
  2004. if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED)))
  2005. {
  2006. IllidanGUID = who->GetGUID();
  2007. who->CastSpell(who, SPELL_CAGED, true);
  2008. DespawnTimer = 5000;
  2009. if (who->HasAura(SPELL_ENRAGE))
  2010. who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage
  2011. // if (GameObject* CageTrap = instance->instance->GetGameObject(instance->GetData64(CageTrapGUID)))
  2012.  
  2013. // CageTrap->SetLootState(GO_JUST_DEACTIVATED);
  2014. }
  2015. }
  2016. }
  2017. }
  2018.  
  2019. void UpdateAI(uint32 diff) OVERRIDE
  2020. {
  2021. if (DespawnTimer)
  2022. {
  2023. if (DespawnTimer <= diff)
  2024. me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
  2025. else DespawnTimer -= diff;
  2026. }
  2027.  
  2028. // if (IllidanGUID && !SummonedBeams)
  2029. // {
  2030. // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID)
  2031. // {
  2032. // /// @todo Find proper spells and properly apply 'caged' Illidan effect
  2033. // }
  2034. // }
  2035. }
  2036.  
  2037. public:
  2038. bool Active;
  2039. private:
  2040. uint64 IllidanGUID;
  2041. uint32 DespawnTimer;
  2042. bool SummonedBeams;
  2043. };
  2044.  
  2045. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  2046. {
  2047. return new cage_trap_triggerAI(creature);
  2048. }
  2049. };
  2050.  
  2051. class gameobject_cage_trap : public GameObjectScript
  2052. {
  2053. public:
  2054. gameobject_cage_trap() : GameObjectScript("gameobject_cage_trap") { }
  2055.  
  2056. bool OnGossipHello(Player* player, GameObject* go) OVERRIDE
  2057. {
  2058. float x, y, z;
  2059. player->GetPosition(x, y, z);
  2060.  
  2061. // Grid search for nearest live Creature of entry 23304 within 10 yards
  2062. if (Creature* pTrigger = go->FindNearestCreature(23304, 10.0f))
  2063. CAST_AI(npc_cage_trap_trigger::cage_trap_triggerAI, pTrigger->AI())->Active = true;
  2064. go->SetGoState(GO_STATE_ACTIVE);
  2065. return true;
  2066. }
  2067. };
  2068.  
  2069. class npc_shadow_demon : public CreatureScript
  2070. {
  2071. public:
  2072. npc_shadow_demon() : CreatureScript("npc_shadow_demon") { }
  2073.  
  2074. struct shadow_demonAI : public ScriptedAI
  2075. {
  2076. shadow_demonAI(Creature* creature) : ScriptedAI(creature) {}
  2077.  
  2078. void EnterCombat(Unit* /*who*/) OVERRIDE
  2079. {
  2080. DoZoneInCombat();
  2081. }
  2082.  
  2083. void Reset() OVERRIDE
  2084. {
  2085. TargetGUID = 0;
  2086. DoCast(me, SPELL_SHADOW_DEMON_PASSIVE, true);
  2087. }
  2088.  
  2089. void JustDied(Unit* /*killer*/) OVERRIDE
  2090. {
  2091. if (Unit* target = Unit::GetUnit(*me, TargetGUID))
  2092. target->RemoveAurasDueToSpell(SPELL_PARALYZE);
  2093. }
  2094.  
  2095. void UpdateAI(uint32 /*diff*/) OVERRIDE
  2096. {
  2097. if (!UpdateVictim())
  2098. return;
  2099.  
  2100. if (me->GetVictim()->GetTypeId() != TYPEID_PLAYER)
  2101. return; // Only cast the below on players.
  2102.  
  2103. if (!me->GetVictim()->HasAura(SPELL_PARALYZE))
  2104. {
  2105. TargetGUID = me->GetVictim()->GetGUID();
  2106. me->AddThreat(me->GetVictim(), 10000000.0f);
  2107. DoCastVictim(SPELL_PURPLE_BEAM, true);
  2108. DoCastVictim(SPELL_PARALYZE, true);
  2109. }
  2110. // Kill our target if we're very close.
  2111. if (me->IsWithinDistInMap(me->GetVictim(), 3))
  2112. DoCastVictim(SPELL_CONSUME_SOUL);
  2113. }
  2114.  
  2115. private:
  2116. uint64 TargetGUID;
  2117. };
  2118.  
  2119. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  2120. {
  2121. return new shadow_demonAI(creature);
  2122. }
  2123. };
  2124.  
  2125. class npc_blade_of_azzinoth : public CreatureScript
  2126. {
  2127. public:
  2128. npc_blade_of_azzinoth() : CreatureScript("npc_blade_of_azzinoth") { }
  2129.  
  2130. struct blade_of_azzinothAI : public NullCreatureAI
  2131. {
  2132. blade_of_azzinothAI(Creature* creature) : NullCreatureAI(creature) {}
  2133.  
  2134. void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
  2135. {
  2136. if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE)
  2137. me->SetDisplayId(MODEL_BLADE);// appear when hit by Illidan's glaive
  2138. }
  2139. };
  2140.  
  2141. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  2142. {
  2143. return new blade_of_azzinothAI(creature);
  2144. }
  2145. };
  2146.  
  2147. class npc_parasitic_shadowfiend : public CreatureScript
  2148. {
  2149. public:
  2150. npc_parasitic_shadowfiend() : CreatureScript("npc_parasitic_shadowfiend") { }
  2151.  
  2152. // Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap
  2153. struct npc_parasitic_shadowfiendAI : public ScriptedAI
  2154. {
  2155. npc_parasitic_shadowfiendAI(Creature* creature) : ScriptedAI(creature)
  2156. {
  2157. instance = creature->GetInstanceScript();
  2158. }
  2159.  
  2160. void Reset() OVERRIDE
  2161. {
  2162. if (instance)
  2163. IllidanGUID = instance->GetData64(DATA_ILLIDAN_STORMRAGE);
  2164. else
  2165. IllidanGUID = 0;
  2166.  
  2167. CheckTimer = 5000;
  2168. DoCast(me, SPELL_SHADOWFIEND_PASSIVE, true);
  2169. }
  2170.  
  2171. void EnterCombat(Unit* /*who*/) OVERRIDE
  2172. {
  2173. DoZoneInCombat();
  2174. }
  2175.  
  2176. void DoMeleeAttackIfReady()
  2177. {
  2178. if (me->isAttackReady() && me->IsWithinMeleeRange(me->GetVictim()))
  2179. {
  2180. if (!me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND)
  2181. && !me->GetVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2))
  2182. {
  2183. if (Creature* illidan = Unit::GetCreature((*me), IllidanGUID))// summon only in 1. phase
  2184. if (CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL)
  2185. me->CastSpell(me->GetVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); // do not stack
  2186. }
  2187. me->AttackerStateUpdate(me->GetVictim());
  2188. me->resetAttackTimer();
  2189. }
  2190. }
  2191.  
  2192. void UpdateAI(uint32 diff) OVERRIDE
  2193. {
  2194. if (!me->GetVictim())
  2195. {
  2196. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true))
  2197. AttackStart(target);
  2198. else
  2199. {
  2200. me->DespawnOrUnsummon();
  2201. return;
  2202. }
  2203. }
  2204.  
  2205. if (CheckTimer <= diff)
  2206. {
  2207. Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID);
  2208. if (!illidan || illidan->IsInEvadeMode())
  2209. {
  2210. me->DespawnOrUnsummon();
  2211. return;
  2212. }
  2213. else
  2214. CheckTimer = 5000;
  2215. }
  2216. else
  2217. CheckTimer -= diff;
  2218.  
  2219. DoMeleeAttackIfReady();
  2220. }
  2221.  
  2222. private:
  2223. InstanceScript* instance;
  2224. uint64 IllidanGUID;
  2225. uint32 CheckTimer;
  2226. };
  2227.  
  2228. CreatureAI* GetAI(Creature* creature) const OVERRIDE
  2229. {
  2230. return new npc_parasitic_shadowfiendAI(creature);
  2231. }
  2232. };
  2233.  
  2234. void AddSC_boss_illidan()
  2235. {
  2236. new boss_illidan_stormrage();
  2237. new npc_akama_illidan();
  2238. new boss_maiev_shadowsong();
  2239. new npc_flame_of_azzinoth();
  2240. new npc_blade_of_azzinoth();
  2241. new gameobject_cage_trap();
  2242. new npc_cage_trap_trigger();
  2243. new npc_shadow_demon();
  2244. new npc_parasitic_shadowfiend();
  2245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement