diff --git a/sql/updates/WIP/theralion_and_valiona.sql b/sql/updates/WIP/theralion_and_valiona.sql
new file mode 100644
index 00000000000..08eb8510208
--- /dev/null
+++ b/sql/updates/WIP/theralion_and_valiona.sql
@@ -0,0 +1,122 @@
+-- Template Updates
+-- Theralion
+UPDATE `creature_template` SET `ScriptName`= 'boss_theralion', `flags_extra`= 512 WHERE `entry`= 45993;
+UPDATE `creature_template` SET `DamageModifier`= 80, `flags_extra`= 512 WHERE `entry` IN (45993);
+-- Valiona
+UPDATE `creature_template` SET `ScriptName`= 'boss_valiona', `flags_extra`= 512 WHERE `entry`= 45992;
+UPDATE `creature_template` SET `DamageModifier`= 80, `flags_extra`= 512 WHERE `entry` IN (45992);
+-- Valiona (Fire Dummy)
+UPDATE `creature_template` SET `flags_extra`= 128 WHERE `entry`= 46147;
+-- Theralion Flight Target Stalker
+UPDATE `creature_template` SET `InhabitType`= 4, `flags_extra`= 128 WHERE `entry`= 46364;
+-- Convective Flames
+UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `InhabitType`= 13 WHERE `entry`= 46588;
+-- Dazzling Destruction Stalker
+UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `InhabitType`= 13 WHERE `entry`= 46374;
+-- Fabolous Flames
+UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `InhabitType`= 13 WHERE `entry`= 46448;
+
+-- Template Addon
+DELETE FROM `creature_template_addon` WHERE `entry` IN (46374, 46448);
+INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES
+(46374, '86383'),
+(46448, '86506');
+
+-- Areatriggers
+DELETE FROM `areatrigger_scripts` WHERE `entry`= 6442;
+INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
+(6442, 'at_theralion_and_valiona_intro');
+
+-- Correct Phasing for Theralion and Valiona
+UPDATE `creature` SET `PhaseId`= 0, `PhaseGroup`= 525 WHERE `id` IN (45992, 45993);
+
+-- Creature Texts
+DELETE FROM `creature_text` WHERE `CreatureID` IN (43324, 45992, 45993);
+-- Cho'Gall
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(43324, 0, 0, 'Valiona, Theralion, put them in their place.', 14, 0, 100, 0, 0, 22063, 47518, 'Cho''gall - Theralion and Valiona Intro'),
+(43324, 1, 0, '(Come closer, closer. Let us see your faces. All will be humbled before his power.)', 14, 0, 100, 0, 0, 22064, 47538, 'Cho''gall - Theralion and Valiona Death'),
+-- Valiona
+(45992, 0, 0, 'Do as the master commands, Theralion! Kill them!', 14, 0, 100, 0, 0, 21894, 47523, 'Valiona - Intro 1'),
+(45992, 1, 0, 'You are worthless, Theralion!', 14, 0, 100, 0, 0, 21895, 47524, 'Valiona - Intro 2'),
+(45992, 2, 0, '|TInterface\\Icons\\spell_fire_twilightnova.blp:20|t%s casts |cFFFF0000|Hspell:86788|h[Blackout]|h|r!', 41, 0, 100, 0, 0, 0, 47624, 'Valiona'),
+(45992, 3, 0, '|TInterface\\Icons\\spell_fire_twilightfire.blp:20|t%s takes a |cFFFF0000|Hspell:86059|h[Deep Breath]|h|r!', 41, 0, 100, 0, 0, 21898, 46712, 'Valiona to Breath Flight Target Stalker'),
+(45992, 4, 0, 'Theralion, I will engulf the hallway. Cover their escape!', 14, 0, 100, 0, 0, 21898, 47961, 'Valiona to Breath Flight Target Stalker'),
+(45992, 5, 0, 'At least... Theralion dies with me...', 14, 0, 100, 0, 0, 21897, 47960, 'Valiona to Player'),
+-- Theralion
+(45993, 0, 0, 'The master was clearly speaking to you, Valiona. I am far too busy to attack ANYONE.', 14, 0, 100, 0, 0, 20300, 47521, 'Theralion - Intro 1'),
+(45993, 1, 0, 'How dare you call me worthless! You will see why I am mother''s favored child!', 14, 0, 100, 0, 0, 20301, 47522, 'Theralion - Intro 2'),
+(45993, 2, 0, 'You are not the boss of me, Valiona! I will engulf as I please!', 14, 0, 100, 0, 0, 20304, 47911, 'Theralion to Theralion Flight Target Stalker'),
+(45993, 3, 0, '|TInterface\\Icons\\spell_fire_twilightpyroblast.blp:20|t%s begins to cast |cFF00EEFF|Hspell:86408|h[Dazzling Destruction]|h|r!', 41, 0, 100, 0, 0, 0, 46714, 'Theralion to Theralion Flight Target Stalker'),
+(45993, 4, 0, '|TInterface\\Icons\\spell_holy_consumemagic.blp:20|t%s begins to cast |cFF00EEFF|Hspell:86622|h[Engulfing Magic]|h|r!', 41, 0, 100, 0, 0, 0, 46713, 'Theralion'),
+(45993, 5, 0, 'WRITHE IN AGONY!', 14, 0, 100, 0, 0, 20306, 47913, 'Theralion to Valiona');
+
+-- Spells
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN
+('spell_valiona_blackout_dummy',
+'spell_valiona_blackout',
+'spell_valiona_devouring_flames_targeting',
+'spell_valiona_devouring_flames',
+'spell_valiona_twilight_meteorite_targeting',
+'spell_theralion_dazzling_destruction_targeting',
+'spell_theralion_dazzling_destruction_dummy',
+'spell_theralion_dazzling_destruction',
+'spell_theralion_dazzling_destruction_twilight_realm',
+'spell_theralion_twilight_shift',
+'spell_theralion_fabulous_flames_targeting',
+'spell_theralion_engulfing_magic_targeting',
+'spell_theralion_engulfing_magic');
+
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(86673, 'spell_valiona_blackout_dummy'),
+(86788, 'spell_valiona_blackout'),
+(92876, 'spell_valiona_blackout'),
+(92877, 'spell_valiona_blackout'),
+(92878, 'spell_valiona_blackout'),
+(86832, 'spell_valiona_devouring_flames_targeting'),
+(86844, 'spell_valiona_devouring_flames'),
+(92872, 'spell_valiona_devouring_flames'),
+(92873, 'spell_valiona_devouring_flames'),
+(92874, 'spell_valiona_devouring_flames'),
+(88518, 'spell_valiona_twilight_meteorite_targeting'),
+(86380, 'spell_theralion_dazzling_destruction_targeting'),
+(92923, 'spell_theralion_dazzling_destruction_targeting'),
+(92924, 'spell_theralion_dazzling_destruction_targeting'),
+(92925, 'spell_theralion_dazzling_destruction_targeting'),
+(86408, 'spell_theralion_dazzling_destruction_dummy'),
+(86406, 'spell_theralion_dazzling_destruction'),
+(92926, 'spell_theralion_dazzling_destruction'),
+(92927, 'spell_theralion_dazzling_destruction'),
+(92928, 'spell_theralion_dazzling_destruction'),
+(93063, 'spell_theralion_dazzling_destruction_twilight_realm'),
+(88436, 'spell_theralion_twilight_shift'),
+(92892, 'spell_theralion_twilight_shift'),
+(92893, 'spell_theralion_twilight_shift'),
+(92894, 'spell_theralion_twilight_shift'),
+(86495, 'spell_theralion_fabulous_flames_targeting'),
+(86607, 'spell_theralion_engulfing_magic_targeting'),
+(92912, 'spell_theralion_engulfing_magic_targeting'),
+(92913, 'spell_theralion_engulfing_magic_targeting'),
+(92914, 'spell_theralion_engulfing_magic_targeting'),
+(86622, 'spell_theralion_engulfing_magic'),
+(95639, 'spell_theralion_engulfing_magic'),
+(95640, 'spell_theralion_engulfing_magic'),
+(95641, 'spell_theralion_engulfing_magic');
+
+-- Conditions
+DELETE FROM `conditions` WHERE `SourceEntry` IN (90346, 90345, 86840, 86379, 86408, 86406, 92926, 92927, 92928) AND `SourceTypeOrReferenceId`= 13;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES
+(13, 1, 90346, 0, 0, 31, 0, 3, 45992, 0, 0, 0, '', 'Share Health - Target Valiona'),
+(13, 1, 90345, 0, 0, 31, 0, 3, 45993, 0, 0, 0, '', 'Share Health - Target Theralion'),
+(13, 1, 86840, 0, 0, 31, 0, 3, 46588, 0, 0, 0, '', 'Devouring Flames - Target Convective Flames'),
+(13, 1, 86379, 0, 0, 31, 0, 3, 46364, 0, 0, 0, '', 'Dazzling Destruction - Target Theralion Flight Target Stalker'),
+(13, 1, 86408, 0, 0, 31, 0, 3, 46374, 0, 0, 0, '', 'Dazzling Destruction - Target Dazzling Destruction Stalker'),
+(13, 2, 86406, 0, 0, 31, 0, 3, 46374, 0, 0, 0, '', 'Dazzling Destruction - Target Dazzling Destruction Stalker'),
+(13, 2, 92926, 0, 0, 31, 0, 3, 46374, 0, 0, 0, '', 'Dazzling Destruction - Target Dazzling Destruction Stalker'),
+(13, 2, 92927, 0, 0, 31, 0, 3, 46374, 0, 0, 0, '', 'Dazzling Destruction - Target Dazzling Destruction Stalker'),
+(13, 2, 92928, 0, 0, 31, 0, 3, 46374, 0, 0, 0, '', 'Dazzling Destruction - Target Dazzling Destruction Stalker');
+
+-- Spell Procs
+DELETE FROM `spell_proc` WHERE `SpellId`= -86622;
+INSERT INTO `spell_proc` (`SpellId`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`) VALUES
+(-86622, 0x00055554, 1 | 2, 2, 0, 32);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 26fcfe587fd..622b679a079 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1671,10 +1671,6 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
if (z < ground_z)
z = ground_z;
}
-
- // Creatures that are simulating flight effects or actual flight should use HoverHeight
- if ((ToUnit() && (ToUnit()->IsFlying() || ToUnit()->IsHovering() || ToUnit()->IsLevitating())) && !ToUnit()->IsUnderWater())
- z += GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
break;
}
case TYPEID_PLAYER:
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 56002dca9c7..99bb288450f 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -4185,6 +4185,34 @@ void SpellMgr::LoadSpellInfoCorrections()
// ENDOF THE VORTEX PINNACLE SPELLS
+ //
+ // BASTION OF TWILIGHT SPELLS
+ //
+ // Theralion and Valiona
+ // Blackout
+ ApplySpellFix({
+ 86825,
+ 92879,
+ 92880,
+ 92881
+ }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE;
+ });
+
+ // Twilight Meteorite
+ ApplySpellFix({
+ 86013,
+ 92859,
+ 92860,
+ 92861
+ }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE;
+ });
+
+ // ENDOF BASTION OF TWILIGHT
+
//
// DEADMINES SPELLS
//
diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.cpp b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.cpp
new file mode 100644
index 00000000000..c7cc6b5a6a6
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.cpp
@@ -0,0 +1,44 @@
+/*
+* Copyright (C) 2008-2018 TrinityCore
+*
+* 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 .
+*/
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "GameObject.h"
+#include "GameObjectAI.h"
+#include "Player.h"
+#include "bastion_of_twilight.h"
+
+class at_theralion_and_valiona_intro : public AreaTriggerScript
+{
+ public:
+ at_theralion_and_valiona_intro() : AreaTriggerScript("at_theralion_and_valiona_intro") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/)
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ instance->SetData(DATA_AT_THERALION_AND_VALIONA_INTRO, IN_PROGRESS);
+ return true;
+ }
+};
+
+void AddSC_bastion_of_twilight()
+{
+ new at_theralion_and_valiona_intro();
+}
\ No newline at end of file
diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h
index d00fb061bc6..64c8e6f91c7 100644
--- a/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h
+++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h
@@ -27,31 +27,37 @@ uint32 const EncounterCountHeroic = 5;
enum BoTDataTypes
{
// Encounter Types
- DATA_HALFUS_WYRMBREAKER = 0,
- DATA_THERALION_AND_VALIONA = 1,
- DATA_ASCENDANT_COUNCIL = 2,
- DATA_CHOGALL = 3,
- DATA_SINESTRA = 4,
+ DATA_HALFUS_WYRMBREAKER = 0,
+ DATA_THERALION_AND_VALIONA = 1,
+ DATA_ASCENDANT_COUNCIL = 2,
+ DATA_CHOGALL = 3,
+ DATA_SINESTRA = 4,
// Creature Types
- DATA_PROTO_BEHEMOTH = 5,
- DATA_THERALION = 6,
- DATA_VALIONA = 7,
- DATA_IGNACIOUS = 8,
- DATA_FELUDIUS = 9,
- DATA_TERRASTRA = 10,
- DATA_ARION = 11,
- DATA_ELEMENTIUM_MONSTROSITY = 12,
+ DATA_PROTO_BEHEMOTH = 5,
+ DATA_THERALION = 6,
+ DATA_VALIONA = 7,
+ DATA_IGNACIOUS = 8,
+ DATA_FELUDIUS = 9,
+ DATA_TERRASTRA = 10,
+ DATA_ARION = 11,
+ DATA_ELEMENTIUM_MONSTROSITY = 12,
// GameObject Types
- DATA_WHELP_CAGE = 13,
+ DATA_WHELP_CAGE = 13,
+
+ // Areatriggers
+ DATA_AT_HALFUS_INTRO = 14,
+ DATA_AT_THERALION_AND_VALIONA_INTRO = 15,
// Encounter Related
/*Halfus Wyrmbreaker*/
DATA_UNRESPONSIVE_DRAGON_FIRST,
DATA_UNRESPONSIVE_DRAGON_SECOND,
DATA_CAST_DRAGON_BUFFS,
- DATA_OPEN_ORPHANED_EMERALD_WHELP_CAGE
+ DATA_OPEN_ORPHANED_EMERALD_WHELP_CAGE,
+
+ /*Theralion and Valiona*/
};
enum BoTDataStates
@@ -60,36 +66,48 @@ enum BoTDataStates
DRAGON_BUFFS_PROTO_BEHEMOTH,
};
+enum BoTAreatriggerIndex
+{
+ AT_INDEX_HALFUS_WYRMBREAKER_INTRO = 1,
+ AT_INDEX_THERALION_AND_VALIONA_INTRO = 2
+};
+
enum BoTCreatures
{
// Bosses
- BOSS_HALFUS_WYRMBREAKER = 44600,
- BOSS_THERALION = 45993,
- BOSS_VALIONA = 45992,
- BOSS_IGNACIOUS = 43686,
- BOSS_FELUDIUS = 43687,
- BOSS_TERRASTRA = 43689,
- BOSS_ARION = 43688,
- BOSS_ELEMENTIUM_MONSTROSITY = 43735,
- BOSS_CHOGALL = 43324,
- BOSS_SINESTRA = 45213,
+ BOSS_HALFUS_WYRMBREAKER = 44600,
+ BOSS_THERALION = 45993,
+ BOSS_VALIONA = 45992,
+ BOSS_IGNACIOUS = 43686,
+ BOSS_FELUDIUS = 43687,
+ BOSS_TERRASTRA = 43689,
+ BOSS_ARION = 43688,
+ BOSS_ELEMENTIUM_MONSTROSITY = 43735,
+ BOSS_CHOGALL = 43324,
+ BOSS_SINESTRA = 45213,
// Encounter related
/*Halfus Wyrmbreaker*/
- NPC_PROTO_BEHEMOTH = 44687,
- NPC_NETHER_SCION = 44645,
- NPC_NETHER_SCION_ENCOUNTER = 44828,
- NPC_SLATE_DRAGON = 44652,
- NPC_SLATE_DRAGON_ENCOUNTER = 44829,
- NPC_STORM_RIDER = 44650,
- NPC_STORM_RIDER_ENCOUNTER = 44826,
- NPC_TIME_WARDEN = 44797,
- NPC_TIME_WARDEN_ENCOUNTER = 44653,
- NPC_ORPHANED_EMERALD_WELP = 44641,
- NPC_SPIKE = 44765,
+ NPC_PROTO_BEHEMOTH = 44687,
+ NPC_NETHER_SCION = 44645,
+ NPC_NETHER_SCION_ENCOUNTER = 44828,
+ NPC_SLATE_DRAGON = 44652,
+ NPC_SLATE_DRAGON_ENCOUNTER = 44829,
+ NPC_STORM_RIDER = 44650,
+ NPC_STORM_RIDER_ENCOUNTER = 44826,
+ NPC_TIME_WARDEN = 44797,
+ NPC_TIME_WARDEN_ENCOUNTER = 44653,
+ NPC_ORPHANED_EMERALD_WELP = 44641,
+ NPC_SPIKE = 44765,
+
+ /*Theralion and Valiona*/
+ NPC_THERALION_FLIGHT_TARGET_STALKER = 46364,
+ NPC_CONVECTIVE_FLAMES = 46588,
+ NPC_DAZZLING_DESTRUCTION_STALKER = 46374,
+ NPC_FABULOUS_FLAMES = 46448,
// Generic Creatures
- NPC_INVISIBLE_STALKER = 42098
+ NPC_INVISIBLE_STALKER = 42098
};
enum BoTGameObjects
@@ -106,13 +124,23 @@ enum BoTGameObjects
enum BoTActions
{
- ACTION_ENABLE_MALEVOLENT_STRIKES = 1,
- ACTION_ENABLE_FRENZIED_ASSAULT = 2,
- ACTION_ENABLE_SHADOW_NOVA = 3,
- ACTION_ENABLE_FIREBALL_BARRAGE = 1,
- ACTION_ENABLE_SCORCHING_BREATH = 2,
- ACTION_CAST_DRAGONS_VENGEANCE = 3,
- ACTION_MOVE_OUT_OF_CAGE = 4
+ // Halfus Wyrmbreaker
+ ACTION_ENABLE_MALEVOLENT_STRIKES = 1,
+ ACTION_ENABLE_FRENZIED_ASSAULT = 2,
+ ACTION_ENABLE_SHADOW_NOVA = 3,
+ ACTION_ENABLE_FIREBALL_BARRAGE = 1,
+ ACTION_ENABLE_SCORCHING_BREATH = 2,
+ ACTION_CAST_DRAGONS_VENGEANCE = 3,
+ ACTION_MOVE_OUT_OF_CAGE = 4,
+
+ // Theralion and Valiona
+ ACTION_START_ARGUMENT_INTRO = 1,
+
+ // Cho'Gall (Non-Boss version)
+ ACTION_TALK_INTRO_HALFUS_WYRMBREAKER = 1,
+
+ // Cho'Gall (Boss)
+ ACTION_TALK_INTRO_THERALION_AND_VALIONA = 1
};
enum BoTEvents
diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_theralion_and_valiona.cpp b/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_theralion_and_valiona.cpp
new file mode 100644
index 00000000000..3ff24b4ac98
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_theralion_and_valiona.cpp
@@ -0,0 +1,1188 @@
+/*
+* Copyright (C) 2008-2018 TrinityCore
+*
+* 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 .
+*/
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "GameObject.h"
+#include "GameObjectAI.h"
+#include "Player.h"
+#include "PhasingHandler.h"
+#include "bastion_of_twilight.h"
+
+enum Texts
+{
+ // Theralion and Valiona
+ SAY_ARGUE_WITH_SIBLING_1 = 0,
+ SAY_ARGUE_WITH_SIBLING_2 = 1,
+
+ // Theralion
+ SAY_DAZZLING_DESTRUCTION = 2,
+ SAY_ANNOUNCE_DAZZLING_DESTRUCTION = 3,
+ SAY_ANNOUNCE_ENGULFING_MAGIC = 4,
+
+ // Valiona
+ SAY_ANNOUNCE_BLACKOUT = 2,
+};
+
+enum Spells
+{
+ // Theralion
+ SPELL_SHARE_HEALTH_1 = 90346,
+ SPELL_TWILIGHT_BLAST = 86369,
+ SPELL_DAZZLING_DESTRUCTION_SCRIPT = 86379, // probably a Blizzard script thing. Unneeded for our handling
+ SPELL_DAZZLING_DESTRUCTION_TARGETIG = 86380,
+ SPELL_DAZZLING_DESTRUCTION_DUMMY = 86408,
+ SPELL_DAZZLING_DESTRUCTION_TWILIGHT_REALM = 93063,
+ SPELL_TWILIGHT_PROTECTION_BUFF = 86415,
+ SPELL_FABULOUS_FLAMES_TARGETING = 86495,
+ SPELL_ENGULFING_MAGIC_TARGETING = 86607,
+ SPELL_ENGULFING_MAGIC_TRIGGERED = 86631,
+
+ // Valiona
+ SPELL_SHARE_HEALTH_2 = 90345,
+ SPELL_BLACKOUT_DUMMY = 86673,
+ SPELL_BLACKOUT_DAMAGE = 86825,
+ SPELL_DEVOURING_FLAMES_TARGETING = 86832,
+ SPELL_DEVOURING_FLAMES = 86840,
+ SPELL_TWILIGHT_METEORITE_TARGETING = 88518,
+ SPELL_DUMMY_NUKE = 80776, // used to select Theralion's current victim. We do it different and better
+ SPELL_TWILIGHT_ZONE = 86214,
+
+ // Dazzling Destruction Stalker
+ SPELL_DAZZLING_DESTRUCTION_STALKER_VISUAL = 86383
+};
+
+enum Events
+{
+ // Theralion and Valiona
+ EVENT_TALK_ARGUMENT_1 = 1,
+ EVENT_TALK_ARGUMENT_2,
+ EVENT_LIFTOFF,
+ EVENT_FLY_TO_DESTINATION,
+ EVENT_LAND,
+ EVENT_ATTACK_PLAYERS,
+
+ // Theralion
+ EVENT_TWILIGHT_BLAST,
+ EVENT_DAZZLING_DESTRUCTION,
+ EVENT_FABULOUS_FLAMES,
+ EVENT_ENGULFING_MAGIC,
+
+ // Valiona
+ EVENT_BLACKOUT,
+ EVENT_DEVOURING_FLAMES,
+ EVENT_TWILIGHT_METEORITE,
+
+ EVENT_DEEP_BREATH,
+ EVENT_FACE_TO_DIRECTION,
+ EVENT_FLY_TO_STARTING_POINT,
+ EVENT_FLY_TO_OTHER_SIDE,
+};
+
+enum Phases
+{
+ PHASE_INTRO = 0,
+ PHASE_COMBAT = 1
+};
+
+enum AnimKits
+{
+ ANIM_KIT_LIFTOFF = 1009
+};
+
+enum MovementPoints
+{
+ POINT_TAKEOFF_DESTINATION = 1,
+ POINT_LAND = 2,
+ POINT_DEEP_BREATH_1 = 3,
+ POINT_DEEP_BREATH_2 = 4
+};
+
+enum PhaseIds
+{
+ PHASE_ID_TWILIGHT_SHIFT = 290
+};
+
+enum DeepBreathSides
+{
+ SIDE_VALIONA = 0,
+ SIDE_THERALION = 1
+};
+
+Position const TheralionLandingPos = { -740.804f, -683.642f, 831.8898f };
+
+Position const DeepBreathStartingPositions[] =
+{
+ { -741.4598f, -592.8389f, 859.1005f }, // Valiona's side
+ { -740.4072f, -776.5493f, 858.7795f } // Theralion's side
+};
+
+class boss_theralion : public CreatureScript
+{
+ public:
+ boss_theralion() : CreatureScript("boss_theralion") { }
+
+ struct boss_theralionAI : public BossAI
+ {
+ boss_theralionAI(Creature* creature) : BossAI(creature, DATA_THERALION_AND_VALIONA)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _dazzlingDestructionCount = 0;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ Initialize();
+ events.SetPhase(PHASE_INTRO);
+ DoCastAOE(SPELL_SHARE_HEALTH_1, true);
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ _JustEngagedWith();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.SetPhase(PHASE_COMBAT);
+
+ if (Creature* valiona = instance->GetCreature(DATA_VALIONA))
+ valiona->AI()->AttackStart(who);
+
+ events.ScheduleEvent(EVENT_LIFTOFF, Milliseconds(1));
+ events.ScheduleEvent(EVENT_DAZZLING_DESTRUCTION, Minutes(1) + Seconds(22));
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ //if (victim->GetTypeId() == TYPEID_PLAYER)
+ // Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ me->SendSetPlayHoverAnim(false);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ summons.DespawnAll();
+ _DespawnAtEvade();
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
+ {
+ if (!caster)
+ return;
+
+ switch (spell->Id)
+ {
+ case SPELL_SHARE_HEALTH_2:
+ if (!caster->HasAura(SPELL_SHARE_HEALTH_1))
+ DoCastAOE(SPELL_SHARE_HEALTH_1, true);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_START_ARGUMENT_INTRO:
+ events.ScheduleEvent(EVENT_TALK_ARGUMENT_1, Seconds(8) + Milliseconds(800));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summons.Summon(summon);
+
+ switch (summon->GetEntry())
+ {
+ case NPC_DAZZLING_DESTRUCTION_STALKER:
+ DoCast(summon, SPELL_DAZZLING_DESTRUCTION_DUMMY);
+ PhasingHandler::InheritPhaseShift(summon, me);
+ break;
+ case NPC_FABULOUS_FLAMES:
+ PhasingHandler::InheritPhaseShift(summon, me);
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ return 0;
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
+
+ switch (id)
+ {
+ case POINT_TAKEOFF_DESTINATION:
+ events.ScheduleEvent(EVENT_TWILIGHT_BLAST, Milliseconds(400));
+ break;
+ case POINT_LAND:
+ me->SetDisableGravity(false);
+ me->SendSetPlayHoverAnim(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.ScheduleEvent(EVENT_ATTACK_PLAYERS, Seconds(2));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_TALK_ARGUMENT_1:
+ Talk(SAY_ARGUE_WITH_SIBLING_1);
+ events.ScheduleEvent(EVENT_TALK_ARGUMENT_2, Seconds(11));
+ break;
+ case EVENT_TALK_ARGUMENT_2:
+ Talk(SAY_ARGUE_WITH_SIBLING_2);
+ break;
+ case EVENT_LIFTOFF:
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->PlayOneShotAnimKitId(ANIM_KIT_LIFTOFF);
+ me->SetDisableGravity(true);
+ me->SendSetPlayHoverAnim(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.ScheduleEvent(EVENT_FLY_TO_DESTINATION, Seconds(1));
+ events.CancelEvent(EVENT_FABULOUS_FLAMES);
+ events.CancelEvent(EVENT_ENGULFING_MAGIC);
+ break;
+ case EVENT_FLY_TO_DESTINATION:
+ if (Creature* stalker = me->FindNearestCreature(NPC_THERALION_FLIGHT_TARGET_STALKER, 100.0f, true))
+ me->GetMotionMaster()->MovePoint(POINT_TAKEOFF_DESTINATION, stalker->GetPosition(), false);
+ break;
+ case EVENT_TWILIGHT_BLAST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, 0))
+ DoCast(target, SPELL_TWILIGHT_BLAST);
+ events.Repeat(Seconds(2) + Milliseconds(400));
+ break;
+ case EVENT_DAZZLING_DESTRUCTION:
+ if (_dazzlingDestructionCount == 0)
+ {
+ DoCastAOE(SPELL_DAZZLING_DESTRUCTION_SCRIPT, true);
+ Talk(SAY_DAZZLING_DESTRUCTION);
+ Talk(SAY_ANNOUNCE_DAZZLING_DESTRUCTION);
+ events.CancelEvent(EVENT_TWILIGHT_BLAST);
+ }
+
+ if (_dazzlingDestructionCount < 3)
+ {
+ DoCastAOE(SPELL_DAZZLING_DESTRUCTION_TARGETIG, true);
+ _dazzlingDestructionCount++;
+ }
+
+ if (_dazzlingDestructionCount < 3)
+ events.Repeat(Seconds(4) + Milliseconds(700));
+ else
+ events.ScheduleEvent(EVENT_LAND, Seconds(4));
+ break;
+ case EVENT_LAND:
+ me->GetMotionMaster()->MoveLand(POINT_LAND, TheralionLandingPos);
+ break;
+ case EVENT_ATTACK_PLAYERS:
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* target = me->GetVictim())
+ me->AI()->AttackStart(target);
+
+ events.ScheduleEvent(EVENT_FABULOUS_FLAMES, Seconds(3) + Milliseconds(600));
+ events.ScheduleEvent(EVENT_ENGULFING_MAGIC, Seconds(12));
+ break;
+ case EVENT_FABULOUS_FLAMES:
+ DoCastAOE(SPELL_FABULOUS_FLAMES_TARGETING);
+ events.Repeat(Seconds(15) + Milliseconds(700));
+ break;
+ case EVENT_ENGULFING_MAGIC:
+ DoCastAOE(SPELL_ENGULFING_MAGIC_TARGETING);
+ Talk(SAY_ANNOUNCE_ENGULFING_MAGIC);
+ events.Repeat(Seconds(40));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ uint8 _dazzlingDestructionCount;
+ };
+
+ CreatureAI* GetAI(Creature *creature) const override
+ {
+ return GetBastionOfTwilightAI(creature);
+ }
+};
+
+class boss_valiona : public CreatureScript
+{
+ public:
+ boss_valiona() : CreatureScript("boss_valiona") { }
+
+ struct boss_valionaAI : public BossAI
+ {
+ boss_valionaAI(Creature* creature) : BossAI(creature, DATA_THERALION_AND_VALIONA)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _deepBreathCount = 0;
+ _currentRoomSide = SIDE_VALIONA;
+
+ FillDeepBreathPaths();
+ }
+
+ void FillDeepBreathPaths()
+ {
+ _deepBreathWaypoints.clear();
+
+ // Pattern is: Valiona's side to Theralion's side
+ // Just invert the logic to get the opposite result
+ // Note: for some reason Blizzard has spawned flight
+ // target stalkers but the positions in sniffs are different
+ _deepBreathWaypoints =
+ {
+ {
+ // Entrance Lane
+ { -759.2115f, -604.4235f, 851.0311f },
+ { -756.6174f, -767.658f, 850.3376f }
+ },
+ {
+ // Exit Lane
+ { -758.427f, -602.9468f, 851.3987f },
+ { -757.4211f, -766.2177f, 849.9313f }
+ },
+ {
+ // Center Lane
+ { -759.2116f, -604.4235f, 851.0311f },
+ { -756.634f, -767.6933f, 850.3306f }
+ }
+ };
+ Trinity::Containers::RandomShuffle(_deepBreathWaypoints);
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ Initialize();
+ events.SetPhase(PHASE_INTRO);
+ DoCastAOE(SPELL_SHARE_HEALTH_2, true);
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ _JustEngagedWith();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.SetPhase(PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_BLACKOUT, Seconds(10) + Milliseconds(500));
+ events.ScheduleEvent(EVENT_DEVOURING_FLAMES, Seconds(25));
+ events.ScheduleEvent(EVENT_LIFTOFF, Minutes(1) + Seconds(37));
+
+ if (Creature* theralion = instance->GetCreature(DATA_THERALION))
+ theralion->AI()->AttackStart(who);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ //if (victim->GetTypeId() == TYPEID_PLAYER)
+ // Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ me->SendSetPlayHoverAnim(false);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ summons.DespawnAll();
+ _DespawnAtEvade();
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
+ {
+ if (!caster)
+ return;
+
+ switch (spell->Id)
+ {
+ case SPELL_SHARE_HEALTH_1:
+ if (!caster->HasAura(SPELL_SHARE_HEALTH_2))
+ DoCastAOE(SPELL_SHARE_HEALTH_2, true);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_START_ARGUMENT_INTRO:
+ events.ScheduleEvent(EVENT_TALK_ARGUMENT_1, Seconds(4));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summons.Summon(summon);
+
+ switch (summon->GetEntry())
+ {
+ case NPC_CONVECTIVE_FLAMES:
+ me->StopMoving();
+ me->SetFacingToObject(summon);
+ DoCast(summon, SPELL_DEVOURING_FLAMES);
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ return 0;
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
+
+ switch (id)
+ {
+ case POINT_TAKEOFF_DESTINATION:
+ events.ScheduleEvent(EVENT_TWILIGHT_METEORITE, Seconds(2));
+ events.ScheduleEvent(EVENT_DEEP_BREATH, Minutes(1) + Seconds(21));
+ break;
+ case POINT_LAND:
+ me->SetDisableGravity(false);
+ me->SendSetPlayHoverAnim(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.ScheduleEvent(EVENT_ATTACK_PLAYERS, Seconds(2));
+ break;
+ case POINT_DEEP_BREATH_1:
+ events.ScheduleEvent(EVENT_FACE_TO_DIRECTION, Seconds(1));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_TALK_ARGUMENT_1:
+ Talk(SAY_ARGUE_WITH_SIBLING_1);
+ events.ScheduleEvent(EVENT_TALK_ARGUMENT_2, Seconds(11));
+ break;
+ case EVENT_TALK_ARGUMENT_2:
+ Talk(SAY_ARGUE_WITH_SIBLING_2);
+ break;
+ case EVENT_BLACKOUT:
+ DoCastAOE(SPELL_BLACKOUT_DUMMY, true);
+ Talk(SAY_ANNOUNCE_BLACKOUT);
+ events.Repeat(Seconds(46));
+ break;
+ case EVENT_DEVOURING_FLAMES:
+ DoCastAOE(SPELL_DEVOURING_FLAMES_TARGETING, true);
+ events.Repeat(Seconds(41));
+ break;
+ case EVENT_LIFTOFF:
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ events.CancelEvent(EVENT_BLACKOUT);
+ events.CancelEvent(EVENT_DEVOURING_FLAMES);
+ me->PlayOneShotAnimKitId(ANIM_KIT_LIFTOFF);
+ me->SetDisableGravity(true);
+ me->SendSetPlayHoverAnim(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ events.ScheduleEvent(EVENT_FLY_TO_DESTINATION, Seconds(1));
+ events.ScheduleEvent(EVENT_DEEP_BREATH, Minutes(1) + Seconds(25) + Milliseconds(100));
+ break;
+ case EVENT_FLY_TO_DESTINATION:
+ {
+ Position pos = me->GetPosition();
+ pos.m_positionZ += 25.0f;
+ me->GetMotionMaster()->MovePoint(POINT_TAKEOFF_DESTINATION, pos, false);
+ break;
+ }
+ case EVENT_TWILIGHT_METEORITE:
+ DoCastAOE(SPELL_TWILIGHT_METEORITE_TARGETING, true);
+ events.Repeat(Seconds(1) + Milliseconds(200));
+ break;
+ case EVENT_DEEP_BREATH:
+ if (_deepBreathCount == 0)
+ events.CancelEvent(EVENT_TWILIGHT_METEORITE);
+
+ if (_currentRoomSide == SIDE_VALIONA)
+ {
+ _currentRoomSide = SIDE_THERALION;
+ me->GetMotionMaster()->MovePoint(POINT_DEEP_BREATH_1, DeepBreathStartingPositions[_currentRoomSide], false);
+ }
+ else
+ {
+ _currentRoomSide = SIDE_VALIONA;
+ me->GetMotionMaster()->MovePoint(POINT_DEEP_BREATH_1, DeepBreathStartingPositions[_currentRoomSide], false);
+ }
+ _deepBreathCount++;
+ break;
+ case EVENT_FACE_TO_DIRECTION:
+ if (_currentRoomSide == SIDE_THERALION)
+ {
+ _currentDeepBreathWaypoint = *_deepBreathWaypoints.begin()->end();
+ me->SetFacingTo(me->GetAngle(*_deepBreathWaypoints.begin()->begin()));
+ }
+ else if (_currentRoomSide == SIDE_VALIONA)
+ {
+ _currentDeepBreathWaypoint = *_deepBreathWaypoints.begin()->begin();
+ me->SetFacingTo(me->GetAngle(*_deepBreathWaypoints.begin()->end()));
+ }
+
+ _deepBreathWaypoints.erase(_deepBreathWaypoints.begin());
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ uint8 _deepBreathCount;
+ uint8 _currentRoomSide;
+ Position _currentDeepBreathWaypoint;
+ std::vector> _deepBreathWaypoints;
+ };
+
+ CreatureAI* GetAI(Creature *creature) const override
+ {
+ return GetBastionOfTwilightAI(creature);
+ }
+};
+
+class spell_theralion_dazzling_destruction_targeting : public SpellScriptLoader
+{
+ public:
+ spell_theralion_dazzling_destruction_targeting() : SpellScriptLoader("spell_theralion_dazzling_destruction_targeting") { }
+
+ class spell_theralion_dazzling_destruction_targeting_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_dazzling_destruction_targeting_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_dazzling_destruction_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_dazzling_destruction_targeting_SpellScript();
+ }
+};
+
+class ValidDazzlingDestructionStalkerCheck
+{
+ public:
+ ValidDazzlingDestructionStalkerCheck() { }
+
+ bool operator()(WorldObject* object)
+ {
+ return (!object->ToUnit()->HasAura(SPELL_DAZZLING_DESTRUCTION_STALKER_VISUAL));
+ }
+};
+
+class spell_theralion_dazzling_destruction_dummy : public SpellScriptLoader
+{
+ public:
+ spell_theralion_dazzling_destruction_dummy() : SpellScriptLoader("spell_theralion_dazzling_destruction_dummy") { }
+
+ class spell_theralion_dazzling_destruction_dummy_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_dazzling_destruction_dummy_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ targets.remove_if(ValidDazzlingDestructionStalkerCheck());
+ }
+
+ void HandleHit(SpellEffIndex effIndex)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_dazzling_destruction_dummy_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_theralion_dazzling_destruction_dummy_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_dazzling_destruction_dummy_SpellScript();
+ }
+};
+
+class IsInTwilightPhaseCheck
+{
+public:
+ IsInTwilightPhaseCheck() { }
+
+ bool operator()(WorldObject* object)
+ {
+ return (object->GetPhaseShift().HasPhase(PHASE_ID_TWILIGHT_SHIFT));
+ }
+};
+
+class spell_theralion_dazzling_destruction : public SpellScriptLoader
+{
+ public:
+ spell_theralion_dazzling_destruction() : SpellScriptLoader("spell_theralion_dazzling_destruction") { }
+
+ class spell_theralion_dazzling_destruction_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_dazzling_destruction_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DAZZLING_DESTRUCTION_TWILIGHT_REALM });
+ }
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ targets.remove_if(IsInTwilightPhaseCheck());
+ }
+
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true);
+ }
+
+ void HandleScriptEffectTrigger(SpellEffIndex effIndex)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ if (GetExplTargetDest() && GetExplTargetDest()->GetPosition() == target->GetPosition())
+ {
+ target->RemoveAllAuras();
+ target->CastSpell(target, GetSpellInfo()->Effects[effIndex].BasePoints, true);
+ target->CastSpell(target, SPELL_DAZZLING_DESTRUCTION_TWILIGHT_REALM, true);
+ }
+ }
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_dazzling_destruction_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_dazzling_destruction_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_theralion_dazzling_destruction_SpellScript::HandleScriptEffectTrigger, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_theralion_dazzling_destruction_SpellScript::HandleScriptEffect, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_dazzling_destruction_SpellScript();
+ }
+};
+
+class TwilightProtectionCheck
+{
+ public:
+ TwilightProtectionCheck() { }
+
+ bool operator()(WorldObject* object)
+ {
+ return (object->ToUnit()->HasAura(SPELL_TWILIGHT_PROTECTION_BUFF)
+ || !object->GetPhaseShift().HasPhase(PHASE_ID_TWILIGHT_SHIFT));
+ }
+};
+
+class spell_theralion_dazzling_destruction_twilight_realm: public SpellScriptLoader
+{
+ public:
+ spell_theralion_dazzling_destruction_twilight_realm() : SpellScriptLoader("spell_theralion_dazzling_destruction_twilight_realm") { }
+
+ class spell_theralion_dazzling_destruction_twilight_realm_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_dazzling_destruction_twilight_realm_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ targets.remove_if(TwilightProtectionCheck());
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_dazzling_destruction_twilight_realm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_dazzling_destruction_twilight_realm_SpellScript();
+ }
+};
+
+class spell_theralion_twilight_shift: public SpellScriptLoader
+{
+ public:
+ spell_theralion_twilight_shift() : SpellScriptLoader("spell_theralion_twilight_shift") { }
+
+ class spell_theralion_twilight_shift_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_twilight_shift_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ targets.remove_if(IsInTwilightPhaseCheck());
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_twilight_shift_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_twilight_shift_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_twilight_shift_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_twilight_shift_SpellScript();
+ }
+};
+
+class spell_theralion_fabulous_flames_targeting : public SpellScriptLoader
+{
+ public:
+ spell_theralion_fabulous_flames_targeting() : SpellScriptLoader("spell_theralion_fabulous_flames_targeting") { }
+
+ class spell_theralion_fabulous_flames_targeting_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_fabulous_flames_targeting_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void HandleHit(SpellEffIndex effIndex)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_fabulous_flames_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_theralion_fabulous_flames_targeting_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_fabulous_flames_targeting_SpellScript();
+ }
+};
+
+class SpellcasterClassCheck
+{
+ public:
+ SpellcasterClassCheck() { }
+
+ bool operator()(WorldObject* object)
+ {
+ if (Unit* target = object->ToUnit())
+ return (target->getClass() == CLASS_HUNTER
+ || target->getClass() == CLASS_WARRIOR
+ || target->getClass() == CLASS_DEATH_KNIGHT);
+
+ return false;
+ }
+};
+
+class spell_theralion_engulfing_magic_targeting : public SpellScriptLoader
+{
+ public:
+ spell_theralion_engulfing_magic_targeting() : SpellScriptLoader("spell_theralion_engulfing_magic_targeting") { }
+
+ class spell_theralion_engulfing_magic_targeting_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_theralion_engulfing_magic_targeting_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ // according to sniffs if no spellcaster class is found, the current victim is the target instead
+ if (targets.size() > 1)
+ targets.remove_if(SpellcasterClassCheck());
+
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_theralion_engulfing_magic_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_theralion_engulfing_magic_targeting_SpellScript();
+ }
+};
+
+class spell_theralion_engulfing_magic : public SpellScriptLoader
+{
+ public:
+ spell_theralion_engulfing_magic() : SpellScriptLoader("spell_theralion_engulfing_magic") { }
+
+ class spell_theralion_engulfing_magic_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_theralion_engulfing_magic_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_ENGULFING_MAGIC_TRIGGERED });
+ }
+
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ int32 bp = 0;
+ if (HealInfo* healInfo = eventInfo.GetHealInfo())
+ bp += healInfo->GetHeal();
+
+ if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo())
+ bp += dmgInfo->GetDamage();
+
+ if (bp)
+ GetCaster()->CastCustomSpell(GetCaster(), SPELL_ENGULFING_MAGIC_TRIGGERED, &bp, nullptr, nullptr, true, nullptr, aurEff);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_theralion_engulfing_magic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_theralion_engulfing_magic_AuraScript();
+ }
+};
+
+class spell_valiona_blackout_dummy : public SpellScriptLoader
+{
+ public:
+ spell_valiona_blackout_dummy() : SpellScriptLoader("spell_valiona_blackout_dummy") { }
+
+ class spell_valiona_blackout_dummy_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_valiona_blackout_dummy_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void HandleHit(SpellEffIndex effIndex)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_valiona_blackout_dummy_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_valiona_blackout_dummy_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_valiona_blackout_dummy_SpellScript();
+ }
+};
+
+class spell_valiona_blackout: public SpellScriptLoader
+{
+ public:
+ spell_valiona_blackout() : SpellScriptLoader("spell_valiona_blackout") { }
+
+ class spell_valiona_blackout_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_valiona_blackout_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BLACKOUT_DAMAGE });
+ }
+
+ void OnAuraRemoveHandler(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL
+ || GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ if (Unit* target = GetTarget())
+ target->CastSpell(target, SPELL_BLACKOUT_DAMAGE, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_valiona_blackout_AuraScript::OnAuraRemoveHandler, EFFECT_0, SPELL_AURA_SCHOOL_HEAL_ABSORB, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_valiona_blackout_AuraScript();
+ }
+};
+
+class spell_valiona_devouring_flames_targeting : public SpellScriptLoader
+{
+ public:
+ spell_valiona_devouring_flames_targeting() : SpellScriptLoader("spell_valiona_devouring_flames_targeting") { }
+
+ class spell_valiona_devouring_flames_targeting_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_valiona_devouring_flames_targeting_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_valiona_devouring_flames_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_valiona_devouring_flames_targeting_SpellScript();
+ }
+};
+
+class spell_valiona_devouring_flames : public SpellScriptLoader
+{
+ public:
+ spell_valiona_devouring_flames() : SpellScriptLoader("spell_valiona_devouring_flames") { }
+
+ class spell_valiona_devouring_flames_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_valiona_devouring_flames_SpellScript);
+
+ void ChangeDamage()
+ {
+ if (Unit* caster = GetCaster())
+ {
+ uint32 damageReduction = CalculatePct(GetHitDamage(), GetHitUnit()->GetDistance(caster));
+ SetHitDamage(GetHitDamage() - damageReduction);
+ }
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_valiona_devouring_flames_SpellScript::ChangeDamage);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_valiona_devouring_flames_SpellScript();
+ }
+};
+
+class TheralionVictimCheck
+{
+ public:
+ TheralionVictimCheck(Unit* _theralion) : theralion(_theralion) { }
+
+ bool operator()(WorldObject* object)
+ {
+ return (theralion->GetVictim() && theralion->GetVictim() == object->ToUnit());
+ }
+ private:
+ Unit* theralion;
+
+};
+
+class spell_valiona_twilight_meteorite_targeting : public SpellScriptLoader
+{
+ public:
+ spell_valiona_twilight_meteorite_targeting() : SpellScriptLoader("spell_valiona_twilight_meteorite_targeting") { }
+
+ class spell_valiona_twilight_meteorite_targeting_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_valiona_twilight_meteorite_targeting_SpellScript);
+
+ void FilterTargets(std::list& targets)
+ {
+ if (targets.empty())
+ return;
+
+ if (Unit* caster = GetCaster())
+ if (InstanceScript* instance = caster->GetInstanceScript())
+ if (Creature* theralion = instance->GetCreature(DATA_THERALION))
+ targets.remove_if(TheralionVictimCheck(theralion));
+
+ if (targets.empty())
+ return;
+
+ Trinity::Containers::RandomResize(targets, 1);
+ }
+
+ void HandleEffect(SpellEffIndex effIndex)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_valiona_twilight_meteorite_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_valiona_twilight_meteorite_targeting_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_valiona_twilight_meteorite_targeting_SpellScript();
+ }
+};
+
+void AddSC_boss_theralion_and_valiona()
+{
+ new boss_theralion();
+ new boss_valiona();
+
+ new spell_theralion_dazzling_destruction_targeting();
+ new spell_theralion_dazzling_destruction_dummy();
+ new spell_theralion_dazzling_destruction();
+ new spell_theralion_dazzling_destruction_twilight_realm();
+ new spell_theralion_twilight_shift();
+ new spell_theralion_fabulous_flames_targeting();
+ new spell_theralion_engulfing_magic_targeting();
+ new spell_theralion_engulfing_magic();
+
+ new spell_valiona_blackout_dummy();
+ new spell_valiona_blackout();
+ new spell_valiona_devouring_flames_targeting();
+ new spell_valiona_devouring_flames();
+ new spell_valiona_twilight_meteorite_targeting();
+}
diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp b/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp
index 1e212d8583f..306f0b6d7e6 100644
--- a/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp
+++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp
@@ -69,6 +69,8 @@ uint32 HalfusDragonEntries[] =
NPC_ORPHANED_EMERALD_WELP
};
+Position const BreathFlightTargetStalkerSortPos = { -740.677f, -592.328f, 859.455f };
+
class instance_bastion_of_twilight : public InstanceMapScript
{
public:
@@ -126,6 +128,15 @@ class instance_bastion_of_twilight : public InstanceMapScript
if (creature->GetPositionZ() < 850.0f)
_dancingFlamesInvisibleStalkerGUIDs.insert(creature->GetGUID());
break;
+ case NPC_CONVECTIVE_FLAMES:
+ if (Creature* valiona = GetCreature(DATA_VALIONA))
+ valiona->AI()->JustSummoned(creature);
+ break;
+ case NPC_DAZZLING_DESTRUCTION_STALKER:
+ case NPC_FABULOUS_FLAMES:
+ if (Creature* theralion = GetCreature(DATA_THERALION))
+ theralion->AI()->JustSummoned(creature);
+ break;
default:
break;
}
@@ -286,6 +297,29 @@ class instance_bastion_of_twilight : public InstanceMapScript
if (orphanedEmeraldWhelp->GetEntry() == NPC_ORPHANED_EMERALD_WELP)
orphanedEmeraldWhelp->AI()->DoAction(ACTION_MOVE_OUT_OF_CAGE);
break;
+ case DATA_AT_HALFUS_INTRO:
+ if (_lastAreatriggerIndex < AT_INDEX_HALFUS_WYRMBREAKER_INTRO)
+ {
+ _lastAreatriggerIndex = AT_INDEX_HALFUS_WYRMBREAKER_INTRO;
+ SaveToDB();
+ }
+ break;
+ case DATA_AT_THERALION_AND_VALIONA_INTRO:
+ if (_lastAreatriggerIndex < AT_INDEX_THERALION_AND_VALIONA_INTRO)
+ {
+ if (Creature* chogall = GetCreature(DATA_CHOGALL))
+ chogall->AI()->DoAction(ACTION_TALK_INTRO_THERALION_AND_VALIONA);
+
+ if (Creature* theralion = GetCreature(DATA_THERALION))
+ theralion->AI()->DoAction(ACTION_START_ARGUMENT_INTRO);
+
+ if (Creature* valiona = GetCreature(DATA_VALIONA))
+ valiona->AI()->DoAction(ACTION_START_ARGUMENT_INTRO);
+
+ _lastAreatriggerIndex = AT_INDEX_THERALION_AND_VALIONA_INTRO;
+ SaveToDB();
+ }
+ break;
default:
break;
}
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 1b90ffc9bd5..91ced24f25f 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -25,7 +25,9 @@ void AddSC_boss_alizabal(); //Baradin Hold
void AddSC_boss_occuthar();
void AddSC_boss_pit_lord_argaloth();
void AddSC_instance_baradin_hold();
-void AddSC_boss_halfus_wyrmbreaker(); //Bastion of Twilight
+void AddSC_bastion_of_twilight(); //Bastion of Twilight
+void AddSC_boss_halfus_wyrmbreaker();
+void AddSC_boss_theralion_and_valiona();
void AddSC_instance_bastion_of_twilight();
void AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns
void AddSC_boss_corla();
@@ -235,7 +237,9 @@ void AddEasternKingdomsScripts()
AddSC_boss_occuthar();
AddSC_boss_pit_lord_argaloth();
AddSC_instance_baradin_hold();
- AddSC_boss_halfus_wyrmbreaker(); //Bastion of Twilight
+ AddSC_bastion_of_twilight(); //Bastion of Twilight
+ AddSC_boss_halfus_wyrmbreaker();
+ AddSC_boss_theralion_and_valiona();
AddSC_instance_bastion_of_twilight();
AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns
AddSC_boss_corla();