From 80c5aec13a3ea2bd8ef995f832e075e2e6128b11 Mon Sep 17 00:00:00 2001 From: SylvaniaCore deploy Date: Sun, 12 Jul 2026 15:27:06 +0000 Subject: [PATCH] Campagne moine : scenario Serenity's End (943/map 1014) + reactivation quete 12103 + choix artefact PlayerChoice 242 - Nouveau scenario_monk_serenitys_end.cpp : InstanceScript map 1014, 7 etapes officielles, escorte Chen, boss Jorvinax, pierre gangrenee 98353, teleport final ile Vagabonde (1514) - spell_monk.cpp : pelerinage zen devie vers map 1014 pendant la quete 12103 - class_hall_monk.cpp : PlayerScript choix artefact (choice 242 -> quetes 40638/39/40) - Data associee : ~/dc-patches/monk_campaign_intro.sql (appliquee) Co-Authored-By: Claude Fable 5 --- .../ClassHalls/class_hall_monk.cpp | 48 ++ .../Scenario/scenario_monk_serenitys_end.cpp | 534 ++++++++++++++++++ .../BrokenIsles/brokenisles_script_loader.cpp | 2 + src/server/scripts/Spells/spell_monk.cpp | 8 +- 4 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 src/server/scripts/BrokenIsles/Scenario/scenario_monk_serenitys_end.cpp diff --git a/src/server/scripts/BrokenIsles/ClassHalls/class_hall_monk.cpp b/src/server/scripts/BrokenIsles/ClassHalls/class_hall_monk.cpp index a2ac0d8..aee0061 100644 --- a/src/server/scripts/BrokenIsles/ClassHalls/class_hall_monk.cpp +++ b/src/server/scripts/BrokenIsles/ClassHalls/class_hall_monk.cpp @@ -17,6 +17,9 @@ */ #include "ScriptMgr.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "ScriptedCreature.h" enum { ///MONK Quest @@ -61,7 +64,52 @@ private: bool SayHi; }; +enum MonkArtifactChoice +{ + PLAYER_CHOICE_MONK_ARTIFACT = 242, + RESPONSE_MONK_MISTWEAVER = 241, + RESPONSE_MONK_BREWMASTER = 242, + RESPONSE_MONK_WINDWALKER = 243, + QUEST_WINDWALKER_CHOSEN = 40638, + QUEST_MISTWEAVER_CHOSEN = 40639, + QUEST_BREWMASTER_CHOSEN = 40640, +}; + +// Choix d artefact au gossip de Ponshu (sort 198902 -> PlayerChoice 242) : +// accorde et recompense la quete de la spe choisie, qui donne l arme prodigieuse. +class monk_artifact_player_choice : public PlayerScript +{ +public: + monk_artifact_player_choice() : PlayerScript("monk_artifact_player_choice") { } + + void OnPlayerChoiceResponse(Player* player, uint32 choiceId, uint32 responseId) override + { + if (player->getClass() != CLASS_MONK || choiceId != PLAYER_CHOICE_MONK_ARTIFACT) + return; + + uint32 questId = 0; + switch (responseId) + { + case RESPONSE_MONK_MISTWEAVER: questId = QUEST_MISTWEAVER_CHOSEN; break; + case RESPONSE_MONK_BREWMASTER: questId = QUEST_BREWMASTER_CHOSEN; break; + case RESPONSE_MONK_WINDWALKER: questId = QUEST_WINDWALKER_CHOSEN; break; + default: return; + } + + if (player->GetQuestStatus(questId) != QUEST_STATUS_NONE) + return; + + if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) + { + player->AddQuest(quest, nullptr); + player->CompleteQuest(questId); + player->RewardQuest(quest, 0, player, true); + } + } +}; + void AddSC_class_hall_monk() { RegisterCreatureAI(npc_initiate_da_nel); + new monk_artifact_player_choice(); } diff --git a/src/server/scripts/BrokenIsles/Scenario/scenario_monk_serenitys_end.cpp b/src/server/scripts/BrokenIsles/Scenario/scenario_monk_serenitys_end.cpp new file mode 100644 index 0000000..3b0cd56 --- /dev/null +++ b/src/server/scripts/BrokenIsles/Scenario/scenario_monk_serenitys_end.cpp @@ -0,0 +1,534 @@ +/* + * Scenario: Serenity's End (ScenarioID 943, Map 1014) + * Monk order hall campaign intro - the Peak of Serenity falls to the Legion. + * Quest 12103 "Before the Storm". + * Positions derived from the identical MoP terrain spawns (map 870). + */ + +#include "ScriptMgr.h" +#include "InstanceScript.h" +#include "Scenario.h" +#include "InstanceScenario.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "PhasingHandler.h" +#include "TemporarySummon.h" +#include "MotionMaster.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "TaskScheduler.h" + +enum SerenitysEndData +{ + DATA_STAGE_COUNCIL = 1, + DATA_STAGE_CRANE = 2, + DATA_STAGE_JOURNEY = 3, + DATA_STAGE_TIGER = 4, + DATA_STAGE_CARGO = 5, + DATA_STAGE_PORTAL_BOSS = 6, + DATA_STAGE_FEL_STONE = 7, + DATA_MAX_STAGES = 8, + + DATA_COUNCIL_TALKED = 20, + DATA_DESTROYER_DEAD = 21, + DATA_VIZZNAK_DEAD = 22, + DATA_JIA_TELEPORT = 23, + DATA_MORVATH_DEAD = 24, + DATA_INVADER_DEAD = 25, + DATA_ESCORT_ARRIVED = 26, + DATA_JORVINAX_DEAD = 27, + DATA_FEL_STONE_DEAD = 28, + + DATA_CURRENT_STAGE = 50, +}; + +enum SerenitysEndCreatures +{ + NPC_MASTER_HIGHT_COUNCIL = 97778, + NPC_MASTER_HIGHT_PORTAL = 98515, + NPC_IRON_BODY_PONSHU = 97777, + NPC_JIA_COUNCIL = 97774, + NPC_JIA_CRANE = 98939, + NPC_MASTER_CHANG = 97954, + NPC_MASTER_HWANG = 97958, + NPC_ASPIRING_MONK = 97679, + NPC_INITIATE_CHUANG = 98001, + NPC_JUNIOR_TRAINEE = 98074, + NPC_CHEN_STORMSTOUT = 100307, + NPC_LADY_KELETRESS = 104755, + NPC_INFERNAL_DESTROYER = 98011, + NPC_CHAOS_MINION = 98286, + NPC_EYE_OF_KELETRESS = 105256, + NPC_FELBLADE_DESTROYER = 97966, + NPC_FELBLOOD_PACKHOUND = 98785, + NPC_EREDAR_SUMMONER = 98505, + NPC_INFERNAL_INVADER = 98496, + NPC_VIZZNAK = 97968, + NPC_MORVATH_THE_REAVER = 97811, + NPC_PORTAL_MASTER_JORVINAX = 98217, + NPC_MASTER_FEL_STONE = 98353, + NPC_CREDIT_PILGRIMAGE = 98514, +}; + +enum SerenitysEndMisc +{ + QUEST_BEFORE_THE_STORM = 12103, + PHASE_NORMAL = 169, + MAP_WANDERING_ISLE = 1514, +}; + +// --- Shrine of the Ox (temple) --- +Position const PosHight = { 3826.0f, 1794.0f, 950.92f, 0.05f }; +Position const PosPonshu = { 3824.5f, 1788.5f, 950.92f, 0.60f }; +Position const PosJiaCouncil = { 3824.5f, 1799.5f, 950.92f, 5.70f }; +Position const PosChang = { 3830.0f, 1788.0f, 950.92f, 1.20f }; +Position const PosHwang = { 3830.0f, 1800.0f, 950.92f, 5.20f }; +Position const PosMonkA = { 3833.5f, 1791.0f, 950.92f, 2.80f }; +Position const PosMonkB = { 3833.5f, 1797.0f, 950.92f, 3.40f }; +Position const PosChuang = { 3846.0f, 1794.0f, 951.00f, 3.14f }; +Position const PosDestroyer = { 3853.0f, 1794.0f, 951.50f, 3.14f }; +// --- road to the Crane shrine (north-west) --- +Position const PosPackA[3] = { { 3836.0f, 1858.0f, 944.0f, 4.7f }, { 3841.0f, 1861.0f, 944.0f, 4.7f }, { 3838.5f, 1865.0f, 944.2f, 4.7f } }; +Position const PosPackB[3] = { { 3828.0f, 1925.0f, 939.0f, 4.9f }, { 3833.0f, 1928.0f, 939.0f, 4.9f }, { 3830.5f, 1932.0f, 939.2f, 4.9f } }; +Position const PosJiaCrane = { 3823.0f, 1990.0f, 936.20f, 3.60f }; +Position const PosVizznak = { 3818.0f, 1994.0f, 936.20f, 0.40f }; +Position const PosKeletress = { 3855.0f, 1862.0f, 988.00f, 3.60f }; +// --- Tiger courtyard (east) --- +Position const PosTigerArrival= { 4008.0f, 1700.0f, 924.80f, 0.30f }; +Position const PosChen = { 4033.0f, 1693.0f, 924.80f, 2.90f }; +Position const PosHounds[3] = { { 4038.0f, 1688.0f, 924.8f, 2.9f }, { 4040.0f, 1697.0f, 924.8f, 3.1f }, { 4035.0f, 1701.0f, 924.8f, 3.4f } }; +Position const PosSummoner = { 4044.0f, 1700.0f, 924.80f, 3.10f }; +Position const PosMorvath = { 4047.0f, 1688.0f, 924.80f, 3.00f }; +Position const PosTrainees[3] = { { 4028.0f, 1690.0f, 924.8f, 2.9f }, { 4029.0f, 1695.0f, 924.8f, 2.9f }, { 4026.0f, 1698.0f, 924.8f, 2.9f } }; +// --- escort waypoints (mmaps pathfinding smooths the Z) --- +Position const WPEscort[4] = { { 4005.0f, 1720.0f, 921.0f }, { 3975.0f, 1750.0f, 915.0f }, { 3955.0f, 1770.0f, 910.0f }, { 3937.0f, 1782.0f, 904.5f } }; +Position const PosAmbush = { 3958.0f, 1778.0f, 910.00f, 4.60f }; +// --- portal site (training grounds) --- +Position const PosJorvinax = { 3915.0f, 1790.0f, 904.30f, 0.10f }; +Position const PosHightPortal = { 3938.0f, 1778.0f, 904.30f, 2.90f }; +Position const PosFelStone = { 3910.0f, 1796.0f, 904.30f, 0.00f }; +Position const PosWakeUp = { 739.77f, 3440.22f, 122.19f, 3.10f }; + +struct scenario_monk_serenitys_end : public InstanceScript +{ + scenario_monk_serenitys_end(InstanceMap* map) : InstanceScript(map) { } + + void Initialize() override + { + SetBossNumber(DATA_MAX_STAGES); + stage = 0; + introDone = false; + ambushDone = false; + } + + void OnPlayerEnter(Player* player) override + { + InstanceScript::OnPlayerEnter(player); + if (player->GetMapId() != 1014) + return; + + PhasingHandler::AddPhase(player, PHASE_NORMAL, true); + player->KilledMonsterCredit(NPC_CREDIT_PILGRIMAGE); + + if (!introDone) + { + introDone = true; + stage = DATA_STAGE_COUNCIL; + SummonCouncil(); + } + } + + void SummonCouncil() + { + if (Creature* hight = instance->SummonCreature(NPC_MASTER_HIGHT_COUNCIL, PosHight)) + hightGUID = hight->GetGUID(); + instance->SummonCreature(NPC_IRON_BODY_PONSHU, PosPonshu); + instance->SummonCreature(NPC_JIA_COUNCIL, PosJiaCouncil); + instance->SummonCreature(NPC_MASTER_CHANG, PosChang); + instance->SummonCreature(NPC_MASTER_HWANG, PosHwang); + instance->SummonCreature(NPC_ASPIRING_MONK, PosMonkA); + instance->SummonCreature(NPC_ASPIRING_MONK, PosMonkB); + } + + void CompleteStep() + { + if (Scenario* scenario = instance->GetInstanceScenario()) + scenario->CompleteCurrStep(); + } + + Creature* GetKeletress() { return instance->GetCreature(keletressGUID); } + + void SetData(uint32 type, uint32 data) override + { + InstanceScript::SetData(type, data); + if (data != DONE) + return; + + switch (type) + { + case DATA_COUNCIL_TALKED: // stage 1: council speech, then the Legion crashes in + { + if (Creature* hight = instance->GetCreature(hightGUID)) + { + hight->AI()->Talk(1); + hight->GetScheduler().Schedule(Seconds(8), [this](TaskContext /*context*/) + { + if (Creature* chuang = instance->SummonCreature(NPC_INITIATE_CHUANG, PosChuang)) + chuang->AI()->Talk(0); + }).Schedule(Seconds(12), [this](TaskContext /*context*/) + { + if (Creature* hight2 = instance->GetCreature(hightGUID)) + hight2->AI()->Talk(2); + if (Creature* destroyer = instance->SummonCreature(NPC_INFERNAL_DESTROYER, PosDestroyer)) + destroyer->SetInCombatWithZone(); + }); + } + break; + } + case DATA_DESTROYER_DEAD: // stage 1 -> 2 + { + stage = DATA_STAGE_CRANE; + CompleteStep(); + if (Creature* hight = instance->GetCreature(hightGUID)) + hight->AI()->Talk(3); + for (uint8 i = 0; i < 3; ++i) + { + instance->SummonCreature(i < 2 ? NPC_CHAOS_MINION : NPC_EYE_OF_KELETRESS, PosPackA[i]); + instance->SummonCreature(i < 2 ? NPC_CHAOS_MINION : NPC_FELBLADE_DESTROYER, PosPackB[i]); + } + if (Creature* keletress = instance->SummonCreature(NPC_LADY_KELETRESS, PosKeletress)) + { + keletressGUID = keletress->GetGUID(); + keletress->SetCanFly(true); + keletress->SetDisableGravity(true); + keletress->AI()->Talk(0); + } + if (Creature* jia = instance->SummonCreature(NPC_JIA_CRANE, PosJiaCrane)) + { + jiaGUID = jia->GetGUID(); + if (Creature* vizznak = instance->SummonCreature(NPC_VIZZNAK, PosVizznak)) + { + jia->AI()->Talk(0); + jia->AI()->AttackStart(vizznak); + vizznak->AI()->AttackStart(jia); + } + } + break; + } + case DATA_VIZZNAK_DEAD: // stage 2 -> 3 (Jia offers her chi teleport) + { + stage = DATA_STAGE_JOURNEY; + CompleteStep(); + if (Creature* keletress = GetKeletress()) + keletress->AI()->Talk(1); + if (Creature* jia = instance->GetCreature(jiaGUID)) + jia->AI()->Talk(1); + break; + } + case DATA_JIA_TELEPORT: // stage 3 -> 4 (rescue Chen) + { + stage = DATA_STAGE_TIGER; + CompleteStep(); + if (Creature* chen = instance->SummonCreature(NPC_CHEN_STORMSTOUT, PosChen)) + { + chenGUID = chen->GetGUID(); + chen->AI()->Talk(0); + } + for (uint8 i = 0; i < 3; ++i) + { + instance->SummonCreature(NPC_JUNIOR_TRAINEE, PosTrainees[i]); + if (Creature* hound = instance->SummonCreature(NPC_FELBLOOD_PACKHOUND, PosHounds[i])) + if (Creature* chen = instance->GetCreature(chenGUID)) + hound->AI()->AttackStart(chen); + } + instance->SummonCreature(NPC_EREDAR_SUMMONER, PosSummoner); + instance->SummonCreature(NPC_MORVATH_THE_REAVER, PosMorvath); + break; + } + case DATA_MORVATH_DEAD: // stage 4 -> 5 (escort back) + { + stage = DATA_STAGE_CARGO; + CompleteStep(); + if (Creature* chen = instance->GetCreature(chenGUID)) + { + chen->AI()->Talk(2); + chen->AI()->DoAction(1); // start escort + } + break; + } + case DATA_INVADER_DEAD: // ambush cleared, resume escort + { + if (Creature* chen = instance->GetCreature(chenGUID)) + chen->AI()->DoAction(2); + break; + } + case DATA_ESCORT_ARRIVED: // stage 5 -> 6 (Jorvinax) + { + stage = DATA_STAGE_PORTAL_BOSS; + CompleteStep(); + if (Creature* keletress = GetKeletress()) + keletress->AI()->Talk(2); + if (Creature* hight = instance->SummonCreature(NPC_MASTER_HIGHT_PORTAL, PosHightPortal)) + hightPortalGUID = hight->GetGUID(); + if (Creature* jorvinax = instance->SummonCreature(NPC_PORTAL_MASTER_JORVINAX, PosJorvinax)) + jorvinax->SetInCombatWithZone(); + break; + } + case DATA_JORVINAX_DEAD: // stage 6 -> 7 (destroy the fel stone) + { + stage = DATA_STAGE_FEL_STONE; + CompleteStep(); + if (Creature* hight = instance->GetCreature(hightPortalGUID)) + hight->AI()->Talk(0); + instance->SummonCreature(NPC_MASTER_FEL_STONE, PosFelStone); + break; + } + case DATA_FEL_STONE_DEAD: // scenario complete -> wake up at the Wandering Isle + { + CompleteStep(); + if (Scenario* scenario = instance->GetInstanceScenario()) + scenario->CompleteScenario(); + if (Creature* keletress = GetKeletress()) + keletress->DespawnOrUnsummon(2000); + if (Creature* hight = instance->GetCreature(hightPortalGUID)) + { + hight->AI()->Talk(1); + hight->GetScheduler().Schedule(Seconds(7), [this](TaskContext /*context*/) + { + DoOnPlayers([](Player* player) + { + player->KilledMonsterCredit(NPC_MASTER_FEL_STONE); + player->TeleportTo(MAP_WANDERING_ISLE, PosWakeUp.GetPositionX(), PosWakeUp.GetPositionY(), PosWakeUp.GetPositionZ(), PosWakeUp.GetOrientation()); + }); + }); + } + break; + } + default: + break; + } + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_CURRENT_STAGE) + return stage; + return InstanceScript::GetData(type); + } + + bool StartAmbush() + { + if (ambushDone) + return false; + ambushDone = true; + return true; + } + +private: + uint32 stage = 0; + bool introDone = false; + bool ambushDone = false; + ObjectGuid hightGUID; + ObjectGuid hightPortalGUID; + ObjectGuid jiaGUID; + ObjectGuid chenGUID; + ObjectGuid keletressGUID; +}; + +// Master Hight (council) - talking to him starts the meeting and credits quest objective +struct npc_serenity_master_hight : public ScriptedAI +{ + npc_serenity_master_hight(Creature* creature) : ScriptedAI(creature), talked(false) { } + + void sGossipHello(Player* player) override + { + CloseGossipMenuFor(player); + player->KilledMonsterCredit(me->GetEntry()); + if (talked) + return; + talked = true; + Talk(0); + if (InstanceScript* instance = me->GetInstanceScript()) + instance->SetData(DATA_COUNCIL_TALKED, DONE); + } + +private: + bool talked; +}; + +// Number Nine Jia (Crane shrine) - her chi sends the player to the Tiger courtyard +struct npc_serenity_number_nine_jia : public ScriptedAI +{ + npc_serenity_number_nine_jia(Creature* creature) : ScriptedAI(creature), sent(false) { } + + void sGossipHello(Player* player) override + { + CloseGossipMenuFor(player); + InstanceScript* instance = me->GetInstanceScript(); + if (!instance || instance->GetData(DATA_CURRENT_STAGE) != DATA_STAGE_JOURNEY) + return; + player->NearTeleportTo(PosTigerArrival.GetPositionX(), PosTigerArrival.GetPositionY(), PosTigerArrival.GetPositionZ(), PosTigerArrival.GetOrientation()); + if (!sent) + { + sent = true; + instance->SetData(DATA_JIA_TELEPORT, DONE); + } + } + +private: + bool sent; +}; + +// generic hostile that reports its death to the instance +struct npc_serenity_death_reporter : public ScriptedAI +{ + npc_serenity_death_reporter(Creature* creature, uint32 dataType) : ScriptedAI(creature), _dataType(dataType) { } + + void JustDied(Unit* /*killer*/) override + { + if (InstanceScript* instance = me->GetInstanceScript()) + instance->SetData(_dataType, DONE); + } + +private: + uint32 _dataType; +}; + +struct npc_serenity_infernal_destroyer : public npc_serenity_death_reporter +{ + npc_serenity_infernal_destroyer(Creature* creature) : npc_serenity_death_reporter(creature, DATA_DESTROYER_DEAD) { } +}; + +struct npc_serenity_vizznak : public npc_serenity_death_reporter +{ + npc_serenity_vizznak(Creature* creature) : npc_serenity_death_reporter(creature, DATA_VIZZNAK_DEAD) { } +}; + +struct npc_serenity_morvath : public npc_serenity_death_reporter +{ + npc_serenity_morvath(Creature* creature) : npc_serenity_death_reporter(creature, DATA_MORVATH_DEAD) { } +}; + +struct npc_serenity_invader : public npc_serenity_death_reporter +{ + npc_serenity_invader(Creature* creature) : npc_serenity_death_reporter(creature, DATA_INVADER_DEAD) { } +}; + +struct npc_serenity_jorvinax : public ScriptedAI +{ + npc_serenity_jorvinax(Creature* creature) : ScriptedAI(creature) { } + + void EnterCombat(Unit* /*who*/) override + { + Talk(0); + } + + void JustDied(Unit* /*killer*/) override + { + Talk(1); + if (InstanceScript* instance = me->GetInstanceScript()) + instance->SetData(DATA_JORVINAX_DEAD, DONE); + } +}; + +// Master Fel Stone - a destructible fel crystal (no melee, no movement) +struct npc_serenity_fel_stone : public ScriptedAI +{ + npc_serenity_fel_stone(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + me->SetControlled(true, UNIT_STATE_ROOT); + } + + void AttackStart(Unit* /*who*/) override { } + void UpdateAI(uint32 /*diff*/) override { } + + void JustDied(Unit* /*killer*/) override + { + if (InstanceScript* instance = me->GetInstanceScript()) + instance->SetData(DATA_FEL_STONE_DEAD, DONE); + } +}; + +// Chen Stormstout - fights at the Tiger courtyard, then escorts the trainees back +struct npc_serenity_chen : public ScriptedAI +{ + npc_serenity_chen(Creature* creature) : ScriptedAI(creature), wp(0), escorting(false) { } + + void DoAction(int32 action) override + { + InstanceScript* instance = me->GetInstanceScript(); + if (!instance) + return; + + if (action == 1) // start the escort + { + escorting = true; + wp = 0; + me->SetWalk(true); + MoveNext(); + } + else if (action == 2) // ambush cleared, keep going + { + Talk(1); + MoveNext(); + } + } + + void MoveNext() + { + if (wp < 4) + me->GetMotionMaster()->MovePoint(wp + 1, WPEscort[wp], true); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE || !escorting) + return; + + InstanceScript* instance = me->GetInstanceScript(); + if (!instance) + return; + + wp = id; + if (id == 2) // ambush halfway + { + if (scenario_monk_serenitys_end* script = dynamic_cast(instance)) + { + if (script->StartAmbush()) + { + Talk(3); + if (Creature* invader = me->SummonCreature(NPC_INFERNAL_INVADER, PosAmbush, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000)) + invader->AI()->AttackStart(me); + return; // wait for DoAction(2) + } + } + MoveNext(); + } + else if (id >= 4) // arrived at the portal site + { + escorting = false; + instance->SetData(DATA_ESCORT_ARRIVED, DONE); + } + else + MoveNext(); + } + +private: + uint8 wp; + bool escorting; +}; + +void AddSC_scenario_monk_serenitys_end() +{ + RegisterInstanceScript(scenario_monk_serenitys_end, 1014); + RegisterCreatureAI(npc_serenity_master_hight); + RegisterCreatureAI(npc_serenity_number_nine_jia); + RegisterCreatureAI(npc_serenity_infernal_destroyer); + RegisterCreatureAI(npc_serenity_vizznak); + RegisterCreatureAI(npc_serenity_morvath); + RegisterCreatureAI(npc_serenity_invader); + RegisterCreatureAI(npc_serenity_jorvinax); + RegisterCreatureAI(npc_serenity_fel_stone); + RegisterCreatureAI(npc_serenity_chen); +} diff --git a/src/server/scripts/BrokenIsles/brokenisles_script_loader.cpp b/src/server/scripts/BrokenIsles/brokenisles_script_loader.cpp index fd140d8..7685698 100644 --- a/src/server/scripts/BrokenIsles/brokenisles_script_loader.cpp +++ b/src/server/scripts/BrokenIsles/brokenisles_script_loader.cpp @@ -216,6 +216,7 @@ void AddSC_scenario_artifact_brokenshore(); void AddSC_scenario_artifact_tirisfal_glades(); void AddSC_scenario_the_violet_hold_dh(); void AddSC_scenario_mage_art(); +void AddSC_scenario_monk_serenitys_end(); // The name of this function should match: // void Add${NameOfDirectory}Scripts() @@ -413,4 +414,5 @@ void AddBrokenIslesScripts() AddSC_scenario_artifact_tirisfal_glades(); AddSC_scenario_the_violet_hold_dh(); AddSC_scenario_mage_art(); + AddSC_scenario_monk_serenitys_end(); } diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index d0b5287..7366aa9 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -1243,7 +1243,13 @@ public: _player->SaveRecallPosition(); //Class Order Hall if (_player->getLevel() >= 98) - _player->TeleportTo(1514, 882.933f, 3605.61f, 192.218f, _player->GetOrientation()); + { + // Pendant la quete 12103 (Before the Storm), le pelerinage mene au pic de la Serenite assiege (scenario 943) + if (_player->GetQuestStatus(12103) == QUEST_STATUS_INCOMPLETE) + _player->TeleportTo(1014, 3819.2f, 1793.27f, 950.35f, _player->GetOrientation()); + else + _player->TeleportTo(1514, 882.933f, 3605.61f, 192.218f, _player->GetOrientation()); + } else _player->TeleportTo(870, 3818.55f, 1793.18f, 950.35f, _player->GetOrientation()); }