PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp

https://gitlab.com/mohsencs/SunWellCore
C++ | 1749 lines | 1567 code | 158 blank | 24 comment | 202 complexity | ba8f2ab7a08f4a831bf8a6ec5bf2b31b MD5 | raw file
  1. /*
  2. REWRITTEN FROM SCRATCH BY PUSSYWIZARD, IT OWNS NOW!
  3. */
  4. #include "ScriptMgr.h"
  5. #include "ScriptedCreature.h"
  6. #include "trial_of_the_crusader.h"
  7. #include "SpellScript.h"
  8. #include "Player.h"
  9. enum eAIs
  10. {
  11. AI_MELEE = 0,
  12. AI_RANGED = 1,
  13. AI_HEALER = 2,
  14. AI_PET = 3,
  15. };
  16. enum eSharedSpells
  17. {
  18. SPELL_ANTI_AOE = 68595,
  19. SPELL_PVP_TRINKET = 65547,
  20. };
  21. struct boss_faction_championsAI : public ScriptedAI
  22. {
  23. boss_faction_championsAI(Creature* pCreature, uint32 aitype) : ScriptedAI(pCreature)
  24. {
  25. pInstance = pCreature->GetInstanceScript();
  26. me->SetReactState(REACT_PASSIVE);
  27. mAIType = aitype;
  28. threatTimer = 2000;
  29. powerTimer = 1000;
  30. }
  31. InstanceScript* pInstance;
  32. uint32 mAIType;
  33. uint32 threatTimer;
  34. uint32 powerTimer;
  35. void EnterCombat(Unit* /*who*/)
  36. {
  37. me->SetInCombatWithZone();
  38. RecalculateThreat();
  39. if( pInstance )
  40. pInstance->SetData(TYPE_FACTION_CHAMPIONS_START, 0);
  41. }
  42. void AttackStart(Unit* who)
  43. {
  44. if( !who )
  45. return;
  46. if( mAIType == AI_MELEE || mAIType == AI_PET )
  47. UnitAI::AttackStart(who);
  48. else
  49. UnitAI::AttackStartCaster(who, 18.5f);
  50. }
  51. float GetThreatMod(float dist, float armor, uint32 health, uint32 /*maxhealth*/, Unit* target)
  52. {
  53. /*float mod_health = ((float)health)/maxhealth;
  54. if (mod_health < 0.4f) mod_health = 0.4f;
  55. float unimportant_dist = (mAIType == AI_MELEE || mAIType == AI_PET ? 5.0f : 20.0f);
  56. if (dist > unimportant_dist)
  57. dist -= unimportant_dist; // compensate melee range
  58. else
  59. dist = 0.0f;
  60. float mod_dist = 25.0f/(25.0f + dist);
  61. float mod_armor = (mAIType == AI_MELEE || mAIType == AI_PET) ? armor / 16635.0f : 0.0f;
  62. return mod_dist / ((0.15f+mod_armor)*mod_health);*/
  63. // TC:
  64. /*float dist_mod = (mAIType == AI_MELEE || mAIType == AI_PET) ? 15.0f / (15.0f + dist) : 1.0f;
  65. float armor_mod = (mAIType == AI_MELEE || mAIType == AI_PET) ? armor / 16635.0f : 0.0f;
  66. float eh = (health + 1) * (1.0f + armor_mod);
  67. return dist_mod * 30000.0f / eh;*/
  68. // third try:
  69. float unimportant_dist = (mAIType == AI_MELEE || mAIType == AI_PET ? 5.0f : 35.0f);
  70. if (dist > unimportant_dist) dist -= unimportant_dist; else dist = 0.0f;
  71. const float dist_factor = (mAIType == AI_MELEE || mAIType == AI_PET ? 15.0f : 25.0f);
  72. float mod_dist = dist_factor/(dist_factor + dist); // 0.2 .. 1.0
  73. float mod_health = health > 40000 ? 2.0f : (60000-health)/10000.0f; // 2.0 .. 6.0
  74. float mod_armor = (mAIType == AI_MELEE || mAIType == AI_PET) ? Unit::CalcArmorReducedDamage(me, target, 10000, NULL)/10000.0f : 1.0f;
  75. return mod_dist * mod_health * mod_armor;
  76. }
  77. void RecalculateThreat()
  78. {
  79. ThreatContainer::StorageType const& tList = me->getThreatManager().getThreatList();
  80. for( ThreatContainer::StorageType::const_iterator itr = tList.begin(); itr != tList.end(); ++itr )
  81. {
  82. Unit* pUnit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
  83. if( pUnit && pUnit->GetTypeId() == TYPEID_PLAYER && me->getThreatManager().getThreat(pUnit) )
  84. {
  85. float threatMod = GetThreatMod(me->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth(), pUnit->GetMaxHealth(), pUnit);
  86. me->getThreatManager().modifyThreatPercent(pUnit, -100);
  87. //me->getThreatManager().doAddThreat(pUnit, 10000000.0f * threatMod);
  88. if (HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(pUnit))
  89. ref->addThreat(10000000.0f * threatMod);
  90. }
  91. }
  92. }
  93. void EventMapGCD(EventMap &e, uint32 delay, uint32 gcd = 0)
  94. {
  95. e.DelayEventsToMax(delay, gcd);
  96. }
  97. void JustDied(Unit* /*pKiller*/)
  98. {
  99. if( pInstance && mAIType != AI_PET )
  100. pInstance->SetData(TYPE_FACTION_CHAMPIONS, DONE);
  101. }
  102. void KilledUnit(Unit* who)
  103. {
  104. if( pInstance )
  105. pInstance->SetData(TYPE_FACTION_CHAMPIONS_PLAYER_DIED, 1);
  106. }
  107. void EnterEvadeMode()
  108. {
  109. if( pInstance )
  110. pInstance->SetData(TYPE_FAILED, 0);
  111. }
  112. bool IsCCed()
  113. {
  114. // check for stun, fear, etc.
  115. // for casting, silence, disarm check individually in the ai
  116. if( me->isFeared() || me->isFrozen() || me->HasUnitState(UNIT_STATE_STUNNED) || me->HasUnitState(UNIT_STATE_CONFUSED) )
  117. {
  118. if( !IsHeroic() )
  119. return true;
  120. if( me->HasSpellCooldown(SPELL_PVP_TRINKET) )
  121. return true;
  122. else
  123. {
  124. me->CastSpell(me, SPELL_PVP_TRINKET, false);
  125. me->AddSpellCooldown(SPELL_PVP_TRINKET, 0, 0);
  126. }
  127. }
  128. return false;
  129. }
  130. Creature* SelectTarget_MostHPLostFriendlyMissingBuff(uint32 spell, float range)
  131. {
  132. std::list<Creature *> lst = DoFindFriendlyMissingBuff(range, spell);
  133. if( lst.empty() )
  134. return NULL;
  135. std::list<Creature *>::const_iterator iter = lst.begin();
  136. uint32 lowestHP = (*iter)->GetMaxHealth() - (*iter)->GetHealth();
  137. for( std::list<Creature *>::const_iterator itr = lst.begin(); itr != lst.end(); ++itr )
  138. if( ((*itr)->GetMaxHealth() - (*itr)->GetHealth()) > lowestHP )
  139. {
  140. iter = itr;
  141. lowestHP = (*itr)->GetMaxHealth() - (*itr)->GetHealth();
  142. }
  143. return (*iter);
  144. }
  145. uint32 EnemiesInRange(float distance)
  146. {
  147. ThreatContainer::StorageType const& tList = me->getThreatManager().getThreatList();
  148. uint32 count = 0;
  149. Unit *target;
  150. for( ThreatContainer::StorageType::const_iterator iter = tList.begin(); iter != tList.end(); ++iter )
  151. {
  152. target = ObjectAccessor::GetUnit((*me), (*iter)->getUnitGuid());
  153. if( target && me->GetDistance2d(target) < distance )
  154. ++count;
  155. }
  156. return count;
  157. }
  158. Unit* SelectEnemyCaster(bool casting, float range)
  159. {
  160. ThreatContainer::StorageType const& tList = me->getThreatManager().getThreatList();
  161. Unit *target;
  162. for( ThreatContainer::StorageType::const_iterator iter = tList.begin(); iter != tList.end(); ++iter )
  163. {
  164. target = ObjectAccessor::GetUnit((*me), (*iter)->getUnitGuid());
  165. if( target && target->getPowerType() == POWER_MANA && (!casting || target->HasUnitState(UNIT_STATE_CASTING)) && me->GetExactDist(target) <= range )
  166. return target;
  167. }
  168. return NULL;
  169. }
  170. void UpdateAI(uint32 diff)
  171. {
  172. if (!me->IsInCombat())
  173. return;
  174. if( threatTimer <= diff )
  175. {
  176. RecalculateThreat();
  177. threatTimer = urand(8750, 9250);
  178. }
  179. else
  180. threatTimer -= diff;
  181. if( me->getPowerType() == POWER_MANA )
  182. {
  183. if( powerTimer <= diff )
  184. {
  185. me->ModifyPower(POWER_MANA, me->GetMaxPower(POWER_MANA)/3);
  186. powerTimer = 4000;
  187. }
  188. else
  189. powerTimer -= diff;
  190. }
  191. else if( me->getPowerType() == POWER_ENERGY )
  192. {
  193. if( powerTimer <= diff )
  194. {
  195. me->ModifyPower(POWER_ENERGY, me->GetMaxPower(POWER_ENERGY)/3);
  196. powerTimer = 1000;
  197. }
  198. else
  199. powerTimer -= diff;
  200. }
  201. }
  202. };
  203. enum eDruidSpells
  204. {
  205. SPELL_LIFEBLOOM = 66093,
  206. SPELL_NOURISH = 66066,
  207. SPELL_REGROWTH = 66067,
  208. SPELL_REJUVENATION = 66065,
  209. SPELL_THORNS = 66068,
  210. SPELL_TRANQUILITY = 66086,
  211. SPELL_BARKSKIN = 65860,
  212. SPELL_NATURE_GRASP = 66071,
  213. };
  214. enum eDruidEvents
  215. {
  216. EVENT_SPELL_LIFEBLOOM = 1,
  217. EVENT_SPELL_NOURISH,
  218. EVENT_SPELL_REGROWTH,
  219. EVENT_SPELL_REJUVENATION,
  220. EVENT_SPELL_THORNS,
  221. EVENT_SPELL_TRANQUILITY,
  222. EVENT_SPELL_NATURE_GRASP,
  223. EVENT_SPELL_BARKSKIN = 101,
  224. };
  225. class npc_toc_druid : public CreatureScript
  226. {
  227. public:
  228. npc_toc_druid() : CreatureScript("npc_toc_druid") { }
  229. CreatureAI* GetAI(Creature *pCreature) const
  230. {
  231. return new npc_toc_druidAI (pCreature);
  232. }
  233. struct npc_toc_druidAI : public boss_faction_championsAI
  234. {
  235. npc_toc_druidAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER)
  236. {
  237. SetEquipmentSlots(false, 51799, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  238. events.Reset();
  239. events.RescheduleEvent(EVENT_SPELL_LIFEBLOOM, urand(5000,15000));
  240. events.RescheduleEvent(EVENT_SPELL_NOURISH, urand(5000,15000));
  241. events.RescheduleEvent(EVENT_SPELL_REGROWTH, urand(5000,15000));
  242. events.RescheduleEvent(EVENT_SPELL_REJUVENATION, urand(5000,15000));
  243. events.RescheduleEvent(EVENT_SPELL_TRANQUILITY, urand(25000,40000));
  244. events.RescheduleEvent(EVENT_SPELL_BARKSKIN, 10000);
  245. events.RescheduleEvent(EVENT_SPELL_THORNS, urand(5000,15000));
  246. events.RescheduleEvent(EVENT_SPELL_NATURE_GRASP, urand(5000,15000));
  247. }
  248. EventMap events;
  249. bool myCanCast()
  250. {
  251. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  252. }
  253. void UpdateAI(uint32 diff)
  254. {
  255. boss_faction_championsAI::UpdateAI(diff);
  256. if( !UpdateVictim() )
  257. return;
  258. events.Update(diff);
  259. if( !myCanCast() )
  260. return;
  261. switch( events.GetEvent() )
  262. {
  263. case 0:
  264. break;
  265. case EVENT_SPELL_LIFEBLOOM:
  266. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_LIFEBLOOM, 40.0f) )
  267. me->CastSpell(target, SPELL_LIFEBLOOM, false);
  268. events.RepeatEvent(urand(10000,15000));
  269. EventMapGCD(events, 1500);
  270. break;
  271. case EVENT_SPELL_NOURISH:
  272. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_NOURISH, 40.0f) )
  273. me->CastSpell(target, SPELL_NOURISH, false);
  274. events.RepeatEvent(urand(10000,15000));
  275. EventMapGCD(events, 1500);
  276. break;
  277. case EVENT_SPELL_REGROWTH:
  278. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_REGROWTH, 40.0f) )
  279. me->CastSpell(target, SPELL_REGROWTH, false);
  280. events.RepeatEvent(urand(10000,15000));
  281. EventMapGCD(events, 1500);
  282. break;
  283. case EVENT_SPELL_REJUVENATION:
  284. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_REJUVENATION, 40.0f) )
  285. me->CastSpell(target, SPELL_REJUVENATION, false);
  286. events.RepeatEvent(urand(10000,15000));
  287. EventMapGCD(events, 1500);
  288. break;
  289. case EVENT_SPELL_THORNS:
  290. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_THORNS, 30.0f) )
  291. me->CastSpell(target, SPELL_THORNS, false);
  292. events.RepeatEvent(urand(10000,15000));
  293. EventMapGCD(events, 1500);
  294. break;
  295. case EVENT_SPELL_TRANQUILITY:
  296. me->CastSpell(me, SPELL_TRANQUILITY, false);
  297. events.RepeatEvent(urand(120000,180000));
  298. EventMapGCD(events, 1500);
  299. break;
  300. case EVENT_SPELL_BARKSKIN:
  301. if( HealthBelowPct(50) )
  302. {
  303. me->CastSpell(me, SPELL_BARKSKIN, false);
  304. events.RepeatEvent(60000);
  305. EventMapGCD(events, 1500);
  306. }
  307. else
  308. events.RepeatEvent(6000);
  309. break;
  310. case EVENT_SPELL_NATURE_GRASP:
  311. me->CastSpell(me, SPELL_NATURE_GRASP, false);
  312. events.RepeatEvent(60000);
  313. EventMapGCD(events, 1500);
  314. break;
  315. }
  316. DoMeleeAttackIfReady();
  317. }
  318. };
  319. };
  320. enum eShamanSpells
  321. {
  322. SPELL_HEALING_WAVE = 66055,
  323. SPELL_RIPTIDE = 66053,
  324. SPELL_SPIRIT_CLEANSE = 66056,
  325. SPELL_HEROISM = 65983,
  326. SPELL_BLOODLUST = 65980,
  327. SPELL_HEX = 66054,
  328. SPELL_EARTH_SHIELD = 66063,
  329. SPELL_EARTH_SHOCK = 65973,
  330. AURA_EXHAUSTION = 57723,
  331. AURA_SATED = 57724,
  332. };
  333. enum eShamanEvents
  334. {
  335. EVENT_SPELL_HEALING_WAVE = 1,
  336. EVENT_SPELL_RIPTIDE,
  337. EVENT_SPELL_SPIRIT_CLEANSE,
  338. EVENT_SPELL_HEROISM_OR_BLOODLUST,
  339. EVENT_SPELL_HEX,
  340. EVENT_SPELL_EARTH_SHIELD,
  341. EVENT_SPELL_EARTH_SHOCK,
  342. };
  343. class npc_toc_shaman : public CreatureScript
  344. {
  345. public:
  346. npc_toc_shaman() : CreatureScript("npc_toc_shaman") { }
  347. CreatureAI* GetAI(Creature *pCreature) const
  348. {
  349. return new npc_toc_shamanAI (pCreature);
  350. }
  351. struct npc_toc_shamanAI : public boss_faction_championsAI
  352. {
  353. npc_toc_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER)
  354. {
  355. SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  356. events.Reset();
  357. events.RescheduleEvent(EVENT_SPELL_HEALING_WAVE, urand(3000,10000));
  358. events.RescheduleEvent(EVENT_SPELL_RIPTIDE, urand(3000,10000));
  359. events.RescheduleEvent(EVENT_SPELL_SPIRIT_CLEANSE, urand(10000,15000));
  360. events.RescheduleEvent(EVENT_SPELL_HEROISM_OR_BLOODLUST, urand(25000,40000));
  361. events.RescheduleEvent(EVENT_SPELL_HEX, urand(3000,10000));
  362. events.RescheduleEvent(EVENT_SPELL_EARTH_SHIELD, urand(15000,25000));
  363. events.RescheduleEvent(EVENT_SPELL_EARTH_SHOCK, urand(3000,10000));
  364. }
  365. EventMap events;
  366. bool myCanCast()
  367. {
  368. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  369. }
  370. void UpdateAI(uint32 diff)
  371. {
  372. boss_faction_championsAI::UpdateAI(diff);
  373. if( !UpdateVictim() )
  374. return;
  375. events.Update(diff);
  376. if( !myCanCast() )
  377. return;
  378. switch( events.GetEvent() )
  379. {
  380. case 0:
  381. break;
  382. case EVENT_SPELL_HEALING_WAVE:
  383. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_HEALING_WAVE, 40.0f) )
  384. me->CastSpell(target, SPELL_HEALING_WAVE, false);
  385. events.RepeatEvent(urand(10000,15000));
  386. EventMapGCD(events, 1500);
  387. break;
  388. case EVENT_SPELL_RIPTIDE:
  389. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_RIPTIDE, 40.0f) )
  390. me->CastSpell(target, SPELL_RIPTIDE, false);
  391. events.RepeatEvent(urand(10000,15000));
  392. EventMapGCD(events, 1500);
  393. break;
  394. case EVENT_SPELL_SPIRIT_CLEANSE:
  395. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_SPIRIT_CLEANSE, 40.0f) )
  396. me->CastSpell(target, SPELL_SPIRIT_CLEANSE, false);
  397. events.RepeatEvent(urand(10000,15000));
  398. EventMapGCD(events, 1500);
  399. break;
  400. case EVENT_SPELL_HEROISM_OR_BLOODLUST:
  401. if( me->GetEntry() == NPC_ALLIANCE_SHAMAN_RESTORATION )
  402. me->CastSpell((Unit*)NULL, SPELL_HEROISM, true);
  403. else
  404. me->CastSpell((Unit*)NULL, SPELL_BLOODLUST, true);
  405. events.RepeatEvent(600000);
  406. EventMapGCD(events, 1500);
  407. break;
  408. case EVENT_SPELL_HEX:
  409. if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true) )
  410. me->CastSpell(target, SPELL_HEX, false);
  411. events.RepeatEvent(45000);
  412. EventMapGCD(events, 1500);
  413. break;
  414. case EVENT_SPELL_EARTH_SHIELD:
  415. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_EARTH_SHIELD, 40.0f) )
  416. me->CastSpell(target, SPELL_EARTH_SHIELD, false);
  417. events.RepeatEvent(urand(10000,15000));
  418. EventMapGCD(events, 1500);
  419. break;
  420. case EVENT_SPELL_EARTH_SHOCK:
  421. if( me->GetVictim() )
  422. me->CastSpell(me->GetVictim(), SPELL_EARTH_SHOCK, false);
  423. events.RepeatEvent(urand(5000,10000));
  424. EventMapGCD(events, 1500);
  425. break;
  426. }
  427. DoMeleeAttackIfReady();
  428. }
  429. };
  430. };
  431. enum ePaladinSpells
  432. {
  433. SPELL_HAND_OF_FREEDOM = 68757,
  434. SPELL_BUBBLE = 66010,
  435. SPELL_CLEANSE = 66116,
  436. SPELL_FLASH_OF_LIGHT = 66113,
  437. SPELL_HOLY_LIGHT = 66112,
  438. SPELL_HOLY_SHOCK = 66114,
  439. SPELL_HAND_OF_PROTECTION = 66009,
  440. SPELL_HAMMER_OF_JUSTICE = 66613,
  441. };
  442. enum ePaladinEvents
  443. {
  444. EVENT_SPELL_HAND_OF_FREEDOM = 1,
  445. EVENT_SPELL_BUBBLE,
  446. EVENT_SPELL_CLEANSE,
  447. EVENT_SPELL_FLASH_OF_LIGHT,
  448. EVENT_SPELL_HOLY_LIGHT,
  449. EVENT_SPELL_HOLY_SHOCK,
  450. EVENT_SPELL_HAND_OF_PROTECTION,
  451. EVENT_SPELL_HAMMER_OF_JUSTICE,
  452. };
  453. class npc_toc_paladin : public CreatureScript
  454. {
  455. public:
  456. npc_toc_paladin() : CreatureScript("npc_toc_paladin") { }
  457. CreatureAI* GetAI(Creature *pCreature) const
  458. {
  459. return new npc_toc_paladinAI (pCreature);
  460. }
  461. struct npc_toc_paladinAI : public boss_faction_championsAI
  462. {
  463. npc_toc_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER)
  464. {
  465. SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE);
  466. events.Reset();
  467. events.RescheduleEvent(EVENT_SPELL_HAND_OF_FREEDOM, urand(10000,15000));
  468. events.RescheduleEvent(EVENT_SPELL_BUBBLE, 10000);
  469. events.RescheduleEvent(EVENT_SPELL_CLEANSE, urand(10000,15000));
  470. events.RescheduleEvent(EVENT_SPELL_FLASH_OF_LIGHT, urand(3000,10000));
  471. events.RescheduleEvent(EVENT_SPELL_HOLY_LIGHT, urand(5000,15000));
  472. events.RescheduleEvent(EVENT_SPELL_HOLY_SHOCK, urand(3000,10000));
  473. events.RescheduleEvent(EVENT_SPELL_HAND_OF_PROTECTION, urand(20000,35000));
  474. events.RescheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, urand(10000,20000));
  475. }
  476. EventMap events;
  477. bool myCanCast()
  478. {
  479. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  480. }
  481. void UpdateAI(uint32 diff)
  482. {
  483. boss_faction_championsAI::UpdateAI(diff);
  484. if( !UpdateVictim() )
  485. return;
  486. events.Update(diff);
  487. if( !myCanCast() )
  488. return;
  489. switch( events.GetEvent() )
  490. {
  491. case 0:
  492. break;
  493. case EVENT_SPELL_HAND_OF_FREEDOM:
  494. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM, 30.0f) )
  495. me->CastSpell(target, SPELL_HAND_OF_FREEDOM, false);
  496. events.RepeatEvent(25000);
  497. EventMapGCD(events, 1500);
  498. break;
  499. case EVENT_SPELL_BUBBLE:
  500. if( HealthBelowPct(25) )
  501. {
  502. me->CastSpell(me, SPELL_BUBBLE, false);
  503. events.RepeatEvent(300000);
  504. EventMapGCD(events, 1500);
  505. }
  506. else
  507. events.RepeatEvent(10000);
  508. break;
  509. case EVENT_SPELL_CLEANSE:
  510. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_CLEANSE, 40.0f) )
  511. me->CastSpell(target, SPELL_CLEANSE, false);
  512. events.RepeatEvent(urand(10000,15000));
  513. EventMapGCD(events, 1500);
  514. break;
  515. case EVENT_SPELL_FLASH_OF_LIGHT:
  516. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_FLASH_OF_LIGHT, 40.0f) )
  517. me->CastSpell(target, SPELL_FLASH_OF_LIGHT, false);
  518. events.RepeatEvent(urand(10000,15000));
  519. EventMapGCD(events, 1500);
  520. break;
  521. case EVENT_SPELL_HOLY_LIGHT:
  522. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_HOLY_LIGHT, 40.0f) )
  523. me->CastSpell(target, SPELL_HOLY_LIGHT, false);
  524. events.RepeatEvent(urand(10000,15000));
  525. EventMapGCD(events, 1500);
  526. break;
  527. case EVENT_SPELL_HOLY_SHOCK:
  528. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_HOLY_SHOCK, 40.0f) )
  529. me->CastSpell(target, SPELL_HOLY_SHOCK, false);
  530. events.RepeatEvent(urand(10000,15000));
  531. EventMapGCD(events, 1500);
  532. break;
  533. case EVENT_SPELL_HAND_OF_PROTECTION:
  534. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_HAND_OF_PROTECTION, 40.0f) )
  535. {
  536. me->CastSpell(target, SPELL_HAND_OF_PROTECTION, false);
  537. events.RepeatEvent(300000);
  538. EventMapGCD(events, 1500);
  539. }
  540. else
  541. events.RepeatEvent(10000);
  542. break;
  543. case EVENT_SPELL_HAMMER_OF_JUSTICE:
  544. if( Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 15.0f, true) )
  545. {
  546. me->CastSpell(target, SPELL_HAMMER_OF_JUSTICE, false);
  547. events.RepeatEvent(40000);
  548. EventMapGCD(events, 1500);
  549. }
  550. else
  551. events.RepeatEvent(10000);
  552. break;
  553. }
  554. DoMeleeAttackIfReady();
  555. }
  556. };
  557. };
  558. enum ePriestSpells
  559. {
  560. SPELL_RENEW = 66177,
  561. SPELL_SHIELD = 66099,
  562. SPELL_FLASH_HEAL = 66104,
  563. SPELL_DISPEL = 65546,
  564. SPELL_MANA_BURN = 66100,
  565. SPELL_PSYCHIC_SCREAM = 65543,
  566. };
  567. enum ePriestEvents
  568. {
  569. EVENT_SPELL_RENEW = 1,
  570. EVENT_SPELL_SHIELD,
  571. EVENT_SPELL_FLASH_HEAL,
  572. EVENT_SPELL_MANA_BURN,
  573. EVENT_SPELL_DISPEL = 100,
  574. EVENT_SPELL_PSYCHIC_SCREAM = 101,
  575. };
  576. class npc_toc_priest : public CreatureScript
  577. {
  578. public:
  579. npc_toc_priest() : CreatureScript("npc_toc_priest") { }
  580. CreatureAI* GetAI(Creature *pCreature) const
  581. {
  582. return new npc_toc_priestAI (pCreature);
  583. }
  584. struct npc_toc_priestAI : public boss_faction_championsAI
  585. {
  586. npc_toc_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER)
  587. {
  588. SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  589. events.Reset();
  590. events.RescheduleEvent(EVENT_SPELL_RENEW, urand(3000,10000));
  591. events.RescheduleEvent(EVENT_SPELL_SHIELD, urand(3000,10000));
  592. events.RescheduleEvent(EVENT_SPELL_FLASH_HEAL, urand(3000,10000));
  593. events.RescheduleEvent(EVENT_SPELL_DISPEL, urand(3000,10000));
  594. events.RescheduleEvent(EVENT_SPELL_MANA_BURN, urand(3000,10000));
  595. events.RescheduleEvent(EVENT_SPELL_PSYCHIC_SCREAM, 10000);
  596. }
  597. EventMap events;
  598. bool myCanCast()
  599. {
  600. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  601. }
  602. void UpdateAI(uint32 diff)
  603. {
  604. boss_faction_championsAI::UpdateAI(diff);
  605. if( !UpdateVictim() )
  606. return;
  607. events.Update(diff);
  608. if( !myCanCast() )
  609. return;
  610. switch( events.GetEvent() )
  611. {
  612. case 0:
  613. break;
  614. case EVENT_SPELL_RENEW:
  615. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_RENEW, 40.0f) )
  616. me->CastSpell(target, SPELL_RENEW, false);
  617. events.RepeatEvent(urand(10000,15000));
  618. EventMapGCD(events, 1500);
  619. break;
  620. case EVENT_SPELL_SHIELD:
  621. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_SHIELD, 40.0f) )
  622. me->CastSpell(target, SPELL_SHIELD, false);
  623. events.RepeatEvent(urand(10000,15000));
  624. EventMapGCD(events, 1500);
  625. break;
  626. case EVENT_SPELL_FLASH_HEAL:
  627. if( Creature* target = SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_FLASH_HEAL, 40.0f) )
  628. me->CastSpell(target, SPELL_FLASH_HEAL, false);
  629. events.RepeatEvent(urand(10000,15000));
  630. EventMapGCD(events, 1500);
  631. break;
  632. case EVENT_SPELL_DISPEL:
  633. if( Unit* target = (urand(0,1) ? SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 30.0f, true) : SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_DISPEL, 40.0f)) )
  634. me->CastSpell(target, SPELL_DISPEL, false);
  635. events.RepeatEvent(urand(10000,15000));
  636. EventMapGCD(events, 1500);
  637. break;
  638. case EVENT_SPELL_MANA_BURN:
  639. if( Unit* target = SelectEnemyCaster(false, 30.0f) )
  640. {
  641. me->CastSpell(target, SPELL_MANA_BURN, false);
  642. events.RepeatEvent(urand(10000,15000));
  643. EventMapGCD(events, 1500);
  644. }
  645. else
  646. events.RepeatEvent(6000);
  647. break;
  648. case EVENT_SPELL_PSYCHIC_SCREAM:
  649. if( HealthBelowPct(50) && EnemiesInRange(8.0f) >= 3 )
  650. {
  651. me->CastSpell((Unit*)NULL, SPELL_PSYCHIC_SCREAM, false);
  652. events.RepeatEvent(30000);
  653. EventMapGCD(events, 1500);
  654. }
  655. else
  656. events.RepeatEvent(6000);
  657. break;
  658. }
  659. DoMeleeAttackIfReady();
  660. }
  661. };
  662. };
  663. enum eShadowPriestSpells
  664. {
  665. SPELL_SILENCE = 65542,
  666. SPELL_VAMPIRIC_TOUCH = 65490,
  667. SPELL_SW_PAIN = 65541,
  668. SPELL_MIND_FLAY = 65488,
  669. SPELL_MIND_BLAST = 65492,
  670. SPELL_HORROR = 65545,
  671. SPELL_DISPERSION = 65544,
  672. SPELL_SHADOWFORM = 16592,
  673. };
  674. enum eShadowPriestEvents
  675. {
  676. EVENT_SPELL_SILENCE = 1,
  677. EVENT_SPELL_VAMPIRIC_TOUCH,
  678. EVENT_SPELL_SW_PAIN,
  679. EVENT_SPELL_MIND_FLAY,
  680. EVENT_SPELL_MIND_BLAST,
  681. EVENT_SPELL_HORROR,
  682. EVENT_SPELL_DISPERSION,
  683. };
  684. class npc_toc_shadow_priest : public CreatureScript
  685. {
  686. public:
  687. npc_toc_shadow_priest() : CreatureScript("npc_toc_shadow_priest") {}
  688. CreatureAI* GetAI(Creature *pCreature) const
  689. {
  690. return new npc_toc_shadow_priestAI (pCreature);
  691. }
  692. struct npc_toc_shadow_priestAI : public boss_faction_championsAI
  693. {
  694. npc_toc_shadow_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED)
  695. {
  696. SetEquipmentSlots(false, 50040, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  697. events.Reset();
  698. events.RescheduleEvent(EVENT_SPELL_SILENCE, urand(3000,10000));
  699. events.RescheduleEvent(EVENT_SPELL_VAMPIRIC_TOUCH, urand(3000,10000));
  700. events.RescheduleEvent(EVENT_SPELL_SW_PAIN, urand(3000,10000));
  701. events.RescheduleEvent(EVENT_SPELL_MIND_FLAY, urand(3000,10000));
  702. events.RescheduleEvent(EVENT_SPELL_MIND_BLAST, urand(3000,10000));
  703. events.RescheduleEvent(EVENT_SPELL_HORROR, urand(3000,10000));
  704. events.RescheduleEvent(EVENT_SPELL_DISPERSION, 10000);
  705. events.RescheduleEvent(EVENT_SPELL_DISPEL, urand(5000,10000));
  706. events.RescheduleEvent(EVENT_SPELL_PSYCHIC_SCREAM, 10000);
  707. }
  708. EventMap events;
  709. bool myCanCast()
  710. {
  711. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  712. }
  713. void UpdateAI(uint32 diff)
  714. {
  715. boss_faction_championsAI::UpdateAI(diff);
  716. if( !UpdateVictim() )
  717. return;
  718. events.Update(diff);
  719. if( !myCanCast() )
  720. return;
  721. switch( events.GetEvent() )
  722. {
  723. case 0:
  724. break;
  725. case EVENT_SPELL_SILENCE:
  726. if( Unit* target = SelectEnemyCaster(false, 30.0f) )
  727. {
  728. me->CastSpell(target, SPELL_SILENCE, false);
  729. events.RepeatEvent(45000);
  730. EventMapGCD(events, 1500);
  731. break;
  732. }
  733. else
  734. events.RepeatEvent(6000);
  735. break;
  736. case EVENT_SPELL_VAMPIRIC_TOUCH:
  737. if( me->GetVictim() )
  738. me->CastSpell(me->GetVictim(), SPELL_VAMPIRIC_TOUCH, false);
  739. events.RepeatEvent(urand(10000,15000));
  740. EventMapGCD(events, 1500);
  741. break;
  742. case EVENT_SPELL_SW_PAIN:
  743. if( me->GetVictim() )
  744. me->CastSpell(me->GetVictim(), SPELL_SW_PAIN, false);
  745. events.RepeatEvent(urand(10000,15000));
  746. EventMapGCD(events, 1500);
  747. break;
  748. case EVENT_SPELL_MIND_FLAY:
  749. if( me->GetVictim() )
  750. me->CastSpell(me->GetVictim(), SPELL_MIND_FLAY, false);
  751. events.RepeatEvent(urand(10000,15000));
  752. EventMapGCD(events, 1500);
  753. break;
  754. case EVENT_SPELL_MIND_BLAST:
  755. if( me->GetVictim() )
  756. me->CastSpell(me->GetVictim(), SPELL_MIND_BLAST, false);
  757. events.RepeatEvent(urand(10000,15000));
  758. EventMapGCD(events, 1500);
  759. break;
  760. case EVENT_SPELL_HORROR:
  761. if( me->GetVictim() && me->GetExactDist2d(me->GetVictim()) <= 30.0f )
  762. {
  763. me->CastSpell(me->GetVictim(), SPELL_HORROR, false);
  764. events.RepeatEvent(120000);
  765. EventMapGCD(events, 1500);
  766. }
  767. else
  768. events.RepeatEvent(10000);
  769. break;
  770. case EVENT_SPELL_DISPERSION:
  771. if( HealthBelowPct(25) )
  772. {
  773. me->CastSpell(me, SPELL_DISPERSION, false);
  774. events.RepeatEvent(180000);
  775. EventMapGCD(events, 1500);
  776. }
  777. else
  778. events.RepeatEvent(6000);
  779. break;
  780. case EVENT_SPELL_DISPEL:
  781. if( Unit* target = (urand(0,1) ? SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 30.0f, true) : SelectTarget_MostHPLostFriendlyMissingBuff(SPELL_DISPEL, 40.0f)) )
  782. me->CastSpell(target, SPELL_DISPEL, false);
  783. events.RepeatEvent(urand(10000,15000));
  784. EventMapGCD(events, 1500);
  785. break;
  786. case EVENT_SPELL_PSYCHIC_SCREAM:
  787. if( EnemiesInRange(8.0f) >= 3 )
  788. {
  789. me->CastSpell((Unit*)NULL, SPELL_PSYCHIC_SCREAM, false);
  790. events.RepeatEvent(30000);
  791. EventMapGCD(events, 1500);
  792. }
  793. else
  794. events.RepeatEvent(6000);
  795. break;
  796. }
  797. DoMeleeAttackIfReady();
  798. }
  799. };
  800. };
  801. enum eWarlockSpells
  802. {
  803. SPELL_HELLFIRE = 65816,
  804. SPELL_CORRUPTION = 65810,
  805. SPELL_CURSE_OF_AGONY = 65814,
  806. SPELL_CURSE_OF_EXHAUSTION = 65815,
  807. SPELL_FEAR = 65809,
  808. SPELL_SEARING_PAIN = 65819,
  809. SPELL_SHADOW_BOLT = 65821,
  810. SPELL_UNSTABLE_AFFLICTION = 65812,
  811. SPELL_UNSTABLE_AFFLICTION_DISPEL = 65813,
  812. SPELL_SUMMON_FELHUNTER = 67514,
  813. };
  814. enum eWarlockEvents
  815. {
  816. EVENT_SPELL_HELLFIRE = 1,
  817. EVENT_SPELL_CORRUPTION,
  818. EVENT_SPELL_CURSE_OF_AGONY,
  819. EVENT_SPELL_CURSE_OF_EXHAUSTION,
  820. EVENT_SPELL_FEAR,
  821. EVENT_SPELL_SEARING_PAIN,
  822. EVENT_SPELL_SHADOW_BOLT,
  823. EVENT_SPELL_UNSTABLE_AFFLICTION,
  824. EVENT_SPELL_SUMMON_FELHUNTER,
  825. };
  826. class npc_toc_warlock : public CreatureScript
  827. {
  828. public:
  829. npc_toc_warlock() : CreatureScript("npc_toc_warlock") { }
  830. CreatureAI* GetAI(Creature *pCreature) const
  831. {
  832. return new npc_toc_warlockAI (pCreature);
  833. }
  834. struct npc_toc_warlockAI : public boss_faction_championsAI
  835. {
  836. npc_toc_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED)
  837. {
  838. SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  839. events.Reset();
  840. events.RescheduleEvent(EVENT_SPELL_HELLFIRE, 10000);
  841. events.RescheduleEvent(EVENT_SPELL_CORRUPTION, urand(3000,10000));
  842. events.RescheduleEvent(EVENT_SPELL_CURSE_OF_AGONY, urand(3000,10000));
  843. events.RescheduleEvent(EVENT_SPELL_CURSE_OF_EXHAUSTION, urand(3000,10000));
  844. events.RescheduleEvent(EVENT_SPELL_FEAR, urand(3000,10000));
  845. events.RescheduleEvent(EVENT_SPELL_SEARING_PAIN, urand(3000,10000));
  846. events.RescheduleEvent(EVENT_SPELL_SHADOW_BOLT, urand(3000,10000));
  847. events.RescheduleEvent(EVENT_SPELL_UNSTABLE_AFFLICTION, urand(3000,10000));
  848. events.RescheduleEvent(EVENT_SPELL_SUMMON_FELHUNTER, 0);
  849. }
  850. EventMap events;
  851. bool myCanCast()
  852. {
  853. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  854. }
  855. void JustSummoned(Creature* c)
  856. {
  857. if( Unit* target = c->SelectNearestTarget(200.0f) )
  858. c->AI()->AttackStart(target);
  859. }
  860. void UpdateAI(uint32 diff)
  861. {
  862. boss_faction_championsAI::UpdateAI(diff);
  863. if( !UpdateVictim() )
  864. return;
  865. events.Update(diff);
  866. if( !myCanCast() )
  867. return;
  868. switch( events.GetEvent() )
  869. {
  870. case 0:
  871. break;
  872. case EVENT_SPELL_SUMMON_FELHUNTER:
  873. DoSummon(35465, *me);
  874. events.PopEvent();
  875. break;
  876. case EVENT_SPELL_HELLFIRE:
  877. if( EnemiesInRange(9.0f) >= 3 )
  878. {
  879. me->CastSpell((Unit*)NULL, SPELL_HELLFIRE, false);
  880. events.RepeatEvent(30000);
  881. EventMapGCD(events, 1500);
  882. }
  883. else
  884. events.RepeatEvent(6000);
  885. break;
  886. case EVENT_SPELL_CORRUPTION:
  887. if( me->GetVictim() )
  888. me->CastSpell(me->GetVictim(), SPELL_CORRUPTION, false);
  889. events.RepeatEvent(urand(10000,20000));
  890. EventMapGCD(events, 1500);
  891. break;
  892. case EVENT_SPELL_CURSE_OF_AGONY:
  893. if( me->GetVictim() )
  894. me->CastSpell(me->GetVictim(), SPELL_CURSE_OF_AGONY, false);
  895. events.RepeatEvent(urand(10000,20000));
  896. EventMapGCD(events, 1500);
  897. break;
  898. case EVENT_SPELL_CURSE_OF_EXHAUSTION:
  899. if( me->GetVictim() )
  900. me->CastSpell(me->GetVictim(), SPELL_CURSE_OF_EXHAUSTION, false);
  901. events.RepeatEvent(urand(10000,20000));
  902. EventMapGCD(events, 1500);
  903. break;
  904. case EVENT_SPELL_FEAR:
  905. if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true) )
  906. me->CastSpell(target, SPELL_FEAR, false);
  907. events.RepeatEvent(urand(10000,15000));
  908. EventMapGCD(events, 1500);
  909. break;
  910. case EVENT_SPELL_SEARING_PAIN:
  911. if( me->GetVictim() )
  912. me->CastSpell(me->GetVictim(), SPELL_SEARING_PAIN, false);
  913. events.RepeatEvent(urand(5000,15000));
  914. EventMapGCD(events, 1500);
  915. break;
  916. case EVENT_SPELL_SHADOW_BOLT:
  917. if( me->GetVictim() )
  918. me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT, false);
  919. events.RepeatEvent(urand(5000,15000));
  920. EventMapGCD(events, 1500);
  921. break;
  922. case EVENT_SPELL_UNSTABLE_AFFLICTION:
  923. if( me->GetVictim() )
  924. me->CastSpell(me->GetVictim(), SPELL_UNSTABLE_AFFLICTION, false);
  925. events.RepeatEvent(urand(5000,15000));
  926. EventMapGCD(events, 1500);
  927. break;
  928. }
  929. DoMeleeAttackIfReady();
  930. }
  931. };
  932. };
  933. enum eMageSpells
  934. {
  935. SPELL_ARCANE_BARRAGE = 65799,
  936. SPELL_ARCANE_BLAST = 65791,
  937. SPELL_ARCANE_EXPLOSION = 65800,
  938. SPELL_BLINK = 65793,
  939. SPELL_COUNTERSPELL = 65790,
  940. SPELL_FROST_NOVA = 65792,
  941. SPELL_FROSTBOLT = 65807,
  942. SPELL_ICE_BLOCK = 65802,
  943. SPELL_POLYMORPH = 65801,
  944. };
  945. enum eMageEvents
  946. {
  947. EVENT_SPELL_ARCANE_BARRAGE = 1,
  948. EVENT_SPELL_ARCANE_BLAST,
  949. EVENT_SPELL_ARCANE_EXPLOSION,
  950. EVENT_SPELL_BLINK,
  951. EVENT_SPELL_BLINK_2,
  952. EVENT_SPELL_COUNTERSPELL,
  953. EVENT_SPELL_FROSTBOLT,
  954. EVENT_SPELL_ICE_BLOCK,
  955. EVENT_SPELL_POLYMORPH,
  956. };
  957. class npc_toc_mage : public CreatureScript
  958. {
  959. public:
  960. npc_toc_mage() : CreatureScript("npc_toc_mage") { }
  961. CreatureAI* GetAI(Creature *pCreature) const
  962. {
  963. return new npc_toc_mageAI (pCreature);
  964. }
  965. struct npc_toc_mageAI : public boss_faction_championsAI
  966. {
  967. npc_toc_mageAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED)
  968. {
  969. SetEquipmentSlots(false, 47524, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  970. events.Reset();
  971. events.RescheduleEvent(EVENT_SPELL_ARCANE_BARRAGE, urand(3000,10000));
  972. events.RescheduleEvent(EVENT_SPELL_ARCANE_BLAST, urand(3000,10000));
  973. events.RescheduleEvent(EVENT_SPELL_ARCANE_EXPLOSION, urand(3000,10000));
  974. events.RescheduleEvent(EVENT_SPELL_BLINK, 10000);
  975. events.RescheduleEvent(EVENT_SPELL_COUNTERSPELL, urand(10000,20000));
  976. events.RescheduleEvent(EVENT_SPELL_FROSTBOLT, urand(3000,10000));
  977. events.RescheduleEvent(EVENT_SPELL_ICE_BLOCK, 10000);
  978. events.RescheduleEvent(EVENT_SPELL_POLYMORPH, urand(5000,10000));
  979. }
  980. EventMap events;
  981. bool myCanCast()
  982. {
  983. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  984. }
  985. void UpdateAI(uint32 diff)
  986. {
  987. boss_faction_championsAI::UpdateAI(diff);
  988. if( !UpdateVictim() )
  989. return;
  990. events.Update(diff);
  991. if( !myCanCast() )
  992. return;
  993. switch( events.GetEvent() )
  994. {
  995. case 0:
  996. break;
  997. case EVENT_SPELL_ARCANE_BARRAGE:
  998. if( me->GetVictim() )
  999. me->CastSpell(me->GetVictim(), SPELL_ARCANE_BARRAGE, false);
  1000. events.RepeatEvent(urand(5000,15000));
  1001. EventMapGCD(events, 1500);
  1002. break;
  1003. case EVENT_SPELL_ARCANE_BLAST:
  1004. if( me->GetVictim() )
  1005. me->CastSpell(me->GetVictim(), SPELL_ARCANE_BLAST, false);
  1006. events.RepeatEvent(urand(5000,15000));
  1007. EventMapGCD(events, 1500);
  1008. break;
  1009. case EVENT_SPELL_ARCANE_EXPLOSION:
  1010. if( EnemiesInRange(9.0f) >= 3 )
  1011. {
  1012. me->CastSpell((Unit*)NULL, SPELL_ARCANE_EXPLOSION, false);
  1013. events.RepeatEvent(6000);
  1014. EventMapGCD(events, 1500);
  1015. }
  1016. else
  1017. events.RepeatEvent(6000);
  1018. break;
  1019. case EVENT_SPELL_BLINK:
  1020. if( HealthBelowPct(50) && EnemiesInRange(10.0f) >= 3 )
  1021. {
  1022. me->CastSpell((Unit*)NULL, SPELL_FROST_NOVA, false);
  1023. events.RepeatEvent(15000);
  1024. EventMapGCD(events, 1500);
  1025. // blink disabled, fucking movement shit not working
  1026. }
  1027. else
  1028. events.RepeatEvent(6000);
  1029. break;
  1030. case EVENT_SPELL_COUNTERSPELL:
  1031. if( Unit* target = SelectEnemyCaster(true, 30.0f) )
  1032. {
  1033. me->CastSpell(target, SPELL_COUNTERSPELL, false);
  1034. events.RepeatEvent(24000);
  1035. EventMapGCD(events, 1500);
  1036. }
  1037. else
  1038. events.RepeatEvent(6000);
  1039. break;
  1040. case EVENT_SPELL_FROSTBOLT:
  1041. if( me->GetVictim() )
  1042. me->CastSpell(me->GetVictim(), SPELL_FROSTBOLT, false);
  1043. events.RepeatEvent(urand(5000,15000));
  1044. EventMapGCD(events, 1500);
  1045. break;
  1046. case EVENT_SPELL_ICE_BLOCK:
  1047. if( HealthBelowPct(25) )
  1048. {
  1049. me->CastSpell(me, SPELL_ICE_BLOCK, false);
  1050. events.RepeatEvent(300000);
  1051. EventMapGCD(events, 1500);
  1052. }
  1053. else
  1054. events.RepeatEvent(6000);
  1055. break;
  1056. case EVENT_SPELL_POLYMORPH:
  1057. if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) )
  1058. me->CastSpell(target, SPELL_POLYMORPH, false);
  1059. events.RepeatEvent(15000);
  1060. EventMapGCD(events, 1500);
  1061. break;
  1062. }
  1063. DoMeleeAttackIfReady();
  1064. }
  1065. };
  1066. };
  1067. enum eHunterSpells
  1068. {
  1069. SPELL_AIMED_SHOT = 65883,
  1070. SPELL_DETERRENCE = 65871,
  1071. SPELL_DISENGAGE = 65870,
  1072. SPELL_EXPLOSIVE_SHOT = 65866,
  1073. SPELL_FROST_TRAP = 65880,
  1074. SPELL_SHOOT = 65868,
  1075. SPELL_STEADY_SHOT = 65867,
  1076. SPELL_WING_CLIP = 66207,
  1077. SPELL_WYVERN_STING = 65877,
  1078. SPELL_CALL_PET = 67777,
  1079. };
  1080. enum eHunterEvents
  1081. {
  1082. EVENT_SPELL_AIMED_SHOT = 1,
  1083. EVENT_SPELL_DETERRENCE,
  1084. EVENT_SPELL_DISENGAGE,
  1085. EVENT_SPELL_EXPLOSIVE_SHOT,
  1086. EVENT_SPELL_FROST_TRAP,
  1087. EVENT_SPELL_STEADY_SHOT,
  1088. EVENT_SPELL_WING_CLIP,
  1089. EVENT_SPELL_WYVERN_STING,
  1090. EVENT_SPELL_CALL_PET,
  1091. };
  1092. class npc_toc_hunter : public CreatureScript
  1093. {
  1094. public:
  1095. npc_toc_hunter() : CreatureScript("npc_toc_hunter") { }
  1096. CreatureAI* GetAI(Creature *pCreature) const
  1097. {
  1098. return new npc_toc_hunterAI (pCreature);
  1099. }
  1100. struct npc_toc_hunterAI : public boss_faction_championsAI
  1101. {
  1102. npc_toc_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED)
  1103. {
  1104. SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711);
  1105. events.Reset();
  1106. events.RescheduleEvent(EVENT_SPELL_AIMED_SHOT, urand(3000,10000));
  1107. events.RescheduleEvent(EVENT_SPELL_DETERRENCE, 10000);
  1108. //events.RescheduleEvent(EVENT_SPELL_DISENGAGE, 10000);
  1109. events.RescheduleEvent(EVENT_SPELL_EXPLOSIVE_SHOT, urand(3000,10000));
  1110. events.RescheduleEvent(EVENT_SPELL_FROST_TRAP, urand(15000,20000));
  1111. events.RescheduleEvent(EVENT_SPELL_STEADY_SHOT, urand(3000,10000));
  1112. events.RescheduleEvent(EVENT_SPELL_WING_CLIP, 10000);
  1113. events.RescheduleEvent(EVENT_SPELL_WYVERN_STING, urand(5000,15000));
  1114. events.RescheduleEvent(EVENT_SPELL_CALL_PET, 0);
  1115. }
  1116. EventMap events;
  1117. bool myCanCast()
  1118. {
  1119. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED) || IsCCed());
  1120. }
  1121. void JustSummoned(Creature* c)
  1122. {
  1123. if( Unit* target = c->SelectNearestTarget(200.0f) )
  1124. c->AI()->AttackStart(target);
  1125. }
  1126. void UpdateAI(uint32 diff)
  1127. {
  1128. boss_faction_championsAI::UpdateAI(diff);
  1129. if( !UpdateVictim() )
  1130. return;
  1131. events.Update(diff);
  1132. if( !myCanCast() )
  1133. return;
  1134. switch( events.GetEvent() )
  1135. {
  1136. case 0:
  1137. break;
  1138. case EVENT_SPELL_CALL_PET:
  1139. DoSummon(35610, *me);
  1140. events.PopEvent();
  1141. break;
  1142. case EVENT_SPELL_AIMED_SHOT:
  1143. if( me->GetVictim() )
  1144. me->CastSpell(me->GetVictim(), SPELL_AIMED_SHOT, false);
  1145. events.RepeatEvent(urand(5000,15000));
  1146. EventMapGCD(events, 1500);
  1147. break;
  1148. case EVENT_SPELL_DETERRENCE:
  1149. if( HealthBelowPct(25) )
  1150. {
  1151. me->CastSpell(me, SPELL_DETERRENCE, false);
  1152. events.RepeatEvent(90000);
  1153. EventMapGCD(events, 1500);
  1154. }
  1155. else
  1156. events.RepeatEvent(6000);
  1157. break;
  1158. case EVENT_SPELL_DISENGAGE:
  1159. if( EnemiesInRange(10.0f) >= 3 )
  1160. {
  1161. me->CastSpell(me, SPELL_DISENGAGE, false);
  1162. events.RepeatEvent(20000);
  1163. EventMapGCD(events, 1500);
  1164. }
  1165. else
  1166. events.RepeatEvent(6000);
  1167. break;
  1168. case EVENT_SPELL_EXPLOSIVE_SHOT:
  1169. if( me->GetVictim() )
  1170. me->CastSpell(me->GetVictim(), SPELL_EXPLOSIVE_SHOT, false);
  1171. events.RepeatEvent(urand(5000,15000));
  1172. EventMapGCD(events, 1500);
  1173. break;
  1174. case EVENT_SPELL_FROST_TRAP:
  1175. me->CastSpell(me, SPELL_FROST_TRAP, false);
  1176. events.RepeatEvent(30000);
  1177. EventMapGCD(events, 1500);
  1178. break;
  1179. case EVENT_SPELL_STEADY_SHOT:
  1180. if( me->GetVictim() )
  1181. me->CastSpell(me->GetVictim(), SPELL_STEADY_SHOT, false);
  1182. events.RepeatEvent(urand(5000,15000));
  1183. EventMapGCD(events, 1500);
  1184. break;
  1185. case EVENT_SPELL_WING_CLIP:
  1186. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) <= 5.0f )
  1187. me->CastSpell(me->GetVictim(), SPELL_WING_CLIP, false);
  1188. events.RepeatEvent(8000);
  1189. EventMapGCD(events, 1500);
  1190. break;
  1191. case EVENT_SPELL_WYVERN_STING:
  1192. if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 35.0f, true) )
  1193. {
  1194. me->CastSpell(target, SPELL_WYVERN_STING, false);
  1195. events.RepeatEvent(60000);
  1196. EventMapGCD(events, 1500);
  1197. break;
  1198. }
  1199. events.RepeatEvent(10000);
  1200. break;
  1201. }
  1202. if( me->isAttackReady() && !me->HasUnitState(UNIT_STATE_CASTING) )
  1203. {
  1204. me->CastSpell(me->GetVictim(), SPELL_SHOOT, true);
  1205. me->resetAttackTimer();
  1206. }
  1207. }
  1208. };
  1209. };
  1210. enum eBoomkinSpells
  1211. {
  1212. SPELL_WRATH = 65862,
  1213. SPELL_MOONFIRE = 65856,
  1214. SPELL_STARFIRE = 65854,
  1215. SPELL_INSECT_SWARM = 65855,
  1216. SPELL_ENTANGLING_ROOTS = 65857,
  1217. SPELL_FAERIE_FIRE = 65863,
  1218. SPELL_CYCLONE = 65859,
  1219. SPELL_FORCE_OF_NATURE = 65861,
  1220. };
  1221. enum eBoomkinEvents
  1222. {
  1223. EVENT_SPELL_WRATH = 1,
  1224. EVENT_SPELL_MOONFIRE,
  1225. EVENT_SPELL_STARFIRE,
  1226. EVENT_SPELL_INSECT_SWARM,
  1227. EVENT_SPELL_ENTANGLING_ROOTS,
  1228. EVENT_SPELL_FAERIE_FIRE,
  1229. EVENT_SPELL_CYCLONE,
  1230. EVENT_SPELL_FORCE_OF_NATURE,
  1231. };
  1232. class npc_toc_boomkin : public CreatureScript
  1233. {
  1234. public:
  1235. npc_toc_boomkin() : CreatureScript("npc_toc_boomkin") { }
  1236. CreatureAI* GetAI(Creature *pCreature) const
  1237. {
  1238. return new npc_toc_boomkinAI (pCreature);
  1239. }
  1240. struct npc_toc_boomkinAI : public boss_faction_championsAI
  1241. {
  1242. npc_toc_boomkinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED)
  1243. {
  1244. SetEquipmentSlots(false, 50966, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
  1245. events.Reset();
  1246. events.RescheduleEvent(EVENT_SPELL_BARKSKIN, 10000);
  1247. events.RescheduleEvent(EVENT_SPELL_WRATH, urand(3000,10000));
  1248. events.RescheduleEvent(EVENT_SPELL_MOONFIRE, urand(3000,10000));
  1249. events.RescheduleEvent(EVENT_SPELL_STARFIRE, urand(3000,10000));
  1250. events.RescheduleEvent(EVENT_SPELL_INSECT_SWARM, urand(3000,10000));
  1251. events.RescheduleEvent(EVENT_SPELL_ENTANGLING_ROOTS, urand(3000,10000));
  1252. events.RescheduleEvent(EVENT_SPELL_FAERIE_FIRE, urand(3000,10000));
  1253. events.RescheduleEvent(EVENT_SPELL_CYCLONE, urand(10000,15000));
  1254. events.RescheduleEvent(EVENT_SPELL_FORCE_OF_NATURE, urand(20000,40000));
  1255. }
  1256. EventMap events;
  1257. bool myCanCast()
  1258. {
  1259. return !(me->HasUnitState(UNIT_STATE_CASTING) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) || IsCCed());
  1260. }
  1261. void JustSummoned(Creature* c)
  1262. {
  1263. if( Unit* target = c->SelectNearestTarget(200.0f) )
  1264. c->AI()->AttackStart(target);
  1265. }
  1266. void UpdateAI(uint32 diff)
  1267. {
  1268. boss_faction_championsAI::UpdateAI(diff);
  1269. if( !UpdateVictim() )
  1270. return;
  1271. events.Update(diff);
  1272. if( !myCanCast() )
  1273. return;
  1274. switch( events.GetEvent() )
  1275. {
  1276. case 0:
  1277. break;
  1278. case EVENT_SPELL_BARKSKIN:
  1279. if( HealthBelowPct(50) )
  1280. {
  1281. me->CastSpell(me, SPELL_BARKSKIN, false);
  1282. events.RepeatEvent(60000);
  1283. EventMapGCD(events, 1500);
  1284. }
  1285. else
  1286. events.RepeatEvent(6000);
  1287. break;
  1288. case EVENT_SPELL_WRATH:
  1289. if( me->GetVictim() )
  1290. me->CastSpell(me->GetVictim(), SPELL_WRATH, false);
  1291. events.RepeatEvent(urand(5000,15000));
  1292. EventMapGCD(events, 1500);
  1293. break;
  1294. case EVENT_SPELL_MOONFIRE:
  1295. if( me->GetVictim() )
  1296. me->CastSpell(me->GetVictim(), SPELL_MOONFIRE, false);
  1297. events.RepeatEvent(urand(5000,15000));
  1298. EventMapGCD(events, 1500);
  1299. break;
  1300. case EVENT_SPELL_STARFIRE:
  1301. if( me->GetVictim() )
  1302. me->CastSpell(me->GetVictim(), SPELL_STARFIRE, false);
  1303. events.RepeatEvent(urand(5000,15000));
  1304. EventMapGCD(events, 1500);
  1305. break;
  1306. case EVENT_SPELL_INSECT_SWARM:
  1307. if( me->GetVictim() )
  1308. me->CastSpell(me->GetVictim(), SPELL_INSECT_SWARM, false);
  1309. events.RepeatEvent(urand(5000,15000));
  1310. EventMapGCD(events, 1500);
  1311. break;
  1312. case EVENT_SPELL_ENTANGLING_ROOTS:
  1313. if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) )
  1314. me->CastSpell(target, SPELL_ENTANGLING_ROOTS, false);
  1315. events.RepeatEvent(urand(10000,15000));
  1316. EventMapGCD(events, 1500);
  1317. break;
  1318. case EVENT_SPELL_FAERIE_FIRE:
  1319. if( me->GetVictim() )
  1320. me->CastSpell(me->GetVictim(), SPELL_FAERIE_FIRE, false);
  1321. events.RepeatEvent(urand(15000,20000));
  1322. EventMapGCD(events, 1500);
  1323. break;
  1324. case EVENT_SPELL_CYCLONE:
  1325. if( Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 20.0f, true) )
  1326. me->CastSpell(target, SPELL_CYCLONE, false);
  1327. events.RepeatEvent(urand(25000,40000));
  1328. EventMapGCD(events, 1500);
  1329. break;
  1330. case EVENT_SPELL_FORCE_OF_NATURE:
  1331. me->CastSpell((Unit*)NULL, SPELL_FORCE_OF_NATURE, false);
  1332. events.RepeatEvent(180000);
  1333. EventMapGCD(events, 1500);
  1334. break;
  1335. }
  1336. DoMeleeAttackIfReady();
  1337. }
  1338. };
  1339. };
  1340. enum eWarriorSpells
  1341. {
  1342. SPELL_BLADESTORM = 65947,
  1343. SPELL_INTIMIDATING_SHOUT = 65930,
  1344. SPELL_MORTAL_STRIKE = 65926,
  1345. SPELL_CHARGE = 68764,
  1346. SPELL_DISARM = 65935,
  1347. SPELL_OVERPOWER = 65924,
  1348. SPELL_SUNDER_ARMOR = 65936,
  1349. SPELL_SHATTERING_THROW = 65940,
  1350. SPELL_RETALIATION = 65932,
  1351. };
  1352. enum eWarriorEvents
  1353. {
  1354. EVENT_SPELL_BLADESTORM = 1,
  1355. EVENT_SPELL_INTIMIDATING_SHOUT,
  1356. EVENT_SPELL_MORTAL_STRIKE,
  1357. EVENT_SPELL_CHARGE,
  1358. EVENT_SPELL_DISARM,
  1359. EVENT_SPELL_OVERPOWER,
  1360. EVENT_SPELL_SUNDER_ARMOR,
  1361. EVENT_SPELL_SHATTERING_THROW,
  1362. EVENT_SPELL_RETALIATION,
  1363. };
  1364. class npc_toc_warrior : public CreatureScript
  1365. {
  1366. public:
  1367. npc_toc_warrior() : CreatureScript("npc_toc_warrior") { }
  1368. CreatureAI* GetAI(Creature *pCreature) const
  1369. {
  1370. return new npc_toc_warriorAI (pCreature);
  1371. }
  1372. struct npc_toc_warriorAI : public boss_faction_championsAI
  1373. {
  1374. npc_toc_warriorAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE)
  1375. {
  1376. SetEquipmentSlots(false, 47427, 46964, EQUIP_NO_CHANGE);
  1377. events.Reset();
  1378. events.RescheduleEvent(EVENT_SPELL_BLADESTORM, 20000);
  1379. events.RescheduleEvent(EVENT_SPELL_INTIMIDATING_SHOUT, 14000);
  1380. events.RescheduleEvent(EVENT_SPELL_MORTAL_STRIKE, urand(5000,10000));
  1381. events.RescheduleEvent(EVENT_SPELL_CHARGE, 3000);
  1382. events.RescheduleEvent(EVENT_SPELL_DISARM, urand(15000,25000));
  1383. events.RescheduleEvent(EVENT_SPELL_OVERPOWER, urand(5000,10000));
  1384. events.RescheduleEvent(EVENT_SPELL_SUNDER_ARMOR, urand(5000,10000));
  1385. events.RescheduleEvent(EVENT_SPELL_SHATTERING_THROW, urand(25000,40000));
  1386. events.RescheduleEvent(EVENT_SPELL_RETALIATION, urand(25000,40000));
  1387. }
  1388. EventMap events;
  1389. bool myCanCast()
  1390. {
  1391. return !(me->HasUnitState(UNIT_STATE_CASTING) || IsCCed());
  1392. }
  1393. void UpdateAI(uint32 diff)
  1394. {
  1395. boss_faction_championsAI::UpdateAI(diff);
  1396. if( !UpdateVictim() )
  1397. return;
  1398. events.Update(diff);
  1399. if( !myCanCast() )
  1400. return;
  1401. switch( events.GetEvent() )
  1402. {
  1403. case 0:
  1404. break;
  1405. case EVENT_SPELL_BLADESTORM:
  1406. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1407. {
  1408. events.RepeatEvent(5000);
  1409. break;
  1410. }
  1411. if( EnemiesInRange(8.0f) >= 3 )
  1412. {
  1413. me->CastSpell(me, SPELL_BLADESTORM, false);
  1414. events.RepeatEvent(90000);
  1415. events.DelayEvents(9000);
  1416. }
  1417. else
  1418. events.RepeatEvent(5000);
  1419. break;
  1420. case EVENT_SPELL_INTIMIDATING_SHOUT:
  1421. if( EnemiesInRange(8.0f) >= 3 )
  1422. {
  1423. me->CastSpell((Unit*)NULL, SPELL_INTIMIDATING_SHOUT, false);
  1424. events.RepeatEvent(120000);
  1425. EventMapGCD(events, 1500);
  1426. }
  1427. else
  1428. events.RepeatEvent(5000);
  1429. break;
  1430. case EVENT_SPELL_MORTAL_STRIKE:
  1431. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1432. {
  1433. events.RepeatEvent(5000);
  1434. break;
  1435. }
  1436. if( me->GetVictim() )
  1437. me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false);
  1438. events.RepeatEvent(urand(6000,8000));
  1439. EventMapGCD(events, 1500);
  1440. break;
  1441. case EVENT_SPELL_CHARGE:
  1442. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) > 8.0f && me->GetDistance2d(me->GetVictim()) < 25.0f )
  1443. {
  1444. me->CastSpell(me->GetVictim(), SPELL_CHARGE, false);
  1445. events.RepeatEvent(10000);
  1446. EventMapGCD(events, 1500);
  1447. }
  1448. else
  1449. events.RepeatEvent(5000);
  1450. break;
  1451. case EVENT_SPELL_DISARM:
  1452. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) < 5.0f )
  1453. {
  1454. me->CastSpell(me->GetVictim(), SPELL_DISARM, false);
  1455. events.RepeatEvent(60000);
  1456. EventMapGCD(events, 1500);
  1457. }
  1458. else
  1459. events.RepeatEvent(5000);
  1460. break;
  1461. case EVENT_SPELL_OVERPOWER:
  1462. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1463. {
  1464. events.RepeatEvent(5000);
  1465. break;
  1466. }
  1467. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) < 5.0f )
  1468. {
  1469. me->CastSpell(me->GetVictim(), SPELL_OVERPOWER, false);
  1470. events.RepeatEvent(urand(10000,15000));
  1471. EventMapGCD(events, 1500);
  1472. }
  1473. else
  1474. events.RepeatEvent(5000);
  1475. break;
  1476. case EVENT_SPELL_SUNDER_ARMOR:
  1477. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1478. {
  1479. events.RepeatEvent(5000);
  1480. break;
  1481. }
  1482. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) < 5.0f )
  1483. {
  1484. me->CastSpell(me->GetVictim(), SPELL_SUNDER_ARMOR, false);
  1485. events.RepeatEvent(urand(10000,15000));
  1486. EventMapGCD(events, 1500);
  1487. }
  1488. else
  1489. events.RepeatEvent(5000);
  1490. break;
  1491. case EVENT_SPELL_SHATTERING_THROW:
  1492. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1493. {
  1494. events.RepeatEvent(5000);
  1495. break;
  1496. }
  1497. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) < 25.0f )
  1498. {
  1499. me->CastSpell(me->GetVictim(), SPELL_SHATTERING_THROW, false);
  1500. events.RepeatEvent(300000);
  1501. EventMapGCD(events, 1500);
  1502. }
  1503. else
  1504. events.RepeatEvent(6000);
  1505. break;
  1506. case EVENT_SPELL_RETALIATION:
  1507. if( me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) )
  1508. {
  1509. events.RepeatEvent(5000);
  1510. break;
  1511. }
  1512. if( EnemiesInRange(8.0f) >= 3 )
  1513. {
  1514. me->CastSpell(me, SPELL_RETALIATION, false);
  1515. events.RepeatEvent(300000);
  1516. EventMapGCD(events, 1500);
  1517. }
  1518. else
  1519. events.RepeatEvent(5000);
  1520. break;
  1521. }
  1522. DoMeleeAttackIfReady();
  1523. }
  1524. };
  1525. };
  1526. enum eDeathKnightSpells
  1527. {
  1528. SPELL_CHAINS_OF_ICE = 66020,
  1529. SPELL_DEATH_COIL = 66019,
  1530. SPELL_DEATH_GRIP = 66017,
  1531. SPELL_FROST_STRIKE = 66047,
  1532. SPELL_ICEBOUND_FORTITUDE = 66023,
  1533. SPELL_ICY_TOUCH = 66021,
  1534. SPELL_STRANGULATE = 66018,
  1535. };
  1536. enum eDeathKnightEvents
  1537. {
  1538. EVENT_SPELL_CHAINS_OF_ICE = 1,
  1539. EVENT_SPELL_DEATH_COIL,
  1540. EVENT_SPELL_DEATH_GRIP,
  1541. EVENT_SPELL_FROST_STRIKE,
  1542. EVENT_SPELL_ICEBOUND_FORTITUDE,
  1543. EVENT_SPELL_ICY_TOUCH,
  1544. EVENT_SPELL_STRANGULATE,
  1545. };
  1546. class npc_toc_dk : public CreatureScript
  1547. {
  1548. public:
  1549. npc_toc_dk() : CreatureScript("npc_toc_dk") { }
  1550. CreatureAI* GetAI(Creature *pCreature) const
  1551. {
  1552. return new npc_toc_dkAI (pCreature);
  1553. }
  1554. struct npc_toc_dkAI : public boss_faction_championsAI
  1555. {
  1556. npc_toc_dkAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE)
  1557. {
  1558. SetEquipmentSlots(false, 47518, 51021, EQUIP_NO_CHANGE);
  1559. events.Reset();
  1560. events.RescheduleEvent(EVENT_SPELL_CHAINS_OF_ICE, urand(3000,10000));
  1561. events.RescheduleEvent(EVENT_SPELL_DEATH_COIL, urand(3000,10000));
  1562. events.RescheduleEvent(EVENT_SPELL_DEATH_GRIP, 0);
  1563. events.RescheduleEvent(EVENT_SPELL_FROST_STRIKE, urand(3000,10000));
  1564. events.RescheduleEvent(EVENT_SPELL_ICEBOUND_FORTITUDE, 10000);
  1565. events.RescheduleEvent(EVENT_SPELL_ICY_TOUCH, urand(3000,10000));
  1566. events.RescheduleEvent(EVENT_SPELL_STRANGULATE, urand(20000,30000));
  1567. }
  1568. EventMap events;
  1569. bool myCanCast()
  1570. {
  1571. return !(me->HasUnitState(UNIT_STATE_CASTING) || IsCCed());
  1572. }
  1573. void UpdateAI(uint32 diff)
  1574. {
  1575. boss_faction_championsAI::UpdateAI(diff);
  1576. if( !UpdateVictim() )
  1577. return;
  1578. events.Update(diff);
  1579. if( !myCanCast() )
  1580. return;
  1581. switch( events.GetEvent() )
  1582. {
  1583. case 0:
  1584. break;
  1585. case EVENT_SPELL_CHAINS_OF_ICE:
  1586. if( me->GetVictim() && me->GetDistance2d(me->GetVictim()) <= 25.0f )
  1587. {
  1588. me->CastSpell(me->GetVictim(), SPELL_CHAINS_OF_ICE, false);
  1589. events.RepeatEvent(urand(10000,15000));
  1590. EventMapGCD(events, 1500);
  1591. }