diff options
author | Aqua Deus <95978183+aquadeus@users.noreply.github.com> | 2025-07-26 15:19:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-26 15:19:32 +0200 |
commit | 43644e4c296dc2036c4cea81854e79c76d81de81 (patch) | |
tree | fba242063eca9b512278d425fdcb68c047c2104b /src/server/scripts | |
parent | 6c51b005c26d57ff70cc479e71a6e227f717e1fd (diff) |
Scripts/ReturnToKarazhan: Implement The Curator encounter (#31146)
Diffstat (limited to 'src/server/scripts')
4 files changed, 346 insertions, 3 deletions
diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_the_curator_rtk.cpp b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_the_curator_rtk.cpp new file mode 100644 index 00000000000..7c4673fdb98 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_the_curator_rtk.cpp @@ -0,0 +1,327 @@ +/* + * 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 "AreaTrigger.h" +#include "AreaTriggerAI.h" +#include "InstanceScript.h" +#include "ScriptedCreature.h" +#include "ScriptMgr.h" +#include "SpellAuras.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "return_to_karazhan.h" + +enum TheCuratorRTKSpells +{ + SPELL_COSMETIC_MANA_DRAIN = 228840, + SPELL_SUMMON_VOLATILE_ENERGY = 227267, + SPELL_SUMMON_VOLATILE_ENERGY_SELECTOR = 234416, + SPELL_POWER_DISCHARGE = 227279, + SPELL_POWER_DISCHARGE_AREATRIGGER = 227289, + SPELL_POWER_DISCHARGE_DAMAGE = 227465, + SPELL_POWER_DISCHARGE_SELECTOR = 227278, + SPELL_EVOCATION = 227254, + SPELL_OVERLOAD = 227256, + SPELL_OVERLOAD_DAMAGE = 227257, + SPELL_ARC_LIGHTNING_DAMAGE = 227270, + SPELL_STATIC_CHARGE = 228736 +}; + +enum TheCuratorRTKEvents +{ + EVENT_VOLATILE_ENERGY = 1, + EVENT_POWER_DISCHARGE, + EVENT_CHECK_MANA, +}; + +enum TheCuratorRTKTexts +{ + SAY_AGGRO = 0, + SAY_VOLATILE_ENERGY = 1, + SAY_EVOCATION = 2, + SAY_SLAY = 3, + SAY_DEAD = 4 +}; + +enum TheCuratorRTKMisc +{ + SUMMON_GROUP_MEDIVH_SCENE = 0 +}; + +// 114247 - The Curator +struct boss_the_curator_rtk : public BossAI +{ + boss_the_curator_rtk(Creature* creature) : BossAI(creature, DATA_THE_CURATOR_RTK) { } + + void RemoveAreaTriggers() const + { + for (AreaTrigger* powerDischarge : me->GetAreaTriggers(SPELL_POWER_DISCHARGE_AREATRIGGER)) + powerDischarge->Remove(); + } + + void JustDied(Unit* /*killer*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _JustDied(); + Talk(SAY_DEAD); + RemoveAreaTriggers(); + + me->SummonCreatureGroup(SUMMON_GROUP_MEDIVH_SCENE); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + summons.DespawnAll(); + RemoveAreaTriggers(); + _EnterEvadeMode(); + _DespawnAtEvade(); + } + + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; + + Talk(SAY_SLAY); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + + DoCastSelf(SPELL_COSMETIC_MANA_DRAIN); + + events.ScheduleEvent(EVENT_VOLATILE_ENERGY, 5s); + events.ScheduleEvent(EVENT_POWER_DISCHARGE, 12s); + events.ScheduleEvent(EVENT_CHECK_MANA, 500ms); + } + + void OnChannelFinished(SpellInfo const* spell) override + { + if (spell->Id != SPELL_EVOCATION) + return; + + DoCastSelf(SPELL_OVERLOAD); + DoCastSelf(SPELL_COSMETIC_MANA_DRAIN); + events.ScheduleEvent(EVENT_VOLATILE_ENERGY, 9200ms); + events.ScheduleEvent(EVENT_POWER_DISCHARGE, 12s); + } + + 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_VOLATILE_ENERGY: + { + Talk(SAY_VOLATILE_ENERGY); + DoCastSelf(SPELL_SUMMON_VOLATILE_ENERGY_SELECTOR); + events.Repeat(9700ms); + break; + } + case EVENT_POWER_DISCHARGE: + { + DoCastSelf(SPELL_POWER_DISCHARGE_SELECTOR); + events.Repeat(12s); + break; + } + case EVENT_CHECK_MANA: + { + if (me->GetPower(POWER_MANA) <= 0) + { + Talk(SAY_EVOCATION); + me->RemoveAurasDueToSpell(SPELL_COSMETIC_MANA_DRAIN); + DoCastSelf(SPELL_EVOCATION); + me->SetReactState(REACT_PASSIVE); + events.CancelEvent(EVENT_VOLATILE_ENERGY); + events.CancelEvent(EVENT_POWER_DISCHARGE); + } + events.Repeat(500ms); + break; + } + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + } +}; + +// 234416 - Summon Volatile Energy +class spell_the_curator_rtk_summon_volatile_energy_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_VOLATILE_ENERGY }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) const + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_VOLATILE_ENERGY, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_curator_rtk_summon_volatile_energy_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 227278 - Power Discharge +class spell_the_curator_rtk_power_discharge_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_POWER_DISCHARGE }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) const + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_POWER_DISCHARGE, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_curator_rtk_power_discharge_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 227269 - Arc Lightning +class spell_the_curator_rtk_arc_lightning_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ARC_LIGHTNING_DAMAGE }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) const + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_ARC_LIGHTNING_DAMAGE, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_curator_rtk_arc_lightning_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 228735 - Static Charge +class spell_the_curator_rtk_static_charge_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_STATIC_CHARGE }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) const + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_STATIC_CHARGE, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_curator_rtk_static_charge_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 227256 - Overload +class spell_the_curator_rtk_overload : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_OVERLOAD_DAMAGE }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) const + { + Creature* creatureCaster = GetCaster()->ToCreature(); + if (!creatureCaster) + return; + + creatureCaster->CastSpell(GetHitUnit(), SPELL_OVERLOAD_DAMAGE, CastSpellExtraArgsInit{ + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + creatureCaster->SetReactState(REACT_AGGRESSIVE); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_curator_rtk_overload::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 227289 Power Discharge +struct at_the_curator_rtk_power_discharge : AreaTriggerAI +{ + using AreaTriggerAI::AreaTriggerAI; + + void OnUnitEnter(Unit* unit) override + { + if (!unit->IsPlayer()) + return; + + Unit* caster = at->GetCaster(); + if (!caster) + return; + + caster->CastSpell(unit, SPELL_POWER_DISCHARGE_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + } + + void OnUnitExit(Unit* unit) override + { + unit->RemoveAurasDueToSpell(SPELL_POWER_DISCHARGE_DAMAGE, at->GetCasterGuid()); + } +}; + +void AddSC_boss_the_curator_rtk() +{ + RegisterReturnToKarazhanCreatureAI(boss_the_curator_rtk); + + RegisterSpellScript(spell_the_curator_rtk_summon_volatile_energy_selector); + RegisterSpellScript(spell_the_curator_rtk_power_discharge_selector); + RegisterSpellScript(spell_the_curator_rtk_arc_lightning_selector); + RegisterSpellScript(spell_the_curator_rtk_static_charge_selector); + RegisterSpellScript(spell_the_curator_rtk_overload); + + RegisterAreaTriggerAI(at_the_curator_rtk_power_discharge); +} diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp index 2a13f3e6fdc..ca3066b5a75 100644 --- a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp @@ -28,16 +28,23 @@ BossBoundaryData const boundaries = ObjectData const creatureData[] = { { BOSS_MAIDEN_OF_VIRTUE_RTK, DATA_MAIDEN_OF_VIRTUE_RTK }, + { BOSS_THE_CURATOR_RTK, DATA_THE_CURATOR_RTK }, { 0, 0 } // END }; +DoorData const doorData[] = +{ + { GO_STRANGE_WALL, DATA_THE_CURATOR_RTK, EncounterDoorBehavior::OpenWhenDone }, + { 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } +}; + DungeonEncounterData const encounters[] = { { DATA_OPERA_HALL, {{ 1957 }} }, { DATA_MAIDEN_OF_VIRTUE_RTK, {{ 1954 }} }, { DATA_MOROES, {{ 1961 }} }, { DATA_ATTUMEN_THE_HUNTSMAN, {{ 1960 }} }, - { DATA_THE_CURATOR, {{ 1964 }} }, + { DATA_THE_CURATOR_RTK, {{ 1964 }} }, { DATA_SHADE_OF_MEDIVH, {{ 1965 }} }, { DATA_MANA_DEVOURER, {{ 1959 }} }, { DATA_VIZADUUM_THE_WATCHER, {{ 2017 }} }, @@ -57,6 +64,7 @@ class instance_return_to_karazhan : public InstanceMapScript SetBossNumber(EncounterCount); LoadObjectData(creatureData, nullptr); LoadBossBoundaries(boundaries); + LoadDoorData(doorData); LoadDungeonEncounterData(encounters); } }; diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h index 0f6ad0c5a72..0448eb5823a 100644 --- a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h +++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h @@ -32,7 +32,7 @@ enum RTKDataTypes : uint8 DATA_MAIDEN_OF_VIRTUE_RTK, DATA_MOROES, DATA_ATTUMEN_THE_HUNTSMAN, - DATA_THE_CURATOR, + DATA_THE_CURATOR_RTK, DATA_SHADE_OF_MEDIVH, DATA_MANA_DEVOURER, DATA_VIZADUUM_THE_WATCHER, @@ -42,7 +42,13 @@ enum RTKDataTypes : uint8 enum RTKCreatureIds { // Bosses - BOSS_MAIDEN_OF_VIRTUE_RTK = 113971 + BOSS_MAIDEN_OF_VIRTUE_RTK = 113971, + BOSS_THE_CURATOR_RTK = 114247 +}; + +enum RTKGameObjectsIds +{ + GO_STRANGE_WALL = 266508 }; template <class AI, class T> diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index 0961807ae42..34bd72b99b9 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -207,6 +207,7 @@ void AddSC_undercity(); // Return to Karazhan void AddSC_instance_return_to_karazhan(); void AddSC_boss_maiden_of_virtue_rtk(); +void AddSC_boss_the_curator_rtk(); // The name of this function should match: // void Add${NameOfDirectory}Scripts() @@ -404,4 +405,5 @@ void AddEasternKingdomsScripts() // Return to Karazhan AddSC_instance_return_to_karazhan(); AddSC_boss_maiden_of_virtue_rtk(); + AddSC_boss_the_curator_rtk(); } |