aboutsummaryrefslogtreecommitdiff
path: root/src/server/scripts
diff options
context:
space:
mode:
authorAqua Deus <95978183+aquadeus@users.noreply.github.com>2025-07-19 14:44:19 +0200
committerGitHub <noreply@github.com>2025-07-19 14:44:19 +0200
commitaaf46b581664ed8060927001e407cba6201766b5 (patch)
tree13cc283b0a961378ff8d1ff36e8841e2eaf3961e /src/server/scripts
parent6b7f7beeb8d182c6657e153f5ea86a9595ab0cf0 (diff)
Scripts/ReturnToKarazhan: Implement Maiden of Virtue encounter (#31105)
Diffstat (limited to 'src/server/scripts')
-rw-r--r--src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_maiden_of_virtue_rtk.cpp326
-rw-r--r--src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp73
-rw-r--r--src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h56
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp8
4 files changed, 463 insertions, 0 deletions
diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_maiden_of_virtue_rtk.cpp b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_maiden_of_virtue_rtk.cpp
new file mode 100644
index 00000000000..a488b0e8549
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/boss_maiden_of_virtue_rtk.cpp
@@ -0,0 +1,326 @@
+/*
+ * 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 "Map.h"
+#include "Player.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
+#include "return_to_karazhan.h"
+
+enum MaidenOfVirtueRTKSpells
+{
+ SPELL_HOLY_BOLT = 227809,
+ SPELL_HOLY_SHOCK = 227800,
+ SPELL_SACRED_GROUND = 227789,
+ SPELL_SACRED_GROUND_DAMAGE = 227848,
+ SPELL_SACRED_GROUND_PERIODIC = 227793,
+ SPELL_MASS_REPENTANCE = 227508,
+ SPELL_HOLY_BULWARK = 227817,
+ SPELL_HOLY_WRATH = 227823,
+ SPELL_PLAY_SCENE = 232516
+};
+
+enum MaidenOfVirtueRTKEvents
+{
+ EVENT_HOLY_BOLT = 1,
+ EVENT_HOLY_SHOCK,
+ EVENT_SACRED_GROUND,
+ EVENT_MASS_REPENTANCE,
+ EVENT_HOLY_BULWARK,
+ EVENT_HOLY_WRATH
+};
+
+enum MaidenOfVirtueRTKActions
+{
+ ACTION_INTERRUPT_HOLY_WRATH = 1
+};
+
+enum MaidenOfVirtueRTKTexts
+{
+ SAY_AGGRO = 0,
+ SAY_WIPE = 1,
+ SAY_SLAY = 2,
+ SAY_HOLY_BOLT = 3,
+ SAY_SACRED_GROUND_WARNING = 4,
+ SAY_SACRED_GROUND = 5,
+ SAY_HOLY_SHOCK = 6,
+ SAY_MASS_REPENTANCE_WARNING = 7,
+ SAY_MASS_REPENTANCE = 8,
+ SAY_HOLY_BULWARK = 9,
+ SAY_HOLY_WRATH = 10,
+ SAY_DEAD = 11
+};
+
+enum MaidenOfVirtueGroup
+{
+ SPAWNGROUP_MAIDEN_OF_VIRTUE_OUTRO = 1267
+};
+
+// 113971 - Maiden of Virtue
+struct boss_maiden_of_virtue_rtk : public BossAI
+{
+ boss_maiden_of_virtue_rtk(Creature* creature) : BossAI(creature, DATA_MAIDEN_OF_VIRTUE_RTK) { }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ _JustDied();
+ me->RemoveAllAreaTriggers();
+ Talk(SAY_DEAD);
+
+ DoCastSelf(SPELL_PLAY_SCENE);
+
+ instance->instance->SpawnGroupSpawn(SPAWNGROUP_MAIDEN_OF_VIRTUE_OUTRO);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+
+ Talk(SAY_WIPE);
+ summons.DespawnAll();
+ me->RemoveAllAreaTriggers();
+ _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);
+
+ events.ScheduleEvent(EVENT_HOLY_BOLT, 8500ms);
+ events.ScheduleEvent(EVENT_HOLY_SHOCK, 15800ms);
+ events.ScheduleEvent(EVENT_SACRED_GROUND, 10900ms);
+ events.ScheduleEvent(EVENT_MASS_REPENTANCE, 48500ms);
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_INTERRUPT_HOLY_WRATH)
+ {
+ me->InterruptNonMeleeSpells(false);
+ events.CancelEvent(EVENT_HOLY_WRATH);
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.ScheduleEvent(EVENT_HOLY_BOLT, 8500ms);
+ events.ScheduleEvent(EVENT_HOLY_SHOCK, 15800ms);
+ events.ScheduleEvent(EVENT_SACRED_GROUND, 10900ms);
+ events.ScheduleEvent(EVENT_MASS_REPENTANCE, 48500ms);
+ }
+ }
+
+ 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_HOLY_BOLT:
+ {
+ Talk(SAY_HOLY_BOLT);
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
+ DoCast(target, SPELL_HOLY_BOLT);
+ events.Repeat(9700ms);
+ break;
+ }
+ case EVENT_HOLY_SHOCK:
+ {
+ Talk(SAY_HOLY_SHOCK);
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
+ DoCast(target, SPELL_HOLY_SHOCK);
+ events.Repeat(13300ms);
+ break;
+ }
+ case EVENT_SACRED_GROUND:
+ {
+ Talk(SAY_SACRED_GROUND);
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
+ {
+ Talk(SAY_SACRED_GROUND_WARNING, target);
+ DoCast(target, SPELL_SACRED_GROUND);
+ }
+ events.Repeat(19400ms);
+ break;
+ }
+ case EVENT_MASS_REPENTANCE:
+ {
+ Talk(SAY_MASS_REPENTANCE_WARNING);
+ Talk(SAY_MASS_REPENTANCE);
+ events.CancelEvent(EVENT_HOLY_BOLT);
+ events.CancelEvent(EVENT_HOLY_SHOCK);
+ events.CancelEvent(EVENT_SACRED_GROUND);
+ me->SetReactState(REACT_PASSIVE);
+ DoCastSelf(SPELL_MASS_REPENTANCE);
+ events.ScheduleEvent(EVENT_HOLY_BULWARK, 7300ms);
+ events.Repeat(51s);
+ break;
+ }
+ case EVENT_HOLY_BULWARK:
+ {
+ events.CancelEvent(EVENT_MASS_REPENTANCE);
+ Talk(SAY_HOLY_BULWARK);
+ DoCastSelf(SPELL_HOLY_BULWARK);
+ events.ScheduleEvent(EVENT_HOLY_WRATH, 1200ms);
+ break;
+ }
+ case EVENT_HOLY_WRATH:
+ {
+ Talk(SAY_HOLY_WRATH);
+ DoCastSelf(SPELL_HOLY_WRATH);
+ events.Repeat(2s);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+ }
+};
+
+// 227793 - Sacred Ground
+class spell_maiden_of_virtue_rtk_sacred_ground : public AuraScript
+{
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
+ }
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/) const
+ {
+ if (!GetCaster())
+ return;
+
+ GetCaster()->CastSpell(GetTarget(), GetEffectInfo(EFFECT_0).CalcValue(), TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_maiden_of_virtue_rtk_sacred_ground::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+// 227817 - Holy Bulwark
+class spell_maiden_of_virtue_rtk_holy_bulwark : public AuraScript
+{
+ void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ InstanceScript* instance = caster->GetInstanceScript();
+ if (!instance)
+ return;
+
+ if (Creature* maiden = instance->GetCreature(DATA_MAIDEN_OF_VIRTUE_RTK))
+ maiden->AI()->DoAction(ACTION_INTERRUPT_HOLY_WRATH);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_maiden_of_virtue_rtk_holy_bulwark::AfterRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// 227789 - Sacred Ground
+struct at_maiden_of_virtue_rtk_sacred_ground : AreaTriggerAI
+{
+ using AreaTriggerAI::AreaTriggerAI;
+
+ void OnUnitEnter(Unit* unit) override
+ {
+ if (!unit->IsPlayer())
+ return;
+
+ Unit* caster = at->GetCaster();
+ if (!caster)
+ return;
+
+ caster->CastSpell(unit, SPELL_SACRED_GROUND_PERIODIC, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
+ }
+
+ void OnUnitExit(Unit* unit) override
+ {
+ unit->RemoveAura(SPELL_SACRED_GROUND_PERIODIC);
+ }
+};
+
+// 232515 - Play Scene 2
+// Id - 1538
+class scene_maiden_of_virtue_outro : public SceneScript
+{
+public:
+ scene_maiden_of_virtue_outro() : SceneScript("scene_maiden_of_virtue_outro") { }
+
+ static void HandleScene(Player* player)
+ {
+ player->ClearUnitState(UNIT_STATE_ROOT);
+ }
+
+ void OnSceneStart(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ player->AddUnitState(UNIT_STATE_ROOT);
+ }
+
+ void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ HandleScene(player);
+ }
+
+ void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ HandleScene(player);
+ }
+};
+
+void AddSC_boss_maiden_of_virtue_rtk()
+{
+ RegisterReturnToKarazhanCreatureAI(boss_maiden_of_virtue_rtk);
+
+ RegisterSpellScript(spell_maiden_of_virtue_rtk_sacred_ground);
+ RegisterSpellScript(spell_maiden_of_virtue_rtk_holy_bulwark);
+
+ RegisterAreaTriggerAI(at_maiden_of_virtue_rtk_sacred_ground);
+
+ new scene_maiden_of_virtue_outro();
+}
diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp
new file mode 100644
index 00000000000..2a13f3e6fdc
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/instance_return_to_karazhan.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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 "AreaBoundary.h"
+#include "InstanceScript.h"
+#include "ScriptMgr.h"
+#include "return_to_karazhan.h"
+
+BossBoundaryData const boundaries =
+{
+ { DATA_MAIDEN_OF_VIRTUE_RTK, new CircleBoundary(Position(-10945.900391f, -2103.530029f, 92.794197f), 55.0f) }
+};
+
+ObjectData const creatureData[] =
+{
+ { BOSS_MAIDEN_OF_VIRTUE_RTK, DATA_MAIDEN_OF_VIRTUE_RTK },
+ { 0, 0 } // END
+};
+
+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_SHADE_OF_MEDIVH, {{ 1965 }} },
+ { DATA_MANA_DEVOURER, {{ 1959 }} },
+ { DATA_VIZADUUM_THE_WATCHER, {{ 2017 }} },
+ { DATA_NIGHTBANE, {{ 2031 }} }
+};
+
+class instance_return_to_karazhan : public InstanceMapScript
+{
+ public:
+ instance_return_to_karazhan() : InstanceMapScript(RTKScriptName, 1651) { }
+
+ struct instance_return_to_karazhan_InstanceMapScript: public InstanceScript
+ {
+ instance_return_to_karazhan_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ {
+ SetHeaders(DataHeader);
+ SetBossNumber(EncounterCount);
+ LoadObjectData(creatureData, nullptr);
+ LoadBossBoundaries(boundaries);
+ LoadDungeonEncounterData(encounters);
+ }
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_return_to_karazhan_InstanceMapScript(map);
+ }
+};
+
+void AddSC_instance_return_to_karazhan()
+{
+ new instance_return_to_karazhan();
+}
diff --git a/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h
new file mode 100644
index 00000000000..0f6ad0c5a72
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/ReturnToKarazhan/return_to_karazhan.h
@@ -0,0 +1,56 @@
+/*
+ * 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_RETURN_TO_KARAZHAN_H_
+#define DEF_RETURN_TO_KARAZHAN_H_
+
+#include "CreatureAIImpl.h"
+
+#define DataHeader "ReturnToKarazhan"
+#define RTKScriptName "instance_return_to_karazhan"
+
+constexpr uint32 EncounterCount = 9;
+
+enum RTKDataTypes : uint8
+{
+ // Encounters
+ DATA_OPERA_HALL = 0,
+ DATA_MAIDEN_OF_VIRTUE_RTK,
+ DATA_MOROES,
+ DATA_ATTUMEN_THE_HUNTSMAN,
+ DATA_THE_CURATOR,
+ DATA_SHADE_OF_MEDIVH,
+ DATA_MANA_DEVOURER,
+ DATA_VIZADUUM_THE_WATCHER,
+ DATA_NIGHTBANE
+};
+
+enum RTKCreatureIds
+{
+ // Bosses
+ BOSS_MAIDEN_OF_VIRTUE_RTK = 113971
+};
+
+template <class AI, class T>
+inline AI* GetReturnToKarazhanAI(T* obj)
+{
+ return GetInstanceAI<AI>(obj, RTKScriptName);
+}
+
+#define RegisterReturnToKarazhanCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetReturnToKarazhanAI)
+
+#endif
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 6f423cc01eb..0961807ae42 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -204,6 +204,10 @@ void AddSC_tol_barad();
void AddSC_undercity();
//void AddSC_western_plaguelands();
+// Return to Karazhan
+void AddSC_instance_return_to_karazhan();
+void AddSC_boss_maiden_of_virtue_rtk();
+
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddEasternKingdomsScripts()
@@ -396,4 +400,8 @@ void AddEasternKingdomsScripts()
AddSC_tol_barad();
AddSC_undercity();
//AddSC_western_plaguelands();
+
+ // Return to Karazhan
+ AddSC_instance_return_to_karazhan();
+ AddSC_boss_maiden_of_virtue_rtk();
}