From ae2af138e269ea8be55c2d39f93d8a790c9d15dc Mon Sep 17 00:00:00 2001 From: bash Date: Wed, 7 Jan 2026 13:53:49 +0100 Subject: [PATCH] script zones --- .../Northrend/DraktharonKeep/boss_dred.cpp | 139 +++---- .../Northrend/DraktharonKeep/boss_novos.cpp | 349 +++++++++--------- .../DraktharonKeep/drak_tharon_keep.h | 1 + .../instance_drak_tharon_keep.cpp | 71 ++-- .../Nexus/Oculus/instance_oculus.cpp | 16 +- .../Ulduar/HallsOfLightning/boss_loken.cpp | 95 ++--- .../Ulduar/HallsOfStone/brann_bronzebeard.cpp | 12 - .../scripts/Northrend/isle_of_conquest.cpp | 10 +- .../scripts/Northrend/zone_borean_tundra.cpp | 35 ++ .../scripts/Northrend/zone_grizzly_hills.cpp | 112 ------ .../scripts/Northrend/zone_sholazar_basin.cpp | 104 ------ .../scripts/Northrend/zone_storm_peaks.cpp | 25 +- src/server/scripts/Northrend/zone_zuldrak.cpp | 6 +- .../BlackTemple/boss_reliquary_of_souls.cpp | 6 +- 14 files changed, 381 insertions(+), 600 deletions(-) diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp index 1017c1ac2..44a6b1182 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp @@ -37,15 +37,7 @@ enum Misc NPC_DRAKKARI_SCYTHECLAW = 26628, NPC_DRAKKARI_GUTRIPPER = 26641, - SAY_CLAW_EMOTE = 0, - - EVENT_SPELL_BELLOWING_ROAR = 1, - EVENT_SPELL_GRIEVOUS_BITE = 2, - EVENT_SPELL_MANGLING_SLASH = 3, - EVENT_SPELL_FEARSOME_ROAR = 4, - EVENT_SPELL_PIERCING_SLASH = 5, - EVENT_SPELL_RAPTOR_CALL = 6, - EVENT_MENACING_CLAW = 7 + SAY_CLAW_EMOTE = 0 }; class boss_dred : public CreatureScript @@ -60,14 +52,52 @@ public: struct boss_dredAI : public BossAI { - boss_dredAI(Creature* creature) : BossAI(creature, DATA_DRED) - { - } + boss_dredAI(Creature* creature) : BossAI(creature, DATA_DRED) { } void Reset() override { BossAI::Reset(); _raptorCount = 0; + + ScheduleHealthCheckEvent({ 67, 34 }, [&] { + DoCastAOE(SPELL_BELLOWING_ROAR); + }, false); + } + + void ScheduleTasks() override + { + ScheduleTimedEvent(20s, [&] { + DoCastVictim(SPELL_GRIEVOUS_BITE); + }, 20s); + + ScheduleTimedEvent(18s + 500ms, [&] { + DoCastVictim(SPELL_MANGLING_SLASH); + }, 20s); + + ScheduleTimedEvent(10s, 20s, [&] { + DoCastAOE(SPELL_FEARSOME_ROAR); + }, 17s); + + ScheduleTimedEvent(17s, [&] { + DoCastVictim(SPELL_PIERCING_SLASH); + }, 20s); + + if (IsHeroic()) + { + ScheduleTimedEvent(16s, [&] { + DoCastSelf(SPELL_RAPTOR_CALL); + }, 30s); + + ScheduleTimedEvent(21s, [&] { + Talk(SAY_CLAW_EMOTE); + me->setAttackTimer(BASE_ATTACK, 2000); + me->AttackerStateUpdate(me->GetVictim()); + if (me->GetVictim()) + me->AttackerStateUpdate(me->GetVictim()); + if (me->GetVictim()) + me->AttackerStateUpdate(me->GetVictim()); + }, 20s); + } } uint32 GetData(uint32 data) const override @@ -87,67 +117,6 @@ public: { BossAI::JustEngagedWith(who); _raptorCount = 0; - - events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 33s); - events.ScheduleEvent(EVENT_SPELL_GRIEVOUS_BITE, 20s); - events.ScheduleEvent(EVENT_SPELL_MANGLING_SLASH, 18s + 500ms); - events.ScheduleEvent(EVENT_SPELL_FEARSOME_ROAR, 10s, 20s); - events.ScheduleEvent(EVENT_SPELL_PIERCING_SLASH, 17s); - if (IsHeroic()) - { - events.ScheduleEvent(EVENT_MENACING_CLAW, 21s); - events.ScheduleEvent(EVENT_SPELL_RAPTOR_CALL, 20s, 25s); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_BELLOWING_ROAR: - me->CastSpell(me, SPELL_BELLOWING_ROAR, false); - events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 40s); - break; - case EVENT_SPELL_GRIEVOUS_BITE: - me->CastSpell(me->GetVictim(), SPELL_GRIEVOUS_BITE, false); - events.ScheduleEvent(EVENT_SPELL_GRIEVOUS_BITE, 20s); - break; - case EVENT_SPELL_MANGLING_SLASH: - me->CastSpell(me->GetVictim(), SPELL_MANGLING_SLASH, false); - events.ScheduleEvent(EVENT_SPELL_MANGLING_SLASH, 20s); - break; - case EVENT_SPELL_FEARSOME_ROAR: - me->CastSpell(me, SPELL_FEARSOME_ROAR, false); - events.ScheduleEvent(EVENT_SPELL_FEARSOME_ROAR, 17s); - break; - case EVENT_SPELL_PIERCING_SLASH: - me->CastSpell(me->GetVictim(), SPELL_PIERCING_SLASH, false); - events.ScheduleEvent(EVENT_SPELL_PIERCING_SLASH, 20s); - break; - case EVENT_SPELL_RAPTOR_CALL: - me->CastSpell(me, SPELL_RAPTOR_CALL, false); - events.ScheduleEvent(EVENT_SPELL_RAPTOR_CALL, 20s); - break; - case EVENT_MENACING_CLAW: - Talk(SAY_CLAW_EMOTE); - me->setAttackTimer(BASE_ATTACK, 2000); - me->AttackerStateUpdate(me->GetVictim()); - if (me->GetVictim()) - me->AttackerStateUpdate(me->GetVictim()); - if (me->GetVictim()) - me->AttackerStateUpdate(me->GetVictim()); - events.ScheduleEvent(EVENT_MENACING_CLAW, 20s); - break; - } - - DoMeleeAttackIfReady(); } private: @@ -181,7 +150,23 @@ class spell_dred_raptor_call : public SpellScript void HandleDummy(SpellEffIndex /*effIndex*/) { - GetCaster()->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), -522.02f, -718.89f, 30.26f, 2.41f); + std::list raptors; + GetCaster()->GetCreatureListWithEntryInGrid(raptors, { NPC_DRAKKARI_SCYTHECLAW, NPC_DRAKKARI_GUTRIPPER }, 100.0f); + + raptors.remove_if([](Creature* raptor) + { + return !raptor->IsAlive() || raptor->IsInCombat(); + }); + + if (raptors.empty()) + return; + + Creature* raptor = Acore::Containers::SelectRandomContainerElement(raptors); + if (!raptor) + return; + + if (GetCaster()->GetVictim()) + raptor->AI()->AttackStart(GetCaster()->GetVictim()); } void Register() override @@ -193,16 +178,14 @@ class spell_dred_raptor_call : public SpellScript class achievement_better_off_dred : public AchievementCriteriaScript { public: - achievement_better_off_dred() : AchievementCriteriaScript("achievement_better_off_dred") - { - } + achievement_better_off_dred() : AchievementCriteriaScript("achievement_better_off_dred") { } bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override { if (!target) return false; - return target->GetAI()->GetData(target->GetEntry()); + return target->GetAI()->GetData(target->GetEntry()) >= 6; } }; diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 692888edf..36f8b555c 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -47,7 +47,7 @@ enum Spells SPELL_COPY_OF_SUMMON_MINIONS = 59933, SPELL_BLIZZARD = 49034, SPELL_FROSTBOLT = 49037, - SPELL_TOUCH_OF_MISERY = 50090 + SPELL_WRATH_OF_MISERY = 50089 }; enum Misc @@ -56,14 +56,7 @@ enum Misc NPC_CRYSTAL_HANDLER = 26627, NPC_SUMMON_CRYSTAL_HANDLER_TARGET = 27583, - EVENT_SUMMON_FETID_TROLL = 1, - EVENT_SUMMON_SHADOWCASTER = 2, - EVENT_SUMMON_HULKING_CORPSE = 3, - EVENT_SUMMON_CRYSTAL_HANDLER = 4, - EVENT_CAST_OFFENSIVE_SPELL = 5, - EVENT_KILL_TALK = 6, - EVENT_CHECK_PHASE = 7, - EVENT_SPELL_SUMMON_MINIONS = 8, + EVENT_KILL_TALK = 1, ROOM_RIGHT = 0, ROOM_LEFT = 1, @@ -77,198 +70,215 @@ std::unordered_map> const npcSummon = { ROOM_STAIRS, { NPC_CRYSTAL_CHANNEL_TARGET, { -378.40f, -813.13f, 59.74f, 0.0f } } }, }; -class boss_novos : public CreatureScript +// 26631 +struct boss_novos : public BossAI { -public: - boss_novos() : CreatureScript("boss_novos") { } + boss_novos(Creature* creature) : BossAI(creature, DATA_NOVOS) { } - struct boss_novosAI : public BossAI + void Reset() override { - boss_novosAI(Creature* creature) : BossAI(creature, DATA_NOVOS) - { - } + BossAI::Reset(); + instance->SetBossState(DATA_NOVOS_CRYSTALS, IN_PROGRESS); + instance->SetBossState(DATA_NOVOS_CRYSTALS, NOT_STARTED); + _crystalCounter = 0; + _summonTargetRightGUID.Clear(); + _summonTargetLeftGUID.Clear(); + _stage = 0; - void Reset() override - { - BossAI::Reset(); - instance->SetBossState(DATA_NOVOS_CRYSTALS, IN_PROGRESS); - instance->SetBossState(DATA_NOVOS_CRYSTALS, NOT_STARTED); - _crystalCounter = 0; - _summonTargetRightGUID.Clear(); - _summonTargetLeftGUID.Clear(); - _stage = 0; + me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + _achievement = true; + } - _achievement = true; - } + uint32 GetData(uint32 data) const override + { + if (data == me->GetEntry()) + return uint32(_achievement); + return 0; + } - uint32 GetData(uint32 data) const override - { - if (data == me->GetEntry()) - return uint32(_achievement); - return 0; - } + void SetData(uint32 type, uint32) override + { + if (type == me->GetEntry()) + _achievement = false; + } - void SetData(uint32 type, uint32) override - { - if (type == me->GetEntry()) - _achievement = false; - } + void MoveInLineOfSight(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* /*who*/) override { } + void JustEngagedWith(Unit* who) override + { + Talk(SAY_AGGRO); + BossAI::JustEngagedWith(who); + scheduler.ClearValidator(); - void JustEngagedWith(Unit* who) override - { - Talk(SAY_AGGRO); - BossAI::JustEngagedWith(who); + ScheduleTimedEvent(3s, [&] { + if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) + trigger->CastSpell(trigger, SPELL_SUMMON_FETID_TROLL_CORPSE, true, nullptr, nullptr, me->GetGUID()); + }, 3s); - events.ScheduleEvent(EVENT_SUMMON_FETID_TROLL, 3s); - events.ScheduleEvent(EVENT_SUMMON_SHADOWCASTER, 9s); - events.ScheduleEvent(EVENT_SUMMON_HULKING_CORPSE, 30s); - events.ScheduleEvent(EVENT_SUMMON_CRYSTAL_HANDLER, 20s); - events.ScheduleEvent(EVENT_CHECK_PHASE, 80s); + ScheduleTimedEvent(9s, [&] { + if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) + trigger->CastSpell(trigger, SPELL_SUMMON_RISEN_SHADOWCASTER, true, nullptr, nullptr, me->GetGUID()); + }, 10s); - me->CastSpell(me, SPELL_ARCANE_BLAST, true); - me->CastSpell(me, SPELL_ARCANE_FIELD, true); - me->CastSpell(me, SPELL_DESPAWN_CRYSTAL_HANDLER, true); + ScheduleTimedEvent(30s, [&] { + if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) + trigger->CastSpell(trigger, SPELL_SUMMON_HULKING_CORPSE, true, nullptr, nullptr, me->GetGUID()); + }, 30s); - for (auto& itr : npcSummon) + scheduler.Schedule(70s, [this](TaskContext context) { + if (me->HasAura(SPELL_BEAM_CHANNEL)) { - uint32 summonEntry; - Position summonPos; - std::tie(summonEntry, summonPos) = itr.second; - if (Creature* creature = me->SummonCreature(summonEntry, summonPos)) - switch (itr.first) - { - case ROOM_LEFT: - _summonTargetLeftGUID = creature->GetGUID(); - break; - case ROOM_RIGHT: - _summonTargetRightGUID = creature->GetGUID(); - break; - } + context.Repeat(2s); + return; } - me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty); - me->RemoveAllAuras(); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - } + scheduler.CancelAll(); - void JustDied(Unit* killer) override - { - Talk(SAY_DEATH); - BossAI::JustDied(killer); - instance->SetBossState(DATA_NOVOS_CRYSTALS, DONE); - } + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->InterruptNonMeleeSpells(false); - void KilledUnit(Unit* /*victim*/) override - { - if (events.GetNextEventTime(EVENT_KILL_TALK) == 0) + scheduler.SetValidator([this] { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); + + ScheduleTimedEvent(5s, 10s, [&] { + DoCastRandomTarget(SPELL_BLIZZARD); + }, 12s, 25s); + + ScheduleTimedEvent(5s, 10s, [&] { + DoCastRandomTarget(SPELL_WRATH_OF_MISERY); + }, 8s, 16s); + + if (IsHeroic()) { - Talk(SAY_KILL); - events.ScheduleEvent(EVENT_KILL_TALK, 6s); + ScheduleTimedEvent(10s, [&] { + DoCastAOE(SPELL_SUMMON_MINIONS); + }, 37s, 55s); } + }); + + for (Seconds timer : { 16s, 32s, 48s, 64s }) + { + me->m_Events.AddEventAtOffset([&] { + Talk(SAY_SUMMONING_ADDS); + Talk(EMOTE_SUMMONING_ADDS); + if (Creature* target = ObjectAccessor::GetCreature(*me, _stage ? _summonTargetLeftGUID : _summonTargetRightGUID)) + target->CastSpell(target, SPELL_SUMMON_CRYSTAL_HANDLER, true, nullptr, nullptr, me->GetGUID()); + _stage = _stage ? 0 : 1; + }, timer); } - void JustSummoned(Creature* summon) override + me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty); + me->RemoveAllAuras(); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + + DoCastSelf(SPELL_ARCANE_BLAST, true); + DoCastSelf(SPELL_ARCANE_FIELD, true); + DoCastSelf(SPELL_DESPAWN_CRYSTAL_HANDLER, true); + + for (auto& itr : npcSummon) { - summons.Summon(summon); - if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) && summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET && summon->GetEntry() != NPC_CRYSTAL_HANDLER) + uint32 summonEntry; + Position summonPos; + std::tie(summonEntry, summonPos) = itr.second; + if (Creature* creature = me->SummonCreature(summonEntry, summonPos)) + switch (itr.first) + { + case ROOM_LEFT: + _summonTargetLeftGUID = creature->GetGUID(); + break; + case ROOM_RIGHT: + _summonTargetRightGUID = creature->GetGUID(); + break; + } + } + } + + void JustDied(Unit* killer) override + { + Talk(SAY_DEATH); + BossAI::JustDied(killer); + instance->SetBossState(DATA_NOVOS_CRYSTALS, DONE); + } + + void KilledUnit(Unit* /*victim*/) override + { + if (!events.HasTimeUntilEvent(EVENT_KILL_TALK)) + { + Talk(SAY_KILL); + events.ScheduleEvent(EVENT_KILL_TALK, 6s); + } + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + // Phase 1 + if (me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + { + if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET && summon->GetEntry() != NPC_CRYSTAL_HANDLER) summon->SetReactState(REACT_DEFENSIVE); - else if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET) + + if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE) + summon->GetMotionMaster()->MovePoint(1, -373.56f, -770.86f, 28.59f); + + if (summon->EntryEquals(NPC_CRYSTAL_HANDLER)) summon->SetInCombatWithZone(); } + // Phase 2 + else if (summon->GetEntry() != NPC_CRYSTAL_CHANNEL_TARGET) + summon->SetInCombatWithZone(); + } - void UpdateAI(uint32 diff) override + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE) + summon->DespawnOrUnsummon(10s); + } + + void SummonMovementInform(Creature* summon, uint32 movementType, uint32 pathId) override + { + if (movementType == POINT_MOTION_TYPE && pathId == 1) { - if (!UpdateVictim()) - return; - - events.Update(diff); - switch (events.ExecuteEvent()) + if (summon->GetEntry() == NPC_FETID_TROLL_CORPSE) { - case EVENT_SUMMON_FETID_TROLL: - if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) - trigger->CastSpell(trigger, SPELL_SUMMON_FETID_TROLL_CORPSE, true, nullptr, nullptr, me->GetGUID()); - events.ScheduleEvent(EVENT_SUMMON_FETID_TROLL, 3s); - break; - case EVENT_SUMMON_HULKING_CORPSE: - if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) - trigger->CastSpell(trigger, SPELL_SUMMON_HULKING_CORPSE, true, nullptr, nullptr, me->GetGUID()); - events.ScheduleEvent(EVENT_SUMMON_HULKING_CORPSE, 30s); - break; - case EVENT_SUMMON_SHADOWCASTER: - if (Creature* trigger = summons.GetCreatureWithEntry(NPC_CRYSTAL_CHANNEL_TARGET)) - trigger->CastSpell(trigger, SPELL_SUMMON_RISEN_SHADOWCASTER, true, nullptr, nullptr, me->GetGUID()); - events.ScheduleEvent(EVENT_SUMMON_SHADOWCASTER, 10s); - break; - case EVENT_SUMMON_CRYSTAL_HANDLER: - if (_crystalCounter++ < 4) - { - Talk(SAY_SUMMONING_ADDS); - Talk(EMOTE_SUMMONING_ADDS); - if (Creature* target = ObjectAccessor::GetCreature(*me, _stage ? _summonTargetLeftGUID : _summonTargetRightGUID)) - target->CastSpell(target, SPELL_SUMMON_CRYSTAL_HANDLER, true, nullptr, nullptr, me->GetGUID()); - _stage = _stage ? 0 : 1; - events.ScheduleEvent(EVENT_SUMMON_CRYSTAL_HANDLER, 20s); - } - break; - case EVENT_CHECK_PHASE: - if (me->HasAura(SPELL_BEAM_CHANNEL)) - { - events.ScheduleEvent(EVENT_CHECK_PHASE, 2s); - break; - } - events.Reset(); - events.ScheduleEvent(EVENT_CAST_OFFENSIVE_SPELL, 3s); - events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 10s); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->InterruptNonMeleeSpells(false); - break; - case EVENT_CAST_OFFENSIVE_SPELL: - if (!me->HasUnitState(UNIT_STATE_CASTING)) - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) - me->CastSpell(target, RAND(SPELL_BLIZZARD, SPELL_FROSTBOLT, SPELL_TOUCH_OF_MISERY), false); - - events.ScheduleEvent(EVENT_CAST_OFFENSIVE_SPELL, 500ms); - break; - case EVENT_SPELL_SUMMON_MINIONS: - if (me->HasUnitState(UNIT_STATE_CASTING)) - { - me->CastSpell(me, SPELL_SUMMON_MINIONS, false); - events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 15s); - break; - } - events.ScheduleEvent(EVENT_SPELL_SUMMON_MINIONS, 500ms); - break; + DoZoneInCombat(summon); + _achievement = false; } } - - bool CheckEvadeIfOutOfCombatArea() const override - { - return !SelectTargetFromPlayerList(80.0f); - } - - private: - uint8 _crystalCounter; - uint8 _stage; - ObjectGuid _summonTargetRightGUID; - ObjectGuid _summonTargetLeftGUID; - - bool _achievement; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetDraktharonKeepAI(creature); } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff); + events.Update(diff); + + if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + DoSpellAttackIfReady(SPELL_FROSTBOLT); + } + + bool CheckEvadeIfOutOfCombatArea() const override + { + return !SelectTargetFromPlayerList(80.0f); + } + +private: + uint8 _crystalCounter; + uint8 _stage; + ObjectGuid _summonTargetRightGUID; + ObjectGuid _summonTargetLeftGUID; + + bool _achievement; }; +// 51403 class spell_novos_despawn_crystal_handler : public SpellScript { PrepareSpellScript(spell_novos_despawn_crystal_handler); @@ -290,6 +300,7 @@ class spell_novos_despawn_crystal_handler : public SpellScript } }; +// 47336 class spell_novos_crystal_handler_death_aura : public AuraScript { PrepareAuraScript(spell_novos_crystal_handler_death_aura); @@ -307,6 +318,7 @@ class spell_novos_crystal_handler_death_aura : public AuraScript } }; +// 59910 class spell_novos_summon_minions : public SpellScript { PrepareSpellScript(spell_novos_summon_minions); @@ -328,6 +340,7 @@ class spell_novos_summon_minions : public SpellScript } }; +// 2057 class achievement_oh_novos : public AchievementCriteriaScript { public: @@ -341,7 +354,7 @@ public: void AddSC_boss_novos() { - new boss_novos(); + RegisterCreatureAIWithFactory(boss_novos, GetDraktharonKeepAI); RegisterSpellScript(spell_novos_despawn_crystal_handler); RegisterSpellScript(spell_novos_crystal_handler_death_aura); RegisterSpellScript(spell_novos_summon_minions); diff --git a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h index e8f2722d0..dceeeafd8 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h +++ b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h @@ -39,6 +39,7 @@ enum Creatures NPC_KURZEL = 26664, NPC_DRAKKARI_GUARDIAN = 26620, NPC_RISEN_DRAKKARI_WARRIOR = 26635, + NPC_FETID_TROLL_CORPSE = 27598, }; enum GameObjects diff --git a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp index 50be90a84..9547a1d69 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp @@ -31,50 +31,39 @@ DoorData const doorData[] = { 0, 0, DOOR_TYPE_ROOM } }; -class instance_drak_tharon_keep : public InstanceMapScript +struct instance_drak_tharon_keep : public InstanceScript { -public: - instance_drak_tharon_keep() : InstanceMapScript("instance_drak_tharon_keep", MAP_DRAK_THARON_KEEP) { } - - struct instance_drak_tharon_keep_InstanceScript : public InstanceScript + instance_drak_tharon_keep(Map* map) : InstanceScript(map) { - instance_drak_tharon_keep_InstanceScript(Map* map) : InstanceScript(map) - { - SetHeaders(DataHeader); - SetBossNumber(MAX_ENCOUNTERS); - LoadDoorData(doorData); - } + SetHeaders(DataHeader); + SetBossNumber(MAX_ENCOUNTERS); + LoadDoorData(doorData); + } - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) - { - case GO_NOVOS_CRYSTAL_1: - case GO_NOVOS_CRYSTAL_2: - case GO_NOVOS_CRYSTAL_3: - case GO_NOVOS_CRYSTAL_4: - AddDoor(go); - break; - } - } - - void OnGameObjectRemove(GameObject* go) override - { - switch (go->GetEntry()) - { - case GO_NOVOS_CRYSTAL_1: - case GO_NOVOS_CRYSTAL_2: - case GO_NOVOS_CRYSTAL_3: - case GO_NOVOS_CRYSTAL_4: - RemoveDoor(go); - break; - } - } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const override + void OnGameObjectCreate(GameObject* go) override { - return new instance_drak_tharon_keep_InstanceScript(map); + switch (go->GetEntry()) + { + case GO_NOVOS_CRYSTAL_1: + case GO_NOVOS_CRYSTAL_2: + case GO_NOVOS_CRYSTAL_3: + case GO_NOVOS_CRYSTAL_4: + AddDoor(go); + break; + } + } + + void OnGameObjectRemove(GameObject* go) override + { + switch (go->GetEntry()) + { + case GO_NOVOS_CRYSTAL_1: + case GO_NOVOS_CRYSTAL_2: + case GO_NOVOS_CRYSTAL_3: + case GO_NOVOS_CRYSTAL_4: + RemoveDoor(go); + break; + } } }; @@ -121,7 +110,7 @@ class spell_dtk_summon_random_drakkari : public SpellScript void AddSC_instance_drak_tharon_keep() { - new instance_drak_tharon_keep(); + RegisterInstanceScript(instance_drak_tharon_keep, MAP_DRAK_THARON_KEEP); RegisterSpellScript(spell_dtk_raise_dead_aura); RegisterSpellScript(spell_dtk_summon_random_drakkari); } diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index 25a253a64..fcf59ae2e 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -63,23 +63,27 @@ public: memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); } - void OnCreatureCreate(Creature* pCreature) override + void OnCreatureCreate(Creature* creature) override { - switch (pCreature->GetEntry()) + switch (creature->GetEntry()) { case NPC_DRAKOS: - uiDrakosGUID = pCreature->GetGUID(); + uiDrakosGUID = creature->GetGUID(); break; case NPC_VAROS: - uiVarosGUID = pCreature->GetGUID(); + uiVarosGUID = creature->GetGUID(); break; case NPC_UROM: - uiUromGUID = pCreature->GetGUID(); + uiUromGUID = creature->GetGUID(); break; case NPC_EREGOS: - uiEregosGUID = pCreature->GetGUID(); + uiEregosGUID = creature->GetGUID(); break; } + + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + if (creature->EntryEquals(NPC_AMBER_DRAKE, NPC_EMERALD_DRAKE, NPC_RUBY_DRAKE)) + creature->SetFaction(FACTION_FRIENDLY); // Friendly faction to allow interaction from both factions } void OnGameObjectCreate(GameObject* pGo) override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 38a73129d..d35b11025 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -30,6 +30,7 @@ enum LokenSpells SPELL_LIGHTNING_NOVA_THUNDERS = 52663, SPELL_PULSING_SHOCKWAVE = 52961, + SPELL_PULSING_SHOCKWAVE_AURA = 59414, // Achievement ACHIEVEMENT_TIMELY_DEATH = 20384 @@ -49,15 +50,6 @@ enum Yells EMOTE_NOVA = 9 }; -enum LokenEvents -{ - EVENT_LIGHTNING_NOVA = 1, - EVENT_SHOCKWAVE = 2, - EVENT_ARC_LIGHTNING = 3, - EVENT_CHECK_HEALTH = 4, - EVENT_AURA_REMOVE = 5 -}; - struct boss_loken : public BossAI { boss_loken(Creature* creature) : BossAI(creature, DATA_LOKEN), _introDone(false) { } @@ -94,18 +86,49 @@ struct boss_loken : public BossAI _introDone = true; } + void OnAuraRemove(AuraApplication* auraApp, AuraRemoveMode /*mode*/) override + { + if (auraApp->GetBase()->GetId() == SPELL_LIGHTNING_NOVA_VISUAL) + { + me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS); + me->ClearUnitState(UNIT_STATE_CASTING); + me->ResumeChasingVictim(); + } + } + + void ScheduleTasks() override + { + me->m_Events.AddEventAtOffset([&] { + DoCastAOE(SPELL_PULSING_SHOCKWAVE_AURA, true); + me->ClearUnitState(UNIT_STATE_CASTING); // the aura above is a channeled spell, so we need this + DoCastSelf(SPELL_PULSING_SHOCKWAVE); + }, 3s); + + ScheduleTimedEvent(15s, [&] { + Talk(SAY_NOVA); + Talk(EMOTE_NOVA); + DoCastSelf(SPELL_LIGHTNING_NOVA_VISUAL, true); + DoCastSelf(SPELL_LIGHTNING_NOVA_THUNDERS, true); + DoCastAOE(SPELL_LIGHTNING_NOVA); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + }, 15s); + + if (IsHeroic()) + { + ScheduleTimedEvent(10s, [&] { + DoCastRandomTarget(SPELL_ARC_LIGHTNING, 0, 100.0f, false); + }, 12s); + + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); + } + } + void JustEngagedWith(Unit*) override { me->m_Events.KillAllEvents(false); _JustEngagedWith(); Talk(SAY_AGGRO); - - events.ScheduleEvent(EVENT_ARC_LIGHTNING, 10s); - events.ScheduleEvent(EVENT_SHOCKWAVE, 3s); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 15s); - - if (IsHeroic()) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); } void JustDied(Unit*) override @@ -122,46 +145,6 @@ struct boss_loken : public BossAI Talk(SAY_SLAY); } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - 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); - - events.DelayEvents(5s); - events.ScheduleEvent(EVENT_AURA_REMOVE, me->GetMap()->IsHeroic() ? 4s : 5s); - - me->CastSpell(me, SPELL_LIGHTNING_NOVA, false); - break; - case EVENT_SHOCKWAVE: - me->CastSpell(me, SPELL_PULSING_SHOCKWAVE, false); - break; - case EVENT_ARC_LIGHTNING: - if (Unit* target = SelectTargetFromPlayerList(100, SPELL_ARC_LIGHTNING)) - me->CastSpell(target, SPELL_ARC_LIGHTNING, false); - - events.Repeat(12s); - break; - case EVENT_AURA_REMOVE: - me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS); - break; - } - - DoMeleeAttackIfReady(); - } private: bool _introDone; }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp index 6071bc703..e24adc5ac 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/brann_bronzebeard.cpp @@ -334,7 +334,6 @@ public: SetDespawnAtEnd(false); ResetEvent(); - me->SetFaction(FACTION_FRIENDLY); me->SetReactState(REACT_PASSIVE); me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); @@ -366,21 +365,12 @@ public: case ACTION_START_ESCORT_EVENT: Start(false, ObjectGuid::Empty, 0, true, false); Talk(SAY_BRANN_ESCORT_START); - me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); me->SetReactState(REACT_AGGRESSIVE); me->SetRegeneratingHealth(true); break; case ACTION_START_TRIBUNAL: { me->SetReactState(REACT_PASSIVE); - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.IsEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - me->SetFaction(i->GetSource()->GetFaction()); - break; - } - SetEscortPaused(false); InitializeEvent(); me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE); @@ -394,7 +384,6 @@ public: break; case ACTION_GO_TO_SJONNIR: Talk(SAY_BRANN_ENTRANCE_MEET); - me->SetFaction(FACTION_FRIENDLY); me->SetReactState(REACT_PASSIVE); me->SetRegeneratingHealth(true); SetEscortPaused(false); @@ -406,7 +395,6 @@ public: me->SetImmuneToAll(true); break; case ACTION_START_SJONNIR_FIGHT: - me->SetFaction(FACTION_FRIENDLY); SetEscortPaused(false); break; case ACTION_SJONNIR_DEAD: diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/isle_of_conquest.cpp index 240fa79f6..41a5b36ae 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/isle_of_conquest.cpp @@ -209,14 +209,14 @@ public: enum BossIoCEvents { EVENT_CHECK_RAGE = 1, - EVENT_BRUTAL_STRIKE = 2, + EVENT_MORTAL_STRIKE = 2, EVENT_CRUSHING_LEAP = 3, EVENT_DAGGER_THROW = 4, }; enum BossIoCSpells { - SPELL_IOCBOSS_BRUTAL_STRIKE = 58460, + SPELL_IOCBOSS_MORTAL_STRIKE = 39171, SPELL_IOCBOSS_CRUSHING_LEAP = 68506, SPELL_IOCBOSS_DAGGER_THROW = 67280, SPELL_IOCBOSS_RAGE = 66776, @@ -262,7 +262,7 @@ public: void JustEngagedWith(Unit* /*who*/) override { events.ScheduleEvent(EVENT_CHECK_RAGE, 2s); - events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 6s); + events.ScheduleEvent(EVENT_MORTAL_STRIKE, 6s); events.ScheduleEvent(EVENT_CRUSHING_LEAP, 22s); events.ScheduleEvent(EVENT_DAGGER_THROW, 10s); } @@ -282,8 +282,8 @@ public: CheckRageBuff(); events.Repeat(2s); break; - case EVENT_BRUTAL_STRIKE: - me->CastSpell(me->GetVictim(), SPELL_IOCBOSS_BRUTAL_STRIKE, false); + case EVENT_MORTAL_STRIKE: + DoCastVictim(SPELL_IOCBOSS_MORTAL_STRIKE); events.Repeat(6s); break; case EVENT_CRUSHING_LEAP: diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 24704b502..ec6a55f17 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -1989,6 +1989,40 @@ class spell_soul_deflection : public AuraScript } }; +enum SpellBloodHaze +{ + SPELL_BLOODSPORE_HAZE = 50380, + SPELL_PSYCHOSIS = 50396 +}; + +// 50380 - Bloodspore Haze +class spell_bloodspore_haze : public SpellScript +{ + PrepareSpellScript(spell_bloodspore_haze); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PSYCHOSIS }); + } + + void HandleEffectHit(SpellEffIndex /*effIndex*/) + { + if (!GetHitUnit()) + return; + + if (GetHitUnit()->GetAuraCount(SPELL_BLOODSPORE_HAZE) >= 5) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PSYCHOSIS, true); + GetHitUnit()->RemoveAura(SPELL_BLOODSPORE_HAZE); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_bloodspore_haze::HandleEffectHit, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + void AddSC_borean_tundra() { RegisterSpellScript(spell_q11919_q11940_drake_hunt_aura); @@ -2013,4 +2047,5 @@ void AddSC_borean_tundra() RegisterCreatureAI(npc_jenny); RegisterSpellScript(spell_necropolis_beam); RegisterSpellScript(spell_soul_deflection); + RegisterSpellScript(spell_bloodspore_haze); } diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 56abff11e..bccd217ad 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -390,116 +390,6 @@ class spell_q12227_camera_shake : public SpellScript OnEffectHitTarget += SpellEffectFn(spell_q12227_camera_shake::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); } }; -// Tallhorn Stage - -enum TallhornStage -{ - //Gameobject - OBJECT_HAUNCH = 188665 -}; - -class npc_tallhorn_stag : public CreatureScript -{ -public: - npc_tallhorn_stag() : CreatureScript("npc_tallhorn_stag") { } - - struct npc_tallhorn_stagAI : public ScriptedAI - { - npc_tallhorn_stagAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _phase = 1; - } - - void UpdateAI(uint32 /*diff*/) override - { - if (_phase == 1) - { - if (me->FindNearestGameObject(OBJECT_HAUNCH, 2.0f)) - { - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetImmuneToPC(true); - me->ReplaceAllDynamicFlags(UNIT_DYNFLAG_DEAD); - } - _phase = 0; - } - DoMeleeAttackIfReady(); - } - private: - uint8 _phase; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_tallhorn_stagAI(creature); - } -}; - -// Amberpine Woodsman - -enum AmberpineWoodsman -{ - // Creature - NPC_TALLHORN_STAG = 26363 -}; - -enum AmberpineWoodsmanEvents -{ - EVENT_WOODSMAN_1 = 1, - EVENT_WOODSMAN_2 = 2 -}; - -class npc_amberpine_woodsman : public CreatureScript -{ -public: - npc_amberpine_woodsman() : CreatureScript("npc_amberpine_woodsman") { } - - struct npc_amberpine_woodsmanAI : public ScriptedAI - { - npc_amberpine_woodsmanAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - if (me->FindNearestCreature(NPC_TALLHORN_STAG, 0.2f)) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING); - } - else - _events.ScheduleEvent(EVENT_WOODSMAN_1, 0ms); - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_WOODSMAN_1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LOOT); - _events.ScheduleEvent(EVENT_WOODSMAN_2, 3s); - break; - case EVENT_WOODSMAN_2: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H); - _events.ScheduleEvent(EVENT_WOODSMAN_1, 4s); - break; - default: - break; - } - } - UpdateVictim(); - } - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_amberpine_woodsmanAI(creature); - } -}; /*###### ## Quest 12288: Overwhelmed! @@ -1178,8 +1068,6 @@ void AddSC_grizzly_hills() new npc_emily(); new npc_mrfloppy(); new npc_ravenous_worg(); - new npc_tallhorn_stag(); - new npc_amberpine_woodsman(); RegisterCreatureAI(npc_wounded_skirmisher); RegisterSpellScript(spell_renew_skirmisher); new npc_venture_co_straggler(); diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index 1a97cd121..4af05b4b9 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -49,7 +49,6 @@ class spell_q12726_song_of_wind_and_water : public SpellScript cr->SetDisplayId(cr->GetDisplayId() == NPC_SOWAW_WATER_MODEL ? NPC_SOWAW_WIND_MODEL : NPC_SOWAW_WATER_MODEL); if (Player* player = cr->GetCharmerOrOwnerPlayerOrPlayerItself()) { - player->KilledMonsterCredit(cr->GetDisplayId() == NPC_SOWAW_WATER_MODEL ? 29008 : 29009); CreatureTemplate const* ct = sObjectMgr->GetCreatureTemplate(cr->GetDisplayId() == NPC_SOWAW_WIND_MODEL ? NPC_SOWAW_WIND_ELEMENTAL : NPC_SOWAW_WATER_ELEMENTAL); for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) cr->m_spells[i] = ct->spells[i]; @@ -1107,108 +1106,6 @@ class spell_q12589_shoot_rjr : public SpellScript } }; -/*###### -## Quest: Reconnaissance Flight (12671) -######*/ -enum ReconnaissanceFlight -{ - NPC_PLANE = 28710, // Vic's Flying Machine - NPC_PILOT = 28646, - - VIC_SAY_0 = 0, - VIC_SAY_1 = 1, - VIC_SAY_2 = 2, - VIC_SAY_3 = 3, - VIC_SAY_4 = 4, - VIC_SAY_5 = 5, - VIC_SAY_6 = 6, - PLANE_EMOTE = 0, - - AURA_ENGINE = 52255, // Engine on Fire - - SPELL_LAND = 52226, // Land Flying Machine - SPELL_CREDIT = 53328 // Land Flying Machine Credit -}; - -class npc_vics_flying_machine : public CreatureScript -{ -public: - npc_vics_flying_machine() : CreatureScript("npc_vics_flying_machine") { } - - struct npc_vics_flying_machineAI : public VehicleAI - { - npc_vics_flying_machineAI(Creature* creature) : VehicleAI(creature) - { - pointId = 0; - } - - uint8 pointId; - - void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override - { - if (apply && passenger->IsPlayer()) - { - me->GetMotionMaster()->MovePath(NPC_PLANE, FORCED_MOVEMENT_NONE, PathSource::WAYPOINT_MGR); - } - } - - void MovementInform(uint32 type, uint32 /*id*/) override - { - if (type != ESCORT_MOTION_TYPE) - return; - - if (Vehicle* veh = me->GetVehicleKit()) - if (Unit* pilot = veh->GetPassenger(0)) - switch (pointId) - { - case 5: - pilot->ToCreature()->AI()->Talk(VIC_SAY_0); - break; - case 11: - pilot->ToCreature()->AI()->Talk(VIC_SAY_1); - break; - case 12: - pilot->ToCreature()->AI()->Talk(VIC_SAY_2); - break; - case 14: - pilot->ToCreature()->AI()->Talk(VIC_SAY_3); - break; - case 15: - pilot->ToCreature()->ToCreature()->AI()->Talk(VIC_SAY_4); - break; - case 17: - pilot->ToCreature()->AI()->Talk(VIC_SAY_5); - break; - case 21: - pilot->ToCreature()->AI()->Talk(VIC_SAY_6); - break; - case 25: - Talk(PLANE_EMOTE); - DoCastSelf(AURA_ENGINE); - break; - } - pointId++; - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if (spell->Id == SPELL_LAND) - { - Unit* passenger = me->GetVehicleKit()->GetPassenger(1); // player should be on seat 1 - if (passenger && passenger->IsPlayer()) - passenger->CastSpell(passenger, SPELL_CREDIT, true); - - me->DespawnOrUnsummon(); - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_vics_flying_machineAI(creature); - } -}; - /*###### ## Quest Dreadsaber Mastery: Stalking the Prey (12550) ######*/ @@ -1296,7 +1193,6 @@ void AddSC_sholazar_basin() new npc_jungle_punch_target(); RegisterSpellScript(spell_q12620_the_lifewarden_wrath); RegisterSpellScript(spell_q12589_shoot_rjr); - new npc_vics_flying_machine(); RegisterSpellScript(spell_shango_tracks); RegisterSpellScript(spell_q12611_deathbolt); diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 87ca825ed..2bdf9dba9 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -31,6 +31,7 @@ enum qSniffingOutThePerpetrator { NPC_FROSTHOUND = 29677, + NPC_FROSTBITE = 29903, SPELL_SUMMON_PURSUERS_PERIODIC = 54993, SPELL_SNIFFING_CREDIT = 55477, TALK_EMOTE_FROSTHOUND_SNIFF = 0, @@ -41,7 +42,7 @@ enum qSniffingOutThePerpetrator struct npc_frosthound : public npc_escortAI { - explicit npc_frosthound(Creature* creature) : npc_escortAI(creature), _summons(creature) {} + explicit npc_frosthound(Creature* creature) : npc_escortAI(creature), _summons(creature), _completionWaypoint((creature->GetEntry() == NPC_FROSTBITE) ? 19 : 34) { } void AttackStart(Unit* /*who*/) override {} void JustEngagedWith(Unit* /*who*/) override {} @@ -77,20 +78,15 @@ struct npc_frosthound : public npc_escortAI if (!player) return; - switch (waypointId) + if (waypointId == 0) + Talk(TALK_SEEN, player); + else if (waypointId == _completionWaypoint) { - case 0: - Talk(TALK_SEEN, player); - break; - case 34: - Talk(TALK_EMOTE_TRACKED_COMPLETE, me); - Talk(TALK_CONFRONT, player); - if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit()) - summoner->ToPlayer()->KilledMonsterCredit(NPC_FROSTHOUND); - _summons.DespawnAll(); - break; - default: - break; + Talk(TALK_EMOTE_TRACKED_COMPLETE, me); + Talk(TALK_CONFRONT, player); + if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit()) + summoner->ToPlayer()->KilledMonsterCredit(NPC_FROSTHOUND); // same credit for Alliance and Horde + _summons.DespawnAll(); } } @@ -112,6 +108,7 @@ struct npc_frosthound : public npc_escortAI private: SummonList _summons; + uint32 _completionWaypoint; }; enum eIronWatcher diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index d0ef8ada5..230678a4e 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -265,6 +265,7 @@ enum OverlordDrakuru NPC_TOTALLY_GENERIC_BUNNY = 29100, NPC_TOTALLY_GENERIC_BUNNY_JSB = 28960, GO_DRAKURUS_LAST_WISH = 202357, + GO_DRAKURUS_BONE = 191458, ACTION_SUMMON_DRAKURU_LAST_WISH = 1, ACTION_DESTROY_DRAKURU_LAST_WISH = 2, @@ -316,7 +317,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI { npc_overlord_drakuru_betrayal(Creature* creature) : ScriptedAI(creature), _summons(me), _state(BETRAYAL_NOT_STARTED) { - me->SetCombatMovement(false); + me->SetControlled(true, UNIT_STATE_ROOT); } void EnterEvadeMode(EvadeReason why) override @@ -375,7 +376,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI { if (Player* player = who->ToPlayer()) { - bool shouldStartEvent = (_state == BETRAYAL_NOT_STARTED) && IsPlayerOnQuest(player) && player->HasAura(SPELL_SCOURGE_DISGUISE) && player->IsWithinDistInMap(me, 80.0f); + bool shouldStartEvent = (_state == BETRAYAL_NOT_STARTED) && IsPlayerOnQuest(player) && player->HasAura(SPELL_SCOURGE_DISGUISE) && player->IsWithinDistInMap(me, 80.0f) && !me->FindNearestGameObject(GO_DRAKURUS_BONE, 80.0f); if (shouldStartEvent) { me->SetVisible(true); @@ -587,6 +588,7 @@ struct npc_overlord_drakuru_betrayal : public ScriptedAI lich->GetMotionMaster()->MovePoint(0, 6141.2393, -2011.2728, 589.8653); break; case EVENT_BETRAYAL_EPILOGUE_10: + _state = BETRAYAL_EVADE; EnterEvadeMode(EVADE_REASON_OTHER); break; } diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index 79ab9a318..0827a0e63 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -141,13 +141,15 @@ public: void MoveInLineOfSight(Unit* who) override { - if (!who || me->getStandState() != UNIT_STAND_STATE_SLEEP || !who->IsPlayer() || me->GetDistance2d(who) > 90.0f || who->ToPlayer()->IsGameMaster()) + if (!who || me->getStandState() != UNIT_STAND_STATE_SLEEP || !who->IsPlayer() || + who->ToPlayer()->IsGameMaster() || me->GetDistance2d(who) > 90.0f || + !me->isInFront(who, M_PI / 4.0f) || !me->IsWithinLOSInMap(who)) return; me->SetInCombatWithZone(); me->SetStandState(UNIT_STAND_STATE_STAND); - ScheduleUniqueTimedEvent(5s, [&] { // 15s + ScheduleUniqueTimedEvent(5s, [&] { me->SetStandState(UNIT_STAND_STATE_SUBMERGED); DoCastSelf(SPELL_SUMMON_ESSENCE_OF_SUFFERING); }, EVENT_ESSENCE_OF_SUFFERING);