TrinityCore
Loading...
Searching...
No Matches
boss_alar.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Everything related to Flame Quills requires sniff verification
20 * When moving to triggers, A'lar shouldn't move to exact trigger's position (positions in sniffs are always different)
21 * Combat timers requires to be revisited
22 * If summoned not on platform, embers should be summoned on the floor, not fall on the floor
23 * SPELL_ASHTONGUE_RUSE_MASTER doesn't appear in sniffs despite it's an aura. Maybe it was a wrong decision to use it
24 */
25
26#include "ScriptMgr.h"
27#include "InstanceScript.h"
28#include "MotionMaster.h"
29#include "ScriptedCreature.h"
30#include "SpellAuraEffects.h"
31#include "SpellInfo.h"
32#include "SpellScript.h"
33#include "the_eye.h"
34
36{
37 // Phase 1
40
41 // Phase 1 & 2
43
44 // Transition
49
50 // Phase 2
53 SPELL_CHARGE = 35412,
55
56 // Phase 2: Dive Bomb
61
62 // Ember of Al'ar
65
66 // Flame Patch
68
69 // Ruse of the Ashtongue
73};
74
106
114
119
121{
122 MODEL_INVISIBLE = 14501
124
125static constexpr std::array<std::string_view, 4> AlarPlatformTrigger =
126{
127 "AlarPlatformTrigger1",
128 "AlarPlatformTrigger2",
129 "AlarPlatformTrigger3",
130 "AlarPlatformTrigger4"
131};
132
133static constexpr std::string_view CenterTriggerStringId = "AlarCenterTrigger";
134
135static constexpr std::array<uint32, 24> FlameQuillsSpells =
136{
137 34269,
138 34270,
139 34271,
140 34272,
141 34273,
142 34274,
143 34275,
144 34276,
145 34277,
146 34278,
147 34279,
148 34280,
149 34281,
150 34282,
151 34283,
152 34284,
153 34285,
154 34286,
155 34287,
156 34288,
157 34289,
158 34314,
159 34315,
160 34316
161};
162
163Position const AlarRessurrectionPosition = { 333.589f, -0.768249f, -2.38949f };
164
165// 19514 - Al'ar
166struct boss_alar : public BossAI
167{
168 boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR),
170
171 void JustAppeared() override
172 {
173 me->SetDisableGravity(true);
174 }
175
185
186 void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
187 {
188 if (damage >= me->GetHealth() && _isFirstPhase)
189 {
190 damage = me->GetHealth() - 1;
191
192 if (_isInTransition)
193 return;
194
195 _isInTransition = true;
196
197 events.Reset();
199 }
200 }
201
202 void MovementInform(uint32 type, uint32 id) override
203 {
204 if (type == POINT_MOTION_TYPE)
205 {
206 switch (id)
207 {
208 case POINT_PLATFORM:
211 me->SetDisableGravity(false);
212 me->SetHover(false);
214 break;
215 case POINT_CENTER:
217 break;
218 case POINT_DIVE_BOMB:
220 break;
221 default:
222 break;
223 }
224 }
225 }
226
227 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
228 {
229 if (spellInfo->Id == SPELL_DIVE_BOMB_VISUAL)
231 }
232
233 void OnSpellCast(SpellInfo const* spell) override
234 {
236 if (spell->Id == SPELL_REBIRTH)
237 me->SetFullHealth();
238 }
239
240 void DoAction(int32 action) override
241 {
242 if (action == ACTION_FLAME_QUILLS_END)
243 {
246 }
247 }
248
250 {
251 if (Creature* trigger = me->FindNearestCreatureWithOptions(250.0f, { .StringId = AlarPlatformTrigger[_currentPlatform] }))
252 me->GetMotionMaster()->MovePoint(POINT_PLATFORM, trigger->GetPositionX(), trigger->GetPositionY(), trigger->GetPositionZ(), false);
253 }
254
256 {
257 if (Creature* trigger = me->FindNearestCreatureWithOptions(250.0f, { .StringId = CenterTriggerStringId }))
258 me->GetMotionMaster()->MovePoint(POINT_CENTER, trigger->GetPositionX(), trigger->GetPositionY(), trigger->GetPositionZ());
259 }
260
261 void EnterEvadeMode(EvadeReason /*why*/) override
262 {
265 }
266
277
278 void UpdateAI(uint32 diff) override
279 {
280 if (!UpdateVictim())
281 return;
282
283 events.Update(diff);
284
286 return;
287
288 while (uint32 eventId = events.ExecuteEvent())
289 {
290 switch (eventId)
291 {
292 // Phase 1
294 {
295 // Verified: A'lar can stay on the same platform (even twice in a row), will summon ember in this case
296 // Verified: After Flame Quills A'lar can move to the old platform
297 // Verified: After Flame Quills A'lar can move to the next platform
298 // Not verified: Can he perform more than one Flame Quills in a row? Currently he can
299
300 // Cancel Flame Buffet so it will be not used during moving
302
303 // If encounter just started, only move to the first platform
305 {
307
308 _isFirstPlatform = false;
309
310 // We are leaving a small chance to stay on the first platform
311 if (roll_chance_i(80))
313 }
314 else
315 {
317 me->SetDisableGravity(true);
318 me->SetHover(true);
320
321 // Else, move either to platform or to center
322 if (roll_chance_i(80))
323 {
325
326 if (_currentPlatform == 3)
327 {
328 // If we are on the last platform, we are leaving a small chance to stay on it
329 if (roll_chance_i(80))
331 }
332 else
333 {
334 // If we are not on the last platform, we leave a small chance to stay on current
335 if (roll_chance_i(80))
337 }
338
339 // If we are moving to the next platform or stay on the same, summon ember
340 _shouldSpawnEmber = true;
341 }
342 else
343 {
345
346 // If we are moving to the center, do not summon ember
347 _shouldSpawnEmber = false;
348 }
349 }
350
353
354 events.Repeat(30s, 40s);
355 break;
356 }
359 break;
360
361 // Phase 1 & 2
365 events.Repeat(2400ms);
366 break;
367
368 // Transition
383 me->SetVisible(false);
385 break;
387 me->SetDisableGravity(true);
388 me->SetHover(true);
392 break;
394 me->SetDisableGravity(false);
395 me->SetHover(false);
397 me->SetVisible(true);
400 break;
405 break;
411
412 _isFirstPhase = false;
413
420 break;
421
422 // Phase 2
423 case EVENT_FLAME_RING:
426 events.Repeat(30s, 45s);
427 break;
428 case EVENT_MELT_ARMOR:
430 events.Repeat(60s);
431 break;
434 DoCast(target, SPELL_CHARGE);
435 events.Repeat(30s, 35s);
436 break;
437 case EVENT_BERSERK:
439 break;
440
441 // Phase 2: Dive Bomb
444
447
448 me->SetDisableGravity(true);
449 me->SetHover(true);
450
451 if (Creature* trigger = me->FindNearestCreatureWithOptions(250.0f, { .StringId = CenterTriggerStringId }))
452 me->GetMotionMaster()->MovePoint(POINT_DIVE_BOMB, trigger->GetPositionX(), trigger->GetPositionY(), trigger->GetPositionZ());
453
454 events.Repeat(40s, 45s);
455 break;
458 break;
463 break;
467 {
468 me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation());
469 DoCast(target, SPELL_DIVE_BOMB);
470 }
472 break;
476 break;
481 break;
483 me->SetDisableGravity(false);
484 me->SetHover(false);
488 break;
489 default:
490 break;
491 }
492
494 return;
495 }
496
498 }
499
500private:
506};
507
508// 19551 - Ember of Al'ar
510{
511 npc_ember_of_alar(Creature* creature) : ScriptedAI(creature) { }
512
513 void InitializeAI() override
514 {
515 me->SetCorpseDelay(5, true);
517 }
518
519 void JustAppeared() override
520 {
521 _scheduler.Schedule(2s, [this](TaskContext /*task*/)
522 {
525 });
526 }
527
528 void JustDied(Unit* /*killer*/) override
529 {
533 }
534
535 void UpdateAI(uint32 diff) override
536 {
537 _scheduler.Update(diff);
538
539 if (UpdateVictim())
541 }
542
543private:
545};
546
547// 20602 - Flame Patch (Al'ar)
549{
550 npc_flame_patch_alar(Creature* creature) : ScriptedAI(creature) { }
551
552 void InitializeAI() override
553 {
555 }
556
557 void JustAppeared() override
558 {
560 }
561};
562
563// 34229 - Flame Quills
565{
567
568 bool Validate(SpellInfo const* /*spellInfo*/) override
569 {
571 }
572
573 bool Load() override
574 {
576 }
577
578 void PeriodicTick(AuraEffect const* aurEff)
579 {
580 for (uint32 spell : FlameQuillsSpells)
581 GetTarget()->CastSpell(nullptr, spell, aurEff);
582 }
583
584 void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
585 {
586 if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
587 return;
588
589 if (Creature* target = GetTarget()->ToCreature())
590 target->AI()->DoAction(ACTION_FLAME_QUILLS_END);
591 }
592
598};
599
600// 39555 - Ashtongue Ruse Master
622
TC_GAME_API bool InstanceHasScript(WorldObject const *obj, char const *scriptName)
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
@ POINT_MOTION_TYPE
bool roll_chance_i(int chance)
Definition Random.h:59
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
@ EFFECT_0
@ AURA_REMOVE_BY_EXPIRE
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:41
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_FLAG_UNINTERACTIBLE
@ UNIT_STATE_ROOT
Definition Unit.h:230
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
void AddSC_boss_alar()
AlarSpells
Definition boss_alar.cpp:36
@ SPELL_CLEAR_ALL_DEBUFFS
Definition boss_alar.cpp:45
@ SPELL_EMBER_BLAST_INVIS
Definition boss_alar.cpp:46
@ SPELL_SUMMON_PHOENIX_ADDS_2
Definition boss_alar.cpp:60
@ SPELL_ASHTONGUE_RUSE_CREDIT
Definition boss_alar.cpp:72
@ SPELL_DIVE_BOMB
Definition boss_alar.cpp:58
@ SPELL_CHARGE
Definition boss_alar.cpp:53
@ SPELL_ASHTONGUE_RUSE_DUMMY
Definition boss_alar.cpp:70
@ SPELL_REBIRTH
Definition boss_alar.cpp:48
@ SPELL_EMBER_BLAST_DAMAGE
Definition boss_alar.cpp:64
@ SPELL_FLAME_PATCH_PERIODIC
Definition boss_alar.cpp:67
@ SPELL_FLIGHT_MODE
Definition boss_alar.cpp:47
@ SPELL_SUMMON_FLAME_RING
Definition boss_alar.cpp:51
@ SPELL_FLAME_QUILLS
Definition boss_alar.cpp:39
@ SPELL_SUMMON_PHOENIX_ADDS_1
Definition boss_alar.cpp:38
@ SPELL_REBIRTH_2
Definition boss_alar.cpp:59
@ SPELL_BERSERK
Definition boss_alar.cpp:54
@ SPELL_DIVE_BOMB_VISUAL
Definition boss_alar.cpp:57
@ SPELL_MELT_ARMOR
Definition boss_alar.cpp:52
@ SPELL_ASHTONGUE_RUSE_MASTER
Definition boss_alar.cpp:71
@ SPELL_FLAME_BUFFET
Definition boss_alar.cpp:42
@ SPELL_EMBER_BLAST
Definition boss_alar.cpp:63
AlarMisc
@ MODEL_INVISIBLE
AlarPoints
@ POINT_CENTER
@ POINT_PLATFORM
@ POINT_DIVE_BOMB
@ POINT_RESSURRECTION
static constexpr std::array< uint32, 24 > FlameQuillsSpells
Position const AlarRessurrectionPosition
static constexpr std::array< std::string_view, 4 > AlarPlatformTrigger
AlarEvents
Definition boss_alar.cpp:76
@ EVENT_FLAME_QUILLS
Definition boss_alar.cpp:79
@ EVENT_TRANSITION_4
Definition boss_alar.cpp:88
@ EVENT_TRANSITION_5
Definition boss_alar.cpp:89
@ EVENT_DIVE_BOMB_1
Definition boss_alar.cpp:98
@ EVENT_MOVE_TO_PLATFORM
Definition boss_alar.cpp:78
@ EVENT_DIVE_BOMB_7
@ EVENT_TRANSITION_1
Definition boss_alar.cpp:85
@ EVENT_DIVE_BOMB_4
@ EVENT_DIVE_BOMB_2
Definition boss_alar.cpp:99
@ EVENT_FLAME_RING
Definition boss_alar.cpp:92
@ EVENT_DIVE_BOMB_6
@ EVENT_BERSERK
Definition boss_alar.cpp:95
@ EVENT_DIVE_BOMB_3
@ EVENT_TRANSITION_2
Definition boss_alar.cpp:86
@ EVENT_MELT_ARMOR
Definition boss_alar.cpp:93
@ EVENT_DIVE_BOMB_5
@ EVENT_FLAME_BUFFET
Definition boss_alar.cpp:82
@ EVENT_CHARGE_ALAR
Definition boss_alar.cpp:94
@ EVENT_TRANSITION_3
Definition boss_alar.cpp:87
static constexpr std::string_view CenterTriggerStringId
AlarActions
@ ACTION_FLAME_QUILLS_END
AuraApplication const * GetTargetApplication() const
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
Unit * GetTarget() const
Unit * GetUnitOwner() const
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetDisplayId(uint32 modelId) override
void SetReactState(ReactStates st)
Definition Creature.h:119
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:89
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:52
void CancelEvent(EventId eventId)
Definition EventMap.cpp:151
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
uint32 Id
Definition SpellInfo.h:289
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:844
void SetVisible(bool x)
Definition Unit.cpp:8513
void SetFullHealth()
Definition Unit.h:927
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11256
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13503
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
uint32 GetNativeDisplayId() const
Definition Unit.h:1584
uint32 GetHealth() const
Definition Unit.h:913
void NearTeleportTo(Position const &pos, bool casting=false)
Definition Unit.cpp:12832
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
Unit * GetVictim() const
Definition Unit.h:859
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
void RemoveAllAuras()
Definition Unit.cpp:4157
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
Creature * FindNearestCreatureWithOptions(float range, FindCreatureOptions const &options) const
Definition Object.cpp:2108
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_alar_ashtongue_ruse_master)
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
PrepareAuraScript(spell_alar_flame_quills)
bool Load() override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
void PeriodicTick(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
void Register() override
void ResetThreatList(Unit *who=nullptr)
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
bool _isFirstPhase
void JustDied(Unit *) override
uint8 _currentPlatform
boss_alar(Creature *creature)
void OnSpellCast(SpellInfo const *spell) override
bool _isInTransition
void JustAppeared() override
void MovementInform(uint32 type, uint32 id) override
bool _isFirstPlatform
void UpdateAI(uint32 diff) override
void DoMoveToPlatform()
void DoAction(int32 action) override
void EnterEvadeMode(EvadeReason) override
bool _shouldSpawnEmber
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void JustEngagedWith(Unit *who) override
void DoMoveToCenter()
void UpdateAI(uint32 diff) override
TaskScheduler _scheduler
void InitializeAI() override
void JustAppeared() override
void JustDied(Unit *) override
npc_ember_of_alar(Creature *creature)
npc_flame_patch_alar(Creature *creature)
void JustAppeared() override
void InitializeAI() override
#define TheEyeScriptName
Definition the_eye.h:23
#define RegisterTheEyeCreatureAI(ai_name)
Definition the_eye.h:74
@ DATA_ALAR
Definition the_eye.h:31