aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2024_06_29_02_world.sql89
-rw-r--r--src/server/scripts/KulTiras/WaycrestManor/boss_heartsbane_triad.cpp1009
-rw-r--r--src/server/scripts/KulTiras/WaycrestManor/instance_waycrest_manor.cpp78
-rw-r--r--src/server/scripts/KulTiras/WaycrestManor/waycrest_manor.h70
-rw-r--r--src/server/scripts/KulTiras/kultiras_script_loader.cpp8
5 files changed, 1254 insertions, 0 deletions
diff --git a/sql/updates/world/master/2024_06_29_02_world.sql b/sql/updates/world/master/2024_06_29_02_world.sql
new file mode 100644
index 00000000000..354b0d8718b
--- /dev/null
+++ b/sql/updates/world/master/2024_06_29_02_world.sql
@@ -0,0 +1,89 @@
+-- Instance
+DELETE FROM `instance_template` WHERE `map`=1862;
+INSERT INTO `instance_template` (`map`, `parent`, `script`) VALUES
+(1862, 0, 'instance_waycrest_manor');
+
+-- Creature
+DELETE FROM `creature` WHERE `guid`=7001260;
+
+UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=2, `LevelScalingDeltaMax`=2, `ContentTuningID`=500, `StaticFlags1`=805306624, `VerifiedBuild`=55165 WHERE (`Entry`=131824 AND `DifficultyID`=0); -- 131824 (Sister Solena) - Sessile, CanSwim, Floating
+UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=2, `LevelScalingDeltaMax`=2, `ContentTuningID`=500, `StaticFlags1`=805306624, `VerifiedBuild`=55165 WHERE (`Entry`=131825 AND `DifficultyID`=0); -- 131825 (Sister Briar) - Sessile, CanSwim, Floating
+UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=2, `LevelScalingDeltaMax`=2, `ContentTuningID`=500, `StaticFlags1`=805306624, `VerifiedBuild`=55165 WHERE (`Entry`=131823 AND `DifficultyID`=0); -- 131823 (Sister Malady) - Sessile, CanSwim, Floating
+UPDATE `creature_template_difficulty` SET `ContentTuningID`=500, `VerifiedBuild`=55165 WHERE (`Entry`=132361 AND `DifficultyID`=0); -- 132361 (Focusing Iris) -
+
+UPDATE `creature_template` SET `ScriptName` = 'boss_sister_briar' WHERE `entry` = 131825;
+UPDATE `creature_template` SET `ScriptName` = 'boss_sister_malady' WHERE `entry` = 131823;
+UPDATE `creature_template` SET `ScriptName` = 'boss_sister_solena' WHERE `entry` = 131824;
+
+-- Summon Groups
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=131824;
+INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`, `Comment`) VALUES
+(131824, 0, 0, 132361, -574.691, -151.559, 235.268, 4.71697, 8, 0, 'Heartsbane Triad - Group 0 - Focusing Iris');
+
+-- Texts
+DELETE FROM `creature_text` WHERE `CreatureID` IN (131823, 131824, 131825);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+-- SAY AGGRO
+(131823, 0, 0, 'I\'ll carve screams from your flesh!', 14, 0, 100, 0, 0, 97511, 144939, 0, 'Sister Malady to Player'),
+(131824, 0, 0, 'You have no power here!', 14, 0, 100, 0, 0, 97519, 144931, 0, 'Sister Solena to Player'),
+(131825, 0, 0, 'Such supple bones!', 14, 0, 100, 0, 0, 97503, 144951, 0, 'Sister Briar to Player'),
+-- SAY_CLAIM_THE_IRIS
+(131823, 1, 0, 'You\'ve had your turn!', 14, 0, 100, 0, 0, 97515, 144944, 0, 'Sister Malady'),
+(131824, 1, 0, 'Give me the iris, you fool! Only I can focus its power!', 14, 0, 100, 0, 0, 97523, 144935, 0, 'Sister Solena'),
+(131825, 1, 0, 'Release the iris to me, sister!', 14, 0, 100, 0, 0, 97509, 144962, 0, 'Sister Briar'),
+-- SAY_SLAY
+(131823, 3, 0, 'Such lovely agony!', 14, 0, 50, 0, 0, 97513, 144941, 0, 'Sister Malady'),
+(131823, 3, 1, 'Your torment is far from over.', 14, 0, 50, 0, 0, 97514, 144942, 0, 'Sister Malady'),
+(131824, 3, 0, 'Such a fragile soul!', 14, 0, 50, 0, 0, 97520, 144932, 0, 'Sister Solena'),
+(131824, 3, 1, 'Your souls belong to me... forever.', 14, 0, 50, 0, 0, 97522, 144934, 0, 'Sister Solena'),
+(131825, 3, 0, 'I love the sound of snapping limbs.', 14, 0, 50, 0, 0, 97504, 144955, 0, 'Sister Briar'),
+(131825, 3, 1, 'Your skulls will make lovely ornaments.', 14, 0, 50, 0, 0, 97506, 144958, 0, 'Sister Briar'),
+-- SAY_DEATH
+(131823, 4, 0, 'My body cracks... but my curse... shall linger...', 14, 0, 100, 0, 0, 97512, 144940, 0, 'Sister Malady to Player'),
+(131824, 4, 0, 'Death will not silence me...', 14, 0, 100, 0, 0, 97521, 144933, 0, 'Sister Solena to Player'),
+(131825, 4, 0, 'My roots will sprout again...', 14, 0, 100, 0, 0, 97509, 144956, 0, 'Sister Briar to Player'),
+-- SAY_DIRE_RITUAL_ALERT
+(131823, 5, 0, '|TInterface\ICONS\SPELL_SHADOW_ANTISHADOW:20|t %s begins to cast |cFFFF0404|Hspell:260773|h[Dire Ritual]|h|r!', 41, 0, 100, 0, 0, 97526, 151946, 0, 'Sister Malady'),
+(131824, 5, 0, '|TInterface\ICONS\SPELL_SHADOW_ANTISHADOW:20|t %s begins to cast |cFFFF0404|Hspell:260773|h[Dire Ritual]|h|r!', 41, 0, 100, 0, 0, 97526, 151946, 0, 'Sister Solena'),
+(131825, 5, 0, '|TInterface\ICONS\SPELL_SHADOW_ANTISHADOW:20|t %s begins to cast |cFFFF0404|Hspell:260773|h[Dire Ritual]|h|r!', 41, 0, 100, 0, 0, 97526, 151946, 0, 'Sister Briar'),
+-- SAY_DIRE_RITUAL
+(131823, 6, 0, 'Rotted flesh and screams so dire, making music like a choir!', 14, 0, 100, 0, 0, 97517, 144946, 0, 'Sister Malady'),
+(131824, 6, 0, 'Blackened soul, the pitch of night, lay to waste all those in sight!', 14, 0, 100, 0, 0, 97526, 144938, 0, 'Sister Solena'),
+(131825, 6, 0, 'Powers high and spirits low, grant my thistles room to grow!', 14, 0, 100, 0, 0, 97515, 144944, 0, 'Sister Briar'),
+-- Sister Malady
+(131823, 2, 0, 'Your destruction is at hand!', 14, 0, 50, 0, 0, 97516, 144945, 0, 'Sister Malady'),
+(131823, 2, 1, 'You bear the black mark!', 14, 0, 50, 0, 0, 97518, 144959, 0, 'Sister Malady'),
+-- Sister Solena
+(131824, 2, 0, 'Dance, puppet! Dance!', 14, 0, 50, 0, 0, 97524, 144936, 0, 'Sister Solena'),
+(131824, 2, 1, 'You belong to me now!', 14, 0, 50, 0, 0, 97525, 144937, 0, 'Sister Solena'),
+-- Sister Briar
+(131825, 2, 0, 'My thorns will rip you to shreds!', 14, 0, 50, 0, 0, 97508, 144961, 0, 'Sister Briar to Player'),
+(131825, 2, 1, 'The more you struggle, the more you\'ll bleed!', 14, 0, 50, 0, 0, 97507, 144960, 0, 'Sister Briar to Player');
+
+-- Areatrigger
+DELETE FROM `areatrigger_create_properties` WHERE (`IsCustom`=0 AND `Id` IN (13196, 13179, 13177));
+INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `TimeToTarget`, `TimeToTargetScale`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES
+(13196, 0, 17807, 0, 4, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 200, 200, 0, 0, 0, 0, 0, 0, 'at_heartsbane_triad_aura_of_thorns', 52485), -- Spell: 268122 (Aura of Thorns)
+(13179, 0, 17791, 0, 4, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 200, 200, 0, 0, 0, 0, 0, 0, 'at_heartsbane_triad_aura_of_dread', 52485), -- Spell: 268088 (Aura of Dread)
+(13177, 0, 17789, 0, 4, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 200, 200, 0, 0, 0, 0, 0, 0, 'at_heartsbane_triad_aura_of_apathy', 52485); -- Spell: 268077 (Aura of Apathy)
+
+DELETE FROM `areatrigger_template` WHERE (`IsCustom`=0 AND `Id` IN (17807, 17791, 17789));
+INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `Flags`, `VerifiedBuild`) VALUES
+(17807, 0, 0, 52485),
+(17791, 0, 0, 52485),
+(17789, 0, 0, 52485);
+
+-- Spells
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (260741, 260852, 260854, 260907, 260923, 260703, 260773, 268077, 268088, 268085, 268122);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(260741, 'spell_heartsbane_triad_jagged_nettles'),
+(260852, 'spell_heartsbane_triad_claim_the_iris'),
+(260854, 'spell_heartsbane_triad_drop_the_iris'),
+(260907, 'spell_heartsbane_triad_soul_manipulation_selector'),
+(260923, 'spell_heartsbane_triad_soul_manipulation_periodic'),
+(260703, 'spell_heartsbane_triad_unstable_runic_mark'),
+(260773, 'spell_heartsbane_triad_dire_ritual'),
+(268077, 'spell_heartsbane_triad_aura_of_apathy'),
+(268088, 'spell_heartsbane_triad_aura_of_dread'),
+(268085, 'spell_heartsbane_triad_aura_of_dread_movement_check'),
+(268122, 'spell_heartsbane_triad_aura_of_thorns');
diff --git a/src/server/scripts/KulTiras/WaycrestManor/boss_heartsbane_triad.cpp b/src/server/scripts/KulTiras/WaycrestManor/boss_heartsbane_triad.cpp
new file mode 100644
index 00000000000..480c122bade
--- /dev/null
+++ b/src/server/scripts/KulTiras/WaycrestManor/boss_heartsbane_triad.cpp
@@ -0,0 +1,1009 @@
+/*
+ * 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 "Creature.h"
+#include "GridNotifiers.h"
+#include "InstanceScript.h"
+#include "Map.h"
+#include "ObjectAccessor.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
+#include "waycrest_manor.h"
+
+enum HeartsbaneTriadSpells
+{
+ // Sister Briar
+ SPELL_BRAMBLE_BOLT = 260701,
+ SPELL_BRAMBLE_BOLT_ENHANCED = 260697,
+ SPELL_JAGGED_NETTLES = 260741,
+ SPELL_IRONBARK_SHIELD = 261265,
+ SPELL_AURA_OF_THORNS = 268122,
+ SPELL_AURA_OF_THORNS_CHECK_PROC = 268125,
+
+ // Sister Malady
+ SPELL_RUINOUS_BOLT = 260700,
+ SPELL_RUINOUS_BOLT_ENHANCED = 260696,
+ SPELL_RUNIC_WARD = 261266,
+ SPELL_UNSTABLE_RUNIC_MARK = 260703,
+ SPELL_UNSTABLE_RUNIC_MARK_DAMAGE = 260702,
+ SPELL_AURA_OF_DREAD = 268088,
+ SPELL_AURA_OF_DREAD_DAMAGE = 268086,
+ SPELL_AURA_OF_DREAD_MOVE_CHECK = 268085,
+
+ // Sister Solena
+ SPELL_SOUL_BOLT = 260699,
+ SPELL_SOUL_BOLT_ENHANCED = 260698,
+ SPELL_SOUL_ARMOR = 261264,
+ SPELL_SOUL_MANIPULATION_SELECTOR = 260907,
+ SPELL_SOUL_MANIPULATION_CHARM = 260900,
+ SPELL_SOUL_MANIPULATION_DAMAGE_REDUCTION = 260923,
+ SPELL_SOUL_MANIPULATION_VISUAL = 260926,
+ SPELL_AURA_OF_APATHY = 268077,
+ SPELL_AURA_OF_APATHY_DEBUFF = 268080,
+
+ SPELL_DIRE_RITUAL = 260773,
+ SPELL_CLAIM_THE_IRIS = 260852,
+ SPELL_DROP_THE_IRIS = 260853,
+ SPELL_FOCUSING_IRIS = 260805
+};
+
+enum HeartsbaneTriadTexts
+{
+ // Shared
+ SAY_AGGRO = 0,
+ SAY_CLAIM_THE_IRIS = 1,
+ SAY_SLAY = 3,
+ SAY_DEATH = 4,
+ SAY_DIRE_RITUAL_ALERT = 5,
+ SAY_DIRE_RITUAL = 6,
+
+ // Sister Solena
+ SAY_SOUL_MANIPULATION = 2,
+
+ // Sister Malady
+ SAY_UNSTABLE_RUNIC_MARK = 2,
+
+ // Sister Briar
+ SAY_JAGGED_NETTLES = 2
+};
+
+enum HeartsbaneTriadEvents
+{
+ // Sister Briar
+ EVENT_BRAMBLE_BOLT = 1,
+ EVENT_BRAMBLE_BOLT_ENHANCED,
+ EVENT_JAGGED_NETTLES,
+ EVENT_AURA_OF_THORNS,
+
+ // Sister Malady
+ EVENT_RUINOUS_BOLT,
+ EVENT_RUINOUS_BOLT_ENHANCED,
+ EVENT_UNSTABLE_RUNIC_MARK,
+ EVENT_AURA_OF_DREAD,
+
+ // Sister Solena
+ EVENT_SOUL_BOLT,
+ EVENT_SOUL_BOLT_ENHANCED,
+ EVENT_SOUL_MANIPULATION,
+ EVENT_AURA_OF_APATHY,
+
+ EVENT_CHECK_POWER,
+ EVENT_CLAIM_IRIS,
+};
+
+enum HeartsbaneTriadActions
+{
+ ACTION_CLAIM_THE_IRIS_INTRO = 1,
+ ACTION_CLAIM_THE_IRIS,
+};
+
+enum HeartsbaneTriadSummonGroups
+{
+ SUMMON_GROUP_TRIAD_FOCUSING_IRIS = 0
+};
+
+uint32 const HeartsbaneTriadData[3] =
+{
+ DATA_SISTER_BRIAR,
+ DATA_SISTER_MALADY,
+ DATA_SISTER_SOLENA
+};
+
+namespace
+{
+void HeartsbaneTriadEncounterStart(InstanceScript* instance)
+{
+ if (instance->GetBossState(DATA_HEARTSBANE_TRIAD) == IN_PROGRESS)
+ return;
+
+ instance->SetBossState(DATA_HEARTSBANE_TRIAD, IN_PROGRESS);
+
+ for (uint32 data : HeartsbaneTriadData)
+ {
+ if (Creature* sister = instance->GetCreature(data))
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, sister, 1);
+ sister->AI()->DoZoneInCombat();
+ }
+ }
+}
+
+void HeartsbaneTriadEncounterFail(InstanceScript* instance, EvadeReason why, Creature* invoker)
+{
+ if (instance->GetBossState(DATA_HEARTSBANE_TRIAD) == FAIL)
+ return;
+
+ instance->SetBossState(DATA_HEARTSBANE_TRIAD, FAIL);
+
+ for (uint32 data : HeartsbaneTriadData)
+ {
+ if (Creature* triad = instance->GetCreature(data))
+ {
+ if (triad == invoker)
+ continue;
+
+ triad->AI()->EnterEvadeMode(why);
+ }
+ }
+}
+
+void HeartsbaneTriadEncounterDone(InstanceScript* instance)
+{
+ if (instance->GetBossState(DATA_HEARTSBANE_TRIAD) == DONE)
+ return;
+
+ for (uint32 data : HeartsbaneTriadData)
+ {
+ if (Creature* sister = instance->GetCreature(data))
+ {
+ if (sister->IsAlive())
+ return;
+ }
+ }
+
+ for (uint32 data : HeartsbaneTriadData)
+ {
+ if (Creature* sister = instance->GetCreature(data))
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, sister);
+ }
+
+ instance->SetBossState(DATA_HEARTSBANE_TRIAD, DONE);
+}
+}
+
+struct HeartsbaneTriadSharedAI : public BossAI
+{
+ HeartsbaneTriadSharedAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId), _healthTriggered(false), _claimedIris(false)
+ {
+ SetBoundary(instance->GetBossBoundary(DATA_HEARTSBANE_TRIAD));
+ }
+
+ virtual void ScheduleEvents()
+ {
+ events.ScheduleEvent(EVENT_CHECK_POWER, 1000ms);
+ };
+
+ virtual void HandleDropIris(bool /*skipShieldPhase*/, bool /*skipIrisDrop*/)
+ {
+ _claimedIris = false;
+ }
+
+ virtual void HandleClaimIris()
+ {
+ _claimedIris = true;
+
+ Talk(SAY_CLAIM_THE_IRIS);
+
+ me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
+
+ if (Creature* focusingIris = me->FindNearestCreature(NPC_FOCUSING_IRIS, 200.0f))
+ me->CastSpell(focusingIris, SPELL_CLAIM_THE_IRIS);
+
+ me->SetUnkillable(false);
+ }
+
+ void Reset() override
+ {
+ events.Reset();
+ _healthTriggered = false;
+ _claimedIris = false;
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ HeartsbaneTriadEncounterFail(instance, why, me);
+
+ me->RemoveAurasDueToSpell(SPELL_FOCUSING_IRIS);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+
+ summons.DespawnAll();
+ _EnterEvadeMode();
+ _DespawnAtEvade();
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ {
+ if (me->HealthBelowPctDamaged(50, damage) && !_healthTriggered)
+ {
+ _healthTriggered = true;
+ me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
+
+ me->SetUnkillable(true);
+
+ HandleDropIris(false, !_claimedIris);
+ }
+ }
+
+ void JustAppeared() override
+ {
+ me->SetPowerType(POWER_ENERGY);
+ me->SetPower(POWER_ENERGY, 0);
+
+ me->SetUnkillable(true);
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ HeartsbaneTriadEncounterStart(instance);
+ ScheduleEvents();
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_CHECK_POWER:
+ {
+ if (me->GetPower(POWER_ENERGY) >= 100)
+ {
+ Talk(SAY_DIRE_RITUAL_ALERT);
+ Talk(SAY_DIRE_RITUAL);
+ DoCast(SPELL_DIRE_RITUAL);
+ }
+ events.Repeat(1000ms);
+ break;
+ }
+ case EVENT_CLAIM_IRIS:
+ {
+ HandleClaimIris();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_CLAIM_THE_IRIS:
+ events.Reset();
+ events.ScheduleEvent(EVENT_CLAIM_IRIS, 1500ms);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+
+ Talk(SAY_DEATH);
+
+ HeartsbaneTriadEncounterDone(instance);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (!victim->IsPlayer())
+ return;
+
+ Talk(SAY_SLAY);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+ }
+
+private:
+ bool _healthTriggered;
+
+protected:
+ bool _claimedIris; // to prevent dropping multiple iris if a sister dies during claim process
+};
+
+// 131825 - Sister Briar
+struct boss_sister_briar : public HeartsbaneTriadSharedAI
+{
+ boss_sister_briar(Creature* creature) : HeartsbaneTriadSharedAI(creature, DATA_SISTER_BRIAR) { }
+
+ void ScheduleEvents() override
+ {
+ HeartsbaneTriadSharedAI::ScheduleEvents();
+
+ events.ScheduleEvent(EVENT_BRAMBLE_BOLT, 2000ms);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ HeartsbaneTriadSharedAI::JustDied(killer);
+
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_JAGGED_NETTLES);
+ }
+
+ void HandleDropIris(bool skipShieldPhase, bool skipIrisDrop) override
+ {
+ HeartsbaneTriadSharedAI::HandleDropIris(skipIrisDrop, skipIrisDrop);
+
+ me->RemoveAurasDueToSpell(SPELL_AURA_OF_THORNS);
+
+ events.CancelEvent(EVENT_BRAMBLE_BOLT_ENHANCED);
+ events.CancelEvent(EVENT_JAGGED_NETTLES);
+
+ if (skipShieldPhase)
+ return;
+
+ if (!skipIrisDrop)
+ DoCastSelf(SPELL_DROP_THE_IRIS);
+ DoCastSelf(SPELL_IRONBARK_SHIELD);
+
+ if (Creature* solena = instance->GetCreature(DATA_SISTER_SOLENA))
+ solena->AI()->DoAction(ACTION_CLAIM_THE_IRIS);
+
+ events.ScheduleEvent(EVENT_BRAMBLE_BOLT, 3200ms);
+ }
+
+ void HandleClaimIris() override
+ {
+ HeartsbaneTriadSharedAI::HandleClaimIris();
+
+ if (IsHeroic() || IsMythic())
+ events.ScheduleEvent(EVENT_AURA_OF_THORNS, 1600ms);
+
+ me->RemoveAurasDueToSpell(SPELL_IRONBARK_SHIELD);
+ events.ScheduleEvent(EVENT_BRAMBLE_BOLT_ENHANCED, 4700ms);
+ events.ScheduleEvent(EVENT_JAGGED_NETTLES, 14600ms);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ HeartsbaneTriadSharedAI::EnterEvadeMode(why);
+
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_JAGGED_NETTLES);
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_BRAMBLE_BOLT:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_BRAMBLE_BOLT);
+ events.Repeat(2400ms);
+ break;
+ }
+ case EVENT_BRAMBLE_BOLT_ENHANCED:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_BRAMBLE_BOLT_ENHANCED);
+ events.Repeat(7300ms);
+ break;
+ }
+ case EVENT_JAGGED_NETTLES:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_JAGGED_NETTLES);
+ Talk(SAY_JAGGED_NETTLES);
+ events.Repeat(14600ms);
+ break;
+ }
+ case EVENT_AURA_OF_THORNS:
+ {
+ DoCastSelf(SPELL_AURA_OF_THORNS);
+ break;
+ }
+ default:
+ HeartsbaneTriadSharedAI::ExecuteEvent(eventId);
+ break;
+ }
+ }
+};
+
+// 131823 - Sister Malady
+struct boss_sister_malady : public HeartsbaneTriadSharedAI
+{
+ boss_sister_malady(Creature* creature) : HeartsbaneTriadSharedAI(creature, DATA_SISTER_MALADY) { }
+
+ void ScheduleEvents() override
+ {
+ HeartsbaneTriadSharedAI::ScheduleEvents();
+
+ events.ScheduleEvent(EVENT_RUINOUS_BOLT, 3200ms);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ HeartsbaneTriadSharedAI::JustDied(killer);
+
+ HandleDropIris(true, _claimedIris);
+ }
+
+ void HandleDropIris(bool skipShieldPhase, bool skipIrisDrop) override
+ {
+ me->RemoveAurasDueToSpell(SPELL_AURA_OF_DREAD);
+ if (!skipIrisDrop)
+ DoCastSelf(SPELL_DROP_THE_IRIS);
+
+ if (Creature* briar = instance->GetCreature(DATA_SISTER_BRIAR))
+ briar->AI()->DoAction(ACTION_CLAIM_THE_IRIS);
+
+ events.CancelEvent(EVENT_RUINOUS_BOLT_ENHANCED);
+ events.CancelEvent(EVENT_UNSTABLE_RUNIC_MARK);
+
+ if (skipShieldPhase)
+ return;
+
+ DoCastSelf(SPELL_RUNIC_WARD);
+ events.ScheduleEvent(EVENT_RUINOUS_BOLT, 3200ms);
+ }
+
+ void HandleClaimIris() override
+ {
+ HeartsbaneTriadSharedAI::HandleClaimIris();
+
+ if (IsHeroic() || IsMythic())
+ events.ScheduleEvent(EVENT_AURA_OF_DREAD, 1600ms);
+
+ me->RemoveAurasDueToSpell(SPELL_RUNIC_WARD);
+
+ events.ScheduleEvent(EVENT_RUINOUS_BOLT_ENHANCED, 4700ms);
+ events.ScheduleEvent(EVENT_UNSTABLE_RUNIC_MARK, 14600ms);
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_RUINOUS_BOLT:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_RUINOUS_BOLT);
+ events.Repeat(2400ms);
+ break;
+ }
+ case EVENT_RUINOUS_BOLT_ENHANCED:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_RUINOUS_BOLT_ENHANCED);
+ events.Repeat(7300ms);
+ break;
+ }
+ case EVENT_UNSTABLE_RUNIC_MARK:
+ {
+ Talk(SAY_UNSTABLE_RUNIC_MARK);
+ DoCast(SPELL_UNSTABLE_RUNIC_MARK);
+ events.Repeat(12100ms);
+ break;
+ }
+ case EVENT_CLAIM_IRIS:
+ {
+ HandleClaimIris();
+ break;
+ }
+ case EVENT_AURA_OF_DREAD:
+ {
+ DoCastSelf(SPELL_AURA_OF_DREAD);
+ break;
+ }
+ default:
+ HeartsbaneTriadSharedAI::ExecuteEvent(eventId);
+ break;
+ }
+ }
+};
+
+// 131824 - Sister Solena
+struct boss_sister_solena : public HeartsbaneTriadSharedAI
+{
+ boss_sister_solena(Creature* creature) : HeartsbaneTriadSharedAI(creature, DATA_SISTER_SOLENA) { }
+
+ void ScheduleEvents() override
+ {
+ HeartsbaneTriadSharedAI::ScheduleEvents();
+
+ events.ScheduleEvent(EVENT_SOUL_BOLT_ENHANCED, 4700ms);
+ events.ScheduleEvent(EVENT_SOUL_MANIPULATION, 12000ms);
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ HeartsbaneTriadSharedAI::JustEngagedWith(who);
+
+ DoAction(ACTION_CLAIM_THE_IRIS_INTRO);
+
+ if (Creature* sister = me->GetInstanceScript()->GetCreature(RAND(DATA_SISTER_SOLENA, DATA_SISTER_BRIAR, DATA_SISTER_MALADY)))
+ sister->AI()->Talk(SAY_AGGRO);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ HeartsbaneTriadSharedAI::JustDied(killer);
+
+ HandleDropIris(true, _claimedIris);
+ }
+
+ void HandleDropIris(bool skipShieldPhase, bool skipIrisDrop) override
+ {
+ me->RemoveAurasDueToSpell(SPELL_AURA_OF_APATHY);
+ if (!skipIrisDrop)
+ DoCastSelf(SPELL_DROP_THE_IRIS);
+
+ if (Creature* malady = instance->GetCreature(DATA_SISTER_MALADY))
+ malady->AI()->DoAction(ACTION_CLAIM_THE_IRIS);
+
+ events.CancelEvent(EVENT_SOUL_BOLT_ENHANCED);
+ events.CancelEvent(EVENT_SOUL_MANIPULATION);
+
+ if (skipShieldPhase)
+ return;
+
+ DoCastSelf(SPELL_SOUL_ARMOR);
+ events.ScheduleEvent(EVENT_SOUL_BOLT, 3200ms);
+ }
+
+ void HandleClaimIris() override
+ {
+ HeartsbaneTriadSharedAI::HandleClaimIris();
+
+ if (IsHeroic() || IsMythic())
+ events.ScheduleEvent(EVENT_AURA_OF_APATHY, 1600ms);
+
+ me->RemoveAurasDueToSpell(SPELL_SOUL_ARMOR);
+
+ events.ScheduleEvent(EVENT_SOUL_BOLT_ENHANCED, 4700ms);
+ events.ScheduleEvent(EVENT_SOUL_MANIPULATION, 14600ms);
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_CLAIM_THE_IRIS_INTRO:
+ {
+ _claimedIris = true;
+
+ if (Creature* focusingIris = me->FindNearestCreature(NPC_FOCUSING_IRIS, 100.0f))
+ DoCast(focusingIris, SPELL_CLAIM_THE_IRIS);
+
+ if (IsHeroic() || IsMythic())
+ events.ScheduleEvent(EVENT_AURA_OF_APATHY, 1600ms);
+ break;
+ }
+ default:
+ HeartsbaneTriadSharedAI::DoAction(actionId);
+ break;
+ }
+ }
+
+ void JustAppeared() override
+ {
+ HeartsbaneTriadSharedAI::JustAppeared();
+ me->SummonCreatureGroup(SUMMON_GROUP_TRIAD_FOCUSING_IRIS);
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_SOUL_BOLT_ENHANCED:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_SOUL_BOLT_ENHANCED);
+ events.Repeat(4900ms);
+ break;
+ }
+ case EVENT_SOUL_BOLT:
+ {
+ if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
+ DoCast(target, SPELL_SOUL_BOLT);
+ events.Repeat(2400ms);
+ break;
+ }
+ case EVENT_SOUL_MANIPULATION:
+ {
+ if (me->GetMap()->GetPlayersCountExceptGMs() > 1) // This event doesn't happen if you go solo because it resets boss
+ {
+ Talk(SAY_SOUL_MANIPULATION);
+ DoCast(SPELL_SOUL_MANIPULATION_SELECTOR);
+ events.RescheduleEvent(EVENT_SOUL_BOLT_ENHANCED, 12s + 100ms);
+ events.Repeat(23100ms, 24200ms);
+ }
+ break;
+ }
+ case EVENT_AURA_OF_APATHY:
+ {
+ DoCastSelf(SPELL_AURA_OF_APATHY);
+ break;
+ }
+ default:
+ HeartsbaneTriadSharedAI::ExecuteEvent(eventId);
+ break;
+ }
+ }
+};
+
+// 260741 - Jagged Nettles
+class spell_heartsbane_triad_jagged_nettles : public AuraScript
+{
+ void HandlePeriodic(AuraEffect const* aurEff)
+ {
+ if (aurEff->GetTickNumber() > 1)
+ {
+ if (GetTarget()->GetHealthPct() >= float(GetEffectInfo(EFFECT_2).CalcValue(GetCaster())))
+ Remove();
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_heartsbane_triad_jagged_nettles::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
+ }
+};
+
+// 260852 - Claim the Iris
+class spell_heartsbane_triad_claim_the_iris : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FOCUSING_IRIS });
+ }
+
+ void HandleHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ Creature* casterCreature = GetCaster()->ToCreature();
+ if (!casterCreature)
+ return;
+
+ if (Creature* hitCreature = GetHitCreature())
+ hitCreature->DespawnOrUnsummon();
+
+ casterCreature->CastSpell(casterCreature, SPELL_FOCUSING_IRIS, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ casterCreature->SetSessile(false);
+ casterCreature->SetFloating(false);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_heartsbane_triad_claim_the_iris::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// 260854 - Drop the Iris
+class spell_heartsbane_triad_drop_the_iris : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FOCUSING_IRIS });
+ }
+
+ void RemoveIris(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->RemoveAurasDueToSpell(SPELL_FOCUSING_IRIS);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_heartsbane_triad_drop_the_iris::RemoveIris, EFFECT_0, SPELL_EFFECT_SUMMON);
+ }
+};
+
+// 260923 - Soul Manipulation
+class spell_heartsbane_triad_soul_manipulation_periodic : public AuraScript
+{
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (GetTarget()->GetHealthPct() > 50.0f)
+ return;
+
+ Remove();
+
+ if (Unit* caster = GetCaster())
+ caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_heartsbane_triad_soul_manipulation_periodic::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+// 260907 Soul Manipulation (Selector)
+class spell_heartsbane_triad_soul_manipulation_selector : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SOUL_MANIPULATION_CHARM, SPELL_SOUL_MANIPULATION_DAMAGE_REDUCTION, SPELL_SOUL_MANIPULATION_VISUAL });
+ }
+
+ void HandleHitTarget(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_SOUL_MANIPULATION_CHARM, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ GetCaster()->CastSpell(GetCaster(), SPELL_SOUL_MANIPULATION_DAMAGE_REDUCTION, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_SOUL_MANIPULATION_VISUAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_heartsbane_triad_soul_manipulation_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// 260703 - Unstable Runic Mark
+class spell_heartsbane_triad_unstable_runic_mark : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_UNSTABLE_RUNIC_MARK_DAMAGE });
+ }
+
+ void HandleDamage(AuraEffect const* /*aurEff*/ , AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
+ return;
+
+ GetTarget()->CastSpell(GetTarget(), SPELL_UNSTABLE_RUNIC_MARK_DAMAGE, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_heartsbane_triad_unstable_runic_mark::HandleDamage, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// 260773 - Dire Ritual
+class spell_heartsbane_triad_dire_ritual : public SpellScript
+{
+ void HandleAfterCast()
+ {
+ GetCaster()->SetPower(POWER_ENERGY, 0);
+ }
+
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_heartsbane_triad_dire_ritual::HandleAfterCast);
+ }
+};
+
+// 17789 - Aura of Apathy
+struct at_heartsbane_triad_aura_of_apathy : AreaTriggerAI
+{
+ at_heartsbane_triad_aura_of_apathy(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
+
+ void OnUnitEnter(Unit* unit) override
+ {
+ if (!unit->IsPlayer())
+ return;
+
+ unit->CastSpell(unit, SPELL_AURA_OF_APATHY_DEBUFF, true);
+ }
+
+ void OnUnitExit(Unit* unit) override
+ {
+ unit->RemoveAurasDueToSpell(SPELL_AURA_OF_APATHY_DEBUFF);
+ }
+
+ void OnRemove() override
+ {
+ for (ObjectGuid const& guid : at->GetInsideUnits())
+ {
+ Unit* unit = ObjectAccessor::GetUnit(*at, guid);
+ if (!unit)
+ continue;
+
+ OnUnitExit(unit);
+ }
+ }
+};
+
+// 17791 - Aura of Dread
+struct at_heartsbane_triad_aura_of_dread : AreaTriggerAI
+{
+ at_heartsbane_triad_aura_of_dread(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
+
+ void OnUnitEnter(Unit* unit) override
+ {
+ if (!unit->IsPlayer())
+ return;
+
+ unit->CastSpell(unit, SPELL_AURA_OF_DREAD_MOVE_CHECK, true);
+ }
+
+ void OnUnitExit(Unit* unit) override
+ {
+ unit->RemoveAurasDueToSpell(SPELL_AURA_OF_DREAD_MOVE_CHECK);
+ unit->RemoveAurasDueToSpell(SPELL_AURA_OF_DREAD_DAMAGE);
+ }
+
+ void OnRemove() override
+ {
+ for (ObjectGuid const& guid : at->GetInsideUnits())
+ {
+ Unit* unit = ObjectAccessor::GetUnit(*at, guid);
+ if (!unit)
+ continue;
+
+ OnUnitExit(unit);
+ }
+ }
+};
+
+// 268088 - Aura of Dread
+class spell_heartsbane_triad_aura_of_dread : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AURA_OF_DREAD_DAMAGE, SPELL_AURA_OF_DREAD_MOVE_CHECK });
+ }
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ for (MapReference const& players : caster->GetMap()->GetPlayers())
+ {
+ if (Player* player = players.GetSource())
+ {
+ if (!player->HasAura(SPELL_AURA_OF_DREAD_MOVE_CHECK))
+ continue;
+
+ player->CastSpell(player, SPELL_AURA_OF_DREAD_DAMAGE, true);
+ }
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_heartsbane_triad_aura_of_dread::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+// 268085 - Aura of Dread
+class spell_heartsbane_triad_aura_of_dread_movement_check : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AURA_OF_DREAD_DAMAGE });
+ }
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ if (caster->isMoving())
+ {
+ if (Aura* stack = caster->GetAura(SPELL_AURA_OF_DREAD_DAMAGE, caster->GetGUID()))
+ {
+ if (stack->GetStackAmount() > 1)
+ caster->RemoveAuraFromStack(SPELL_AURA_OF_DREAD_DAMAGE);
+ }
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_heartsbane_triad_aura_of_dread_movement_check::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+// 17807 - Aura of Thorns
+struct at_heartsbane_triad_aura_of_thorns : AreaTriggerAI
+{
+ at_heartsbane_triad_aura_of_thorns(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
+
+ void OnUnitEnter(Unit* unit) override
+ {
+ if (!unit->IsPlayer())
+ return;
+
+ unit->CastSpell(unit, SPELL_AURA_OF_THORNS_CHECK_PROC, true);
+ }
+
+ void OnUnitExit(Unit* unit) override
+ {
+ unit->RemoveAurasDueToSpell(SPELL_AURA_OF_THORNS_CHECK_PROC);
+ }
+
+ void OnRemove() override
+ {
+ for (ObjectGuid const& guid : at->GetInsideUnits())
+ {
+ Unit* unit = ObjectAccessor::GetUnit(*at, guid);
+ if (!unit)
+ continue;
+
+ OnUnitExit(unit);
+ }
+ }
+};
+
+// 268122 - Aura of Thorns
+class spell_heartsbane_triad_aura_of_thorns : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_AURA_OF_THORNS_CHECK_PROC });
+ }
+
+ bool HandleCheckProc(ProcEventInfo& eventInfo)
+ {
+ return eventInfo.GetActor()->HasAura(SPELL_AURA_OF_THORNS_CHECK_PROC);
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_heartsbane_triad_aura_of_thorns::HandleCheckProc);
+ }
+};
+
+void AddSC_boss_heartsbane_triad()
+{
+ RegisterWaycrestManorCreatureAI(boss_sister_briar);
+ RegisterWaycrestManorCreatureAI(boss_sister_malady);
+ RegisterWaycrestManorCreatureAI(boss_sister_solena);
+
+ RegisterSpellScript(spell_heartsbane_triad_jagged_nettles);
+ RegisterSpellScript(spell_heartsbane_triad_claim_the_iris);
+ RegisterSpellScript(spell_heartsbane_triad_drop_the_iris);
+ RegisterSpellScript(spell_heartsbane_triad_soul_manipulation_periodic);
+ RegisterSpellScript(spell_heartsbane_triad_soul_manipulation_selector);
+ RegisterSpellScript(spell_heartsbane_triad_unstable_runic_mark);
+ RegisterSpellScript(spell_heartsbane_triad_dire_ritual);
+
+ RegisterAreaTriggerAI(at_heartsbane_triad_aura_of_apathy);
+ RegisterAreaTriggerAI(at_heartsbane_triad_aura_of_dread);
+ RegisterSpellScript(spell_heartsbane_triad_aura_of_dread);
+ RegisterSpellScript(spell_heartsbane_triad_aura_of_dread_movement_check);
+ RegisterAreaTriggerAI(at_heartsbane_triad_aura_of_thorns);
+ RegisterSpellScript(spell_heartsbane_triad_aura_of_thorns);
+}
diff --git a/src/server/scripts/KulTiras/WaycrestManor/instance_waycrest_manor.cpp b/src/server/scripts/KulTiras/WaycrestManor/instance_waycrest_manor.cpp
new file mode 100644
index 00000000000..00611f4ace4
--- /dev/null
+++ b/src/server/scripts/KulTiras/WaycrestManor/instance_waycrest_manor.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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 "waycrest_manor.h"
+
+static BossBoundaryData const boundaries =
+{
+ { DATA_HEARTSBANE_TRIAD, new BoundaryIntersectionBoundary(new ZRangeBoundary(235.0f, 243.0f), new RectangleBoundary(-618.580f, -524.305f, -188.971f, -137.363f)) },
+};
+
+ObjectData const creatureData[] =
+{
+ { BOSS_SISTER_BRIAR, DATA_SISTER_BRIAR },
+ { BOSS_SISTER_MALADY, DATA_SISTER_MALADY },
+ { BOSS_SISTER_SOLENA, DATA_SISTER_SOLENA },
+ { 0, 0 } // END
+};
+
+DoorData const doorData[] =
+{
+ { GO_HEARTSBANE_TRIAD_DOOR, DATA_HEARTSBANE_TRIAD, EncounterDoorBehavior::OpenWhenNotInProgress },
+ { 0, 0, EncounterDoorBehavior::OpenWhenNotInProgress } // END
+};
+
+DungeonEncounterData const encounters[] =
+{
+ { DATA_HEARTSBANE_TRIAD, {{ 2113 }} },
+ { DATA_SOULBOUND_GOLIATH, {{ 2114 }} },
+ { DATA_RAAL_THE_GLUTTONOUS, {{ 2115 }} },
+ { DATA_LORD_AND_LADY_WAYCREST, {{ 2116 }} },
+ { DATA_GORAK_TUL, {{ 2117 }} }
+};
+
+class instance_waycrest_manor : public InstanceMapScript
+{
+public:
+ instance_waycrest_manor() : InstanceMapScript("instance_waycrest_manor", 1862) { }
+
+ struct instance_waycrest_manor_InstanceMapScript : public InstanceScript
+ {
+ instance_waycrest_manor_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ {
+ SetHeaders(DataHeader);
+ SetBossNumber(EncounterCount);
+ LoadObjectData(creatureData, nullptr);
+ LoadDoorData(doorData);
+ LoadBossBoundaries(boundaries);
+ LoadDungeonEncounterData(encounters);
+ }
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_waycrest_manor_InstanceMapScript(map);
+ }
+};
+
+void AddSC_instance_waycrest_manor()
+{
+ new instance_waycrest_manor();
+}
diff --git a/src/server/scripts/KulTiras/WaycrestManor/waycrest_manor.h b/src/server/scripts/KulTiras/WaycrestManor/waycrest_manor.h
new file mode 100644
index 00000000000..477be0bdcaf
--- /dev/null
+++ b/src/server/scripts/KulTiras/WaycrestManor/waycrest_manor.h
@@ -0,0 +1,70 @@
+/*
+ * 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 _Waycrest_Manor_h__
+#define _Waycrest_Manor_h__
+
+#include "CreatureAIImpl.h"
+
+constexpr char const* DataHeader = "WM";
+constexpr char const* WaycrestManorScriptName = "instance_waycrest_manor";
+
+constexpr uint32 const EncounterCount = 5;
+
+enum WaycrestManorDataTypes
+{
+ // Encounters
+ DATA_HEARTSBANE_TRIAD = 0,
+ DATA_SOULBOUND_GOLIATH = 1,
+ DATA_RAAL_THE_GLUTTONOUS = 2,
+ DATA_LORD_AND_LADY_WAYCREST = 3,
+ DATA_GORAK_TUL = 4,
+
+ DATA_SISTER_BRIAR,
+ DATA_SISTER_MALADY,
+ DATA_SISTER_SOLENA
+};
+
+enum WaycrestManorCreatureIds
+{
+ // Bosses
+ BOSS_SISTER_BRIAR = 131825,
+ BOSS_SISTER_MALADY = 131823,
+ BOSS_SISTER_SOLENA = 131824,
+ BOSS_SOULBOUND_GOLIATH = 131667,
+ BOSS_RAAL_THE_GLUTTONOUS = 131863,
+ BOSS_LADY_WAYCREST = 136918,
+ BOSS_LORD_WAYCREST = 131527,
+ BOSS_GORAK_TUL = 131863,
+
+ NPC_FOCUSING_IRIS = 132361
+};
+
+enum WaycrestManorGameObjectIds
+{
+ GO_HEARTSBANE_TRIAD_DOOR = 282410
+};
+
+template <class AI, class T>
+inline AI* GetWaycrestManorAI(T* obj)
+{
+ return GetInstanceAI<AI>(obj, WaycrestManorScriptName);
+}
+
+#define RegisterWaycrestManorCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetWaycrestManorAI)
+
+#endif // _Waycrest_Manor_h__
diff --git a/src/server/scripts/KulTiras/kultiras_script_loader.cpp b/src/server/scripts/KulTiras/kultiras_script_loader.cpp
index e4ed7ba007f..d4f7d82f68f 100644
--- a/src/server/scripts/KulTiras/kultiras_script_loader.cpp
+++ b/src/server/scripts/KulTiras/kultiras_script_loader.cpp
@@ -19,9 +19,17 @@
void AddSC_zone_boralus();
+// Waycrest Manor
+void AddSC_boss_heartsbane_triad();
+void AddSC_instance_waycrest_manor();
+
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddKulTirasScripts()
{
AddSC_zone_boralus();
+
+ // Waycrest Manor
+ AddSC_boss_heartsbane_triad();
+ AddSC_instance_waycrest_manor();
}