Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_ionar.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/*
7 * Comment: Timer check pending
8 */
9
10#include "ScriptMgr.h"
11#include "ScriptedCreature.h"
12#include "halls_of_lightning.h"
13#include "SpellInfo.h"
14
30
32{
37};
38
40{
42};
43
49
50/*######
51## Boss Ionar
52######*/
53
55{
56public:
57 boss_ionar() : CreatureScript("boss_ionar") { }
58
60 {
61 return new boss_ionarAI(creature);
62 }
63
64 struct boss_ionarAI : public ScriptedAI
65 {
66 boss_ionarAI(Creature* creature) : ScriptedAI(creature), lSparkList(creature)
67 {
68 instance = creature->GetInstanceScript();
69 }
70
72
74
77
79
82
84
86 {
87 lSparkList.DespawnAll();
88
89 bIsSplitPhase = true;
90 bHasDispersed = false;
91
93
94 uiStaticOverloadTimer = std::rand() % (6 * IN_MILLISECONDS) + (5*IN_MILLISECONDS);
95 uiBallLightningTimer = std::rand() % (11 * IN_MILLISECONDS) + (10*IN_MILLISECONDS);
96
97 uiDisperseHealth = 45 + (std::rand() % 10);
98
100
101 if (!me->IsVisible())
102 me->SetVisible(true);
103
104 if (instance)
105 instance->SetBossState(DATA_IONAR, NOT_STARTED);
106 }
107
108 void EnterCombat(Unit* /*who*/) OVERRIDE
109 {
111
112 if (instance)
113 instance->SetBossState(DATA_IONAR, IN_PROGRESS);
114 }
115
116 void JustDied(Unit* /*killer*/) OVERRIDE
117 {
119
120 lSparkList.DespawnAll();
121
122 if (instance)
123 instance->SetBossState(DATA_IONAR, DONE);
124 }
125
126 void KilledUnit(Unit* /*victim*/) OVERRIDE
127 {
128 Talk(SAY_SLAY);
129 }
130
131 void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
132 {
133 if (spell->Id == SPELL_DISPERSE)
134 {
135 for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i)
136 me->CastSpell(me, SPELL_SUMMON_SPARK, true);
137
138 me->AttackStop();
139 me->SetVisible(false);
141
142 me->GetMotionMaster()->Clear();
143 me->GetMotionMaster()->MoveIdle();
144 }
145 }
146
147 //make sparks come back
149 {
150 //should never be empty here, but check
151 if (lSparkList.empty())
152 return;
153
154 Position pos;
155 me->GetPosition(&pos);
156
157 for (std::list<uint64>::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr)
158 {
159 if (Creature* pSpark = Unit::GetCreature(*me, *itr))
160 {
161 if (pSpark->IsAlive())
162 {
163 pSpark->SetSpeed(MOVE_RUN, 2.0f);
164 pSpark->GetMotionMaster()->Clear();
165 pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos);
166 }
167 else
168 pSpark->DespawnOrUnsummon();
169 }
170 }
171 }
172
173 void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) OVERRIDE
174 {
175 if (!me->IsVisible())
176 uiDamage = 0;
177 }
178
180 {
181 if (summoned->GetEntry() == NPC_SPARK_OF_IONAR)
182 {
183 lSparkList.Summon(summoned);
184
185 summoned->CastSpell(summoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER, H_SPELL_SPARK_VISUAL_TRIGGER), true);
186
187 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
188 {
189 summoned->SetInCombatWith(target);
190 summoned->GetMotionMaster()->Clear();
191 summoned->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
192 }
193 }
194 }
195
197 {
198 if (summoned->GetEntry() == NPC_SPARK_OF_IONAR)
199 lSparkList.Despawn(summoned);
200 }
201
203 {
204 //Return since we have no target
205 if (!UpdateVictim())
206 return;
207
208 // Splitted
209 if (!me->IsVisible())
210 {
211 if (uiSplitTimer <= uiDiff)
212 {
213 uiSplitTimer = 2500;
214
215 // Return sparks to where Ionar splitted
216 if (bIsSplitPhase)
217 {
219 bIsSplitPhase = false;
220 }
221 // Lightning effect and restore Ionar
222 else if (lSparkList.empty())
223 {
224 me->SetVisible(true);
226
228
230 bIsSplitPhase = true;
231
232 if (me->GetVictim())
233 me->GetMotionMaster()->MoveChase(me->GetVictim());
234 }
235 }
236 else
237 uiSplitTimer -= uiDiff;
238
239 return;
240 }
241
242 if (uiStaticOverloadTimer <= uiDiff)
243 {
244 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
246
247 uiStaticOverloadTimer = std::rand() % (6 * IN_MILLISECONDS) + (5*IN_MILLISECONDS);
248 }
249 else
250 uiStaticOverloadTimer -= uiDiff;
251
252 if (uiBallLightningTimer <= uiDiff)
253 {
255 uiBallLightningTimer = std::rand() % (11 * IN_MILLISECONDS) + (10*IN_MILLISECONDS);
256 }
257 else
258 uiBallLightningTimer -= uiDiff;
259
260 // Health check
262 {
263 bHasDispersed = true;
264
266
267 if (me->IsNonMeleeSpellCasted(false))
268 me->InterruptNonMeleeSpells(false);
269
270 DoCast(me, SPELL_DISPERSE, false);
271 }
272
274 }
275 };
276};
277
278/*######
279## npc_spark_of_ionar
280######*/
281
283{
284public:
285 npc_spark_of_ionar() : CreatureScript("npc_spark_of_ionar") { }
286
288 {
289 return new npc_spark_of_ionarAI(creature);
290 }
291
293 {
295 {
296 instance = creature->GetInstanceScript();
297 }
298
300
302
304 {
306 me->SetReactState(REACT_PASSIVE);
307 }
308
309 void MovementInform(uint32 uiType, uint32 uiPointId) OVERRIDE
310 {
311 if (uiType != POINT_MOTION_TYPE || !instance)
312 return;
313
314 if (uiPointId == DATA_POINT_CALLBACK)
315 me->DespawnOrUnsummon();
316 }
317
318 void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) OVERRIDE
319 {
320 uiDamage = 0;
321 }
322
324 {
325 // Despawn if the encounter is not running
326 if (instance && instance->GetBossState(DATA_IONAR) != IN_PROGRESS)
327 {
328 me->DespawnOrUnsummon();
329 return;
330 }
331
332 // Prevent them to follow players through the whole instance
333 if (uiCheckTimer <= uiDiff)
334 {
335 if (instance)
336 {
337 Creature* pIonar = instance->instance->GetCreature(instance->GetData64(DATA_IONAR));
338 if (pIonar && pIonar->IsAlive())
339 {
340 if (me->GetDistance(pIonar) > 90.0f)
341 {
342 Position pos;
343 pIonar->GetPosition(&pos);
344
345 me->SetSpeed(MOVE_RUN, 2.0f);
346 me->GetMotionMaster()->Clear();
347 me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos);
348 }
349 }
350 else
351 me->DespawnOrUnsummon();
352 }
354 }
355 else
356 uiCheckTimer -= uiDiff;
357
358 // No melee attack at all!
359 }
360 };
361};
362
364{
365 new boss_ionar();
366 new npc_spark_of_ionar();
367}
@ IN_MILLISECONDS
Definition Common.h:125
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
@ POINT_MOTION_TYPE
@ MOVE_RUN
Definition Unit.h:556
@ REACT_PASSIVE
Definition Unit.h:1156
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_DISABLE_MOVE
Definition Unit.h:627
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
Creatures
@ SAY_SLAY
#define SAY_DEATH
#define SAY_AGGRO
@ SAY_SPLIT
@ NPC_SPARK_OF_IONAR
@ DATA_MAX_SPARKS
@ DATA_POINT_CALLBACK
@ SAY_DEATH
@ SAY_AGGRO
@ SAY_SPLIT
@ SAY_SLAY
@ SPELL_SUMMON_SPARK
@ H_SPELL_BALL_LIGHTNING
@ SPELL_BALL_LIGHTNING
@ SPELL_SPARK_DESPAWN
@ H_SPELL_SPARK_VISUAL_TRIGGER
@ H_SPELL_STATIC_OVERLOAD
@ SPELL_STATIC_OVERLOAD
@ SPELL_DISPERSE
@ SPELL_SPARK_VISUAL_TRIGGER
void AddSC_boss_ionar()
@ SPELL_BALL_LIGHTNING
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
bool IsAlive() const
Definition Unit.h:2032
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ DATA_IONAR
void GetPosition(float &x, float &y) const
Definition Object.h:333
Creature * me
bool HealthBelowPct(uint32 pct) const
ScriptedAI(Creature *creature)
const T & DUNGEON_MODE(const T &normal5, const T &heroic5) const
void JustSummoned(Creature *summoned) OVERRIDE
void SummonedCreatureDespawn(Creature *summoned) OVERRIDE
void KilledUnit(Unit *) OVERRIDE
void SpellHit(Unit *, const SpellInfo *spell) OVERRIDE
void JustDied(Unit *) OVERRIDE
InstanceScript * instance
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *, uint32 &uiDamage) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void Reset() OVERRIDE
boss_ionarAI(Creature *creature)
void MovementInform(uint32 uiType, uint32 uiPointId) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *, uint32 &uiDamage) OVERRIDE