From c88a6193f6b8f59e2587eacaee3fb8be297fecc2 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 11 Jan 2020 15:03:37 +0100 Subject: [PATCH] Scripts/SFK: rewrite Lord Godfrey encounter * updated scripts to new model * corrected timer handling * removed unneeded script for Bloodthirsty Ghouls * properly handle left / right cast visuals for summoning Bloodthirsty Ghouls and Pistol Barrage * reset achievement progress on each new attempt --- .../custom/custom_2020_01_11_01_world.sql | 6 + .../ShadowfangKeep/boss_lord_godfrey.cpp | 625 ++++++++---------- .../ShadowfangKeep/boss_lord_walden.cpp | 1 - .../instance_shadowfang_keep.cpp | 5 + 4 files changed, 270 insertions(+), 367 deletions(-) create mode 100644 sql/updates/world/custom/custom_2020_01_11_01_world.sql diff --git a/sql/updates/world/custom/custom_2020_01_11_01_world.sql b/sql/updates/world/custom/custom_2020_01_11_01_world.sql new file mode 100644 index 00000000000..02462966099 --- /dev/null +++ b/sql/updates/world/custom/custom_2020_01_11_01_world.sql @@ -0,0 +1,6 @@ +UPDATE `creature_template` SET `ScriptName`= '' WHERE `ScriptName`= 'npc_sfk_bloodthirsty_ghoul'; +DELETE FROM `achievement_criteria_data` WHERE `ScriptName`= 'achievement_bullet_time'; +UPDATE `spell_script_names` SET `ScriptName`= 'spell_godfrey_summon_bloodthirsty_ghouls' WHERE `ScriptName`= 'spell_sfk_summon_bloodthirsty_ghouls'; +UPDATE `spell_script_names` SET `ScriptName`= 'spell_godfrey_pistol_barrage' WHERE `ScriptName`= 'spell_sfk_pistol_barrage'; +UPDATE `spell_script_names` SET `ScriptName`= 'spell_godfrey_pistol_barrage_aoe' WHERE `ScriptName`= 'spell_sfk_pistol_barrage_summon'; +UPDATE `spell_script_names` SET `ScriptName`= 'spell_godfrey_cursed_bullets' WHERE `ScriptName`= 'spell_sfk_cursed_bullets'; diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_godfrey.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_godfrey.cpp index 175157d3eae..fdbcc4cbe32 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_godfrey.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_godfrey.cpp @@ -42,7 +42,6 @@ enum Events EVENT_SUMMON_BLOODTHIRSTY_GHOULS, EVENT_PISTOL_BARRAGE, EVENT_PISTOL_BARRAGE_CAST, - EVENT_APPLY_IMMUNITY, // Bloodthirsty Ghoul EVENT_ATTACK @@ -53,22 +52,19 @@ enum Spells SPELL_CURSED_BULLETS = 93629, SPELL_CURSED_BULLETS_HC = 93761, SPELL_MORTAL_WOUND = 93675, - SPELL_SUMMON_BLOODTHIRSTY_GHOULS_AURA = 93707, + SPELL_SUMMON_BLOODTHIRSTY_GHOULS = 93707, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1 = 93709, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2 = 93714, SPELL_WEAR_CHRISTMAS_HAT_GREEN_SELF_DND = 61401, - SPELL_PISTOL_BARRAGE_FORCE_CAST = 96344, - SPELL_PISTOL_BARRAGE_CAST = 93520, + SPELL_PISTOL_BARRAGE_AOE = 96344, + SPELL_PISTOL_BARRAGE = 93520, SPELL_BULLET_TIME_CREDIT = 95929, + SPELL_BULLET_TIME_RESET_CREDIT = 95930, - SPELL_PISTOL_BARRAGE_TRIGGER_1 = 93566, - SPELL_PISTOL_BARRAGE_TRIGGER_2 = 93558 -}; - -enum AchievementData -{ - DATA_BULLET_TIME = 1, + SPELL_PISTOL_BARRAGE_PERIODIC = 93566, + SPELL_PISTOL_BARRAGE_MISSILE_1 = 93557, + SPELL_PISTOL_BARRAGE_MISSILE_2 = 93558 }; enum Misc @@ -76,59 +72,181 @@ enum Misc GAME_EVENT_WINTER_VEIL = 2 }; -class boss_lord_godfrey : public CreatureScript +struct boss_lord_godfrey : public BossAI { -public: - boss_lord_godfrey() : CreatureScript("boss_lord_godfrey") { } + boss_lord_godfrey(Creature* creature) : BossAI(creature, DATA_LORD_GODFREY) { } - struct boss_lord_godfreyAI : public BossAI + void JustAppeared() override { - boss_lord_godfreyAI(Creature* creature) : BossAI(creature, DATA_LORD_GODFREY), _killedGhoulCounter(0) { } + if (sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL)) + DoCastSelf(SPELL_WEAR_CHRISTMAS_HAT_GREEN_SELF_DND); + } - void JustAppeared() override + void Reset() override + { + _Reset(); + MakeInterruptable(false); + } + + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + Talk(instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE ? SAY_AGGRO_ALLIANCE : SAY_AGGRO_HORDE); + DoCastAOE(SPELL_BULLET_TIME_RESET_CREDIT); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + events.ScheduleEvent(EVENT_MORTAL_WOUND, 3s, 4s); + events.ScheduleEvent(EVENT_SUMMON_BLOODTHIRSTY_GHOULS, 6s); + } + + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _JustDied(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + switch (summon->GetEntry()) { - if (sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL)) - DoCastSelf(SPELL_WEAR_CHRISTMAS_HAT_GREEN_SELF_DND); + case NPC_PISTOL_BARRAGE_DUMMY: + _pistolBarrageDummyGUID = summon->GetGUID(); + events.ScheduleEvent(EVENT_PISTOL_BARRAGE_CAST, 500ms); + break; + case NPC_BLOODTHIRSTY_GHOUL: + summon->SetReactState(REACT_PASSIVE); + summon->m_Events.AddEventAtOffset([summon]() + { + if (summon->IsAIEnabled) + summon->AI()->DoZoneInCombat(); + }, 1s + 300ms); + + summon->m_Events.AddEventAtOffset([summon]() + { + summon->SetReactState(REACT_AGGRESSIVE); + }, 5s); + break; + default: + break; } + } - void Reset() override + + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + switch (summon->GetEntry()) { - _Reset(); - MakeInterruptable(false); + case NPC_BLOODTHIRSTY_GHOUL: + if (killer->GetEntry() == BOSS_LORD_GODFREY && IsHeroic()) + { + DoCastAOE(SPELL_BULLET_TIME_CREDIT, true); + _killedGhoulCounter++; + } + break; + default: + break; } + } - void JustEngagedWith(Unit* /*who*/) override + void KilledUnit(Unit* target) override + { + if (target->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + summons.DespawnAll(); + me->SetReactState(REACT_AGGRESSIVE); + instance->SetBossState(DATA_LORD_GODFREY, FAIL); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _DespawnAtEvade(); + } + + void MakeInterruptable(bool apply) + { + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, !apply); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, !apply); + } + + void OnSpellCastInterrupt(SpellInfo const* spell) override + { + switch (spell->Id) { - if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - Talk(SAY_AGGRO_ALLIANCE); - else - Talk(SAY_AGGRO_HORDE); - - _JustEngagedWith(); - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - events.ScheduleEvent(EVENT_CURSED_BULLETS, Seconds(10) + Milliseconds(800)); - events.ScheduleEvent(EVENT_MORTAL_WOUND, Seconds(3) + Milliseconds(500)); - events.ScheduleEvent(EVENT_SUMMON_BLOODTHIRSTY_GHOULS, Seconds(6)); - if (IsHeroic()) - events.ScheduleEvent(EVENT_PISTOL_BARRAGE, Seconds(12) + Milliseconds(500)); + case SPELL_CURSED_BULLETS: + case SPELL_CURSED_BULLETS_HC: + MakeInterruptable(false); + break; + default: + break; } + } - void JustDied(Unit* /*killer*/) override + void OnSuccessfulSpellCast(SpellInfo const* spell) override + { + switch (spell->Id) { - Talk(SAY_DEATH); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - _JustDied(); + case SPELL_CURSED_BULLETS: + case SPELL_CURSED_BULLETS_HC: + MakeInterruptable(false); + break; + default: + break; } + } - void SummonedCreatureDies(Creature* summon, Unit* killer) override + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - switch (summon->GetEntry()) + switch (eventId) { - case NPC_BLOODTHIRSTY_GHOUL: - if (killer->GetEntry() == BOSS_LORD_GODFREY && IsHeroic()) + case EVENT_CURSED_BULLETS: + MakeInterruptable(true); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_CURSED_BULLETS); + events.Repeat(12s); + break; + case EVENT_MORTAL_WOUND: + DoCastVictim(SPELL_MORTAL_WOUND); + events.Repeat(5s); + break; + case EVENT_SUMMON_BLOODTHIRSTY_GHOULS: + me->StopMoving(); + DoCastSelf(SPELL_SUMMON_BLOODTHIRSTY_GHOULS); + events.Repeat(30s); + + // Bloodthirsty summon casts re-allign the other basic abilities + events.RescheduleEvent(EVENT_CURSED_BULLETS, 7s); + events.RescheduleEvent(EVENT_MORTAL_WOUND, 5s); + + if (IsHeroic()) + events.ScheduleEvent(EVENT_PISTOL_BARRAGE, 5s); + break; + case EVENT_PISTOL_BARRAGE: + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + DoCastAOE(SPELL_PISTOL_BARRAGE_AOE); + events.RescheduleEvent(EVENT_MORTAL_WOUND, 8s + 500ms); + + break; + case EVENT_PISTOL_BARRAGE_CAST: + if (Creature* target = ObjectAccessor::GetCreature(*me, _pistolBarrageDummyGUID)) { - DoCastAOE(SPELL_BULLET_TIME_CREDIT, true); - _killedGhoulCounter++; + Talk(SAY_ANNOUNCE_PISTOL_BARRAGE); + me->SetFacingToObject(target); + DoCastSelf(SPELL_PISTOL_BARRAGE); } break; default: @@ -136,360 +254,135 @@ public: } } - void KilledUnit(Unit* target) override - { - if (target->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void EnterEvadeMode(EvadeReason /*why*/) override - { - _EnterEvadeMode(); - summons.DespawnAll(); - me->SetReactState(REACT_AGGRESSIVE); - instance->SetBossState(DATA_LORD_GODFREY, FAIL); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - _DespawnAtEvade(); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - } - - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_BULLET_TIME: - return _killedGhoulCounter;; - default: - break; - } - return 0; - } - - void MakeInterruptable(bool apply) - { - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, !apply); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, !apply); - } - - void OnSpellCastInterrupt(SpellInfo const* spell) override - { - switch (spell->Id) - { - case SPELL_CURSED_BULLETS: - case SPELL_CURSED_BULLETS_HC: - events.CancelEvent(EVENT_APPLY_IMMUNITY); - MakeInterruptable(false); - 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 EVENT_CURSED_BULLETS: - MakeInterruptable(true); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - DoCast(target, SPELL_CURSED_BULLETS); - events.ScheduleEvent(EVENT_CURSED_BULLETS, Seconds(12)); - events.ScheduleEvent(EVENT_APPLY_IMMUNITY, Seconds(1) + Milliseconds(500)); - break; - case EVENT_MORTAL_WOUND: - DoCastVictim(SPELL_MORTAL_WOUND); - events.Repeat(Seconds(6)); - break; - case EVENT_SUMMON_BLOODTHIRSTY_GHOULS: - DoCastAOE(SPELL_SUMMON_BLOODTHIRSTY_GHOULS_AURA, true); - events.Repeat(Seconds(30)); - break; - case EVENT_PISTOL_BARRAGE: - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - DoCastAOE(SPELL_PISTOL_BARRAGE_FORCE_CAST); - events.ScheduleEvent(EVENT_PISTOL_BARRAGE_CAST, Milliseconds(500)); - break; - case EVENT_PISTOL_BARRAGE_CAST: - if (Creature* target = me->FindNearestCreature(NPC_PISTOL_BARRAGE_DUMMY, 500.0f, true)) - { - Talk(SAY_ANNOUNCE_PISTOL_BARRAGE); - me->SetFacingToObject(target); - DoCastAOE(SPELL_PISTOL_BARRAGE_CAST); - } - events.ScheduleEvent(EVENT_PISTOL_BARRAGE, Seconds(30) + Milliseconds(100)); - break; - case EVENT_APPLY_IMMUNITY: - MakeInterruptable(false); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - uint8 _killedGhoulCounter; - }; - - CreatureAI* GetAI(Creature *creature) const override - { - return GetShadowfangKeepAI(creature); + DoMeleeAttackIfReady(); } + +private: + ObjectGuid _pistolBarrageDummyGUID; + uint8 _killedGhoulCounter; }; -class npc_sfk_bloodthirsty_ghoul : public CreatureScript +class spell_godfrey_summon_bloodthirsty_ghouls : public AuraScript { -public: - npc_sfk_bloodthirsty_ghoul() : CreatureScript("npc_sfk_bloodthirsty_ghoul") { } + PrepareAuraScript(spell_godfrey_summon_bloodthirsty_ghouls); - struct npc_sfk_bloodthirsty_ghoulAI : public ScriptedAI + bool Validate(SpellInfo const* /*spellInfo*/) override { - npc_sfk_bloodthirsty_ghoulAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void IsSummonedBy(Unit* summoner) override - { - if (!summoner->IsInCombat()) - me->DespawnOrUnsummon(); - me->SetReactState(REACT_PASSIVE); - - me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - DoZoneInCombat(); - _events.ScheduleEvent(EVENT_ATTACK, Seconds(4)); - } - - void JustDied(Unit* /*killer*/) override - { - me->DespawnOrUnsummon(Seconds(5)); - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_ATTACK: - me->SetReactState(REACT_AGGRESSIVE); - if (Unit* target = me->SelectNearestPlayer(100.0f)) - me->AI()->AttackStart(target); - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - private: - InstanceScript* _instance; - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetShadowfangKeepAI(creature); - } -}; - -class spell_sfk_summon_bloodthirsty_ghouls : public SpellScriptLoader -{ -public: - spell_sfk_summon_bloodthirsty_ghouls() : SpellScriptLoader("spell_sfk_summon_bloodthirsty_ghouls") { } - - class spell_sfk_summon_bloodthirsty_ghouls_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sfk_summon_bloodthirsty_ghouls_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo( + return ValidateSpellInfo( { SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2 }); - } - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - switch (RAND(0, 1)) - { - case 0: - GetCaster()->CastSpell((Unit*)NULL, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1, true); - break; - case 1: - GetCaster()->CastSpell((Unit*)NULL, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2, true); - break; - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_summon_bloodthirsty_ghouls_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_sfk_summon_bloodthirsty_ghouls_AuraScript(); } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + uint32 spellId = _useLeftGun ? SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1 : SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2; + _useLeftGun = _useLeftGun ? false : true; + GetTarget()->CastSpell(GetTarget(), spellId, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_godfrey_summon_bloodthirsty_ghouls::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +private: + bool _useLeftGun = true; }; -class spell_sfk_pistol_barrage : public SpellScriptLoader +class spell_godfrey_pistol_barrage : public AuraScript { -public: - spell_sfk_pistol_barrage() : SpellScriptLoader("spell_sfk_pistol_barrage") { } + PrepareAuraScript(spell_godfrey_pistol_barrage); - class spell_sfk_pistol_barrage_AuraScript : public AuraScript + bool Validate(SpellInfo const* /*spellInfo*/) override { - PrepareAuraScript(spell_sfk_pistol_barrage_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo( + return ValidateSpellInfo( { - SPELL_PISTOL_BARRAGE_TRIGGER_1, - SPELL_PISTOL_BARRAGE_TRIGGER_2 + SPELL_PISTOL_BARRAGE_PERIODIC, + SPELL_PISTOL_BARRAGE_MISSILE_1, + SPELL_PISTOL_BARRAGE_MISSILE_2 }); - } + } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - caster->CastSpell(caster, SPELL_PISTOL_BARRAGE_TRIGGER_1, true); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - { - if (caster->ToCreature()) - caster->ToCreature()->SetReactState(REACT_AGGRESSIVE); - caster->RemoveAurasDueToSpell(SPELL_PISTOL_BARRAGE_TRIGGER_1); - } - } - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* caster = GetCaster()) - { - float ori = caster->GetOrientation() + frand(-0.5236f, 0.5236f); - float posX = caster->GetPositionX() + cos(ori) * 60; - float posY = caster->GetPositionY() + sin(ori) * 60; - float posZ = caster->GetPositionZ(); - GetCaster()->CastSpell(posX, posY, posZ, SPELL_PISTOL_BARRAGE_TRIGGER_2, true); - } - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_sfk_pistol_barrage_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_sfk_pistol_barrage_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_pistol_barrage_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - return new spell_sfk_pistol_barrage_AuraScript(); + GetTarget()->CastSpell(GetTarget(), SPELL_PISTOL_BARRAGE_PERIODIC, true); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->RemoveAurasDueToSpell(SPELL_PISTOL_BARRAGE_PERIODIC); + + if (target->ToCreature()) + target->ToCreature()->SetReactState(REACT_AGGRESSIVE); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + float maxOffset = float(M_PI / 6); + float offset = _useLeftGun ? frand(0.f, maxOffset) : frand(--maxOffset, 0.f); + uint32 spellId = _useLeftGun ? SPELL_PISTOL_BARRAGE_MISSILE_1 : SPELL_PISTOL_BARRAGE_MISSILE_2; + + float ori = target->GetOrientation() + offset; + float posX = target->GetPositionX() + cos(ori) * 60; + float posY = target->GetPositionY() + sin(ori) * 60; + float posZ = target->GetPositionZ(); + target->CastSpell(posX, posY, posZ, spellId, true); + _useLeftGun = _useLeftGun ? false : true; + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_godfrey_pistol_barrage::AfterApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_godfrey_pistol_barrage::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_godfrey_pistol_barrage::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +private: + bool _useLeftGun = true; +}; + +class spell_godfrey_pistol_barrage_aoe : public SpellScript +{ + PrepareSpellScript(spell_godfrey_pistol_barrage_aoe); + + void FilterTargets(std::list& targets) + { + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_godfrey_pistol_barrage_aoe::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; -class spell_sfk_pistol_barrage_summon : public SpellScriptLoader +class spell_godfrey_cursed_bullets : public AuraScript { -public: - spell_sfk_pistol_barrage_summon() : SpellScriptLoader("spell_sfk_pistol_barrage_summon") { } + PrepareAuraScript(spell_godfrey_cursed_bullets); - class spell_sfk_pistol_barrage_summon_SpellScript : public SpellScript + void OnPeriodic(AuraEffect const* aurEff) { - PrepareSpellScript(spell_sfk_pistol_barrage_summon_SpellScript); + if (aurEff->GetTickNumber() == 1) + _baseDamage = aurEff->GetAmount(); - void FilterTargets(std::list& targets) - { - Trinity::Containers::RandomResize(targets, 1); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sfk_pistol_barrage_summon_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_sfk_pistol_barrage_summon_SpellScript(); + GetEffect(EFFECT_1)->ChangeAmount(_baseDamage * aurEff->GetTickNumber()); } -}; -class spell_sfk_cursed_bullets : public SpellScriptLoader -{ -public: - spell_sfk_cursed_bullets() : SpellScriptLoader("spell_sfk_cursed_bullets") { } - - class spell_sfk_cursed_bullets_AuraScript : public AuraScript + void Register() override { - PrepareAuraScript(spell_sfk_cursed_bullets_AuraScript); - - void OnPeriodic(AuraEffect const* aurEff) - { - uint64 damage; - damage = aurEff->GetBaseAmount() * aurEff->GetTickNumber(); - GetEffect(EFFECT_1)->ChangeAmount(damage); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_cursed_bullets_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_sfk_cursed_bullets_AuraScript(); - } -}; - -class achievement_bullet_time : public AchievementCriteriaScript -{ -public: - achievement_bullet_time() : AchievementCriteriaScript("achievement_bullet_time") { } - - bool OnCheck(Player* /*source*/, Unit* target) - { - if (!target) - return false; - - if (target->GetMap()->IsHeroic()) - return target->GetAI()->GetData(DATA_BULLET_TIME) >= 12; - - return false; + OnEffectPeriodic += AuraEffectPeriodicFn(spell_godfrey_cursed_bullets::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); } +private: + uint32 _baseDamage = 0; }; void AddSC_boss_lord_godfrey() { - new boss_lord_godfrey(); - new npc_sfk_bloodthirsty_ghoul(); - new spell_sfk_summon_bloodthirsty_ghouls(); - new spell_sfk_pistol_barrage(); - new spell_sfk_pistol_barrage_summon(); - new spell_sfk_cursed_bullets(); - new achievement_bullet_time(); + RegisterShadowfangKeepCreatureAI(boss_lord_godfrey); + RegisterAuraScript(spell_godfrey_summon_bloodthirsty_ghouls); + RegisterAuraScript(spell_godfrey_pistol_barrage); + RegisterSpellScript(spell_godfrey_pistol_barrage_aoe); + RegisterAuraScript(spell_godfrey_cursed_bullets); } diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_walden.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_walden.cpp index bdf8f228686..5de2c1fa7be 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_walden.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_lord_walden.cpp @@ -113,7 +113,6 @@ struct boss_lord_walden : public BossAI { _EnterEvadeMode(); summons.DespawnAll(); - instance->SetBossState(DATA_LORD_WALDEN, FAIL); instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); _DespawnAtEvade(); } diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp index 95ec77846e6..68f5350c2b2 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp @@ -159,6 +159,11 @@ public: if (creature->ToTempSummon()) _cromushGUID = creature->GetGUID(); break; + case NPC_PISTOL_BARRAGE_DUMMY: + if (Creature* godfrey = GetCreature(DATA_LORD_GODFREY)) + if (godfrey->IsAIEnabled) + godfrey->AI()->JustSummoned(creature); + break; default: break; }