diff options
author | Naddley <64811442+Naddley@users.noreply.github.com> | 2024-05-05 05:30:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-05 05:30:37 +0200 |
commit | 62156f57b285ee252c2c4143236a3df95f219ca5 (patch) | |
tree | 5bbb3bffc7034ae9adf695cfeace3b72757f809f /src | |
parent | 240b7e58d81688e31d84511db4afd6229337c9e9 (diff) |
Scripts/ScarletHalls: Implement Armsmaster Harlan encounter (#29944)
Diffstat (limited to 'src')
5 files changed, 492 insertions, 0 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d689481661d..6bd0010f723 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4643,6 +4643,34 @@ void SpellMgr::LoadSpellInfoCorrections() // ENDOF FIRELANDS // + // SCARLET HALLS SPELLS + // + + // 111755 - Call Reinforcement + ApplySpellFix({ 111755 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT; + + ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) + { + spellEffectInfo->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); + }); + }); + + // 111756 - Call Reinforcement + ApplySpellFix({ 111756 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT; + + ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) + { + spellEffectInfo->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); + }); + }); + + // ENDOF SCARLET HALLS SPELLS + + // // MARDUM SPELLS // diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/boss_armsmaster_harlan.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/boss_armsmaster_harlan.cpp new file mode 100644 index 00000000000..7ebb5a47785 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/boss_armsmaster_harlan.cpp @@ -0,0 +1,334 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CreatureAI.h" +#include "CreatureAIImpl.h" +#include "InstanceScript.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuras.h" +#include "SharedDefines.h" +#include "Vehicle.h" +#include "scarlet_halls.h" + +enum HarlanSpells +{ + // Armsmaster Harlan + SPELL_HARLAN_DRAGONS_REACH = 111217, + SPELL_HARLAN_CALL_REINFORCEMENT = 111755, + SPELL_HARLAN_HEROIC_LEAP_JUMP = 111219, + SPELL_HARLAN_BERSERKERS_RAGE = 111221, + SPELL_HARLAN_BLADES_OF_LIGHT_CAST = 111216, + SPELL_HARLAN_BLADES_OF_LIGHT_VEHICLE = 112955, + SPELL_HARLAN_BLADES_OF_LIGHT_DAMAGE = 111215, + SPELL_HARLAN_LEAVE_VEHICLE = 112953, + + // Scarlet Defender + SPELL_SCARLET_DEFENDER_UNARMORED = 113969 +}; + +enum HarlanEvents +{ + EVENT_HARLAN_DRAGONS_REACH = 1, + EVENT_HARLAN_CALL_FOR_HELP, + EVENT_HARLAN_HEROIC_LEAP, + EVENT_HARLAN_BERSERKER_RAGE, + EVENT_HARLAN_BLADES_OF_LIGHT, + EVENT_HARLAN_CALL_REINFORCEMENT, + EVENT_HARLAN_FINISH_BLADES_OF_LIGHT, +}; + +enum HarlanTexts +{ + SAY_HARLAN_AGGRO = 0, + SAY_HARLAN_CALL_FOR_HELP = 1, + ANNOUNCE_HARLAN_CALL_FOR_HELP = 2, + ANNOUNCE_HARLAN_BLADE_FOR_LIGHT = 3, + SAY_HARLAN_DEATH = 4 +}; + +enum HarlanPathIds +{ + PATH_HARLAN_BLADES_OF_LIGHT_LEFT = 5863200, + PATH_HARLAN_BLADES_OF_LIGHT_RIGHT = 5863201 +}; + +// 58632 - Armsmaster Harlan +struct boss_armsmaster_harlan : public BossAI +{ + boss_armsmaster_harlan(Creature* creature) : BossAI(creature, DATA_ARMSMASTER_HARLAN), _berserkerRage(false) { } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_HARLAN_AGGRO); + events.ScheduleEvent(EVENT_HARLAN_DRAGONS_REACH, 7s); + events.ScheduleEvent(EVENT_HARLAN_CALL_FOR_HELP, 20s); + events.ScheduleEvent(EVENT_HARLAN_HEROIC_LEAP, 41s); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + summons.DespawnAll(); + _EnterEvadeMode(); + _DespawnAtEvade(); + } + + void Reset() override + { + _Reset(); + _berserkerRage = false; + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_HARLAN_DEATH); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + } + + void MovementInform(uint32 /*type*/, uint32 id) override + { + if (id == EVENT_JUMP) + { + me->SetReactState(REACT_PASSIVE); + Talk(ANNOUNCE_HARLAN_BLADE_FOR_LIGHT); + events.CancelEvent(EVENT_HARLAN_DRAGONS_REACH); + events.CancelEvent(EVENT_HARLAN_CALL_FOR_HELP); + events.CancelEvent(EVENT_HARLAN_HEROIC_LEAP); + DoCastSelf(SPELL_HARLAN_BLADES_OF_LIGHT_CAST); + } + } + + void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override + { + if (!_berserkerRage && me->HealthBelowPctDamaged(50, damage)) + { + _berserkerRage = true; + DoCastSelf(SPELL_HARLAN_BERSERKERS_RAGE); + } + } + + void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) override + { + events.ScheduleEvent(EVENT_HARLAN_FINISH_BLADES_OF_LIGHT, 1s); + events.ScheduleEvent(EVENT_HARLAN_DRAGONS_REACH, 6s); + events.ScheduleEvent(EVENT_HARLAN_CALL_FOR_HELP, 19s); + events.ScheduleEvent(EVENT_HARLAN_HEROIC_LEAP, 29s); + } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_HARLAN_DRAGONS_REACH: + DoCastVictim(SPELL_HARLAN_DRAGONS_REACH); + events.ScheduleEvent(EVENT_HARLAN_DRAGONS_REACH, 7s); + break; + case EVENT_HARLAN_CALL_FOR_HELP: + Talk(SAY_HARLAN_CALL_FOR_HELP); + events.ScheduleEvent(EVENT_HARLAN_CALL_REINFORCEMENT, 4s); + break; + case EVENT_HARLAN_HEROIC_LEAP: + DoCast(SPELL_HARLAN_HEROIC_LEAP_JUMP); + break; + case EVENT_HARLAN_CALL_REINFORCEMENT: + Talk(ANNOUNCE_HARLAN_CALL_FOR_HELP); + DoCast(SPELL_HARLAN_CALL_REINFORCEMENT); + events.ScheduleEvent(EVENT_HARLAN_CALL_FOR_HELP, 20s); + break; + case EVENT_HARLAN_FINISH_BLADES_OF_LIGHT: + me->RemoveAurasDueToSpell(SPELL_HARLAN_BLADES_OF_LIGHT_CAST); + me->SetHover(false); + DoCastSelf(SPELL_HARLAN_LEAVE_VEHICLE); + me->SetReactState(REACT_AGGRESSIVE); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + } +private: + bool _berserkerRage; +}; + +// 111216 - Blades of Light +class spell_harlan_blades_of_light : public SpellScript +{ + void HandleAfterCast() + { + Creature* caster = GetCaster()->ToCreature(); + if (!caster) + return; + + caster->GetMotionMaster()->Clear(); + caster->SetHover(true); + + if (urand(0, 1) == 0) + caster->GetMotionMaster()->MovePath(PATH_HARLAN_BLADES_OF_LIGHT_LEFT, false); + else + caster->GetMotionMaster()->MovePath(PATH_HARLAN_BLADES_OF_LIGHT_RIGHT, false); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_harlan_blades_of_light::HandleAfterCast); + } +}; + +// 111394 - Blades of Light +class spell_harlan_blades_of_light_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_HARLAN_BLADES_OF_LIGHT_CAST }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->HasAuraType(AuraType::SPELL_AURA_SPIRIT_OF_REDEMPTION)) + return; + + GetHitUnit()->CastSpell(GetCaster(), SPELL_HARLAN_BLADES_OF_LIGHT_VEHICLE, true); + GetCaster()->CastSpell(GetHitUnit(), SPELL_HARLAN_BLADES_OF_LIGHT_DAMAGE, false); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_harlan_blades_of_light_selector::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 112953 - Leave Vehicle +class spell_harlan_leave_vehicle : public SpellScript +{ + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->ExitVehicle(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_harlan_leave_vehicle::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +// 113959 - Heavy Armor +class spell_scarlet_defender_heavy_armor : public AuraScript +{ + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_SCARLET_DEFENDER_UNARMORED); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_scarlet_defender_heavy_armor::OnRemove, EFFECT_1, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); + } +}; + +constexpr Position CallReinforcmentsRightPosition = { 1182.020f, 447.325f, 11.98933f }; +constexpr Position CallReinforcmentsLeftPosition = { 1181.833f, 440.649f, 11.98763f }; + +// 111755 - Call Reinforcements +class spell_call_reinforcements_right : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(CallReinforcmentsRightPosition); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_call_reinforcements_right::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + } +}; + +// 111756 - Call Reinforcements +class spell_call_reinforcements_left : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(CallReinforcmentsLeftPosition); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_call_reinforcements_left::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + } +}; + +// 128930 - Eject Spirits of Redemption +class spell_eject_spirits_of_redemption : public SpellScript +{ + void HandleHitTarget(SpellEffIndex /*effIndex*/) + { + Vehicle* veh = GetCaster()->GetVehicleKit(); + if (!veh) + return; + + for (auto const& [_, seat] : veh->Seats) + { + Unit* passenger = ObjectAccessor::GetUnit(*GetCaster(), seat.Passenger.Guid); + if (!passenger) + continue; + + if (passenger->HasAuraType(AuraType::SPELL_AURA_SPIRIT_OF_REDEMPTION)) + passenger->ExitVehicle(); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_eject_spirits_of_redemption::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +void AddSC_boss_armsmaster_harlan() +{ + // Creature + RegisterScarletHallsCreatureAI(boss_armsmaster_harlan); + + // Spells + RegisterSpellScript(spell_harlan_blades_of_light); + RegisterSpellScript(spell_harlan_blades_of_light_selector); + RegisterSpellScript(spell_harlan_leave_vehicle); + RegisterSpellScript(spell_scarlet_defender_heavy_armor); + RegisterSpellScript(spell_call_reinforcements_right); + RegisterSpellScript(spell_call_reinforcements_left); + RegisterSpellScript(spell_eject_spirits_of_redemption); +} diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.cpp new file mode 100644 index 00000000000..c3acef9db49 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.cpp @@ -0,0 +1,69 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "InstanceScript.h" +#include "ScriptMgr.h" +#include "scarlet_halls.h" + +ObjectData const creatureData[] = +{ + { BOSS_HOUNDMASTER_BRAUN, DATA_HOUNDMASTER_BRAUN }, + { BOSS_ARMSMASTER_HARLAN, DATA_ARMSMASTER_HARLAN }, + { BOSS_FLAMEWEAVER_KOEGLER, DATA_FLAMEWEAVER_KOEGLER }, + { 0, 0 } // END +}; + +DoorData const doorData[] = +{ + { GO_HERODS_DOOR_HARLAN_ENCOUNTER_ENTRANCE, DATA_ARMSMASTER_HARLAN, EncounterDoorBehavior::OpenWhenNotInProgress }, + { 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } //End +}; + +DungeonEncounterData const encounters[] = +{ + { DATA_HOUNDMASTER_BRAUN, {{ 1422 }} }, + { DATA_ARMSMASTER_HARLAN, {{ 1421 }} }, + { DATA_FLAMEWEAVER_KOEGLER, {{ 1420 }} }, +}; + +class instance_scarlet_halls : public InstanceMapScript +{ +public: + instance_scarlet_halls() : InstanceMapScript(ScarletHallsScriptName, 1001) { } + + struct instance_scarlet_halls_InstanceMapScript : public InstanceScript + { + instance_scarlet_halls_InstanceMapScript(InstanceMap* map) : InstanceScript(map) + { + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadObjectData(creatureData, nullptr); + LoadDoorData(doorData); + LoadDungeonEncounterData(encounters); + } + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_scarlet_halls_InstanceMapScript(map); + } +}; + +void AddSC_instance_scarlet_halls() +{ + new instance_scarlet_halls(); +} diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.h b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.h new file mode 100644 index 00000000000..599895acdd2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/ScarletHalls/scarlet_halls.h @@ -0,0 +1,57 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DEF_SCARLET_HALLS_H_ +#define DEF_SCARLET_HALLS_H_ + +#include "CreatureAIImpl.h" + +#define DataHeader "ScarletHalls" +#define ScarletHallsScriptName "instance_scarlet_halls" + +uint32 const EncounterCount = 3; + +enum ScarletHallsTypes +{ + // Encounters + DATA_HOUNDMASTER_BRAUN = 0, + DATA_ARMSMASTER_HARLAN = 1, + DATA_FLAMEWEAVER_KOEGLER = 2 +}; + +enum ScarletHallsCreatureIds +{ + // Bosses + BOSS_HOUNDMASTER_BRAUN = 59303, + BOSS_ARMSMASTER_HARLAN = 58632, + BOSS_FLAMEWEAVER_KOEGLER = 59150 +}; + +enum ScarletHallsGameObjectIds +{ + GO_HERODS_DOOR_HARLAN_ENCOUNTER_ENTRANCE = 210480 +}; + +template <class AI, class T> +inline AI* GetScarletHallsAI(T* obj) +{ + return GetInstanceAI<AI>(obj, ScarletHallsScriptName); +} + +#define RegisterScarletHallsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetScarletHallsAI) + +#endif diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index b818c1e6f10..8316eec13f4 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -112,6 +112,8 @@ void AddSC_boss_interrogator_vishas(); void AddSC_boss_scorn(); void AddSC_instance_scarlet_monastery(); void AddSC_boss_mograine_and_whitemane(); +void AddSC_instance_scarlet_halls(); // Scarlet Halls +void AddSC_boss_armsmaster_harlan(); void AddSC_boss_darkmaster_gandling(); //Scholomance void AddSC_boss_death_knight_darkreaver(); void AddSC_boss_theolenkrastinov(); @@ -301,6 +303,8 @@ void AddEasternKingdomsScripts() AddSC_boss_scorn(); AddSC_instance_scarlet_monastery(); AddSC_boss_mograine_and_whitemane(); + AddSC_instance_scarlet_halls(); // Scarlet Halls + AddSC_boss_armsmaster_harlan(); AddSC_boss_darkmaster_gandling(); //Scholomance AddSC_boss_death_knight_darkreaver(); AddSC_boss_theolenkrastinov(); |