PageRenderTime 65ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp

https://bitbucket.org/EMPulseGaming/mycore4kata
C++ | 351 lines | 281 code | 34 blank | 36 comment | 33 complexity | 5fc93f83cc58cf2ba83455ea059bc96b MD5 | raw file
  1. /*
  2. * Copyright (C) 2008-2011 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. /* ScriptData
  19. SDName: Boss_Ragnaros
  20. SD%Complete: 95
  21. SDComment: some spells doesnt work correctly
  22. SDCategory: Molten Core
  23. EndScriptData */
  24. #include "ScriptPCH.h"
  25. #include "molten_core.h"
  26. enum Texts
  27. {
  28. SAY_REINFORCEMENTS1 = -1409013,
  29. SAY_REINFORCEMENTS2 = -1409014,
  30. SAY_HAND = -1409015,
  31. SAY_WRATH = -1409016,
  32. SAY_KILL = -1409017,
  33. SAY_MAGMABURST = -1409018,
  34. SAY_SUMMON_MAJ = -1409008,
  35. SAY_ARRIVAL1_RAG = -1409009,
  36. SAY_ARRIVAL2_MAJ = -1409010,
  37. SAY_ARRIVAL3_RAG = -1409011,
  38. SAY_ARRIVAL5_RAG = -1409012,
  39. };
  40. enum Spells
  41. {
  42. SPELL_HAND_OF_RAGNAROS = 19780,
  43. SPELL_WRATH_OF_RAGNAROS = 20566,
  44. SPELL_LAVA_BURST = 21158,
  45. SPELL_MAGMA_BLAST = 20565, // Ranged attack
  46. SPELL_SONS_OF_FLAME_DUMMY = 21108, // Server side effect
  47. SPELL_RAGSUBMERGE = 21107, // Stealth aura
  48. SPELL_RAGEMERGE = 20568,
  49. SPELL_MELT_WEAPON = 21388,
  50. SPELL_ELEMENTAL_FIRE = 20564,
  51. SPELL_ERRUPTION = 17731,
  52. };
  53. enum Events
  54. {
  55. EVENT_ERUPTION = 1,
  56. EVENT_WRATH_OF_RAGNAROS = 2,
  57. EVENT_HAND_OF_RAGNAROS = 3,
  58. EVENT_LAVA_BURST = 4,
  59. EVENT_ELEMENTAL_FIRE = 5,
  60. EVENT_MAGMA_BLAST = 6,
  61. EVENT_SUBMERGE = 7,
  62. EVENT_INTRO_1 = 8,
  63. EVENT_INTRO_2 = 9,
  64. EVENT_INTRO_3 = 10,
  65. EVENT_INTRO_4 = 11,
  66. EVENT_INTRO_5 = 12,
  67. };
  68. class boss_ragnaros : public CreatureScript
  69. {
  70. public:
  71. boss_ragnaros() : CreatureScript("boss_ragnaros") { }
  72. struct boss_ragnarosAI : public BossAI
  73. {
  74. boss_ragnarosAI(Creature* creature) : BossAI(creature, BOSS_RAGNAROS)
  75. {
  76. _introState = 0;
  77. me->SetReactState(REACT_PASSIVE);
  78. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  79. }
  80. void Reset()
  81. {
  82. BossAI::Reset();
  83. _emergeTimer = 90000;
  84. _hasYelledMagmaBurst = false;
  85. _hasSubmergedOnce = false;
  86. _isBanished = false;
  87. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
  88. }
  89. void EnterCombat(Unit* victim)
  90. {
  91. BossAI::EnterCombat(victim);
  92. events.ScheduleEvent(EVENT_ERUPTION, 15000);
  93. events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30000);
  94. events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 25000);
  95. events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
  96. events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, 3000);
  97. events.ScheduleEvent(EVENT_MAGMA_BLAST, 2000);
  98. events.ScheduleEvent(EVENT_SUBMERGE, 180000);
  99. }
  100. void KilledUnit(Unit* /*victim*/)
  101. {
  102. if (urand(0, 99 < 25))
  103. DoScriptText(SAY_KILL, me);
  104. }
  105. void UpdateAI(const uint32 diff)
  106. {
  107. if (_introState != 2)
  108. {
  109. if (!_introState)
  110. {
  111. me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
  112. events.ScheduleEvent(EVENT_INTRO_1, 4000);
  113. events.ScheduleEvent(EVENT_INTRO_2, 23000);
  114. events.ScheduleEvent(EVENT_INTRO_3, 42000);
  115. events.ScheduleEvent(EVENT_INTRO_4, 43000);
  116. events.ScheduleEvent(EVENT_INTRO_5, 53000);
  117. _introState = 1;
  118. }
  119. events.Update(diff);
  120. while (uint32 eventId = events.ExecuteEvent())
  121. {
  122. switch (eventId)
  123. {
  124. case EVENT_INTRO_1:
  125. DoScriptText(SAY_ARRIVAL1_RAG, me);
  126. break;
  127. case EVENT_INTRO_2:
  128. DoScriptText(SAY_ARRIVAL3_RAG, me);
  129. break;
  130. case EVENT_INTRO_3:
  131. me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
  132. break;
  133. case EVENT_INTRO_4:
  134. DoScriptText(SAY_ARRIVAL5_RAG, me);
  135. if (instance)
  136. if (Creature* executus = Unit::GetCreature(*me, instance->GetData64(BOSS_MAJORDOMO_EXECUTUS)))
  137. me->Kill(executus);
  138. break;
  139. case EVENT_INTRO_5:
  140. me->SetReactState(REACT_AGGRESSIVE);
  141. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  142. _introState = 2;
  143. break;
  144. default:
  145. break;
  146. }
  147. }
  148. }
  149. else
  150. {
  151. if (instance)
  152. {
  153. if (_isBanished && ((_emergeTimer <= diff) || (instance->GetData(DATA_RAGNAROS_ADDS)) > 8))
  154. {
  155. //Become unbanished again
  156. me->SetReactState(REACT_AGGRESSIVE);
  157. me->setFaction(14);
  158. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  159. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
  160. me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
  161. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  162. AttackStart(target);
  163. instance->SetData(DATA_RAGNAROS_ADDS, 0);
  164. //DoCast(me, SPELL_RAGEMERGE); //"phase spells" didnt worked correctly so Ive commented them and wrote solution witch doesnt need core support
  165. _isBanished = false;
  166. }
  167. else if (_isBanished)
  168. {
  169. _emergeTimer -= diff;
  170. //Do nothing while banished
  171. return;
  172. }
  173. }
  174. //Return since we have no target
  175. if (!UpdateVictim())
  176. return;
  177. events.Update(diff);
  178. while (uint32 eventId = events.ExecuteEvent())
  179. {
  180. switch (eventId)
  181. {
  182. case EVENT_ERUPTION:
  183. DoCastVictim(SPELL_ERRUPTION);
  184. events.ScheduleEvent(EVENT_ERUPTION, urand(20000, 45000));
  185. break;
  186. case EVENT_WRATH_OF_RAGNAROS:
  187. DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
  188. if (urand(0, 1))
  189. DoScriptText(SAY_WRATH, me);
  190. events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 25000);
  191. break;
  192. case EVENT_HAND_OF_RAGNAROS:
  193. DoCast(me, SPELL_HAND_OF_RAGNAROS);
  194. if (urand(0, 1))
  195. DoScriptText(SAY_HAND, me);
  196. events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 20000);
  197. break;
  198. case EVENT_LAVA_BURST:
  199. DoCastVictim(SPELL_LAVA_BURST);
  200. events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
  201. break;
  202. case EVENT_ELEMENTAL_FIRE:
  203. DoCastVictim(SPELL_ELEMENTAL_FIRE);
  204. events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000));
  205. break;
  206. case EVENT_MAGMA_BLAST:
  207. if (me->IsWithinMeleeRange(me->getVictim()))
  208. {
  209. DoCastVictim(SPELL_MAGMA_BLAST);
  210. if (!_hasYelledMagmaBurst)
  211. {
  212. //Say our dialog
  213. DoScriptText(SAY_MAGMABURST, me);
  214. _hasYelledMagmaBurst = true;
  215. }
  216. }
  217. events.ScheduleEvent(EVENT_MAGMA_BLAST, 2500);
  218. break;
  219. case EVENT_SUBMERGE:
  220. {
  221. if (instance && !_isBanished)
  222. {
  223. //Creature spawning and ragnaros becomming unattackable
  224. //is not very well supported in the core //no it really isnt
  225. //so added normaly spawning and banish workaround and attack again after 90 secs.
  226. me->AttackStop();
  227. DoResetThreat();
  228. me->SetReactState(REACT_PASSIVE);
  229. me->InterruptNonMeleeSpells(false);
  230. //Root self
  231. //DoCast(me, 23973);
  232. me->setFaction(35);
  233. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  234. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
  235. me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
  236. instance->SetData(DATA_RAGNAROS_ADDS, 0);
  237. if (!_hasSubmergedOnce)
  238. {
  239. DoScriptText(SAY_REINFORCEMENTS1, me);
  240. // summon 8 elementals
  241. for (uint8 i = 0; i < 8; ++i)
  242. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  243. if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
  244. summoned->AI()->AttackStart(target);
  245. _hasSubmergedOnce = true;
  246. _isBanished = true;
  247. //DoCast(me, SPELL_RAGSUBMERGE);
  248. _emergeTimer = 90000;
  249. }
  250. else
  251. {
  252. DoScriptText(SAY_REINFORCEMENTS2, me);
  253. for (uint8 i = 0; i < 8; ++i)
  254. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  255. if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
  256. summoned->AI()->AttackStart(target);
  257. _isBanished = true;
  258. //DoCast(me, SPELL_RAGSUBMERGE);
  259. _emergeTimer = 90000;
  260. }
  261. }
  262. events.ScheduleEvent(EVENT_SUBMERGE, 180000);
  263. break;
  264. }
  265. default:
  266. break;
  267. }
  268. }
  269. DoMeleeAttackIfReady();
  270. }
  271. }
  272. private:
  273. uint32 _emergeTimer;
  274. uint8 _introState;
  275. bool _hasYelledMagmaBurst;
  276. bool _hasSubmergedOnce;
  277. bool _isBanished;
  278. };
  279. CreatureAI* GetAI(Creature* creature) const
  280. {
  281. return new boss_ragnarosAI(creature);
  282. }
  283. };
  284. class mob_son_of_flame : public CreatureScript
  285. {
  286. public:
  287. mob_son_of_flame() : CreatureScript("mob_SonOfFlame") { }
  288. struct mob_son_of_flameAI : public ScriptedAI //didnt work correctly in EAI for me...
  289. {
  290. mob_son_of_flameAI(Creature* c) : ScriptedAI(c)
  291. {
  292. instance = me->GetInstanceScript();
  293. }
  294. void JustDied(Unit* /*victim*/)
  295. {
  296. if (instance)
  297. instance->SetData(DATA_RAGNAROS_ADDS, 1);
  298. }
  299. void UpdateAI(const uint32 /*diff*/)
  300. {
  301. if (!UpdateVictim())
  302. return;
  303. DoMeleeAttackIfReady();
  304. }
  305. private:
  306. InstanceScript* instance;
  307. };
  308. CreatureAI* GetAI(Creature* creature) const
  309. {
  310. return new mob_son_of_flameAI(creature);
  311. }
  312. };
  313. void AddSC_boss_ragnaros()
  314. {
  315. new boss_ragnaros();
  316. new mob_son_of_flame();
  317. }