aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAqua Deus <95978183+aquadeus@users.noreply.github.com>2025-02-01 18:58:48 +0100
committerGitHub <noreply@github.com>2025-02-01 18:58:48 +0100
commitfa75f796d5f8a5e8f51a32ea36ee11beb541eb06 (patch)
treebba94a6b9fa509930fbd4d13737a97e391c05cf5 /src
parent4db19d3a1aa766ab2e6a5f4916df87a6326210b7 (diff)
Scripts/Auchindoun: Implement Auchindoun events until first boss (#30034)
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Draenor/Auchindoun/auchindoun.cpp410
-rw-r--r--src/server/scripts/Draenor/Auchindoun/auchindoun.h66
-rw-r--r--src/server/scripts/Draenor/Auchindoun/instance_auchindoun.cpp71
-rw-r--r--src/server/scripts/Draenor/draenor_script_loader.cpp8
4 files changed, 555 insertions, 0 deletions
diff --git a/src/server/scripts/Draenor/Auchindoun/auchindoun.cpp b/src/server/scripts/Draenor/Auchindoun/auchindoun.cpp
new file mode 100644
index 00000000000..6bbf61e3903
--- /dev/null
+++ b/src/server/scripts/Draenor/Auchindoun/auchindoun.cpp
@@ -0,0 +1,410 @@
+/*
+ * 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 "GameObject.h"
+#include "InstanceScript.h"
+#include "Map.h"
+#include "MotionMaster.h"
+#include "ObjectAccessor.h"
+#include "PhasingHandler.h"
+#include "Player.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellScript.h"
+#include "TaskScheduler.h"
+#include "auchindoun.h"
+
+enum AuchindounSpells
+{
+ SPELL_HALO_HEAL = 157795,
+ SPELL_TUULANI_UNLOCK_VISUAL = 160415,
+ SPELL_GRIMRAIL_DEPOT_SCENE = 178747,
+ SPELL_GRIMRAIL_DEPOT_SELECTOR = 178800,
+ SPELL_GRIMRAIL_DEPOT_TELEPORT = 178799,
+ SPELL_GRIMRAIL_DEPOT_REMOVE_AURA = 178746
+
+ // SPELL_INSTANCE_BOOTSTRAPPER = 171344 // This spell appears in a lot of sniffs, but the purpose is unknown
+};
+
+enum AuchindounActions
+{
+ ACTION_TUULANI_INTRO = 1,
+ ACTION_TUULANI_BREAK_BARRIER,
+ ACTION_AUCHENAI_DEFENDER_TALK
+};
+
+enum AuchindounTexts
+{
+ // Auchenai Defender
+ SAY_NYAMI_AWAITS = 0,
+
+ // Soulbinder Tuulani
+ SAY_WELCOME_1 = 0,
+ SAY_WELCOME_2 = 1,
+ SAY_WELCOME_3 = 2,
+ SAY_BREAK_BARRIER_1 = 3,
+ SAY_BREAK_BARRIER_2 = 4,
+ SAY_HEROES_SOULS = 5
+};
+
+enum AuchindounMisc
+{
+ // Waypoint
+ PATH_BARRIER = 7924800,
+ PATH_MOVE_TO_BOSS = 7924801,
+
+ POINT_TALK = 2,
+ POINT_BARRIER = 8,
+
+ POINT_SOULS = 5,
+
+ // Spawngroups
+ SPAWNGROUP_TUULANI_IMPRISONED = 1264
+};
+
+// 9973 - Areatrigger
+class at_auchindoun_entrance : public OnlyOnceAreaTriggerScript
+{
+public:
+ at_auchindoun_entrance() : OnlyOnceAreaTriggerScript("at_auchindoun_entrance") { }
+
+ bool TryHandleOnce(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ {
+ if (Creature* tuulani = instance->GetCreature(DATA_SOULBINDER_TUULANI))
+ tuulani->AI()->DoAction(ACTION_TUULANI_INTRO);
+ }
+ return true;
+ }
+};
+
+// 10072 - Areatrigger
+class at_auchindoun_auchenai_defender_intro : public OnlyOnceAreaTriggerScript
+{
+public:
+ at_auchindoun_auchenai_defender_intro() : OnlyOnceAreaTriggerScript("at_auchindoun_auchenai_defender_intro") { }
+
+ bool TryHandleOnce(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (Creature* auchenaiDefender = player->FindNearestCreatureWithOptions(30.0f, { .StringId = "npc_auchenai_defender_intro" }))
+ auchenaiDefender->AI()->DoAction(ACTION_AUCHENAI_DEFENDER_TALK);
+
+ return true;
+ }
+};
+
+// 9974 - Areatrigger
+// Not OnlyOnce because players can trigger this AT before Tuulani reaches the barrier
+class at_auchindoun_barrier : public AreaTriggerScript
+{
+public:
+ at_auchindoun_barrier() : AreaTriggerScript("at_auchindoun_barrier") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ {
+ if (Creature* tuulani = instance->GetCreature(DATA_SOULBINDER_TUULANI))
+ tuulani->AI()->DoAction(ACTION_TUULANI_BREAK_BARRIER);
+ }
+ return true;
+ }
+};
+
+// 10280 - Areatrigger
+class at_auchindoun_soulbinder_nyami_scene : public OnlyOnceAreaTriggerScript
+{
+public:
+ at_auchindoun_soulbinder_nyami_scene() : OnlyOnceAreaTriggerScript("at_auchindoun_soulbinder_nyami_scene") { }
+
+ bool TryHandleOnce(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ player->CastSpell(player, SPELL_GRIMRAIL_DEPOT_SELECTOR, true);
+
+ if (InstanceScript* instance = player->GetInstanceScript())
+ {
+ if (Creature* tuulani = instance->GetCreature(DATA_SOULBINDER_TUULANI))
+ tuulani->DespawnOrUnsummon();
+ }
+ return true;
+ }
+};
+
+// 77693 - Auchenai Defender
+struct npc_auchindoun_auchenai_defender : public ScriptedAI
+{
+ npc_auchindoun_auchenai_defender(Creature* creature) : ScriptedAI(creature) { }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_AUCHENAI_DEFENDER_TALK)
+ {
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+
+ _scheduler.Schedule(1s + 300ms, [this](TaskContext /*task*/)
+ {
+ me->SetFacingTo(3.8194849f);
+ Talk(SAY_NYAMI_AWAITS);
+ });
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
+};
+
+// 79248 - Soulbinder Tuulani
+struct npc_auchindoun_soulbinder_tuulani : public ScriptedAI
+{
+ npc_auchindoun_soulbinder_tuulani(Creature* creature) : ScriptedAI(creature), _isAtBarrier(false), _actionStarted(false) { }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_TUULANI_INTRO)
+ {
+ Talk(SAY_WELCOME_1);
+
+ _scheduler.Schedule(4s + 300ms, [this](TaskContext task)
+ {
+ Talk(SAY_WELCOME_2);
+
+ task.Schedule(6s, [this](TaskContext /*task*/)
+ {
+ me->GetMotionMaster()->MovePath(PATH_BARRIER, false);
+ });
+ });
+ }
+ else if (action == ACTION_TUULANI_BREAK_BARRIER)
+ {
+ if (!_isAtBarrier || _actionStarted)
+ return;
+
+ _actionStarted = true;
+
+ Talk(SAY_BREAK_BARRIER_1);
+
+ _scheduler.Schedule(3s, [this](TaskContext task)
+ {
+ DoCast(SPELL_TUULANI_UNLOCK_VISUAL);
+
+ task.Schedule(4s, [this](TaskContext task)
+ {
+ if (GameObject* holyBarrier = me->GetInstanceScript()->GetGameObject(DATA_HOLY_BARRIER))
+ holyBarrier->SetGoState(GO_STATE_ACTIVE);
+
+ task.Schedule(2s + 300ms, [this](TaskContext task)
+ {
+ Talk(SAY_BREAK_BARRIER_2);
+
+ task.Schedule(1s + 300ms, [this](TaskContext /*task*/)
+ {
+ me->GetMotionMaster()->MovePath(PATH_MOVE_TO_BOSS, false);
+ });
+ });
+ });
+ });
+ }
+ }
+
+ void WaypointReached(uint32 waypointId, uint32 pathId) override
+ {
+ if (pathId == PATH_BARRIER)
+ {
+ switch (waypointId)
+ {
+ case POINT_TALK:
+ {
+ _scheduler.Schedule(500ms, [this](TaskContext /*task*/)
+ {
+ Talk(SAY_WELCOME_3);
+ });
+ break;
+ }
+ case POINT_BARRIER:
+ {
+ _isAtBarrier = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if (pathId == PATH_MOVE_TO_BOSS)
+ {
+ if (waypointId == POINT_SOULS)
+ {
+ _scheduler.Schedule(500ms, [this](TaskContext /*task*/)
+ {
+ me->SetFacingTo(1.727875f);
+ Talk(SAY_HEROES_SOULS);
+ });
+ }
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
+ bool _isAtBarrier;
+ bool _actionStarted;
+};
+
+// 155647 - NPC Reaction
+struct at_auchindoun_npc_reaction : AreaTriggerAI
+{
+ at_auchindoun_npc_reaction(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
+
+ void OnUnitEnter(Unit* unit) override
+ {
+ if (!unit->IsCreature() || unit->GetEmoteState() == EMOTE_STATE_READY1H_ALLOW_MOVEMENT || unit->GetEntry() == NPC_SOULBINDER_TUULANI)
+ return;
+
+ _scheduler.Schedule(1500ms, [this, unitGUID = unit->GetGUID()](TaskContext task)
+ {
+ Creature* auchenaiDefender = ObjectAccessor::GetCreature(*at, unitGUID);
+ if (!auchenaiDefender)
+ return;
+
+ if (Unit* caster = at->GetCaster())
+ auchenaiDefender->SetFacingToObject(caster);
+ auchenaiDefender->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+
+ task.Schedule(4s, [this, unitGUID](TaskContext /*task*/)
+ {
+ Creature* auchenaiDefender = ObjectAccessor::GetCreature(*at, unitGUID);
+ if (!auchenaiDefender)
+ return;
+
+ auchenaiDefender->SetFacingTo(auchenaiDefender->GetHomePosition().GetOrientation());
+ });
+ });
+ }
+
+ void OnUpdate(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
+};
+
+// 157762 - Halo
+class spell_auchindoun_halo : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_HALO_HEAL });
+ }
+
+ void HandleHit(SpellEffIndex /*effIndex*/) const
+ {
+ if (!GetHitUnit()->IsCreature())
+ return;
+
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_HALO_HEAL, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_auchindoun_halo::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// 178800 - Grimrail Depot
+class spell_auchindoun_grimrail_depot_scene_selector : public SpellScript
+{
+ void HandleDummy(SpellEffIndex /*effIndex*/) const
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_GRIMRAIL_DEPOT_SCENE, true);
+ // GetCaster()->CastSpell(GetHitUnit(), SPELL_INSTANCE_BOOTSTRAPPER, false);
+ }
+
+ void HandleEvent(SpellEffIndex /*effIndex*/) const
+ {
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_PHASE_SHIFT_CHANGED, nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_auchindoun_grimrail_depot_scene_selector::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHit += SpellEffectFn(spell_auchindoun_grimrail_depot_scene_selector::HandleEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT);
+ }
+};
+
+// 178747 - Grimrail Depot
+class scene_auchindoun_soulbinder_nyami : public SceneScript
+{
+public:
+ scene_auchindoun_soulbinder_nyami() : SceneScript("scene_auchindoun_soulbinder_nyami") { }
+
+ static void HandleScene(Player* player)
+ {
+ player->ClearUnitState(UNIT_STATE_ROOT);
+ player->CastSpell(player, SPELL_GRIMRAIL_DEPOT_TELEPORT, true);
+ player->CastSpell(player, SPELL_GRIMRAIL_DEPOT_REMOVE_AURA, TRIGGERED_FULL_MASK);
+ PhasingHandler::OnConditionChange(player);
+
+ Map* map = player->GetMap();
+ if (!map->IsSpawnGroupActive(SPAWNGROUP_TUULANI_IMPRISONED))
+ map->SpawnGroupSpawn(SPAWNGROUP_TUULANI_IMPRISONED);
+ }
+
+ 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_auchindoun()
+{
+ new at_auchindoun_entrance();
+ new at_auchindoun_auchenai_defender_intro();
+ new at_auchindoun_barrier();
+ new at_auchindoun_soulbinder_nyami_scene();
+
+ RegisterAuchindounCreatureAI(npc_auchindoun_auchenai_defender);
+ RegisterAuchindounCreatureAI(npc_auchindoun_soulbinder_tuulani);
+ RegisterAreaTriggerAI(at_auchindoun_npc_reaction);
+ RegisterSpellScript(spell_auchindoun_halo);
+ RegisterSpellScript(spell_auchindoun_grimrail_depot_scene_selector);
+
+ new scene_auchindoun_soulbinder_nyami();
+}
diff --git a/src/server/scripts/Draenor/Auchindoun/auchindoun.h b/src/server/scripts/Draenor/Auchindoun/auchindoun.h
new file mode 100644
index 00000000000..9383fe3aa0b
--- /dev/null
+++ b/src/server/scripts/Draenor/Auchindoun/auchindoun.h
@@ -0,0 +1,66 @@
+/*
+ * 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 _Auchindoun_h__
+#define _Auchindoun_h__
+
+#include "CreatureAIImpl.h"
+
+constexpr char const* DataHeader = "Auchindoun";
+constexpr char const* AuchindounScriptName = "instance_auchindoun";
+
+constexpr uint32 EncounterCount = 4;
+
+enum AuchindounDataTypes
+{
+ // Encounters
+ DATA_VIGILANT_KAATHAR = 0,
+ DATA_SOULBINDER_NYAMI = 1,
+ DATA_AZZAKEL = 2,
+ DATA_TERONGOR = 3,
+
+ DATA_SOULBINDER_TUULANI,
+
+ // GameObjects
+ DATA_HOLY_BARRIER,
+};
+
+enum AuchindounCreatureIds
+{
+ // Bosses
+ BOSS_VIGILANT_KAATHAR = 75839,
+ BOSS_SOULBINDER_NYAMI = 76177,
+ BOSS_AZZAKEL = 75927,
+ BOSS_TERONGOR = 77734,
+
+ NPC_SOULBINDER_TUULANI = 79248
+};
+
+enum AuchindounGameobjectIds
+{
+ GO_HOLY_BARRIER = 230398
+};
+
+template <class AI, class T>
+inline AI* GetAuchindounAI(T* obj)
+{
+ return GetInstanceAI<AI>(obj, AuchindounScriptName);
+}
+
+#define RegisterAuchindounCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAuchindounAI)
+
+#endif // _Auchindoun_h__
diff --git a/src/server/scripts/Draenor/Auchindoun/instance_auchindoun.cpp b/src/server/scripts/Draenor/Auchindoun/instance_auchindoun.cpp
new file mode 100644
index 00000000000..8f5fc172a4a
--- /dev/null
+++ b/src/server/scripts/Draenor/Auchindoun/instance_auchindoun.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 "auchindoun.h"
+
+constexpr ObjectData creatureData[] =
+{
+ { BOSS_VIGILANT_KAATHAR, DATA_VIGILANT_KAATHAR },
+ { BOSS_SOULBINDER_NYAMI, DATA_SOULBINDER_NYAMI },
+ { BOSS_AZZAKEL, DATA_AZZAKEL },
+ { BOSS_TERONGOR, DATA_TERONGOR },
+ { NPC_SOULBINDER_TUULANI, DATA_SOULBINDER_TUULANI },
+ { 0, 0 } // END
+};
+
+constexpr ObjectData objectData[] =
+{
+ { GO_HOLY_BARRIER, DATA_HOLY_BARRIER },
+ { 0, 0 } // END
+};
+
+constexpr DungeonEncounterData encounters[] =
+{
+ { DATA_VIGILANT_KAATHAR, {{ 1678 }} },
+ { DATA_SOULBINDER_NYAMI, {{ 1685 }} },
+ { DATA_AZZAKEL, {{ 1686 }} },
+ { DATA_TERONGOR, {{ 1714 }} }
+};
+
+class instance_auchindoun : public InstanceMapScript
+{
+public:
+ instance_auchindoun() : InstanceMapScript("instance_auchindoun", 1182) { }
+
+ struct instance_auchindoun_InstanceMapScript : public InstanceScript
+ {
+ instance_auchindoun_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ {
+ SetHeaders(DataHeader);
+ SetBossNumber(EncounterCount);
+ LoadObjectData(creatureData, objectData);
+ LoadDungeonEncounterData(encounters);
+ }
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_auchindoun_InstanceMapScript(map);
+ }
+};
+
+void AddSC_instance_auchindoun()
+{
+ new instance_auchindoun();
+}
diff --git a/src/server/scripts/Draenor/draenor_script_loader.cpp b/src/server/scripts/Draenor/draenor_script_loader.cpp
index b913ee77253..a9ea6c61bd0 100644
--- a/src/server/scripts/Draenor/draenor_script_loader.cpp
+++ b/src/server/scripts/Draenor/draenor_script_loader.cpp
@@ -20,6 +20,10 @@ void AddSC_assault_on_the_dark_portal();
void AddSC_draenor_shadowmoon_valley();
void AddSC_garrison_generic();
+// Auchindoun
+void AddSC_instance_auchindoun();
+void AddSC_auchindoun();
+
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddDraenorScripts()
@@ -27,4 +31,8 @@ void AddDraenorScripts()
AddSC_assault_on_the_dark_portal();
AddSC_draenor_shadowmoon_valley();
AddSC_garrison_generic();
+
+ // Auchindoun
+ AddSC_instance_auchindoun();
+ AddSC_auchindoun();
}