diff options
| author | Dan <83884799+elthehablo@users.noreply.github.com> | 2024-02-08 03:43:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-07 23:43:19 -0300 |
| commit | bc25ade49825501aaee80b9da79ce14b1e7839cc (patch) | |
| tree | 3976840c61946ed81680dd15191c9d243ac9edcc /src | |
| parent | b8118fa06b7444bcf7cbb9049f6b82fc50e914f0 (diff) | |
fix(Scripts/TheEye): refactor Al'ar (#18264)
* initial
* restore quill event
* with ismoving and debug
* final before timers
* clear all debuffs
* remove justreachedhome bossai
* huh?
* some fixes
* more fixes
* add 2 extra platforms for p1
* fix coords
* finalise
* change melt armor timer so it is not delayed
indefinitely - this is because we have a dive after 30 secs
that delays all timers. So at 30 secs we will have melt armor at
33 seconds, which then gets an extra 15 seconds from the delay all and another dive
after 30 so it gets pushed back even more before being able to be cast
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp | 503 |
1 files changed, 257 insertions, 246 deletions
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 7264a07ae5..e8e82b4439 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -28,6 +28,7 @@ enum Spells SPELL_FLAME_QUILLS = 34229, SPELL_QUILL_MISSILE_1 = 34269, // 21 SPELL_QUILL_MISSILE_2 = 34314, // 3 + SPELL_CLEAR_ALL_DEBUFFS = 34098, SPELL_FLAME_BUFFET = 34121, SPELL_EMBER_BLAST = 34341, SPELL_REBIRTH_PHASE2 = 34342, @@ -38,15 +39,18 @@ enum Spells SPELL_DIVE_BOMB = 35181 }; -const Position alarPoints[7] = +// @todo: Alar doesnt seem to move to waypoints but instead to the triggers in p1 +const Position alarPoints[9] = { - {340.15f, 58.65f, 17.71f, 4.60f}, - {388.09f, 31.54f, 20.18f, 1.61f}, - {388.18f, -32.85f, 20.18f, 0.52f}, - {340.29f, -60.19f, 17.72f, 5.71f}, - {332.0f, 0.01f, 43.0f, 0.0f}, - {331.0f, 0.01f, -2.38f, 0.0f}, - {332.0f, 0.01f, 43.0f, 0.0f} + {335.638f, 59.4879f, 17.9319f, 4.60f}, //first platform + {388.751007f, 31.731199f, 20.263599f, 1.61f}, + {388.790985f, -33.105900f, 20.263599f, 0.52f}, + {332.722992f, -61.159f, 17.979099f, 5.71f}, + {258.959015f, -38.687099f, 20.262899f, 5.21f}, + {259.2277997, 35.879002f, 20.263f, 4.81f}, //sixth platform + {332.0f, 0.01f, 43.0f, 0.0f}, //quill + {331.0f, 0.01f, -2.38f, 0.0f}, //middle (p2) + {332.0f, 0.01f, 43.0f, 0.0f} // dive }; enum Misc @@ -56,26 +60,28 @@ enum Misc NPC_FLAME_PATCH = 20602, POINT_PLATFORM = 0, - POINT_QUILL = 4, - POINT_MIDDLE = 5, - POINT_DIVE = 6, - - EVENT_SWITCH_PLATFORM = 1, - EVENT_START_QUILLS = 2, - EVENT_RELOCATE_MIDDLE = 3, - EVENT_REBIRTH = 4, - EVENT_SPELL_MELT_ARMOR = 5, - EVENT_SPELL_FLAME_PATCH = 6, - EVENT_SPELL_CHARGE = 7, - EVENT_SPELL_DIVE_BOMB = 8, - EVENT_START_DIVE = 9, - EVENT_CAST_DIVE_BOMB = 10, - EVENT_SUMMON_DIVE_PHOENIX = 11, - EVENT_REBIRTH_DIVE = 12, - EVENT_SPELL_BERSERK = 13, - - EVENT_MOVE_TO_PHASE_2 = 20, - EVENT_FINISH_DIVE = 21 + POINT_QUILL = 6, + POINT_MIDDLE = 7, + POINT_DIVE = 8, + + EVENT_RELOCATE_MIDDLE = 1, + EVENT_REBIRTH = 2, + EVENT_SPELL_BERSERK = 3, + + EVENT_MOVE_TO_PHASE_2 = 4, + EVENT_FINISH_DIVE = 5 +}; + +enum PlatformMoveDirections +{ + DIRECTION_ANTI_CLOCKWISE = 0, + DIRECTION_CLOCKWISE = 1, + DIRECTION_ACROSS = 2 +}; + +enum GroupAlar +{ + GROUP_FLAME_BUFFET = 1 }; // Xinef: Ruse of the Ashtongue (10946) @@ -85,279 +91,284 @@ enum qruseoftheAshtongue QUEST_RUSE_OF_THE_ASHTONGUE = 10946, }; -class boss_alar : public CreatureScript +struct boss_alar : public BossAI { -public: - boss_alar() : CreatureScript("boss_alar") { } - struct boss_alarAI : public BossAI + boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR) { - boss_alarAI(Creature* creature) : BossAI(creature, DATA_ALAR) - { - startPath = true; - SetCombatMovement(false); - } - - uint8 platform; - uint8 noQuillTimes; - bool startPath; + SetCombatMovement(false); + } - void JustReachedHome() override + void JustReachedHome() override + { + BossAI::JustReachedHome(); + if (me->IsEngaged()) { - BossAI::JustReachedHome(); - startPath = true; + ConstructWaypointsAndMove(); } + } - void Reset() override - { - BossAI::Reset(); - platform = 0; - noQuillTimes = 0; - me->SetModelVisible(true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true); - me->SetReactState(REACT_AGGRESSIVE); - } + void Reset() override + { + BossAI::Reset(); + _canAttackCooldown = true; + _baseAttackOverride = false; + _spawnPhoenixes = false; + _platform = 0; + _platformRoll = 0; + _noQuillTimes = 0; + _platformMoveRepeatTimer = 16s; + me->SetModelVisible(true); + me->SetReactState(REACT_AGGRESSIVE); + ConstructWaypointsAndMove(); + } - void JustEngagedWith(Unit* who) override + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + ScheduleTimedEvent(0s, [&] { - BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 0); - } + if (roll_chance_i(20 * _noQuillTimes)) + { + _noQuillTimes = 0; + _platform = RAND(0, 5); + me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true); + _platformMoveRepeatTimer = 16s; + } + else + { + if (_noQuillTimes++ > 0) + { + me->SetOrientation(alarPoints[_platform].GetOrientation()); + if (_spawnPhoenixes) + { + SpawnPhoenixes(3, me); + } + } + me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[_platform], false, true); + _platformRoll = RAND(0, 2); + switch(_platformRoll) + { + case DIRECTION_ANTI_CLOCKWISE: + _platform = (_platform+5)%6; + _spawnPhoenixes = false; + break; + case DIRECTION_CLOCKWISE: + _platform = (_platform+1)%6; + _spawnPhoenixes = false; + break; + case DIRECTION_ACROSS: + _platform = (_platform+3)%6; + _spawnPhoenixes = true; + break; + } + _platformMoveRepeatTimer = 30s; + } + }, _platformMoveRepeatTimer); + ScheduleMainSpellAttack(0s); + } - void JustDied(Unit* killer) override - { - me->SetModelVisible(true); - BossAI::JustDied(killer); + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + me->SetModelVisible(true); - // Xinef: Ruse of the Ashtongue (10946) - Map::PlayerList const& pl = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + if (Map* map = me->GetMap()) + { + map->DoForAllPlayers([&](Player* player) { - Player* player = itr->GetSource(); if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE) + { if (player->HasAura(SPELL_ASHTONGUE_RUSE)) + { player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE); - } + } + } + }); } + } + + void MoveInLineOfSight(Unit* /*who*/) override { } - void JustSummoned(Creature* summon) override + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override + { + if (damage >= me->GetHealth() && _platform < POINT_MIDDLE) { - summons.Summon(summon); - if (summon->GetEntry() == NPC_EMBER_OF_ALAR) - summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true); - } + damage = 0; + me->InterruptNonMeleeSpells(false); + me->SetHealth(me->GetMaxHealth()); + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + DoCastSelf(SPELL_EMBER_BLAST, true); + scheduler.CancelAll(); + ScheduleUniqueTimedEvent(8s, [&]{ + me->SetPosition(alarPoints[POINT_MIDDLE]); + }, EVENT_RELOCATE_MIDDLE); + ScheduleUniqueTimedEvent(12s, [&] + { + me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST); + DoCastSelf(SPELL_REBIRTH_PHASE2); + }, EVENT_MOVE_TO_PHASE_2); + ScheduleUniqueTimedEvent(16001ms, [&]{ + me->SetReactState(REACT_AGGRESSIVE); + _platform = POINT_MIDDLE; + me->GetMotionMaster()->MoveChase(me->GetVictim()); + ScheduleAbilities(); + }, EVENT_REBIRTH); - void MoveInLineOfSight(Unit* /*who*/) override { } + } + } - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + void ScheduleAbilities() + { + ScheduleTimedEvent(57s, [&] + { + DoCastVictim(SPELL_MELT_ARMOR); + }, 60s); + ScheduleTimedEvent(10s, [&] { - if (damage >= me->GetHealth() && platform < POINT_MIDDLE) + DoCastRandomTarget(SPELL_CHARGE, 0, 50.0f); + }, 30s); + ScheduleTimedEvent(20s, [&] + { + // find spell from sniffs? + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true)) { - damage = 0; - if (events.GetNextEventTime(EVENT_REBIRTH) == 0) - { - me->InterruptNonMeleeSpells(false); - me->SetHealth(me->GetMaxHealth()); - me->SetReactState(REACT_PASSIVE); - me->CastSpell(me, SPELL_EMBER_BLAST, true); - - me->setAttackTimer(BASE_ATTACK, 16000); - events.Reset(); - events.ScheduleEvent(EVENT_RELOCATE_MIDDLE, 8000); - events.ScheduleEvent(EVENT_MOVE_TO_PHASE_2, 12000); - events.ScheduleEvent(EVENT_REBIRTH, 16001); - } + me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS); } - } + }, 30s); + ScheduleTimedEvent(30s, [&] + { + me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true); + scheduler.DelayAll(15s); + }, 30s); + ScheduleUniqueTimedEvent(10min, [&] + { + DoCastSelf(SPELL_BERSERK); + }, EVENT_SPELL_BERSERK); + ScheduleMainSpellAttack(0s); + } - void MovementInform(uint32 type, uint32 id) override + void SpawnPhoenixes(uint8 count, Unit* targetToSpawnAt) + { + if (targetToSpawnAt) { - if (type != POINT_MOTION_TYPE) + for (uint8 i = 0; i < count; ++i) { - if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat()) - startPath = true; - return; + me->SummonCreature(NPC_EMBER_OF_ALAR, *targetToSpawnAt, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000); } + } + } - if (id == POINT_PLATFORM) - me->setAttackTimer(BASE_ATTACK, 1000); - else if (id == POINT_QUILL) - events.ScheduleEvent(EVENT_START_QUILLS, 1000); - else if (id == POINT_DIVE) + void DoDiveBomb() + { + scheduler.Schedule(2s, [this](TaskContext) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true)) { - events.ScheduleEvent(EVENT_START_DIVE, 1000); - events.ScheduleEvent(EVENT_CAST_DIVE_BOMB, 5000); + SpawnPhoenixes(2, target); } + }).Schedule(6s, [this](TaskContext) + { + me->SetModelVisible(true); + DoCastSelf(SPELL_REBIRTH_DIVE); + }).Schedule(10s, [this](TaskContext) + { + me->GetMotionMaster()->MoveChase(me->GetVictim()); + }); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true)) + { + DoCast(target, SPELL_DIVE_BOMB); + me->SetPosition(*target); + me->StopMovingOnCurrentPos(); } + me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); - void UpdateAI(uint32 diff) override + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) { - if (startPath) + if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat()) { - me->StopMoving(); - startPath = false; - if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath())) - { - Movement::PointsArray pathPoints; - pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ())); - for (uint8 i = 0; i < i_path->size(); ++i) - { - WaypointData const* node = i_path->at(i); - pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z)); - } - me->GetMotionMaster()->MoveSplinePath(&pathPoints); - } + ConstructWaypointsAndMove(); } + return; + } - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) + switch(id) + { + case POINT_QUILL: + scheduler.CancelGroup(GROUP_FLAME_BUFFET); + scheduler.Schedule(1s, [this](TaskContext) + { + DoCastSelf(SPELL_FLAME_QUILLS); + }); + ScheduleMainSpellAttack(13s); + break; + case POINT_DIVE: + scheduler.Schedule(1s, [this](TaskContext) + { + DoCastSelf(SPELL_DIVE_BOMB_VISUAL); + }).Schedule(5s, [this](TaskContext) + { + DoDiveBomb(); + }); + break; + default: return; + } + } - switch (events.ExecuteEvent()) + void ScheduleMainSpellAttack(std::chrono::seconds timer) + { + scheduler.Schedule(timer, GROUP_FLAME_BUFFET, [this](TaskContext context) + { + if (!me->IsWithinMeleeRange(me->GetVictim()) && !me->isMoving()) { - case EVENT_SWITCH_PLATFORM: - if (roll_chance_i(20 * noQuillTimes)) - { - noQuillTimes = 0; - platform = RAND(0, 3); - me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true); - events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 16000); - } - else - { - if (noQuillTimes++ > 0) - { - me->SetOrientation(alarPoints[platform].GetOrientation()); - me->SummonCreature(NPC_EMBER_OF_ALAR, *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000); - } - me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[platform], false, true); - platform = (platform + 1) % 4; - events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 30000); - } - me->setAttackTimer(BASE_ATTACK, 20000); - break; - case EVENT_START_QUILLS: - me->CastSpell(me, SPELL_FLAME_QUILLS, false); - break; - case EVENT_RELOCATE_MIDDLE: - me->SetPosition(alarPoints[POINT_MIDDLE]); - break; - case EVENT_MOVE_TO_PHASE_2: - me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST); - me->CastSpell(me, SPELL_REBIRTH_PHASE2, false); - break; - case EVENT_REBIRTH: - me->SetReactState(REACT_AGGRESSIVE); - platform = POINT_MIDDLE; - me->GetMotionMaster()->MoveChase(me->GetVictim()); - - events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 67000); - events.ScheduleEvent(EVENT_SPELL_CHARGE, 10000); - events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 20000); - events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000); - break; - case EVENT_SPELL_MELT_ARMOR: - me->CastSpell(me->GetVictim(), SPELL_MELT_ARMOR, false); - events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 60000); - break; - case EVENT_SPELL_CHARGE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true)) - me->CastSpell(target, SPELL_CHARGE, false); - events.ScheduleEvent(EVENT_SPELL_CHARGE, 30000); - break; - case EVENT_SPELL_FLAME_PATCH: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true)) - me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 30000); - break; - case EVENT_SPELL_DIVE_BOMB: - me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true); - events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000); - events.DelayEvents(15000); - me->setAttackTimer(BASE_ATTACK, 20000); - break; - case EVENT_START_DIVE: - me->CastSpell(me, SPELL_DIVE_BOMB_VISUAL, false); - break; - case EVENT_CAST_DIVE_BOMB: - events.ScheduleEvent(EVENT_SUMMON_DIVE_PHOENIX, 2000); - events.ScheduleEvent(EVENT_REBIRTH_DIVE, 6000); - events.ScheduleEvent(EVENT_FINISH_DIVE, 10000); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true)) - { - me->CastSpell(target, SPELL_DIVE_BOMB, false); - me->SetPosition(*target); - me->StopMovingOnCurrentPos(); - } - - me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); - break; - case EVENT_SUMMON_DIVE_PHOENIX: - { - Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true); - me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000); - me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000); - break; - } - case EVENT_REBIRTH_DIVE: - me->SetModelVisible(true); - me->CastSpell(me, SPELL_REBIRTH_DIVE, false); - break; - case EVENT_FINISH_DIVE: - me->GetMotionMaster()->MoveChase(me->GetVictim()); - break; - case EVENT_SPELL_BERSERK: - me->CastSpell(me, SPELL_BERSERK, true); - break; + DoCastVictim(SPELL_FLAME_BUFFET); } + context.Repeat(2s); + }); + } - if (me->isAttackReady()) + void ConstructWaypointsAndMove() + { + me->StopMoving(); + if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath())) + { + Movement::PointsArray pathPoints; + pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ())); + for (uint8 i = 0; i < i_path->size(); ++i) { - if (me->IsWithinMeleeRange(me->GetVictim())) - { - me->AttackerStateUpdate(me->GetVictim()); - me->resetAttackTimer(); - } - else - { - me->resetAttackTimer(); - ThreatContainer::StorageType const& threatList = me->GetThreatMgr().GetThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) - if (me->IsWithinMeleeRange(unit)) - { - me->AttackerStateUpdate(unit); - return; - } - - me->CastSpell(me, SPELL_FLAME_BUFFET, false); - } + WaypointData const* node = i_path->at(i); + pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z)); } + me->GetMotionMaster()->MoveSplinePath(&pathPoints); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetTheEyeAI<boss_alarAI>(creature); } + +private: + bool _canAttackCooldown; + bool _baseAttackOverride; + bool _spawnPhoenixes; + uint8 _platform; + uint8 _platformRoll; + uint8 _noQuillTimes; + std::chrono::seconds _platformMoveRepeatTimer; }; class CastQuill : public BasicEvent { public: - CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId) - { - } + CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId){ } bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override { _caster->CastSpell(_caster, _spellId, true); return true; } - private: Unit* _caster; uint32 _spellId; @@ -496,7 +507,7 @@ public: void AddSC_boss_alar() { - new boss_alar(); + RegisterTheEyeAI(boss_alar); new spell_alar_flame_quills(); new spell_alar_ember_blast(); new spell_alar_ember_blast_death(); |
