PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/Snapper/TrinityCore_434
C++ | 355 lines | 283 code | 36 blank | 36 comment | 29 complexity | e4edb2142aa1d7c6010fb486ed43404c MD5 | raw file
  1. /*
  2. * Copyright (C) 2008-2016 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. Initialize();
  78. _introState = 0;
  79. me->SetReactState(REACT_PASSIVE);
  80. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  81. SetCombatMovement(false);
  82. }
  83. void Initialize()
  84. {
  85. _emergeTimer = 90000;
  86. _hasYelledMagmaBurst = false;
  87. _hasSubmergedOnce = false;
  88. _isBanished = false;
  89. }
  90. void Reset() override
  91. {
  92. BossAI::Reset();
  93. Initialize();
  94. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
  95. }
  96. void EnterCombat(Unit* victim) override
  97. {
  98. BossAI::EnterCombat(victim);
  99. events.ScheduleEvent(EVENT_ERUPTION, 15000);
  100. events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30000);
  101. events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 25000);
  102. events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
  103. events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, 3000);
  104. events.ScheduleEvent(EVENT_MAGMA_BLAST, 2000);
  105. events.ScheduleEvent(EVENT_SUBMERGE, 180000);
  106. }
  107. void KilledUnit(Unit* /*victim*/) override
  108. {
  109. if (urand(0, 99) < 25)
  110. Talk(SAY_KILL);
  111. }
  112. void UpdateAI(uint32 diff) override
  113. {
  114. if (_introState != 2)
  115. {
  116. if (!_introState)
  117. {
  118. me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
  119. events.ScheduleEvent(EVENT_INTRO_1, 4000);
  120. events.ScheduleEvent(EVENT_INTRO_2, 23000);
  121. events.ScheduleEvent(EVENT_INTRO_3, 42000);
  122. events.ScheduleEvent(EVENT_INTRO_4, 43000);
  123. events.ScheduleEvent(EVENT_INTRO_5, 53000);
  124. _introState = 1;
  125. }
  126. events.Update(diff);
  127. while (uint32 eventId = events.ExecuteEvent())
  128. {
  129. switch (eventId)
  130. {
  131. case EVENT_INTRO_1:
  132. Talk(SAY_ARRIVAL1_RAG);
  133. break;
  134. case EVENT_INTRO_2:
  135. Talk(SAY_ARRIVAL3_RAG);
  136. break;
  137. case EVENT_INTRO_3:
  138. me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
  139. break;
  140. case EVENT_INTRO_4:
  141. Talk(SAY_ARRIVAL5_RAG);
  142. if (Creature* executus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MAJORDOMO_EXECUTUS)))
  143. me->Kill(executus);
  144. break;
  145. case EVENT_INTRO_5:
  146. me->SetReactState(REACT_AGGRESSIVE);
  147. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  148. _introState = 2;
  149. break;
  150. default:
  151. break;
  152. }
  153. }
  154. }
  155. else
  156. {
  157. if (_isBanished && ((_emergeTimer <= diff) || (instance->GetData(DATA_RAGNAROS_ADDS)) > 8))
  158. {
  159. //Become unbanished again
  160. me->SetReactState(REACT_AGGRESSIVE);
  161. me->setFaction(14);
  162. me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  163. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
  164. me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
  165. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  166. AttackStart(target);
  167. instance->SetData(DATA_RAGNAROS_ADDS, 0);
  168. //DoCast(me, SPELL_RAGEMERGE); //"phase spells" didnt worked correctly so Ive commented them and wrote solution witch doesnt need core support
  169. _isBanished = false;
  170. }
  171. else if (_isBanished)
  172. {
  173. _emergeTimer -= diff;
  174. //Do nothing while banished
  175. return;
  176. }
  177. //Return since we have no target
  178. if (!UpdateVictim())
  179. return;
  180. events.Update(diff);
  181. while (uint32 eventId = events.ExecuteEvent())
  182. {
  183. switch (eventId)
  184. {
  185. case EVENT_ERUPTION:
  186. DoCastVictim(SPELL_ERRUPTION);
  187. events.ScheduleEvent(EVENT_ERUPTION, urand(20000, 45000));
  188. break;
  189. case EVENT_WRATH_OF_RAGNAROS:
  190. DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
  191. if (urand(0, 1))
  192. Talk(SAY_WRATH);
  193. events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 25000);
  194. break;
  195. case EVENT_HAND_OF_RAGNAROS:
  196. DoCast(me, SPELL_HAND_OF_RAGNAROS);
  197. if (urand(0, 1))
  198. Talk(SAY_HAND);
  199. events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 20000);
  200. break;
  201. case EVENT_LAVA_BURST:
  202. DoCastVictim(SPELL_LAVA_BURST);
  203. events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
  204. break;
  205. case EVENT_ELEMENTAL_FIRE:
  206. DoCastVictim(SPELL_ELEMENTAL_FIRE);
  207. events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000));
  208. break;
  209. case EVENT_MAGMA_BLAST:
  210. if (!me->IsWithinMeleeRange(me->GetVictim()))
  211. {
  212. DoCastVictim(SPELL_MAGMA_BLAST);
  213. if (!_hasYelledMagmaBurst)
  214. {
  215. //Say our dialog
  216. Talk(SAY_MAGMABURST);
  217. _hasYelledMagmaBurst = true;
  218. }
  219. }
  220. events.ScheduleEvent(EVENT_MAGMA_BLAST, 2500);
  221. break;
  222. case EVENT_SUBMERGE:
  223. {
  224. if (!_isBanished)
  225. {
  226. //Creature spawning and ragnaros becomming unattackable
  227. //is not very well supported in the core //no it really isnt
  228. //so added normaly spawning and banish workaround and attack again after 90 secs.
  229. me->AttackStop();
  230. DoResetThreat();
  231. me->SetReactState(REACT_PASSIVE);
  232. me->InterruptNonMeleeSpells(false);
  233. //Root self
  234. //DoCast(me, 23973);
  235. me->setFaction(35);
  236. me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
  237. me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
  238. me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
  239. instance->SetData(DATA_RAGNAROS_ADDS, 0);
  240. if (!_hasSubmergedOnce)
  241. {
  242. Talk(SAY_REINFORCEMENTS1);
  243. // summon 8 elementals
  244. for (uint8 i = 0; i < 8; ++i)
  245. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  246. if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
  247. summoned->AI()->AttackStart(target);
  248. _hasSubmergedOnce = true;
  249. _isBanished = true;
  250. //DoCast(me, SPELL_RAGSUBMERGE);
  251. _emergeTimer = 90000;
  252. }
  253. else
  254. {
  255. Talk(SAY_REINFORCEMENTS2);
  256. for (uint8 i = 0; i < 8; ++i)
  257. if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
  258. if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
  259. summoned->AI()->AttackStart(target);
  260. _isBanished = true;
  261. //DoCast(me, SPELL_RAGSUBMERGE);
  262. _emergeTimer = 90000;
  263. }
  264. }
  265. events.ScheduleEvent(EVENT_SUBMERGE, 180000);
  266. break;
  267. }
  268. default:
  269. break;
  270. }
  271. }
  272. DoMeleeAttackIfReady();
  273. }
  274. }
  275. private:
  276. uint32 _emergeTimer;
  277. uint8 _introState;
  278. bool _hasYelledMagmaBurst;
  279. bool _hasSubmergedOnce;
  280. bool _isBanished;
  281. };
  282. CreatureAI* GetAI(Creature* creature) const override
  283. {
  284. return GetInstanceAI<boss_ragnarosAI>(creature);
  285. }
  286. };
  287. class npc_son_of_flame : public CreatureScript
  288. {
  289. public:
  290. npc_son_of_flame() : CreatureScript("npc_SonOfFlame") { }
  291. struct npc_son_of_flameAI : public ScriptedAI //didnt work correctly in EAI for me...
  292. {
  293. npc_son_of_flameAI(Creature* creature) : ScriptedAI(creature)
  294. {
  295. instance = me->GetInstanceScript();
  296. }
  297. void JustDied(Unit* /*killer*/) override
  298. {
  299. instance->SetData(DATA_RAGNAROS_ADDS, 1);
  300. }
  301. void UpdateAI(uint32 /*diff*/) override
  302. {
  303. if (!UpdateVictim())
  304. return;
  305. DoMeleeAttackIfReady();
  306. }
  307. private:
  308. InstanceScript* instance;
  309. };
  310. CreatureAI* GetAI(Creature* creature) const override
  311. {
  312. return GetInstanceAI<npc_son_of_flameAI>(creature);
  313. }
  314. };
  315. void AddSC_boss_ragnaros()
  316. {
  317. new boss_ragnaros();
  318. new npc_son_of_flame();
  319. }