Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_alar.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/* ScriptData
6SDName: boss_alar
7SD%Complete: 95
8SDComment:
9SDCategory: Tempest Keep, The Eye
10EndScriptData */
11
12#include "ScriptMgr.h"
13#include "ScriptedCreature.h"
14#include "the_eye.h"
15#include "SpellInfo.h"
16
18{
19 SPELL_FLAME_BUFFET = 34121, // Flame Buffet - every 1, 5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions
20 SPELL_FLAME_QUILLS = 34229, // Randomly after changing position in phase after watching tons of movies, set probability 20%
21 SPELL_REBIRTH = 34342, // Rebirth - beginning of second phase(after losing all health in phase 1)
22 SPELL_REBIRTH_2 = 35369, // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2
23 SPELL_MELT_ARMOR = 35410, // Melt Armor - every 60 sec in phase 2
24 SPELL_CHARGE = 35412, // Charge - 30 sec cooldown
25 SPELL_DIVE_BOMB_VISUAL = 35367, // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec
26 SPELL_DIVE_BOMB = 35181, // after watching tonns of movies, set cooldown to 40+rand()%5.
27 SPELL_BERSERK = 45078, // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown)
28
29 CREATURE_EMBER_OF_ALAR = 19551, // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loses 3% health.
30 SPELL_EMBER_BLAST = 34133, // When Ember of Al'ar dies, it casts Ember Blast
31
32 CREATURE_FLAME_PATCH_ALAR = 20602, // Flame Patch - every 30 sec in phase 2
34};
35
36static float waypoint[6][3] =
37{
38 {340.15f, 58.65f, 17.71f},
39 {388.09f, 31.54f, 20.18f},
40 {388.18f, -32.85f, 20.18f},
41 {340.29f, -60.19f, 17.72f},
42 {332.0f, 0.01f, 39.0f}, // better not use the same xy coord
43 {331.0f, 0.01f, -2.39f}
44};
45
60
62{
63public:
64 boss_alar() : CreatureScript("boss_alar") { }
65
66 struct boss_alarAI : public ScriptedAI
67 {
68 boss_alarAI(Creature* creature) : ScriptedAI(creature)
69 {
70 instance = creature->GetInstanceScript();
72
74 WaitTimer = 0;
78 Charge_Timer = 0;
80 Berserk_Timer = 0;
81
82 AfterMoving = false;
83 Phase1 = false;
84 ForceMove = false;
85 ForceTimer = 0;
86 cur_wp = 0;
87 }
88
90 {
91 if (instance)
93
94 Berserk_Timer = 1200000;
96
97 Phase1 = true;
99 WaitTimer = 0;
100 AfterMoving = false;
101 ForceMove = false;
102 ForceTimer = 5000;
103
104 cur_wp = 4;
105
106 me->SetDisplayId(me->GetNativeDisplayId());
107 me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
108 //me->SetFloatValue(UNIT_FIELD_BOUNDING_RADIUS, 10);
109 //me->SetFloatValue(UNIT_FIELD_COMBAT_REACH, 10);
110 me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
111 me->SetDisableGravity(true);
113 me->setActive(false);
114 }
115
116 void EnterCombat(Unit* /*who*/) OVERRIDE
117 {
118 if (instance)
120
121 me->SetDisableGravity(true); // after enterevademode will be set walk movement
123 me->setActive(true);
124 }
125
126 void JustDied(Unit* /*killer*/) OVERRIDE
127 {
128 if (instance)
129 instance->SetData(DATA_ALAREVENT, DONE);
130 }
131
133 {
134 if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR)
135 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
136 summon->AI()->AttackStart(target);
137 }
138
139 void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { }
140
142 {
143 if (Phase1)
145 else
147 }
148
149 void DamageTaken(Unit* /*killer*/, uint32 &damage) OVERRIDE
150 {
151 if (damage >= me->GetHealth() && Phase1)
152 {
153 damage = 0;
154 if (!WaitEvent)
155 {
157 WaitTimer = 0;
158 me->SetHealth(0);
159 me->InterruptNonMeleeSpells(true);
160 me->RemoveAllAuras();
162 me->AttackStop();
163 me->SetTarget(0);
164 me->SetSpeed(MOVE_RUN, 5.0f);
165 me->GetMotionMaster()->Clear();
166 me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]);
167 }
168 }
169 }
170
171 void SpellHit(Unit*, const SpellInfo* spell) OVERRIDE
172 {
173 if (spell->Id == SPELL_DIVE_BOMB_VISUAL)
174 {
175 me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
176 me->SetDisplayId(11686);
177 //me->SendUpdateObjectToAllExcept(NULL);
178 }
179 }
180
182 {
183 if (type == POINT_MOTION_TYPE)
184 {
185 WaitTimer = 1;
186 AfterMoving = true;
187 ForceMove = false;
188 }
189 }
190
192 {
193 if (!me->IsInCombat()) // sometimes IsInCombat but !incombat, faction bug?
194 return;
195
196 if (Berserk_Timer <= diff)
197 {
198 DoCast(me, SPELL_BERSERK, true);
199 Berserk_Timer = 60000;
200 }
201 else
202 Berserk_Timer -= diff;
203
204 if (ForceMove)
205 {
206 if (ForceTimer <= diff)
207 {
208 me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]);
209 ForceTimer = 5000;
210 }
211 else
212 ForceTimer -= diff;
213 }
214 if (WaitEvent)
215 {
216 if (WaitTimer)
217 {
218 if (WaitTimer <= diff)
219 {
220 if (AfterMoving)
221 {
222 me->GetMotionMaster()->MoveIdle();
223 AfterMoving = false;
224 }
225
226 switch (WaitEvent)
227 {
228 case WE_PLATFORM:
229 {
230 Platforms_Move_Timer = 30000 + rand() % 5000;
231 break;
232 }
233 case WE_QUILL:
234 {
237 WaitTimer = 10000;
239 return;
240 }
241 case WE_DIE:
242 {
243 ForceMove = false;
245 WaitTimer = 5000;
247 return;
248 }
249 case WE_REVIVE:
250 {
252 me->SetFullHealth();
253 me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
256 DoCast(me, SPELL_REBIRTH, true);
257 MeltArmor_Timer = 60000;
258 Charge_Timer = 7000;
259 DiveBomb_Timer = 40000 + rand() % 5000;
260 FlamePatch_Timer = 30000;
261 Phase1 = false;
262 break;
263 }
264 case WE_METEOR:
265 {
266 me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false);
269 WaitTimer = 4000;
270 return;
271 }
272 case WE_DIVE:
273 {
274 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
275 {
276 me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
277 DoCast(target, SPELL_DIVE_BOMB, true);
278 float dist = 3.0f;
279 if (me->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f))
280 dist = 5.0f;
281 WaitTimer = 1000 + uint32(floor(dist / 80 * 1000.0f));
282 me->SetPosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f);
283 me->StopMoving();
285 break;
286 }
287 else
288 {
290 return;
291 }
292 }
293 case WE_LAND:
294 {
296 WaitTimer = 2000;
297 return;
298 }
299 case WE_SUMMON:
300 {
301 for (uint8 i = 0; i < 2; ++i)
302 {
304 }
305 me->SetFloatValue(UNIT_FIELD_BOUNDING_RADIUS, 10);
307 me->SetDisplayId(me->GetNativeDisplayId());
308 DoCast(me, SPELL_REBIRTH_2, true);
309 break;
310 }
311 case WE_DUMMY:
312 default:
313 break;
314 }
315
317 WaitTimer = 0;
318 }
319 else
320 WaitTimer -= diff;
321 }
322 return;
323 }
324
325 if (Phase1)
326 {
327 if (me->getThreatManager().getThreatList().empty())
328 {
330 return;
331 }
332
333 if (Platforms_Move_Timer <= diff)
334 {
335 if (cur_wp == 4)
336 {
337 cur_wp = 0;
339 }
340 else
341 {
342 if (std::rand() % 4) // next platform
343 {
345 if (cur_wp == 3)
346 cur_wp = 0;
347 else
348 ++cur_wp;
350 }
351 else // flame quill
352 {
353 cur_wp = 4;
355 }
356 }
357 ForceMove = true;
358 ForceTimer = 5000;
359 me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]);
360 WaitTimer = 0;
361 return;
362 }
363 else
364 Platforms_Move_Timer -= diff;
365 }
366 else
367 {
368 if (Charge_Timer <= diff)
369 {
370 Unit* target= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true);
371 if (target)
372 DoCast(target, SPELL_CHARGE);
373 Charge_Timer = 30000;
374 }
375 else
376 Charge_Timer -= diff;
377
378 if (MeltArmor_Timer <= diff)
379 {
381 MeltArmor_Timer = 60000;
382 }
383 else
384 MeltArmor_Timer -= diff;
385
386 if (DiveBomb_Timer <= diff)
387 {
388 me->AttackStop();
389 me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]);
391 me->SetFloatValue(UNIT_FIELD_BOUNDING_RADIUS, 50);
393 WaitTimer = 0;
394 DiveBomb_Timer = 40000+rand()%5000;
395 return;
396 }
397 else
398 DiveBomb_Timer -= diff;
399
400 if (FlamePatch_Timer <= diff)
401 {
402 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
403 {
404 Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 120000);
405 if (Summoned)
406 {
408 Summoned->SetObjectScale(Summoned->GetObjectScale() * 2.5f);
409 Summoned->SetDisplayId(11686);
410 Summoned->setFaction(me->getFaction());
411 Summoned->SetLevel(me->getLevel());
412 Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false);
413 }
414 }
415 FlamePatch_Timer = 30000;
416 }
417 else
418 FlamePatch_Timer -= diff;
419 }
420
422 }
423
425 {
426 if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false))
427 {
428 if (me->IsWithinMeleeRange(me->GetVictim()))
429 {
430 me->AttackerStateUpdate(me->GetVictim());
431 me->resetAttackTimer();
432 }
433 else
434 {
435 Unit* target = NULL;
436 target = me->SelectNearestTargetInAttackDistance(5);
437 if (target)
438 me->AI()->AttackStart(target);
439 else
440 {
442 me->setAttackTimer(WeaponAttackType::BASE_ATTACK, 1500);
443 }
444 }
445 }
446 }
447
449
452
454
461
463
464 bool Phase1;
467
469 };
470
472 {
473 return new boss_alarAI(creature);
474 }
475};
476
478{
479 public:
480 npc_ember_of_alar() : CreatureScript("npc_ember_of_alar") { }
481
483 {
485 {
486 instance = creature->GetInstanceScript();
487 creature->SetDisableGravity(true);
489 toDie = false;
490 }
491
493 {
494 toDie = false;
495 }
496
497 void EnterCombat(Unit* /*who*/) OVERRIDE
498 {
500 }
501
503 {
504 me->setDeathState(DeathState::JUST_DIED);
505 }
506
507 void DamageTaken(Unit* killer, uint32 &damage) OVERRIDE
508 {
509 if (damage >= me->GetHealth() && killer != me && !toDie)
510 {
511 damage = 0;
513 me->SetDisplayId(11686);
515 if (instance && instance->GetData(DATA_ALAREVENT) == 2)
516 {
517 if (Unit* Alar = Unit::GetUnit(*me, instance->GetData64(DATA_ALAR)))
518 {
519 int32 AlarHealth = int32(Alar->GetHealth()) - int32(Alar->CountPctFromMaxHealth(3));
520 if (AlarHealth > 0)
521 Alar->SetHealth(AlarHealth);
522 else
523 Alar->SetHealth(1);
524 }
525 }
526 toDie = true;
527 }
528 }
529
530 void UpdateAI(uint32 /*diff*/) OVERRIDE
531 {
532 if (!UpdateVictim())
533 return;
534
535 if (toDie)
536 {
537 me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
538 //me->SetVisibility(VISIBILITY_OFF);
539 }
540
542 }
543
545 bool toDie;
546 };
547
549 {
550 return new npc_ember_of_alarAI(creature);
551 }
552};
553
555{
556 public:
557 npc_flame_patch_alar() : CreatureScript("npc_flame_patch_alar") { }
558
560 {
561 npc_flame_patch_alarAI(Creature* creature) : ScriptedAI(creature) { }
562 void Reset() OVERRIDE { }
563 void EnterCombat(Unit* /*who*/) OVERRIDE { }
564 void AttackStart(Unit* /*who*/) OVERRIDE { }
565 void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { }
566
567 void UpdateAI(uint32 /*diff*/) OVERRIDE { }
568 };
569
571 {
572 return new npc_flame_patch_alarAI(creature);
573 }
574};
575
577{
578 new boss_alar();
579 new npc_ember_of_alar();
581}
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
#define OVERRIDE
Definition Define.h:60
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ POINT_MOTION_TYPE
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition Object.h:71
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ IMMUNITY_SCHOOL
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_SCHOOL_MASK_FIRE
@ JUST_DIED
Definition Unit.h:504
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
@ MOVE_RUN
Definition Unit.h:556
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ DIRECT_DAMAGE
Definition Unit.h:614
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_BOUNDING_RADIUS
@ UNIT_FIELD_ANIM_TIER
@ UNIT_FIELD_FLAGS
@ SPELL_CHARGE
void AddSC_boss_alar()
@ SPELL_DIVE_BOMB
Definition boss_alar.cpp:26
@ SPELL_CHARGE
Definition boss_alar.cpp:24
@ SPELL_REBIRTH
Definition boss_alar.cpp:21
@ SPELL_FLAME_QUILLS
Definition boss_alar.cpp:20
@ SPELL_FLAME_PATCH
Definition boss_alar.cpp:33
@ CREATURE_FLAME_PATCH_ALAR
Definition boss_alar.cpp:32
@ SPELL_REBIRTH_2
Definition boss_alar.cpp:22
@ CREATURE_EMBER_OF_ALAR
Definition boss_alar.cpp:29
@ SPELL_BERSERK
Definition boss_alar.cpp:27
@ SPELL_DIVE_BOMB_VISUAL
Definition boss_alar.cpp:25
@ SPELL_MELT_ARMOR
Definition boss_alar.cpp:23
@ SPELL_FLAME_BUFFET
Definition boss_alar.cpp:19
@ SPELL_EMBER_BLAST
Definition boss_alar.cpp:30
WaitEventType
Definition boss_alar.cpp:47
@ WE_REVIVE
Definition boss_alar.cpp:53
@ WE_DUMMY
Definition boss_alar.cpp:49
@ WE_LAND
Definition boss_alar.cpp:57
@ WE_METEOR
Definition boss_alar.cpp:55
@ WE_DIVE
Definition boss_alar.cpp:56
@ WE_DIE
Definition boss_alar.cpp:52
@ WE_NONE
Definition boss_alar.cpp:48
@ WE_PLATFORM
Definition boss_alar.cpp:50
@ WE_SUMMON
Definition boss_alar.cpp:58
@ WE_QUILL
Definition boss_alar.cpp:51
@ WE_CHARGE
Definition boss_alar.cpp:54
static float waypoint[6][3]
Definition boss_alar.cpp:36
#define SPELL_BERSERK
@ SPELL_REBIRTH
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
bool UpdateVictim()
virtual void EnterEvadeMode()
void SetDisplayId(uint32 modelId) OVERRIDE
void SetObjectScale(float scale) OVERRIDE
CreatureScript(const char *name)
float GetObjectScale() const
Definition Object.h:128
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
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
void setFaction(uint32 faction)
Definition Unit.h:1699
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
float GetSpeedRate(UnitMoveType mtype) const
Definition Unit.h:2581
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition Unit.cpp:3580
bool SetDisableGravity(bool disable, bool packetOnly=false)
Definition Unit.cpp:9156
void SetLevel(uint8 lvl)
Definition Unit.cpp:5150
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
@ SPELL_FLAME_BUFFET
Creature * me
void AttackStartNoMove(Unit *target)
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, TempSummonType type, uint32 despawntime)
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void JustDied(Unit *) OVERRIDE
void MoveInLineOfSight(Unit *) OVERRIDE
void JustSummoned(Creature *summon) OVERRIDE
boss_alarAI(Creature *creature)
Definition boss_alar.cpp:68
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void AttackStart(Unit *who) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void MovementInform(uint32 type, uint32) OVERRIDE
void Reset() OVERRIDE
Definition boss_alar.cpp:89
void DamageTaken(Unit *, uint32 &damage) OVERRIDE
InstanceScript * instance
void SpellHit(Unit *, const SpellInfo *spell) OVERRIDE
WaitEventType WaitEvent
void DamageTaken(Unit *killer, uint32 &damage) OVERRIDE
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
@ DATA_ALAR
Definition the_eye.h:21
@ DATA_ALAREVENT
Definition the_eye.h:11