Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_volkhan.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* ScriptData
7SDName: Boss Volkhan
8SD%Complete: 90%
9SDComment: Event should be pretty close minus a few visual flaws
10SDCategory: Halls of Lightning
11EndScriptData */
12
13#include "ScriptMgr.h"
14#include "ScriptedCreature.h"
15#include "halls_of_lightning.h"
16#include "Player.h"
17#include "SpellInfo.h"
18
54
55/*######
56## Boss Volkhan
57######*/
59{
60public:
61 boss_volkhan() : CreatureScript("boss_volkhan") { }
62
64 {
65 return new boss_volkhanAI(creature);
66 }
67
68 struct boss_volkhanAI : public ScriptedAI
69 {
70 boss_volkhanAI(Creature* creature) : ScriptedAI(creature)
71 {
72 instance = creature->GetInstanceScript();
73 }
74
76
77 std::list<uint64> m_lGolemGUIDList;
78
82
89
91
93 {
94 m_bIsStriking = false;
95 m_bHasTemper = false;
96 m_bCanShatterGolem = false;
97
98 m_uiPause_Timer = 3500;
100 m_uiShatter_Timer = 5000;
101 m_uiDelay_Timer = 1000;
102 m_uiSummonPhase = 0;
103 GolemsShattered = 0;
104
106
107 DespawnGolem();
108 m_lGolemGUIDList.clear();
109
110 if (instance)
111 instance->SetBossState(DATA_VOLKHAN, NOT_STARTED);
112 }
113
114 void EnterCombat(Unit* /*who*/) OVERRIDE
115 {
117
118 if (instance)
119 instance->SetBossState(DATA_VOLKHAN, IN_PROGRESS);
120 }
121
123 {
124 if (me->Attack(who, true))
125 {
126 me->AddThreat(who, 0.0f);
127 me->SetInCombatWith(who);
128 who->SetInCombatWith(me);
129
130 if (!m_bHasTemper)
131 me->GetMotionMaster()->MoveChase(who);
132 }
133 }
134
135 void JustDied(Unit* /*killer*/) OVERRIDE
136 {
138 DespawnGolem();
139
140 if (instance)
141 instance->SetBossState(DATA_VOLKHAN, DONE);
142 }
143
144 void KilledUnit(Unit* /*victim*/) OVERRIDE
145 {
146 Talk(SAY_SLAY);
147 }
148
150 {
151 if (m_lGolemGUIDList.empty())
152 return;
153
154 for (std::list<uint64>::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
155 {
156 if (Creature* temp = Unit::GetCreature(*me, *itr))
157 {
158 if (temp->IsAlive())
159 temp->DespawnOrUnsummon();
160 }
161 }
162
163 m_lGolemGUIDList.clear();
164 }
165
167 {
168 if (m_lGolemGUIDList.empty())
169 return;
170
171 for (std::list<uint64>::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr)
172 {
173 if (Creature* temp = Unit::GetCreature(*me, *itr))
174 {
175 // Only shatter brittle golems
176 if (temp->IsAlive() && temp->GetEntry() == NPC_BRITTLE_GOLEM)
177 {
178 temp->CastSpell(temp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false);
179 GolemsShattered += 1;
180 }
181 }
182 }
183 }
184
186 {
187 if (summoned->GetEntry() == NPC_MOLTEN_GOLEM)
188 {
189 m_lGolemGUIDList.push_back(summoned->GetGUID());
190
191 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
192 summoned->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
193
194 // Why healing when just summoned?
195 summoned->CastSpell(summoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID());
196 }
197 }
198
200 {
201 if (m_uiSummonPhase == 2)
202 {
203 me->SetOrientation(2.29f);
204 m_uiSummonPhase = 3;
205 }
206 }
207
209 {
210 if (data == DATA_SHATTER_RESISTANT)
211 return GolemsShattered;
212
213 return 0;
214 }
215
217 {
218 if (!UpdateVictim())
219 return;
220
221 if (m_bIsStriking)
222 {
223 if (m_uiPause_Timer <= uiDiff)
224 {
225 if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
226 if (me->GetVictim())
227 me->GetMotionMaster()->MoveChase(me->GetVictim());
228
229 m_bHasTemper = false;
230 m_bIsStriking = false;
231 m_uiPause_Timer = 3500;
232 }
233 else
234 m_uiPause_Timer -= uiDiff;
235
236 return;
237 }
238
239 // When to start shatter? After 60, 40 or 20% hp?
241 {
242 if (m_uiShatteringStomp_Timer <= uiDiff)
243 {
244 // Should he stomp even if he has no brittle golem to shatter?
246
248
250
252 m_bCanShatterGolem = true;
253 }
254 else
256 }
257
258 // Shatter Golems 3 seconds after Shattering Stomp
260 {
261 if (m_uiShatter_Timer <= uiDiff)
262 {
263 ShatterGolem();
264 m_uiShatter_Timer = 3000;
265 m_bCanShatterGolem = false;
266 }
267 else
268 m_uiShatter_Timer -= uiDiff;
269 }
270
271 // Health check
272 if (!m_bCanShatterGolem && me->HealthBelowPct(100 - 20 * m_uiHealthAmountModifier))
273 {
275
276 if (me->IsNonMeleeSpellCasted(false))
277 me->InterruptNonMeleeSpells(false);
278
280
281 m_bHasTemper = true;
282
283 m_uiSummonPhase = 1;
284 }
285
286 switch (m_uiSummonPhase)
287 {
288 case 1:
289 // 1 - Start run to Anvil
291 me->GetMotionMaster()->MoveTargetedHome();
292 m_uiSummonPhase = 2; // Set Next Phase
293 break;
294
295 case 2:
296 // 2 - Check if reached Anvil
297 // This is handled in: void JustReachedHome() OVERRIDE
298 break;
299
300 case 3:
301 // 3 - Cast Temper on the Anvil
302 if (Unit* target = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true))
303 {
304 me->SetOrientation(2.29f);
305 DoCast(target, SPELL_TEMPER, false);
306 DoCast(target, SPELL_TEMPER_DUMMY, false);
307 }
308 m_uiDelay_Timer = 1000; // Delay 2 seconds before next phase can begin
309 m_uiSummonPhase = 4; // Set Next Phase
310 break;
311
312 case 4:
313 // 4 - Wait for delay to expire
314 if (m_uiDelay_Timer <= uiDiff)
315 {
316 if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
317 {
318 me->SetReactState(REACT_AGGRESSIVE);
319 me->SetInCombatWith(target);
320 me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
321 }
322 m_uiSummonPhase = 5;
323 }
324 else
325 m_uiDelay_Timer -= uiDiff;
326 break;
327
328 case 5:
329 // 5 - Spawn the Golems
330 if (Creature* creatureTarget = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true))
331 for (uint8 i = 0; i < MAX_GOLEM; ++i)
332 me->CastSpell(creatureTarget, SPELL_SUMMON_MOLTEN_GOLEM, true);
333
334 m_bIsStriking = true;
335 m_uiSummonPhase = 0; // Reset back to Phase 0 for next time
336 break;
337 }
338
340 }
341 };
342};
343
344/*######
345## npc_molten_golem
346######*/
348{
349public:
350 npc_molten_golem() : CreatureScript("npc_molten_golem") { }
351
353 {
354 return new npc_molten_golemAI(creature);
355 }
356
358 {
359 npc_molten_golemAI(Creature* creature) : ScriptedAI(creature) { }
360
362
366
368 {
369 m_bIsFrozen = false;
370
371 m_uiBlast_Timer = 20000;
374 }
375
377 {
378 if (me->Attack(who, true))
379 {
380 me->AddThreat(who, 0.0f);
381 me->SetInCombatWith(who);
382 who->SetInCombatWith(me);
383
384 if (!m_bIsFrozen)
385 me->GetMotionMaster()->MoveChase(who);
386 }
387 }
388
389 void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) OVERRIDE
390 {
391 if (uiDamage > me->GetHealth())
392 {
393 me->UpdateEntry(NPC_BRITTLE_GOLEM);
394 me->SetHealth(1);
395 uiDamage = 0;
396 me->RemoveAllAuras();
397 me->AttackStop();
398 // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); //Set in DB
399 // me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //Set in DB
400 if (me->IsNonMeleeSpellCasted(false))
401 me->InterruptNonMeleeSpells(false);
402 if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
403 me->GetMotionMaster()->MovementExpired();
404 m_bIsFrozen = true;
405 }
406 }
407
408 void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell) OVERRIDE
409 {
410 // This is the dummy effect of the spells
411 if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H)
412 if (me->GetEntry() == NPC_BRITTLE_GOLEM)
413 me->DespawnOrUnsummon();
414 }
415
417 {
418 // Return since we have no target or if we are frozen
419 if (!UpdateVictim() || m_bIsFrozen)
420 return;
421
422 if (m_uiBlast_Timer <= uiDiff)
423 {
425 m_uiBlast_Timer = 20000;
426 }
427 else
428 m_uiBlast_Timer -= uiDiff;
429
430 if (m_uiImmolation_Timer <= uiDiff)
431 {
434 }
435 else
436 m_uiImmolation_Timer -= uiDiff;
437
439 }
440 };
441};
442
444{
445 public:
446 achievement_shatter_resistant() : AchievementCriteriaScript("achievement_shatter_resistant") { }
447
448 bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
449 {
450 return target && target->GetAI()->GetData(DATA_SHATTER_RESISTANT) < 5;
451 }
452};
453
455{
456 new boss_volkhan();
457 new npc_molten_golem();
459}
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ CHASE_MOTION_TYPE
Creature * GetClosestCreatureWithEntry(WorldObject *source, uint32 entry, float maxSearchRange, bool alive)
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ SELECT_TARGET_TOPAGGRO
Definition UnitAI.h:24
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
Enums
@ SAY_SLAY
#define SAY_DEATH
#define SAY_AGGRO
@ SAY_STOMP
@ EMOTE_SHATTER
@ SAY_DEATH
@ SPELL_SUMMON_MOLTEN_GOLEM
@ SPELL_TEMPER_DUMMY
@ NPC_MOLTEN_GOLEM
@ SAY_FORGE
@ SAY_AGGRO
@ MAX_GOLEM
@ SPELL_HEAT_H
@ SPELL_HEAT_N
@ DATA_SHATTER_RESISTANT
@ SPELL_BLAST_WAVE
@ SPELL_IMMOLATION_STRIKE_N
@ SPELL_SHATTERING_STOMP_H
@ SAY_STOMP
@ SAY_SLAY
@ NPC_BRITTLE_GOLEM
@ SPELL_SHATTERING_STOMP_N
@ SPELL_SHATTER_N
@ EMOTE_SHATTER
@ SPELL_SHATTER_H
@ EMOTE_TO_ANVIL
@ NPC_VOLKHAN_ANVIL
@ SPELL_TEMPER
@ SPELL_IMMOLATION_STRIKE_H
void AddSC_boss_volkhan()
AchievementCriteriaScript(const char *name)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ DATA_VOLKHAN
Creature * me
ScriptedAI(Creature *creature)
const T & DUNGEON_MODE(const T &normal5, const T &heroic5) const
std::list< uint64 > m_lGolemGUIDList
uint32 GetData(uint32 data) const OVERRIDE
void KilledUnit(Unit *) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void AttackStart(Unit *who) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void JustDied(Unit *) OVERRIDE
void JustSummoned(Creature *summoned) OVERRIDE
boss_volkhanAI(Creature *creature)
void DamageTaken(Unit *, uint32 &uiDamage) OVERRIDE
void AttackStart(Unit *who) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, const SpellInfo *pSpell) OVERRIDE