diff options
author | Teleqraph <nyrdeveloper@gmail.com> | 2023-10-22 05:23:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-22 05:23:04 +0200 |
commit | 3d3979f1cabf59321fbafcde1f0d1e600d29e974 (patch) | |
tree | 8820cd5ff0d829d1422d2a11416bc2651037bb97 /src | |
parent | 13b5e4990687b92ed2d1db20eb12eed182d5a6ff (diff) |
Scripts/SOD: Implement Sylvanas Windrunner introduction (#28554)
Diffstat (limited to 'src')
4 files changed, 869 insertions, 0 deletions
diff --git a/src/server/scripts/Shadowlands/SanctumOfDomination/boss_sylvanas_windrunner.cpp b/src/server/scripts/Shadowlands/SanctumOfDomination/boss_sylvanas_windrunner.cpp new file mode 100644 index 00000000000..4ed74a7b144 --- /dev/null +++ b/src/server/scripts/Shadowlands/SanctumOfDomination/boss_sylvanas_windrunner.cpp @@ -0,0 +1,489 @@ +/* + * 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 "Conversation.h" +#include "CreatureAI.h" +#include "CreatureAIImpl.h" +#include "InstanceScript.h" +#include "Map.h" +#include "MotionMaster.h" +#include "Player.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "sanctum_of_domination.h" + +Position const SylvanasIntroPos[4] = +{ + { 231.15799f, -832.816f, 4105.0386f }, + { 242.00348f, -840.51215f, 4105.0386f }, + { 241.23091f, -830.0955f, 4105.0386f }, + { 225.73611f, -844.0746f, 4104.9882f, 1.3613f } +}; + +enum SylvanasSpells +{ + // Stances + SPELL_RANGER_BOW_STANCE = 347560, + SPELL_RANGER_DAGGERS_STANCE = 348010, + + // Miscellanea + SPELL_GENERIC_ANCHOR_HERE = 45313, + SPELL_GENERIC_DUAL_WIELD = 42459, + SPELL_SYLVANAS_DISPLAY_POWER_SUFFERING = 352311, + SPELL_SYLVANAS_ROOT = 347608 +}; + +enum SylvanasPhases +{ + PHASE_ONE = 1, + PHASE_INTERMISSION = 4, + PHASE_TWO = 2, + PHASE_THREE = 3, + PHASE_INTERMISSION_WORLD_STATE = 11 +}; + +enum SylvanasEventGroups +{ + EVENT_GROUP_NORMAL_EVENTS = 1, + EVENT_GROUP_WINDRUNNER_EVENTS = 2 +}; + +enum SylvanasEvents +{ + EVENT_INTRODUCTION = 1, + EVENT_SIZE_MAX = 200 +}; + +enum SylvanasTexts +{ + SAY_ENGAGE = 0, + SAY_SLAY = 1, + SAY_DISENGAGE = 2 +}; + +enum SylvanasConversations +{ + CONVERSATION_SYLVANAS_INTRODUCTION = 17368, + CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_SYLVANAS_ID = 0, + CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID = 1 +}; + +enum SylvanasSpawnGroups +{ + SPAWN_GROUP_CHAMPIONS_FIRST_PHASE = 0, + SPAWN_GROUP_CHAMPIONS_THIRD_PHASE, + SPAWN_GROUP_CHAMPIONS_OUTRODUCTION +}; + +enum SylvanasPoints +{ + POINT_INTRODUCTION = 1 +}; + +enum SylvanasSpellVisualKits +{ + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_01 = 150067, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_02 = 150068, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_03 = 150069, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_04 = 150071, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_05 = 150072, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_06 = 150070, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_07 = 150074, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_08 = 150077, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_09 = 150076, + SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_10 = 150075, + SPELL_VISUAL_KIT_BOLVAR_INTRODUCTION_TALK_01 = 150073, + + SPELL_VISUAL_KIT_SYLVANAS_TELEPORT = 150078 +}; + +// 178355 - Sylvanas Shadowcopy (Riding) +struct npc_sylvanas_windrunner_shadowcopy_riding : public ScriptedAI +{ + npc_sylvanas_windrunner_shadowcopy_riding(Creature* creature) : ScriptedAI(creature) { } + + void JustAppeared() override + { + me->SetImmuneToAll(true, true); + me->SetUninteractible(true); + me->SetReactState(REACT_PASSIVE); + } +}; + +// 175732 - Sylvanas Windrunner +struct boss_sylvanas_windrunner : public BossAI +{ + boss_sylvanas_windrunner(Creature* creature) : BossAI(creature, DATA_SYLVANAS_WINDRUNNER) { } + + void JustAppeared() override + { + DoCastSelf(SPELL_GENERIC_DUAL_WIELD, true); + DoCastSelf(SPELL_SYLVANAS_DISPLAY_POWER_SUFFERING, true); + + me->SetPower(me->GetPowerType(), 0); + + if (instance->GetData(DATA_SYLVANAS_INTRODUCTION) == DONE) + { + me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1); + me->SetImmuneToAll(false); + me->SetSpeed(MOVE_RUN, 14.0f); + } + else + { + me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1); + me->SetImmuneToAll(true); + me->SetSpeed(MOVE_RUN, 4.0f); + } + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + Talk(SAY_DISENGAGE); + + _EnterEvadeMode(); + + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + + _DespawnAtEvade(); + } + + void Reset() override + { + _Reset(); + + // Note: every creature involved in the fight adds UNIT_FLAG_PET_IN_COMBAT or UNIT_FLAG_RENAME when engaging, meaning they're most likely summoned by Sylvanas. + me->SummonCreatureGroup(SPAWN_GROUP_CHAMPIONS_FIRST_PHASE); + + instance->DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE, PHASE_ONE); + + events.Reset(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == POINT_INTRODUCTION) + DoCastSelf(SPELL_GENERIC_ANCHOR_HERE, true); + } + + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; + + Talk(SAY_SLAY); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + + Talk(SAY_ENGAGE); + + instance->DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE, PHASE_ONE); + + events.SetPhase(PHASE_ONE); + + // Note: Sylvanas uses her root with 2s at the beginning of the encounter, most likely to avoid moving when engaging at stance switch. + DoCastSelf(SPELL_SYLVANAS_ROOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_DURATION, 2000)); + + // Note: we won't allow engaging until Phase 1 PR is merged. + me->Say("Only introduction is implemented so far, evading.", LANG_UNIVERSAL); + EnterEvadeMode(EvadeReason::Other); + } +}; + +// 45 - Sylvanas Windrunner's Position Z Check (Serverside) +struct at_sylvanas_windrunner_z_check : AreaTriggerAI +{ + at_sylvanas_windrunner_z_check(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + if (!unit->IsAlive()) + return; + + if (Player* player = unit->ToPlayer()) + { + if (player->IsGameMaster()) + return; + + if (player->IsAlive()) + player->KillSelf(false); + } + } +}; + +// 46 - Sylvanas Windrunner's Conversation Introduction (Serverside) +struct at_sylvanas_windrunner_introduction : AreaTriggerAI +{ + at_sylvanas_windrunner_introduction(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + InstanceScript* instance = at->GetInstanceScript(); + if (!instance) + return; + + Player* player = unit->ToPlayer(); + if (!player || player->IsGameMaster()) + return; + + if (Creature* sylvanas = instance->GetCreature(DATA_SYLVANAS_WINDRUNNER)) + Conversation::CreateConversation(CONVERSATION_SYLVANAS_INTRODUCTION, sylvanas, sylvanas->GetPosition(), ObjectGuid::Empty); + + at->Remove(); + } +}; + +// 17368 - Sylvanas Windrunner's Introduction (Conversation) +class conversation_sylvanas_windrunner_introduction : public ConversationScript +{ +public: + conversation_sylvanas_windrunner_introduction() : ConversationScript("conversation_sylvanas_windrunner_introduction") { } + + void OnConversationCreate(Conversation* conversation, Unit* creator) override + { + InstanceScript* instance = creator->GetInstanceScript(); + if (!instance) + return; + + Creature* bolvar = instance->GetCreature(DATA_BOLVAR_FORDRAGON_PINNACLE); + if (!bolvar) + return; + + instance->SetData(DATA_SYLVANAS_INTRODUCTION, IN_PROGRESS); + conversation->AddActor(NPC_BOLVAR_FORDRAGON_PINNACLE, CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID, bolvar->GetGUID()); + + _events.ScheduleEvent(EVENT_INTRODUCTION, 5s + 500ms); + } + + void OnConversationUpdate(Conversation* conversation, uint32 diff) override + { + _events.Update(diff); + + uint32 eventId = _events.ExecuteEvent(); + Creature* sylvanas = nullptr; + Creature* bolvar = nullptr; + + if (eventId) + { + sylvanas = conversation->GetActorCreature(CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_SYLVANAS_ID); + if (!sylvanas) + return; + + bolvar = conversation->GetActorCreature(CONVERSATION_SYLVANAS_INTRODUCTION_ACTOR_BOLVAR_ID); + if (!bolvar) + return; + } + + switch (eventId) + { + case EVENT_INTRODUCTION: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_01, 0, 0); + sylvanas->SetFacingToObject(bolvar); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 1, 1s + 140ms); + break; + } + + case EVENT_INTRODUCTION + 1: + { + sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[0], false); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 2, 1s + 500ms); + break; + } + + case EVENT_INTRODUCTION + 2: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_02, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 3, 3s + 360ms); + break; + } + + case EVENT_INTRODUCTION + 3: + { + sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[1], false); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 4, 469ms); + break; + } + + case EVENT_INTRODUCTION + 4: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_03, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 5, 3s + 500ms); + break; + } + + case EVENT_INTRODUCTION + 5: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_04, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 6, 2s); + break; + } + + case EVENT_INTRODUCTION + 6: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_05, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 7, 5s); + break; + } + + case EVENT_INTRODUCTION + 7: + { + sylvanas->SetFacingToObject(bolvar); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 8, 750ms); + break; + } + + case EVENT_INTRODUCTION + 8: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_06, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 9, 457ms); + break; + } + + case EVENT_INTRODUCTION + 9: + { + sylvanas->GetMotionMaster()->MovePoint(POINT_INTRODUCTION, SylvanasIntroPos[2], false); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 10, 5s + 89ms); + break; + } + + case EVENT_INTRODUCTION + 10: + { + bolvar->SetFacingToObject(sylvanas); + bolvar->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_BOLVAR_INTRODUCTION_TALK_01, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 11, 13s + 567ms); + break; + } + + case EVENT_INTRODUCTION + 11: + { + sylvanas->SetFacingToObject(bolvar); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 12, 484ms); + break; + } + + case EVENT_INTRODUCTION + 12: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_07, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 13, 5s + 516ms); + break; + } + + case EVENT_INTRODUCTION + 13: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_08, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 14, 1s + 516ms); + break; + } + + case EVENT_INTRODUCTION + 14: + { + sylvanas->NearTeleportTo(SylvanasIntroPos[3], false); + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_TELEPORT, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 15, 1s + 265ms); + break; + } + + case EVENT_INTRODUCTION + 15: + { + sylvanas->SetFacingToObject(bolvar); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 16, 969ms); + break; + } + + case EVENT_INTRODUCTION + 16: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_09, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 17, 4s + 766ms); + break; + } + + case EVENT_INTRODUCTION + 17: + { + sylvanas->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_SYLVANAS_INTRODUCTION_TALK_10, 0, 0); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 18, 3s + 250ms); + break; + } + + case EVENT_INTRODUCTION + 18: + { + sylvanas->CastSpell(sylvanas, SPELL_RANGER_BOW_STANCE); + + _events.ScheduleEvent(EVENT_INTRODUCTION + 19, 16ms); + break; + } + + case EVENT_INTRODUCTION + 19: + { + sylvanas->CastSpell(sylvanas, SPELL_GENERIC_ANCHOR_HERE); + + if (InstanceScript* instance = sylvanas->GetInstanceScript()) + instance->SetData(DATA_SYLVANAS_INTRODUCTION, DONE); + break; + } + + default: + break; + } + } + +private: + EventMap _events; +}; + +void AddSC_boss_sylvanas_windrunner() +{ + RegisterSanctumOfDominationCreatureAI(boss_sylvanas_windrunner); + RegisterSanctumOfDominationCreatureAI(npc_sylvanas_windrunner_shadowcopy_riding); + + RegisterAreaTriggerAI(at_sylvanas_windrunner_z_check); + RegisterAreaTriggerAI(at_sylvanas_windrunner_introduction); + + new conversation_sylvanas_windrunner_introduction(); +} diff --git a/src/server/scripts/Shadowlands/SanctumOfDomination/instance_sanctum_of_domination.cpp b/src/server/scripts/Shadowlands/SanctumOfDomination/instance_sanctum_of_domination.cpp new file mode 100644 index 00000000000..dfba70edc87 --- /dev/null +++ b/src/server/scripts/Shadowlands/SanctumOfDomination/instance_sanctum_of_domination.cpp @@ -0,0 +1,254 @@ +/* + * 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 "Creature.h" +#include "GameObject.h" +#include "InstanceScript.h" +#include "Map.h" +#include "Player.h" +#include "ScriptMgr.h" +#include "sanctum_of_domination.h" + +ObjectData const creatureData[] = +{ + { BOSS_SYLVANAS_WINDRUNNER, DATA_SYLVANAS_WINDRUNNER }, + { NPC_SYLVANAS_SHADOWCOPY_RIDING, DATA_SYLVANAS_SHADOWCOPY_RIDING }, + { NPC_BOLVAR_FORDRAGON_PINNACLE, DATA_BOLVAR_FORDRAGON_PINNACLE }, + { NPC_JAINA_PROUDMOORE_PINNACLE, DATA_JAINA_PROUDMOORE_PINNACLE }, + { NPC_THRALL_PINNACLE, DATA_THRALL_PINNACLE }, + { NPC_THRONE_OF_THE_DAMNED, DATA_THRONE_OF_THE_DAMNED }, + { 0, 0 } // END +}; + +DungeonEncounterData const encounters[] = +{ + { DATA_THE_TARRAGRUE, {{ 2423 }} }, + { DATA_THE_EYE_OF_THE_JAILER, {{ 2433 }} }, + { DATA_THE_NINE, {{ 2429 }} }, + { DATA_REMNANT_OF_NERZHUL, {{ 2432 }} }, + { DATA_SOULRENDER_DORMAZAIN, {{ 2434 }} }, + { DATA_PAINSMITH_RAZNAL, {{ 2430 }} }, + { DATA_GUARDIAN_OF_THE_FIRST_ONES, {{ 2436 }} }, + { DATA_FATESCRIBE_ROHKALO, {{ 2431 }} }, + { DATA_KELTHUZAD, {{ 2422 }} }, + { DATA_SYLVANAS_WINDRUNNER, {{ 2435 }} } +}; + +class instance_sanctum_of_domination : public InstanceMapScript +{ +public: + instance_sanctum_of_domination() : InstanceMapScript(SODScriptName, 2450) { } + + struct instance_sanctum_of_domination_InstanceMapScript : public InstanceScript + { + instance_sanctum_of_domination_InstanceMapScript(InstanceMap* map) : InstanceScript(map) + { + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadDungeonEncounterData(encounters); + LoadObjectData(creatureData, nullptr); + + SylvanasIntroductionState = NOT_STARTED; + } + + void OnCreatureCreate(Creature* creature) override + { + InstanceScript::OnCreatureCreate(creature); + + switch (creature->GetEntry()) + { + case BOSS_SYLVANAS_WINDRUNNER: + SylvanasGUID = creature->GetGUID(); + break; + + case NPC_SYLVANAS_SHADOWCOPY_RIDING: + SylvanasShadowcopyRidingGUID = creature->GetGUID(); + break; + + case NPC_BOLVAR_FORDRAGON_PINNACLE: + BolvarPinnacleGUID = creature->GetGUID(); + break; + + case NPC_JAINA_PROUDMOORE_PINNACLE: + JainaPinnacleGUID = creature->GetGUID(); + break; + + case NPC_THRALL_PINNACLE: + ThrallPinnacleGUID = creature->GetGUID(); + break; + + case NPC_THRONE_OF_THE_DAMNED: + ThroneOfTheDamnedGUID = creature->GetGUID(); + break; + + default: + break; + } + } + + void OnGameObjectCreate(GameObject* go) override + { + switch (go->GetEntry()) + { + case GAMEOBJECT_TORGHAST_SPIKE_01: + case GAMEOBJECT_TORGHAST_SPIKE_02: + case GAMEOBJECT_TORGHAST_SPIKE_03: + case GAMEOBJECT_TORGHAST_SPIKE_04: + case GAMEOBJECT_TORGHAST_SPIKE_05: + case GAMEOBJECT_TORGHAST_SPIKE_06: + case GAMEOBJECT_TORGHAST_SPIKE_07: + case GAMEOBJECT_TORGHAST_SPIKE_08: + case GAMEOBJECT_TORGHAST_SPIKE_09: + case GAMEOBJECT_TORGHAST_SPIKE_10: + case GAMEOBJECT_TORGHAST_SPIKE_11: + case GAMEOBJECT_TORGHAST_SPIKE_12: + TorghastSpikeGUIDs.push_back(go->GetGUID()); + break; + + default: + break; + } + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_SYLVANAS_WINDRUNNER: + return SylvanasGUID; + case DATA_BOLVAR_FORDRAGON_PINNACLE: + return BolvarPinnacleGUID; + case DATA_JAINA_PROUDMOORE_PINNACLE: + return JainaPinnacleGUID; + case DATA_THRALL_PINNACLE: + return ThrallPinnacleGUID; + case DATA_THRONE_OF_THE_DAMNED: + return ThroneOfTheDamnedGUID; + default: + break; + } + + return ObjectGuid::Empty; + } + + bool SetBossState(uint32 id, EncounterState state) override + { + if (!InstanceScript::SetBossState(id, state)) + return false; + + switch (id) + { + case DATA_SYLVANAS_WINDRUNNER: + { + if (state == NOT_STARTED) + { + DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED, 0); + + if (Creature* throneTeleporter = GetCreature(DATA_THRONE_OF_THE_DAMNED)) + throneTeleporter->SetVisible(true); + + for (ObjectGuid const& spikeGUID : TorghastSpikeGUIDs) + if (GameObject* torghastSpike = instance->GetGameObject(spikeGUID)) + torghastSpike->SetSpellVisualId(0); + } + else if (state == IN_PROGRESS) + { + DoUpdateWorldState(WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED, 1); + + if (Creature* throneTeleporter = GetCreature(DATA_THRONE_OF_THE_DAMNED)) + throneTeleporter->SetVisible(false); + } + + break; + } + + default: + break; + } + + return true; + } + + void SetData(uint32 type, uint32 data) override + { + switch (type) + { + case DATA_SYLVANAS_INTRODUCTION: + { + switch (data) + { + case IN_PROGRESS: + SylvanasIntroductionState = IN_PROGRESS; + if (Creature* sylvanas = GetCreature(DATA_SYLVANAS_WINDRUNNER)) + sylvanas->SetHomePosition(SylvanasRespawnPos); + break; + + case DONE: + SylvanasIntroductionState = DONE; + if (Creature* sylvanas = GetCreature(DATA_SYLVANAS_WINDRUNNER)) + { + sylvanas->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1); + sylvanas->SetImmuneToAll(false); + sylvanas->SetSpeed(MOVE_RUN, 14.0f); + } + break; + + default: + break; + } + break; + } + + default: + break; + } + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_SYLVANAS_INTRODUCTION: + return SylvanasIntroductionState; + default: + break; + } + + return 0; + } + + protected: + ObjectGuid SylvanasGUID; + ObjectGuid SylvanasShadowcopyRidingGUID; + ObjectGuid BolvarPinnacleGUID; + ObjectGuid JainaPinnacleGUID; + ObjectGuid ThrallPinnacleGUID; + ObjectGuid ThroneOfTheDamnedGUID; + std::vector<ObjectGuid> TorghastSpikeGUIDs; + uint8 SylvanasIntroductionState; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_sanctum_of_domination_InstanceMapScript(map); + } +}; + +void AddSC_instance_sanctum_of_domination() +{ + new instance_sanctum_of_domination(); +} diff --git a/src/server/scripts/Shadowlands/SanctumOfDomination/sanctum_of_domination.h b/src/server/scripts/Shadowlands/SanctumOfDomination/sanctum_of_domination.h new file mode 100644 index 00000000000..498aecfd715 --- /dev/null +++ b/src/server/scripts/Shadowlands/SanctumOfDomination/sanctum_of_domination.h @@ -0,0 +1,117 @@ +/* + * 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_SANCTUM_OF_DOMINATION_H_ +#define DEF_SANCTUM_OF_DOMINATION_H_ + +#include "CreatureAIImpl.h" + +#define DataHeader "SanctumOfDomination" +#define SODScriptName "instance_sanctum_of_domination" + +uint32 const EncounterCount = 10; + +Position const SylvanasRespawnPos = { 225.73611f, -844.0746f, 4104.9882f, 1.3613f }; + +enum SanctumOfDominationDataTypes +{ + DATA_THE_TARRAGRUE = 0, + DATA_THE_EYE_OF_THE_JAILER = 1, + DATA_THE_NINE = 2, + DATA_REMNANT_OF_NERZHUL = 3, + DATA_SOULRENDER_DORMAZAIN = 4, + DATA_PAINSMITH_RAZNAL = 5, + DATA_GUARDIAN_OF_THE_FIRST_ONES = 6, + DATA_FATESCRIBE_ROHKALO = 7, + DATA_KELTHUZAD = 8, + DATA_SYLVANAS_WINDRUNNER = 9, + + /* Encounter-related data */ + + /* Sylvanas Windrunner */ + DATA_SYLVANAS_INTRODUCTION, + DATA_SYLVANAS_SHADOWCOPY_RIDING, + DATA_BOLVAR_FORDRAGON_PINNACLE, + DATA_JAINA_PROUDMOORE_PINNACLE, + DATA_THRALL_PINNACLE, + DATA_THRONE_OF_THE_DAMNED +}; + +enum SanctumOfDominationCreatureIds +{ + // Bosses + BOSS_SYLVANAS_WINDRUNNER = 175732, + + /* Encounter-related creatures */ + + /* Sylvanas Windrunner Encounter */ + NPC_SYLVANAS_SHADOWCOPY_RIDING = 178355, + NPC_BOLVAR_FORDRAGON_PINNACLE = 178081, + NPC_JAINA_PROUDMOORE_PINNACLE = 176533, + NPC_THRALL_PINNACLE = 176532, + + NPC_THRONE_OF_THE_DAMNED = 180803 +}; + +enum SanctumOfDominationGameObjectIds +{ + GAMEOBJECT_TORGHAST_SPIKE_01 = 368743, + GAMEOBJECT_TORGHAST_SPIKE_02 = 368744, + GAMEOBJECT_TORGHAST_SPIKE_03 = 368745, + GAMEOBJECT_TORGHAST_SPIKE_04 = 368746, + GAMEOBJECT_TORGHAST_SPIKE_05 = 368747, + GAMEOBJECT_TORGHAST_SPIKE_06 = 368748, + GAMEOBJECT_TORGHAST_SPIKE_07 = 368749, + GAMEOBJECT_TORGHAST_SPIKE_08 = 368750, + GAMEOBJECT_TORGHAST_SPIKE_09 = 368751, + GAMEOBJECT_TORGHAST_SPIKE_10 = 368752, + GAMEOBJECT_TORGHAST_SPIKE_11 = 368753, + GAMEOBJECT_TORGHAST_SPIKE_12 = 368754 +}; + +enum SanctumOfDominationAreas +{ + AREA_PINNACLE_OF_DOMINANCE = 13653, + AREA_EDGE_OF_THE_ABYSS = 13654, + AREA_THE_CRUCIBLE = 13655 +}; + +enum SanctumofDominationWorldStates +{ + WORLD_STATE_SYLVANAS_ENCOUNTER_STARTED = 20346, + WORLD_STATE_SYLVANAS_ENCOUNTER_COMPLETED = 20347, + WORLD_STATE_SYLVANAS_ENCOUNTER_PHASE = 20348, + WORLD_STATE_SYLVANAS_UNK_01 = 21210, // Info: sets to 0 several times on phase 3. + WORLD_STATE_SYLVANAS_UNK_02 = 21166, // Info: sets to 1 when SPELL_FINAL_SCENE is cast on players. + WORLD_STATE_SYLVANAS_UNK_03 = 21120, // Info: sets to 1 when 353687 spell is cast by NPC 179262. + WORLD_STATE_SYLVANAS_ACHIEVEMENT_COMPLETED = 21134, + WORLD_STATE_SYLVANAS_UNK_04 = 20439, // Info: this is always 1 on INIT and the following are 0. + WORLD_STATE_SYLVANAS_UNK_05 = 20440, + WORLD_STATE_SYLVANAS_UNK_06 = 20441, + WORLD_STATE_SYLVANAS_UNK_07 = 20442, + WORLD_STATE_SYLVANAS_UNK_08 = 20443 +}; + +template <class AI, class T> +inline AI* GetSanctumOfDominationAI(T* obj) +{ + return GetInstanceAI<AI>(obj, SODScriptName); +} + +#define RegisterSanctumOfDominationCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSanctumOfDominationAI) + +#endif diff --git a/src/server/scripts/Shadowlands/shadowlands_script_loader.cpp b/src/server/scripts/Shadowlands/shadowlands_script_loader.cpp index c6452c75c37..a21eae2a9f4 100644 --- a/src/server/scripts/Shadowlands/shadowlands_script_loader.cpp +++ b/src/server/scripts/Shadowlands/shadowlands_script_loader.cpp @@ -19,8 +19,17 @@ void AddSC_covenant_spell_scripts(); void AddSC_torghast_spell_scripts(); +void AddSC_boss_sylvanas_windrunner(); +void AddSC_instance_sanctum_of_domination(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() void AddShadowlandsScripts() { AddSC_covenant_spell_scripts(); AddSC_torghast_spell_scripts(); + + // Sanctum of Domination + AddSC_boss_sylvanas_windrunner(); + AddSC_instance_sanctum_of_domination(); } |