PageRenderTime 84ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp

https://github.com/Antology/Dragon
C++ | 337 lines | 275 code | 45 blank | 17 comment | 50 complexity | 52091cd2de824c34cfd5ab5a8894f4b2 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "ScriptPCH.h"
  18. #include "pit_of_saron.h"
  19. enum Yells
  20. {
  21. SAY_AGGRO = -1658001,
  22. SAY_SLAY_1 = -1658002,
  23. SAY_SLAY_2 = -1658003,
  24. SAY_DEATH = -1658004,
  25. SAY_PHASE2 = -1658005,
  26. SAY_PHASE3 = -1658006,
  27. SAY_TYRANNUS_DEATH = -1659007,
  28. };
  29. enum Spells
  30. {
  31. SPELL_PERMAFROST = 70326,
  32. SPELL_THROW_SARONITE = 68788,
  33. SPELL_THUNDERING_STOMP = 68771,
  34. SPELL_CHILLING_WAVE = 68778,
  35. SPELL_DEEP_FREEZE = 70381,
  36. SPELL_FORGE_MACE = 68785,
  37. SPELL_FORGE_BLADE = 68774,
  38. };
  39. #define SPELL_PERMAFROST_HELPER RAID_MODE<uint32>(68786, 70336)
  40. #define SPELL_FORGE_BLADE_HELPER RAID_MODE<uint32>(68774, 70334)
  41. enum Events
  42. {
  43. EVENT_THROW_SARONITE = 1,
  44. EVENT_CHILLING_WAVE = 2,
  45. EVENT_DEEP_FREEZE = 3,
  46. EVENT_JUMP = 4,
  47. EVENT_FORGING = 5,
  48. EVENT_RESUME_ATTACK = 6,
  49. };
  50. enum Phases
  51. {
  52. PHASE_ONE = 1,
  53. PHASE_TWO = 2,
  54. PHASE_THREE = 3,
  55. PHASE_ONE_MASK = 1 << PHASE_ONE,
  56. PHASE_TWO_MASK = 1 << PHASE_TWO,
  57. PHASE_THREE_MASK = 1 << PHASE_THREE,
  58. };
  59. enum MiscData
  60. {
  61. EQUIP_ID_SWORD = 49345,
  62. EQUIP_ID_MACE = 49344,
  63. ACHIEV_DOESNT_GO_TO_ELEVEN = 0,
  64. POINT_FORGE = 0,
  65. };
  66. Position const northForgePos = {722.5643f, -234.1615f, 527.182f, 2.16421f};
  67. Position const southForgePos = {639.257f, -210.1198f, 529.015f, 0.523599f};
  68. class boss_garfrost : public CreatureScript
  69. {
  70. public:
  71. boss_garfrost() : CreatureScript("boss_garfrost") { }
  72. struct boss_garfrostAI : public BossAI
  73. {
  74. boss_garfrostAI(Creature* creature) : BossAI(creature, DATA_GARFROST)
  75. {
  76. }
  77. void InitializeAI()
  78. {
  79. if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(PoSScriptName))
  80. me->IsAIEnabled = false;
  81. else if (!me->isDead())
  82. Reset();
  83. }
  84. void Reset()
  85. {
  86. events.Reset();
  87. events.SetPhase(PHASE_ONE);
  88. SetEquipmentSlots(true);
  89. _permafrostStack = 0;
  90. instance->SetBossState(DATA_GARFROST, NOT_STARTED);
  91. }
  92. void EnterCombat(Unit* /*who*/)
  93. {
  94. DoScriptText(SAY_AGGRO, me);
  95. DoCast(me, SPELL_PERMAFROST);
  96. events.ScheduleEvent(EVENT_THROW_SARONITE, 7000);
  97. instance->SetBossState(DATA_GARFROST, IN_PROGRESS);
  98. }
  99. void KilledUnit(Unit* victim)
  100. {
  101. if (victim->GetTypeId() == TYPEID_PLAYER)
  102. DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me);
  103. }
  104. void JustDied(Unit* /*killer*/)
  105. {
  106. DoScriptText(SAY_DEATH, me);
  107. if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS)))
  108. DoScriptText(SAY_TYRANNUS_DEATH, tyrannus);
  109. instance->SetBossState(DATA_GARFROST, DONE);
  110. }
  111. void DamageTaken(Unit* /*attacker*/, uint32& /*uiDamage*/)
  112. {
  113. if (events.GetPhaseMask() & PHASE_ONE_MASK && !HealthAbovePct(66))
  114. {
  115. events.SetPhase(PHASE_TWO);
  116. events.DelayEvents(8000);
  117. DoCast(me, SPELL_THUNDERING_STOMP);
  118. events.ScheduleEvent(EVENT_JUMP, 1500);
  119. return;
  120. }
  121. if (events.GetPhaseMask() & PHASE_TWO_MASK && !HealthAbovePct(33))
  122. {
  123. events.SetPhase(PHASE_THREE);
  124. events.DelayEvents(8000);
  125. DoCast(me, SPELL_THUNDERING_STOMP);
  126. events.ScheduleEvent(EVENT_JUMP, 1500);
  127. return;
  128. }
  129. }
  130. void MovementInform(uint32 type, uint32 id)
  131. {
  132. if (type != POINT_MOTION_TYPE || id != POINT_FORGE)
  133. return;
  134. if (events.GetPhaseMask() & PHASE_TWO_MASK)
  135. DoCast(me, SPELL_FORGE_BLADE);
  136. if (events.GetPhaseMask() & PHASE_THREE_MASK)
  137. {
  138. me->RemoveAurasDueToSpell(SPELL_FORGE_BLADE_HELPER);
  139. DoCast(me, SPELL_FORGE_MACE);
  140. }
  141. events.ScheduleEvent(EVENT_RESUME_ATTACK, 5000);
  142. }
  143. void SpellHitTarget(Unit* target, const SpellInfo* spell)
  144. {
  145. if (spell->Id == SPELL_PERMAFROST_HELPER)
  146. {
  147. if (Aura *aura = target->GetAura(SPELL_PERMAFROST_HELPER))
  148. _permafrostStack = std::max<uint32>(_permafrostStack, aura->GetStackAmount());
  149. }
  150. else if (spell->Id == SPELL_FORGE_BLADE)
  151. SetEquipmentSlots(false, EQUIP_ID_SWORD);
  152. else if (spell->Id == SPELL_FORGE_MACE)
  153. SetEquipmentSlots(false, EQUIP_ID_MACE);
  154. }
  155. uint32 GetData(uint32 /*type*/)
  156. {
  157. return _permafrostStack;
  158. }
  159. void UpdateAI(const uint32 diff)
  160. {
  161. if (!UpdateVictim())
  162. return;
  163. events.Update(diff);
  164. if (me->HasUnitState(UNIT_STAT_CASTING))
  165. return;
  166. while (uint32 eventId = events.ExecuteEvent())
  167. {
  168. switch (eventId)
  169. {
  170. case EVENT_THROW_SARONITE:
  171. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  172. DoCast(target, SPELL_THROW_SARONITE);
  173. events.ScheduleEvent(EVENT_THROW_SARONITE, urand(12500, 20000));
  174. break;
  175. case EVENT_CHILLING_WAVE:
  176. DoCast(me, SPELL_CHILLING_WAVE);
  177. events.ScheduleEvent(EVENT_CHILLING_WAVE, 40000, 0, PHASE_TWO);
  178. break;
  179. case EVENT_DEEP_FREEZE:
  180. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  181. DoCast(target, SPELL_DEEP_FREEZE);
  182. events.ScheduleEvent(EVENT_DEEP_FREEZE, 35000, 0, PHASE_THREE);
  183. break;
  184. case EVENT_JUMP:
  185. me->AttackStop();
  186. if (events.GetPhaseMask() & PHASE_TWO_MASK)
  187. me->GetMotionMaster()->MoveJump(northForgePos.GetPositionX(), northForgePos.GetPositionY(), northForgePos.GetPositionZ(), 25.0f, 15.0f);
  188. else if (events.GetPhaseMask() & PHASE_THREE_MASK)
  189. me->GetMotionMaster()->MoveJump(southForgePos.GetPositionX(), southForgePos.GetPositionY(), southForgePos.GetPositionZ(), 25.0f, 15.0f);
  190. break;
  191. case EVENT_RESUME_ATTACK:
  192. if (events.GetPhaseMask() & PHASE_TWO_MASK)
  193. events.ScheduleEvent(EVENT_CHILLING_WAVE, 5000, 0, PHASE_TWO);
  194. else if (events.GetPhaseMask() & PHASE_THREE_MASK)
  195. events.ScheduleEvent(EVENT_DEEP_FREEZE, 10000, 0, PHASE_THREE);
  196. AttackStart(me->getVictim());
  197. break;
  198. default:
  199. break;
  200. }
  201. }
  202. DoMeleeAttackIfReady();
  203. }
  204. private:
  205. uint32 _permafrostStack;
  206. };
  207. CreatureAI* GetAI(Creature* creature) const
  208. {
  209. return new boss_garfrostAI(creature);
  210. }
  211. };
  212. class spell_garfrost_permafrost : public SpellScriptLoader
  213. {
  214. public:
  215. spell_garfrost_permafrost() : SpellScriptLoader("spell_garfrost_permafrost") { }
  216. class spell_garfrost_permafrost_SpellScript : public SpellScript
  217. {
  218. PrepareSpellScript(spell_garfrost_permafrost_SpellScript);
  219. bool Load()
  220. {
  221. prevented = false;
  222. return true;
  223. }
  224. void PreventHitByLoS()
  225. {
  226. if (Unit* target = GetHitUnit())
  227. {
  228. Unit* caster = GetCaster();
  229. //Temporary Line of Sight Check
  230. std::list<GameObject*> blockList;
  231. caster->GetGameObjectListWithEntryInGrid(blockList, GO_SARONITE_ROCK, 100.0f);
  232. if (!blockList.empty())
  233. {
  234. for (std::list<GameObject*>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
  235. {
  236. if ((*itr)->isVisibleForInState(target))
  237. {
  238. if ((*itr)->IsInBetween(caster, target, 4.0f))
  239. {
  240. prevented = true;
  241. target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, true);
  242. PreventHitDefaultEffect(EFFECT_0);
  243. PreventHitDefaultEffect(EFFECT_1);
  244. PreventHitDefaultEffect(EFFECT_2);
  245. PreventHitDamage();
  246. break;
  247. }
  248. }
  249. }
  250. }
  251. }
  252. }
  253. void RestoreImmunity()
  254. {
  255. if (Unit* target = GetHitUnit())
  256. {
  257. target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, false);
  258. if (prevented)
  259. PreventHitAura();
  260. }
  261. }
  262. void Register()
  263. {
  264. BeforeHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::PreventHitByLoS);
  265. AfterHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::RestoreImmunity);
  266. }
  267. bool prevented;
  268. };
  269. SpellScript* GetSpellScript() const
  270. {
  271. return new spell_garfrost_permafrost_SpellScript();
  272. }
  273. };
  274. class achievement_doesnt_go_to_eleven : public AchievementCriteriaScript
  275. {
  276. public:
  277. achievement_doesnt_go_to_eleven() : AchievementCriteriaScript("achievement_doesnt_go_to_eleven") { }
  278. bool OnCheck(Player* /*source*/, Unit* target)
  279. {
  280. if (target)
  281. if (Creature* garfrost = target->ToCreature())
  282. if (garfrost->AI()->GetData(ACHIEV_DOESNT_GO_TO_ELEVEN) <= 10)
  283. return true;
  284. return false;
  285. }
  286. };
  287. void AddSC_boss_garfrost()
  288. {
  289. new boss_garfrost();
  290. new spell_garfrost_permafrost();
  291. new achievement_doesnt_go_to_eleven();
  292. }