From ba01651fffe7f655abcec23be2da902184d4ef20 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 1 May 2021 12:19:50 +0200 Subject: [PATCH] Scripts/SFK: reworked Baron Silverlaine encounter --- .../world/4.3.4/2021_05_01_00_world.sql | 4 + .../ShadowfangKeep/boss_baron_silverlaine.cpp | 750 +++++++----------- .../ShadowfangKeep/shadowfang_keep.h | 9 +- 3 files changed, 284 insertions(+), 479 deletions(-) create mode 100644 sql/updates/world/4.3.4/2021_05_01_00_world.sql diff --git a/sql/updates/world/4.3.4/2021_05_01_00_world.sql b/sql/updates/world/4.3.4/2021_05_01_00_world.sql new file mode 100644 index 00000000000..09625deadd7 --- /dev/null +++ b/sql/updates/world/4.3.4/2021_05_01_00_world.sql @@ -0,0 +1,4 @@ +UPDATE `creature_template` SET `ScriptName`= 'npc_sfk_worgen_spirit' WHERE `entry` IN (50851, 50857, 50869, 50834); +UPDATE `creature_template_addon` SET `auras`= '93853 7486' WHERE `entry` IN (50869, 51034); +UPDATE `creature_template` SET `DamageModifier`= 60, `BaseVariance`= 0.5 WHERE `entry` IN (50852, 51086, 51034, 50835); +UPDATE `creature_template` SET `DamageModifier`= 5, `BaseVariance`= 0.5 WHERE `entry`= 50924; diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_baron_silverlaine.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_baron_silverlaine.cpp index 1e23b1857fb..3b7ad85d87d 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_baron_silverlaine.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_baron_silverlaine.cpp @@ -43,14 +43,13 @@ enum Events // Odo the Blindwatcher EVENT_HOWLING_RAGE, + EVENT_BLINDING_SHADOWS, // Wolf Master Nandos EVENT_CLAW, // Razorclaw the Butcher EVENT_SPECTRAL_RUSH, - EVENT_SPECTRAL_RAVAGING, - EVENT_BUTCHER_DRAIN, // Rethilgore EVENT_SOUL_DRAIN @@ -63,540 +62,343 @@ enum Actions enum Spells { - SPELL_VEIL_OF_SHADOWS = 23224, - SPELL_CURSED_VEIL = 93956, - SPELL_SUMMON_WORGEN_SPIRIT = 93857, + SPELL_VEIL_OF_SHADOWS = 23224, + SPELL_CURSED_VEIL = 93956, + SPELL_SUMMON_WORGEN_SPIRIT = 93857, - SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY = 93896, // Dummy Summon - SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_SUMMON = 93899, + SPELL_SUMMON_SPIRIT_OF_WOLF_MASTER_NANDOS_DUMMY = 93896, // Dummy Summon + SPELL_SUMMON_SPIRIT_OF_WOLF_MASTER_NANDOS_SUMMON = 93899, - SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY = 93859, // Dummy Summon - SPELL_SUMMON_WORGEN_SPIRIT_ODO_SUMMON = 93899, + SPELL_SUMMON_SPIRIT_OF_ODO_THE_BLINDWATCHER_DUMMY = 93859, // Dummy Summon + SPELL_SUMMON_SPIRIT_OF_ODO_THE_BLINDWATCHER_SUMMON = 93864, - SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY = 93921, // Dummy Summon - SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_SUMMON = 93924, + SPELL_SUMMON_SPIRIT_OF_RAZORCLAW_THE_BUTCHER_DUMMY = 93921, // Dummy Summon + SPELL_SUMMON_SPIRIT_OF_RAZORCLAW_THE_BUTCHER_SUMMON = 93924, - SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY = 93925, // Dummy Summon - SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_SUMMON = 93927, + SPELL_SUMMON_SPIRIT_OF_RETHILGORE_DUMMY = 93925, // Dummy Summon + SPELL_SUMMON_SPIRIT_OF_RETHILGORE_SUMMON = 93927, // Odo the Blindwatcher - SPELL_HOWLING_RAGE = 93931, - SPELL_BLINDING_SHADOWS = 93952, + SPELL_HOWLING_RAGE = 93931, + SPELL_BLINDING_SHADOWS = 93952, // Wolf Master Nandos - SPELL_CLAW = 16827, - SPELL_SUMMON_LUPINE_SPECTRE = 94199, + SPELL_CLAW = 93861, + SPELL_SUMMON_LUPINE_SPECTRE = 94199, // Razorclaw the Butcher - SPELL_SPECTRAL_RAVAGING = 93930, - SPELL_SPECTRAL_RUSH = 93914, - SPELL_BUTCHER_DRAIN = 7485, + SPELL_SPECTRAL_RUSH = 93914, // Rethilgore - SPELL_SOUL_DRAIN = 93863 + SPELL_SOUL_DRAIN = 93863 }; -class boss_baron_silverlaine : public CreatureScript +struct boss_baron_silverlaine : public BossAI { -public: - boss_baron_silverlaine() : CreatureScript("boss_baron_silverlaine") { } + boss_baron_silverlaine(Creature* creature) : BossAI(creature, DATA_BARON_SILVERLAINE), _summonedSpiritCounter(0) { } - struct boss_baron_silverlaineAI : public BossAI + void InitializeAI() override { - boss_baron_silverlaineAI(Creature* creature) : BossAI(creature, DATA_BARON_SILVERLAINE) { } - - void Reset() override + // Initialize the summon spells that we are going to use in this encounter + _worgenSummonSpells = { - _Reset(); - _worgenCounter = 0; + SPELL_SUMMON_SPIRIT_OF_WOLF_MASTER_NANDOS_DUMMY, + SPELL_SUMMON_SPIRIT_OF_ODO_THE_BLINDWATCHER_DUMMY, + SPELL_SUMMON_SPIRIT_OF_RAZORCLAW_THE_BUTCHER_DUMMY, + SPELL_SUMMON_SPIRIT_OF_RETHILGORE_DUMMY + }; + + Trinity::Containers::RandomResize(_worgenSummonSpells, IsHeroic() ? 3 : 2); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + + if (IsHeroic()) + events.ScheduleEvent(EVENT_CURSED_VEIL, 5s); + else + events.ScheduleEvent(EVENT_VEIL_OF_SHADOW, 5s); + } + + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + DespawnWorgenSpirits(); + _JustDied(); + } + + void KilledUnit(Unit* target) override + { + if (target->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + summons.DespawnAll(); + instance->SetBossState(DATA_BARON_SILVERLAINE, FAIL); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + DespawnWorgenSpirits(); + _DespawnAtEvade(); + } + + void DespawnWorgenSpirits() + { + EntryCheckPredicate nandos(NPC_WOLF_MASTER_NANDOS); + summons.DoAction(ACTION_DESPAWN, nandos); + + EntryCheckPredicate odo(NPC_ODO_THE_BLINDWATCHER); + summons.DoAction(ACTION_DESPAWN, odo); + + EntryCheckPredicate razorclaw(NPC_RAZORCLAW_THE_BUTCHER); + summons.DoAction(ACTION_DESPAWN, razorclaw); + + EntryCheckPredicate rethilgore(NPC_RETHILGORE); + summons.DoAction(ACTION_DESPAWN, rethilgore); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + switch (summon->GetEntry()) + { + case NPC_WORGEN_SPIRIT_ODO: + summon->CastSpell(summon, SPELL_SUMMON_SPIRIT_OF_ODO_THE_BLINDWATCHER_SUMMON); + break; + case NPC_WORGEN_SPIRIT_RAZORCLAW: + summon->CastSpell(summon, SPELL_SUMMON_SPIRIT_OF_WOLF_MASTER_NANDOS_SUMMON); + break; + case NPC_WORGEN_SPIRIT_NANDOS: + summon->CastSpell(summon, SPELL_SUMMON_SPIRIT_OF_WOLF_MASTER_NANDOS_SUMMON); + break; + case NPC_WORGEN_SPIRIT_RETHILGORE: + summon->CastSpell(summon, SPELL_SUMMON_SPIRIT_OF_RETHILGORE_SUMMON); + break; + default: + break; } + } - void JustEngagedWith(Unit* who) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (IsHeroic()) { - BossAI::JustEngagedWith(who); - Talk(SAY_AGGRO); - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - if (IsHeroic()) - events.ScheduleEvent(EVENT_CURSED_VEIL, Seconds(6)); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - DespawnWorgenSpirits(); - _JustDied(); - } - - void KilledUnit(Unit* target) override - { - if (target->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void EnterEvadeMode(EvadeReason /*why*/) override - { - _EnterEvadeMode(); - summons.DespawnAll(); - instance->SetBossState(DATA_BARON_SILVERLAINE, FAIL); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - DespawnWorgenSpirits(); - _DespawnAtEvade(); - } - - void DespawnWorgenSpirits() - { - EntryCheckPredicate nandos(NPC_WOLF_MASTER_NANDOS); - summons.DoAction(ACTION_DESPAWN, nandos); - - EntryCheckPredicate odo(NPC_ODO_THE_BLINDWATCHER); - summons.DoAction(ACTION_DESPAWN, odo); - - EntryCheckPredicate razorclaw(NPC_RAZORCLAW_THE_BUTCHER); - summons.DoAction(ACTION_DESPAWN, razorclaw); - - EntryCheckPredicate rethilgore(NPC_RETHILGORE); - summons.DoAction(ACTION_DESPAWN, rethilgore); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - switch (summon->GetEntry()) + if (me->HealthBelowPctDamaged(90, damage) && _summonedSpiritCounter == 0) { - case NPC_ODO_DUMMY: - summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_ODO_SUMMON); + events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, 1ms); + ++_summonedSpiritCounter; + } + else if (me->HealthBelowPctDamaged(60, damage) && _summonedSpiritCounter == 1) + { + events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, 1ms); + ++_summonedSpiritCounter; + } + else if (me->HealthBelowPctDamaged(30, damage) && _summonedSpiritCounter == 2) + { + events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, 1ms); + ++_summonedSpiritCounter; + } + } + else + { + if (me->HealthBelowPctDamaged(75, damage) && _summonedSpiritCounter == 0) + { + events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, 1ms); + ++_summonedSpiritCounter; + } + else if (me->HealthBelowPctDamaged(35, damage) && _summonedSpiritCounter == 1) + { + events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, 1ms); + ++_summonedSpiritCounter; + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_VEIL_OF_SHADOW: + DoCastVictim(SPELL_VEIL_OF_SHADOWS); + events.Repeat(17s); break; - case NPC_NANDOS_DUMMY: - summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_SUMMON); + case EVENT_CURSED_VEIL: + DoCastAOE(SPELL_CURSED_VEIL); + events.Repeat(27s); break; - case NPC_RAZORCLAW_DUMMY: - summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_SUMMON); - break; - case NPC_RETHILGORE_DUMMY: - summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_SUMMON); + case EVENT_SUMMON_WORGEN_SPIRIT: + { + int32 bp0 = _worgenSummonSpells.front(); + _worgenSummonSpells.erase(_worgenSummonSpells.begin()); + DoCastAOE(SPELL_SUMMON_WORGEN_SPIRIT, CastSpellExtraArgs().AddSpellBP0(bp0)); break; + } default: break; } - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (IsHeroic()) - { - if (me->HealthBelowPctDamaged(90, damage) && _worgenCounter == 0) - { - events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1))); - _worgenCounter++; - } - else if (me->HealthBelowPctDamaged(60, damage) && _worgenCounter == 1) - { - events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1))); - _worgenCounter++; - } - else if (me->HealthBelowPctDamaged(30, damage) && _worgenCounter == 2) - { - events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1))); - _worgenCounter++; - } - } - else - { - if (me->HealthBelowPctDamaged(75, damage) && _worgenCounter == 0) - { - events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1))); - _worgenCounter++; - } - else if (me->HealthBelowPctDamaged(35, damage) && _worgenCounter == 1) - { - events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1))); - _worgenCounter++; - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) return; - - while(uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CURSED_VEIL: - DoCastAOE(SPELL_CURSED_VEIL); - events.Repeat(Seconds(26) + Milliseconds(500)); - break; - case EVENT_SUMMON_WORGEN_SPIRIT: - DoCastAOE(SPELL_SUMMON_WORGEN_SPIRIT); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); } - private: - uint8 _worgenCounter; - }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowfangKeepAI(creature); + DoMeleeAttackIfReady(); } +private: + std::vector _worgenSummonSpells; + uint8 _summonedSpiritCounter; }; -class npc_wolf_master_nandos : public CreatureScript +struct npc_sfk_worgen_spirit : public ScriptedAI { -public: - npc_wolf_master_nandos() : CreatureScript("npc_wolf_master_nandos") { } + npc_sfk_worgen_spirit(Creature* creature) : ScriptedAI(creature), _instance(nullptr), _summons(me) { } - struct npc_wolf_master_nandosAI : public ScriptedAI + void InitializeAI() override { - npc_wolf_master_nandosAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + _instance = me->GetInstanceScript(); + } - void IsSummonedBy(Unit* /*summoner*/) override - { - if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE)) + void JustAppeared() override + { + if (!_instance) + return; + + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE)) + if (silverlaine->IsAIEnabled) silverlaine->AI()->JustSummoned(me); - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_CLAW, Seconds(1) + Milliseconds(600)); - for (uint8 i = 0; i < 3; i++) - DoCast(me, SPELL_SUMMON_LUPINE_SPECTRE, true); - } + DoZoneInCombat(); - void JustDied(Unit* /*killer*/) override + switch (me->GetEntry()) { - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Seconds(5)); + case NPC_WOLF_MASTER_NANDOS: + for (uint8 i = 0; i < 3; ++i) + DoCastSelf(SPELL_SUMMON_LUPINE_SPECTRE); + _events.ScheduleEvent(EVENT_CLAW, 7s); + break; + case NPC_ODO_THE_BLINDWATCHER: + _events.ScheduleEvent(EVENT_HOWLING_RAGE, 5s); + _events.ScheduleEvent(EVENT_BLINDING_SHADOWS, 5s); + break; + case NPC_RAZORCLAW_THE_BUTCHER: + _events.ScheduleEvent(EVENT_SPECTRAL_RUSH, 4s); + break; + case NPC_RETHILGORE: + _events.ScheduleEvent(EVENT_SOUL_DRAIN, 8s); + break; + default: + break; } + } - void DoAction(int32 action) override + void JustDied(Unit* /*killer*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _summons.DespawnAll(); + me->DespawnOrUnsummon(5s); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void DoAction(int32 action) override + { + switch (action) { - switch (action) + case ACTION_DESPAWN: + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->DespawnOrUnsummon(); + _summons.DespawnAll(); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - case ACTION_DESPAWN: - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Milliseconds(1)); + case EVENT_CLAW: + DoCastVictim(SPELL_CLAW); + _events.Repeat(6s, 7s); + break; + case EVENT_HOWLING_RAGE: + DoCastAOE(SPELL_HOWLING_RAGE); + _events.Repeat(11s); + break; + case EVENT_BLINDING_SHADOWS: + DoCastVictim(SPELL_BLINDING_SHADOWS); + _events.Repeat(14s); + break; + case EVENT_SPECTRAL_RUSH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.f, true, false)) + DoCast(target, SPELL_SPECTRAL_RUSH); + else + DoCastVictim(SPELL_SPECTRAL_RUSH); + _events.Repeat(11s); + break; + case EVENT_SOUL_DRAIN: + DoCastVictim(SPELL_SOUL_DRAIN); + _events.Repeat(13s); break; default: break; } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CLAW: - DoCastVictim(SPELL_CLAW); - events.Repeat(Seconds(3)); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - - private: - InstanceScript* _instance; - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowfangKeepAI(creature); + DoMeleeAttackIfReady(); } + +private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; }; -class npc_odo_the_blindwatcher : public CreatureScript +class spell_sfk_summon_worgen_spirit : public SpellScript { -public: - npc_odo_the_blindwatcher() : CreatureScript("npc_odo_the_blindwatcher") { } - - struct npc_odo_the_blindwatcherAI : public ScriptedAI + void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - npc_odo_the_blindwatcherAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void IsSummonedBy(Unit* /*summoner*/) override - { - if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE)) - silverlaine->AI()->JustSummoned(me); - - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - DoZoneInCombat(); - _events.ScheduleEvent(EVENT_HOWLING_RAGE, Seconds(5) + Milliseconds(500)); - } - - void JustDied(Unit* /*killer*/) override - { - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Seconds(5)); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_DESPAWN: - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Milliseconds(1)); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_HOWLING_RAGE: - DoCastVictim(SPELL_BLINDING_SHADOWS); - DoCastAOE(SPELL_HOWLING_RAGE); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - InstanceScript* _instance; - EventMap _events; - - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowfangKeepAI(creature); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, GetEffectValue()); } -}; -class npc_razorclaw_the_butcher : public CreatureScript -{ -public: - npc_razorclaw_the_butcher() : CreatureScript("npc_razorclaw_the_butcher") { } - - struct npc_razorclaw_the_butcherAI : public ScriptedAI + void Register() override { - npc_razorclaw_the_butcherAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void IsSummonedBy(Unit* /*summoner*/) override - { - _player = ObjectGuid::Empty; - if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE)) - silverlaine->AI()->JustSummoned(me); - - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - DoZoneInCombat(); - _events.ScheduleEvent(EVENT_SPECTRAL_RUSH, Seconds(16)); - _events.ScheduleEvent(EVENT_BUTCHER_DRAIN, Seconds(2) + Milliseconds(500)); - } - - void JustDied(Unit* /*killer*/) override - { - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Seconds(5)); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_DESPAWN: - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Milliseconds(1)); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SPECTRAL_RUSH: - if (Unit* target = SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, 50.0f, true)) - { - _events.ScheduleEvent(EVENT_SPECTRAL_RAVAGING, Milliseconds(500)); - DoCast(target, SPELL_SPECTRAL_RUSH); - _player = target->GetGUID(); - } - break; - case EVENT_SPECTRAL_RAVAGING: - if (Unit* target = ObjectAccessor::GetPlayer(*me, _player)) - DoCast(target, SPELL_SPECTRAL_RAVAGING); - break; - case EVENT_BUTCHER_DRAIN: - DoCastVictim(SPELL_BUTCHER_DRAIN); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - InstanceScript* _instance; - EventMap _events; - ObjectGuid _player; - - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowfangKeepAI(creature); - } -}; - -class npc_rethilgore : public CreatureScript -{ -public: - npc_rethilgore() : CreatureScript("npc_rethilgore") { } - - struct npc_rethilgoreAI : public ScriptedAI - { - npc_rethilgoreAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void IsSummonedBy(Unit* /*summoner*/) override - { - if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE)) - silverlaine->AI()->JustSummoned(me); - - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - DoZoneInCombat(); - _events.ScheduleEvent(EVENT_SOUL_DRAIN, Seconds(10)); - } - - void JustDied(Unit* /*killer*/) override - { - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Seconds(5)); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_DESPAWN: - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->DespawnOrUnsummon(Milliseconds(1)); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SOUL_DRAIN: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) - DoCast(target, SPELL_SOUL_DRAIN); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - InstanceScript* _instance; - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const - { - return GetShadowfangKeepAI(creature); - } -}; - -class spell_sfk_summon_worgen_spirit : public SpellScriptLoader -{ -public: - spell_sfk_summon_worgen_spirit() : SpellScriptLoader("spell_sfk_summon_worgen_spirit") { } - - class spell_sfk_summon_worgen_spirit_SpellScript : public SpellScript - { - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo( - { - SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY, - SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY, - SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY, - SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY - }); - } - - void HandleScriptEffect(SpellEffIndex /*effIndex*/) - { - if (Unit* caster = GetCaster()) - { - switch (RAND(0, 3)) - { - case 0: // Nandos - caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY, true); - break; - case 1: // Odo - caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY, true); - break; - case 2: // Razorclaw - caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY, true); - break; - case 3: // Rethilgore - caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY, true); - break; - } - } - } - - void Register() override - { - OnEffectLaunch.Register(&spell_sfk_summon_worgen_spirit_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_sfk_summon_worgen_spirit_SpellScript(); + OnEffectHitTarget.Register(&spell_sfk_summon_worgen_spirit::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; void AddSC_boss_baron_silverlaine() { - new boss_baron_silverlaine(); - new npc_wolf_master_nandos(); - new npc_odo_the_blindwatcher(); - new npc_razorclaw_the_butcher(); - new npc_rethilgore(); - new spell_sfk_summon_worgen_spirit(); + RegisterShadowfangKeepCreatureAI(boss_baron_silverlaine); + RegisterShadowfangKeepCreatureAI(npc_sfk_worgen_spirit); + RegisterSpellScript(spell_sfk_summon_worgen_spirit); } diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h index e4a1838a412..e60e62d6ec5 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h @@ -57,14 +57,13 @@ enum SKCreatures // Encounter related creatures /*Baron Silverlaine*/ - NPC_NANDOS_DUMMY = 51047, + NPC_WORGEN_SPIRIT_NANDOS = 51047, NPC_WOLF_MASTER_NANDOS = 50851, - NPC_LUPINE_SPECTRE = 50923, - NPC_ODO_DUMMY = 50934, + NPC_WORGEN_SPIRIT_ODO = 50934, NPC_ODO_THE_BLINDWATCHER = 50857, - NPC_RAZORCLAW_DUMMY = 51080, + NPC_WORGEN_SPIRIT_RAZORCLAW = 51080, NPC_RAZORCLAW_THE_BUTCHER = 50869, - NPC_RETHILGORE_DUMMY = 51085, + NPC_WORGEN_SPIRIT_RETHILGORE = 51085, NPC_RETHILGORE = 50834, /*Commander Springvale*/