diff options
Diffstat (limited to 'src')
5 files changed, 104 insertions, 288 deletions
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index 916fad6a57..3c51b4fa0f 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -25,10 +25,8 @@ enum IonarSpells { - SPELL_BALL_LIGHTNING_N = 52780, - SPELL_BALL_LIGHTNING_H = 59800, - SPELL_STATIC_OVERLOAD_N = 52658, - SPELL_STATIC_OVERLOAD_H = 59795, + SPELL_BALL_LIGHTNING = 52780, + SPELL_STATIC_OVERLOAD = 52658, SPELL_STATIC_OVERLOAD_KNOCK = 53337, SPELL_DISPERSE = 52770, @@ -36,8 +34,7 @@ enum IonarSpells SPELL_SPARK_DESPAWN = 52776, //Spark of Ionar - SPELL_SPARK_VISUAL_TRIGGER_N = 52667, - SPELL_SPARK_VISUAL_TRIGGER_H = 59833, + SPELL_SPARK_VISUAL_TRIGGER = 52667, SPELL_RANDOM_LIGHTNING = 52663, }; @@ -75,8 +72,11 @@ struct boss_ionar : public BossAI void Reset() override { _Reset(); - HealthCheck = 50; me->SetVisible(true); + + ScheduleHealthCheckEvent(50, [&] { + DoCastSelf(SPELL_DISPERSE); + }); } void ScheduleEvents(bool spark) @@ -120,16 +120,14 @@ struct boss_ionar : public BossAI { Talk(SAY_SPLIT); - Creature* spark; for (uint8 i = 0; i < 5; ++i) { - if ((spark = me->SummonCreature(NPC_SPARK_OF_IONAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000))) + if (Creature* spark = me->SummonCreature(NPC_SPARK_OF_IONAR, me->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 20000)) { - summons.Summon(spark); - spark->CastSpell(spark, me->GetMap()->IsHeroic() ? SPELL_SPARK_VISUAL_TRIGGER_H : SPELL_SPARK_VISUAL_TRIGGER_N, true); + spark->CastSpell(spark, SPELL_SPARK_VISUAL_TRIGGER, true); spark->CastSpell(spark, SPELL_RANDOM_LIGHTNING, true); spark->SetUnitFlag(UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - spark->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0); + spark->SetHomePosition(me->GetPosition()); if (Player* tgt = SelectTargetFromPlayerList(100)) spark->GetMotionMaster()->MoveFollow(tgt, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); @@ -156,23 +154,13 @@ struct boss_ionar : public BossAI switch (events.ExecuteEvent()) { case EVENT_BALL_LIGHTNING: - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_BALL_LIGHTNING_H : SPELL_BALL_LIGHTNING_N, false); - + DoCastRandomTarget(SPELL_BALL_LIGHTNING, 1, 0.0f, false); events.Repeat(10s, 11s); break; case EVENT_STATIC_OVERLOAD: - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_STATIC_OVERLOAD_H : SPELL_STATIC_OVERLOAD_N, false); - + DoCastRandomTarget(SPELL_STATIC_OVERLOAD); events.Repeat(5s, 6s); break; - case EVENT_CHECK_HEALTH: - if (HealthBelowPct(HealthCheck)) - me->CastSpell(me, SPELL_DISPERSE, false); - - events.Repeat(1s); - return; case EVENT_CALL_SPARKS: { EntryCheckPredicate pred(NPC_SPARK_OF_IONAR); @@ -192,9 +180,6 @@ struct boss_ionar : public BossAI DoMeleeAttackIfReady(); } - - private: - uint8 HealthCheck; }; struct npc_spark_of_ionar : public ScriptedAI @@ -252,7 +237,8 @@ class spell_ionar_static_overload : public AuraScript return; if (Unit* target = GetTarget()) - target->CastSpell(target, SPELL_STATIC_OVERLOAD_KNOCK, true); + if (target->GetMap() && !target->GetMap()->IsHeroic()) + target->CastSpell(target, SPELL_STATIC_OVERLOAD_KNOCK, true); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index c70f60ee6d..043f9087d4 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -62,36 +62,43 @@ enum LokenEvents struct boss_loken : public BossAI { - boss_loken(Creature* creature) : BossAI(creature, DATA_LOKEN) - { - isActive = instance->GetData(DATA_LOKEN_INTRO); - } - - void MoveInLineOfSight(Unit*) override { } + boss_loken(Creature* creature) : BossAI(creature, DATA_LOKEN), _introDone(false) { } void Reset() override { _Reset(); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); - HealthCheck = 75; - IntroTimer = 0; me->RemoveAllAuras(); - if (!isActive) - { - me->SetControlled(true, UNIT_STATE_STUNNED); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - } + ScheduleHealthCheckEvent(75, [&] { + Talk(SAY_75HEALTH); + }); + + ScheduleHealthCheckEvent(50, [&] { + Talk(SAY_50HEALTH); + }); + + ScheduleHealthCheckEvent(25, [&] { + Talk(SAY_25HEALTH); + }); + } + + void MoveInLineOfSight(Unit* who) override + { + BossAI::MoveInLineOfSight(who); + + if (_introDone || !who->IsPlayer() || !me->IsWithinDistInMap(who, 40.0f)) + return; + + Talk(SAY_INTRO_1); + Talk(SAY_INTRO_2, 10s); + _introDone = true; } void JustEngagedWith(Unit*) override { + me->m_Events.KillAllEvents(false); _JustEngagedWith(); Talk(SAY_AGGRO); @@ -109,27 +116,6 @@ struct boss_loken : public BossAI Talk(SAY_DEATH); } - void LokenSpeach(bool hp) - { - if (hp) - { - switch (HealthCheck) - { - case 75: - Talk(SAY_75HEALTH); - break; - case 50: - Talk(SAY_50HEALTH); - break; - case 25: - Talk(SAY_25HEALTH); - break; - } - } - else - Talk(SAY_NOVA); - } - void KilledUnit(Unit* victim) override { if (!victim->IsPlayer()) @@ -140,40 +126,6 @@ struct boss_loken : public BossAI void UpdateAI(uint32 diff) override { - if (!isActive) - { - IntroTimer += diff; - if (IntroTimer > 5000 && IntroTimer < 10000) - { - if (SelectTargetFromPlayerList(60)) - { - Talk(SAY_INTRO_1); - IntroTimer = 10000; - } - else - IntroTimer = 0; - } - - if (IntroTimer >= 30000 && IntroTimer < 40000) - { - Talk(SAY_INTRO_2); - IntroTimer = 40000; - } - if (IntroTimer >= 60000) - { - isActive = true; - instance->SetData(DATA_LOKEN_INTRO, 1); - - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - - if (GameObject* globe = instance->GetGameObject(DATA_LOKEN_THRONE)) - globe->SetGoState(GO_STATE_ACTIVE); - } - - return; - } - //Return since we have no target if (!UpdateVictim()) return; @@ -185,16 +137,8 @@ struct boss_loken : public BossAI switch (events.ExecuteEvent()) { - case EVENT_CHECK_HEALTH: - if (HealthBelowPct(HealthCheck)) - { - LokenSpeach(true); - HealthCheck -= 25; - } - - events.Repeat(1s); - break; case EVENT_LIGHTNING_NOVA: + Talk(SAY_NOVA); events.Repeat(15s); me->CastSpell(me, SPELL_LIGHTNING_NOVA_VISUAL, true); me->CastSpell(me, SPELL_LIGHTNING_NOVA_THUNDERS, true); @@ -221,9 +165,7 @@ struct boss_loken : public BossAI DoMeleeAttackIfReady(); } private: - bool isActive; - uint32 IntroTimer; - uint8 HealthCheck; + bool _introDone; }; class spell_loken_pulsing_shockwave : public SpellScript diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 2489020e51..30e110231f 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -372,160 +372,8 @@ private: InstanceScript* m_pInstance; }; -enum monumentSpells -{ - SPELL_FREEZE_ANIM = 16245, - SPELL_AWAKEN = 52875, - - SPELL_PIERCING_HOWL = 23600, - SPELL_PENETRATING_STRIKE = 52890, - SPELL_FRIGHTENING_SHOUT = 19134, - SPELL_BLADE_TURNING_N = 52891, - SPELL_BLADE_TURNING_H = 59173, - - SPELL_DEADLY_THROW_N = 52885, - SPELL_DEADLY_THROW_H = 59180, - SPELL_DEFLECTION_N = 52879, - SPELL_DEFLECTION_H = 59181, - SPELL_THROW_N = 52904, - SPELL_THROW_H = 59179, -}; - -enum monumentEvents -{ - EVENT_PIERCING_HOWL = 1, - EVENT_PENETRATING_STRIKE = 2, - EVENT_FRIGHTENING_SHOUT = 3, - EVENT_BLADE_TURNING = 4, - - EVENT_DEADLY_THROW = 11, - EVENT_DEFLECTION = 12, - EVENT_THROW = 13, - - EVENT_UNFREEZE = 20, -}; - -struct npc_hol_monument : public ScriptedAI -{ - npc_hol_monument(Creature* creature) : ScriptedAI(creature) - { - _attackGUID.Clear(); - _isActive = urand(0, 1); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->CastSpell(me, SPELL_FREEZE_ANIM, true); - } - - void MoveInLineOfSight(Unit* who) override - { - if (_attackGUID) - ScriptedAI::MoveInLineOfSight(who); - else if (_isActive && who->IsPlayer()) - { - if ((who->GetPositionX() < me->GetPositionX() || who->GetPositionY() < -220.0f) && me->GetDistance2d(who) < 40) - { - _isActive = false; - _attackGUID = who->GetGUID(); - events.Reset(); - events.RescheduleEvent(EVENT_UNFREEZE, 5s); - } - } - } - - void JustEngagedWith(Unit*) override - { - events.Reset(); - if (me->GetEntry() == 28961) // NPC_TITANIUM_SIEGEBREAKER - { - events.ScheduleEvent(EVENT_PIERCING_HOWL, 10s, 25s); - events.ScheduleEvent(EVENT_PENETRATING_STRIKE, 5s, 10s); - events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 20s, 28s); - events.ScheduleEvent(EVENT_BLADE_TURNING, 12s); - } - else - { - events.ScheduleEvent(EVENT_THROW, 10s, 25s); - events.ScheduleEvent(EVENT_DEADLY_THROW, 15s, 30s); - events.ScheduleEvent(EVENT_DEFLECTION, 15s); - } - } - - void AttackStart(Unit* who) override - { - if (!_attackGUID || !_isActive) - return; - ScriptedAI::AttackStart(who); - } - - void UpdateAI(uint32 diff) override - { - if (!_isActive && !_attackGUID) - return; - - events.Update(diff); - uint32 eventId = events.ExecuteEvent(); - - if (eventId == EVENT_UNFREEZE) - { - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->CastSpell(me, SPELL_AWAKEN, true); - me->RemoveAllAuras(); - _isActive = true; - if (Unit* target = ObjectAccessor::GetUnit(*me, _attackGUID)) - AttackStart(target); - return; - } - - //Return since we have no target or if we are disabled from fight - if (!UpdateVictim()) - return; - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (eventId) - { - case EVENT_PIERCING_HOWL: - me->CastSpell(me->GetVictim(), SPELL_PIERCING_HOWL, false); - events.Repeat(10s, 25s); - break; - case EVENT_PENETRATING_STRIKE: - me->CastSpell(me->GetVictim(), SPELL_PENETRATING_STRIKE, false); - events.Repeat(5s, 10s); - break; - case EVENT_FRIGHTENING_SHOUT: - me->CastSpell(me->GetVictim(), SPELL_FRIGHTENING_SHOUT, false); - events.Repeat(20s, 28s); - break; - case EVENT_BLADE_TURNING: - me->CastSpell(me->GetVictim(), me->GetMap()->IsHeroic() ? SPELL_BLADE_TURNING_H : SPELL_BLADE_TURNING_N, false); - events.Repeat(12s); - break; - case EVENT_THROW: - me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_THROW_H : SPELL_THROW_N, true); - events.Repeat(10s, 25s); - break; - case EVENT_DEADLY_THROW: - me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_DEADLY_THROW_H : SPELL_DEADLY_THROW_N, true); - events.Repeat(15s, 30s); - break; - case EVENT_DEFLECTION: - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_DEFLECTION_H : SPELL_DEFLECTION_N, false); - events.Repeat(15s); - break; - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap events; - bool _isActive; - ObjectGuid _attackGUID; -}; - void AddSC_boss_volkhan() { RegisterHallOfLightningCreatureAI(boss_volkhan); RegisterHallOfLightningCreatureAI(npc_molten_golem); - RegisterHallOfLightningCreatureAI(npc_hol_monument); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h index 80f06acab6..99b3fecb81 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h @@ -35,8 +35,6 @@ enum HoLBossIds enum HoLDataTypes { - DATA_LOKEN_INTRO = 0, - // GameObject data DATA_LOKEN_THRONE = 0, @@ -47,17 +45,20 @@ enum HoLDataTypes enum HoLNPCs { - NPC_BJARNGRIM = 28586, - NPC_VOLKHAN = 28587, - NPC_IONAR = 28546, - NPC_LOKEN = 28923, + NPC_TITANIUM_THUNDERER = 28965, + NPC_TITANIUM_SIEGEBREAKER = 28961 }; enum HoLGOs { GO_VOLKHAN_DOOR = 191325, GO_IONAR_DOOR = 191326, - GO_LOKEN_THRONE = 192654, + GO_LOKEN_THRONE = 192654 +}; + +enum HoLActions +{ + ACTION_ACTIVATE_TITANIUM_VRYKUL, }; template <class AI, class T> diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp index fb480c0a47..1341f31c06 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -15,8 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "AreaTriggerScript.h" #include "CreatureScript.h" #include "InstanceMapScript.h" +#include "Player.h" #include "ScriptedCreature.h" #include "halls_of_lightning.h" @@ -46,8 +48,8 @@ public: SetBossNumber(MAX_ENCOUNTERS); LoadDoorData(doorData); LoadObjectData(nullptr, gameObjectData); - volkhanAchievement = false; - bjarngrimAchievement = false; + _volkhanAchievement = false; + _bjarngrimAchievement = false; }; bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override @@ -55,33 +57,25 @@ public: switch (criteria_id) { case 7321: //Shatter Resistant (2042) - return volkhanAchievement; + return _volkhanAchievement; case 6835: // Lightning Struck (1834) - return bjarngrimAchievement; + return _bjarngrimAchievement; } return false; } void SetData(uint32 uiType, uint32 uiData) override { - if (uiType == DATA_LOKEN_INTRO) - SaveToDB(); - // Achievements if (uiType == DATA_BJARNGRIM_ACHIEVEMENT) - bjarngrimAchievement = (bool)uiData; + _bjarngrimAchievement = (bool)uiData; else if (uiType == DATA_VOLKHAN_ACHIEVEMENT) - volkhanAchievement = (bool)uiData; - - if (uiData != DONE) - return; - - SaveToDB(); + _volkhanAchievement = (bool)uiData; } private: - bool volkhanAchievement; - bool bjarngrimAchievement; + bool _volkhanAchievement; + bool _bjarngrimAchievement; }; InstanceScript* GetInstanceScript(InstanceMap* pMap) const override @@ -90,7 +84,52 @@ public: } }; +enum TitaniumHallwaySpells +{ + SPELL_FREEZE_ANIM = 16245, + SPELL_AWAKEN = 52875, +}; + +class at_hol_hall_of_watchers : public OnlyOnceAreaTriggerScript +{ +public: + at_hol_hall_of_watchers() : OnlyOnceAreaTriggerScript("at_hol_hall_of_watchers") {} + + bool _OnTrigger(Player* player, const AreaTrigger* /*at*/) override + { + std::list<Creature*> creatures; + player->GetCreatureListWithEntryInGrid(creatures, { NPC_TITANIUM_SIEGEBREAKER, NPC_TITANIUM_THUNDERER }, 50.0f); + creatures.remove_if([&](Creature const* creature) -> bool + { + return !player->IsWithinLOSInMap(creature) || !creature->HasAura(SPELL_FREEZE_ANIM); + }); + + if (creatures.empty()) + return false; + + Acore::Containers::RandomResize(creatures, urand(2, 4)); + + ObjectGuid target = player->GetGUID(); + + for (Creature* creature : creatures) + { + creature->SetHomePosition(player->GetPosition()); + creature->AI()->DoCastSelf(SPELL_AWAKEN); + creature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + + creature->m_Events.AddEventAtOffset([creature, target] { + creature->AI()->DoAction(ACTION_ACTIVATE_TITANIUM_VRYKUL); + if (Player* targetPlayer = ObjectAccessor::GetPlayer(*creature, target)) + creature->AI()->AttackStart(targetPlayer); + }, 5s); + } + + return false; + } +}; + void AddSC_instance_halls_of_lightning() { new instance_halls_of_lightning(); + new at_hol_hall_of_watchers(); } |