PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

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

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