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
267 void JustDied(Unit* /*killer*/) override
268 {
270
271 _JustDied();
272
275 me->SetUninteractible(false);
276 }
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(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(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(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(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
378 me->SetUninteractible(true);
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;
407 me->SetUninteractible(false);
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;
460 me->SetUninteractible(true);
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);
486 me->SetUninteractible(false);
488 break;
489 default:
490 break;
491 }
492
494 return;
495 }
496 }
497
498private:
504};
505
506// 19551 - Ember of Al'ar
508{
509 npc_ember_of_alar(Creature* creature) : ScriptedAI(creature) { }
510
511 void InitializeAI() override
512 {
513 me->SetCorpseDelay(5, true);
515 }
516
517 void JustAppeared() override
518 {
519 _scheduler.Schedule(2s, [this](TaskContext const& /*task*/)
520 {
523 });
524 }
525
526 void JustDied(Unit* /*killer*/) override
527 {
531 }
532
533 void UpdateAI(uint32 diff) override
534 {
535 _scheduler.Update(diff);
536
537 UpdateVictim();
538 }
539
540private:
542};
543
544// 20602 - Flame Patch (Al'ar)
546{
547 npc_flame_patch_alar(Creature* creature) : ScriptedAI(creature) { }
548
549 void InitializeAI() override
550 {
552 }
553
554 void JustAppeared() override
555 {
557 }
558};
559
560// 34229 - Flame Quills
562{
563 bool Validate(SpellInfo const* /*spellInfo*/) override
564 {
566 }
567
568 bool Load() override
569 {
571 }
572
573 void PeriodicTick(AuraEffect const* aurEff)
574 {
575 for (uint32 spell : FlameQuillsSpells)
576 GetTarget()->CastSpell(nullptr, spell, aurEff);
577 }
578
579 void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
580 {
581 if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
582 return;
583
584 if (Creature* target = GetTarget()->ToCreature())
585 target->AI()->DoAction(ACTION_FLAME_QUILLS_END);
586 }
587
593};
594
595// 39555 - Ashtongue Ruse Master
597{
598 bool Validate(SpellInfo const* /*spellInfo*/) override
599 {
601 }
602
603 void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
604 {
605 Unit* target = GetTarget();
607 target->CastSpell(target, SPELL_ASHTONGUE_RUSE_CREDIT, true);
608 }
609
614};
615
TC_GAME_API bool InstanceHasScript(WorldObject const *obj, char const *scriptName)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ POINT_MOTION_TYPE
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
@ EFFECT_0
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ AURA_REMOVE_BY_EXPIRE
@ 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)
EvadeReason
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:49
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:42
DamageEffectType
@ UNIT_STATE_ROOT
Definition Unit.h:285
@ UNIT_STATE_CASTING
Definition Unit.h:290
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()
Definition CreatureAI.h:169
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetReactState(ReactStates st)
Definition Creature.h:180
void SetDisplayId(uint32 displayId, bool setNative=false) override
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:118
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:56
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={}, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
uint32 const Id
Definition SpellInfo.h:328
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & Update()
Update the scheduler to the current time.
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:722
void SetVisible(bool x)
Definition Unit.cpp:8787
void SetFullHealth()
Definition Unit.h:814
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10804
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11631
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13656
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
uint32 GetNativeDisplayId() const
Definition Unit.h:1640
uint64 GetHealth() const
Definition Unit.h:800
Unit * GetVictim() const
Definition Unit.h:738
void NearTeleportTo(TeleportLocation const &target, bool casting=false)
Definition Unit.cpp:13054
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void RemoveAllAuras()
Definition Unit.cpp:4400
bool SetDisableGravity(bool disable, bool updateAnimTier=true, bool updatePlayHoverAnim=true)
Definition Unit.cpp:13440
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
Creature * FindNearestCreatureWithOptions(float range, FindCreatureOptions const &options) const
Definition Object.cpp:1531
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
bool Validate(SpellInfo const *) override
void AfterApply(AuraEffect const *, AuraEffectHandleModes)
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