aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt1
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp1732
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp155
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp1183
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h19
6 files changed, 1540 insertions, 1552 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index b486eb45915..3b340f8d147 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -449,6 +449,7 @@ void AddSC_oculus();
void AddSC_boss_malygos(); // The Nexus: Eye of Eternity
void AddSC_instance_eye_of_eternity();
void AddSC_boss_sartharion(); //Obsidian Sanctum
+void AddSC_obsidian_sanctum();
void AddSC_instance_obsidian_sanctum();
void AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning
void AddSC_boss_loken();
@@ -1287,6 +1288,7 @@ void AddNorthrendScripts()
AddSC_boss_malygos(); // The Nexus: Eye of Eternity
AddSC_instance_eye_of_eternity();
AddSC_boss_sartharion(); //Obsidian Sanctum
+ AddSC_obsidian_sanctum();
AddSC_instance_obsidian_sanctum();
AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning
AddSC_boss_loken();
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 3c56361d096..285f8f866cb 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -45,6 +45,7 @@ set(scripts_STAT_SRCS
Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp
Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h
Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
+ Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp
Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h
Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
index 2088ef2fa2e..a212a74df86 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp
@@ -37,9 +37,6 @@ enum Enums
SAY_SARTHARION_SLAY = 8,
WHISPER_LAVA_CHURN = 9,
- WHISPER_HATCH_EGGS = 6,
- WHISPER_OPEN_PORTAL = 6, // whisper, shared by two dragons
-
WHISPER_SHADRON_DICIPLE = 7,
WHISPER_VESPERON_DICIPLE = 7,
@@ -58,70 +55,25 @@ enum Enums
SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes
SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494)
- SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO
- SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura
- SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase
- SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave)
-
- //Mini bosses common spells
- SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase
-
- //Miniboses (Vesperon, Shadron, Tenebron)
- SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster.
- SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster.
-
- SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec.
- SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec.
-
//Vesperon
//In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon
SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%.
- SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988
- SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988
//Shadron
//In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron
SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%.
- SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron
- SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion
- SPELL_VOID_BLAST = 57581, // Twilight Fissure
- SPELL_VOID_BLAST_H = 59128,
//Tenebron
//in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708
SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%.
- //Tenebron, dummy spell
- SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP
- SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP
-
- SPELL_HATCH_EGGS_H = 59189,
- SPELL_HATCH_EGGS = 58542,
- SPELL_HATCH_EGGS_EFFECT_H = 59190,
- SPELL_HATCH_EGGS_EFFECT = 58685,
- NPC_TWILIHT_WHELP = 31214,
- NPC_TWILIGHT_EGG = 30882,
- NPC_SARTHARION_TWILIGHT_EGG = 31204,
-
- //Whelps
- NPC_TWILIGHT_WHELP = 30890,
- NPC_SHARTHARION_TWILIGHT_WHELP = 31214,
- SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s
-
- //flame tsunami
- SPELL_FLAME_TSUNAMI = 57494, // the visual dummy
- SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction
-
- SPELL_FLAME_TSUNAMI_DMG_AURA = 57491, // periodic damage, npc has this aura
- SPELL_FLAME_TSUNAMI_BUFF = 60430,
NPC_FLAME_TSUNAMI = 30616, // for the flame waves
- NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike
//using these custom points for dragons start and end
POINT_ID_INIT = 100,
- POINT_ID_LAND = 200,
+ POINT_ID_LAND = 200
};
enum Misc
@@ -129,25 +81,32 @@ enum Misc
DATA_CAN_LOOT = 0
};
-struct Waypoint
-{
- float m_fX, m_fY, m_fZ;
-};
-
struct Location
{
float x, y, z;
};
-struct Locations
+
+static Location FlameRight1Spawn = { 3200.00f, 573.211f, 57.1551f };
+static Location FlameRight1Direction = { 3289.28f, 573.211f, 57.1551f };
+static Location FlameRight2Spawn = { 3200.00f, 532.211f, 57.1551f };
+static Location FlameRight2Direction = { 3289.28f, 532.211f, 57.1551f };
+static Location FlameRight3Spawn = { 3200.00f, 491.211f, 57.1551f };
+static Location FlameRight3Direction = { 3289.28f, 491.211f, 57.1551f };
+static Location FlameLeft1Spawn = { 3289.28f, 511.711f, 57.1551f };
+static Location FlameLeft1Direction = { 3200.00f, 511.711f, 57.1551f };
+static Location FlameLeft2Spawn = { 3289.28f, 552.711f, 57.1551f };
+static Location FlameLeft2Direction = { 3200.00f, 552.711f, 57.1551f };
+
+struct Waypoint
{
- float x, y, z;
+ float m_fX, m_fY, m_fZ;
};
//each dragons special points. First where fly to before connect to connon, second where land point is.
Waypoint m_aTene[]=
{
- {3212.854f, 575.597f, 109.856f}, //init
- {3246.425f, 565.367f, 61.249f} //end
+ {3212.854f, 575.597f, 109.856f}, // init
+ {3246.425f, 565.367f, 61.249f} // end
};
Waypoint m_aShad[]=
@@ -162,54 +121,19 @@ Waypoint m_aVesp[]=
{3227.268f, 533.238f, 59.995f}
};
-#define MAX_WAYPOINT 6
-//points around raid "isle", counter clockwise. should probably be adjusted to be more alike
-Waypoint m_aDragonCommon[MAX_WAYPOINT]=
+enum SartharionEvents
{
- {3214.012f, 468.932f, 98.652f},
- {3244.950f, 468.427f, 98.652f},
- {3283.520f, 496.869f, 98.652f},
- {3287.316f, 555.875f, 98.652f},
- {3250.479f, 585.827f, 98.652f},
- {3209.969f, 566.523f, 98.652f}
+ EVENT_HARD_ENRAGE = 1,
+ EVENT_FLAME_TSUNAMI = 2,
+ EVENT_FLAME_BREATH = 3,
+ EVENT_TAIL_SWEEP = 4,
+ EVENT_CLEAVE_ATTACK = 5,
+ EVENT_LAVA_STRIKE = 6,
+ EVENT_CALL_TENEBRON = 7,
+ EVENT_CALL_SHADRON = 8,
+ EVENT_CALL_VESPERON = 9
};
-static Location FlameRight1Spawn = { 3200.00f, 573.211f, 57.1551f };
-static Location FlameRight1Direction = { 3289.28f, 573.211f, 57.1551f };
-static Location FlameRight2Spawn = { 3200.00f, 532.211f, 57.1551f };
-static Location FlameRight2Direction = { 3289.28f, 532.211f, 57.1551f };
-static Location FlameRight3Spawn = { 3200.00f, 491.211f, 57.1551f };
-static Location FlameRight3Direction = { 3289.28f, 491.211f, 57.1551f };
-static Location FlameLeft1Spawn = { 3289.28f, 511.711f, 57.1551f };
-static Location FlameLeft1Direction = { 3200.00f, 511.711f, 57.1551f };
-static Location FlameLeft2Spawn = { 3289.28f, 552.711f, 57.1551f };
-static Location FlameLeft2Direction = { 3200.00f, 552.711f, 57.1551f };
-
-static Location AcolyteofShadron = { 3363.92f, 534.703f, 97.2683f };
-static Location AcolyteofShadron2 = { 3246.57f, 551.263f, 58.6164f };
-static Location AcolyteofVesperon = { 3145.68f, 520.71f, 89.7f };
-static Location AcolyteofVesperon2 = { 3246.57f, 551.263f, 58.6164f };
-Locations TwilightEggs[] =
-{
- {3219.28f, 669.121f, 88.5549f},
- {3221.55f, 682.852f, 90.5361f},
- {3239.77f, 685.94f, 90.3168f},
- {3250.33f, 669.749f, 88.7637f},
- {3246.6f, 642.365f, 84.8752f},
- {3233.68f, 653.117f, 85.7051f}
-};
-Locations TwilightEggsSarth[] =
-{
- {3252.73f, 515.762f, 58.5501f},
- {3256.56f, 521.119f, 58.6061f},
- {3255.63f, 527.513f, 58.7568f},
- {3264.90f, 525.865f, 58.6436f},
- {3264.26f, 516.364f, 58.8011f},
- {3257.54f, 502.285f, 58.2077f}
-};
-
-#define TWILIGHT_ACHIEVEMENTS 1
-
/*######
## Boss Sartharion
######*/
@@ -219,169 +143,71 @@ class boss_sartharion : public CreatureScript
public:
boss_sartharion() : CreatureScript("boss_sartharion") { }
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new boss_sartharionAI(creature);
- }
-
- struct boss_sartharionAI : public ScriptedAI
+ struct boss_sartharionAI : public BossAI
{
- boss_sartharionAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
-
- bool m_bIsBerserk;
- bool m_bIsSoftEnraged;
-
- uint32 m_uiEnrageTimer;
- bool m_bIsHardEnraged;
-
- uint32 m_uiTenebronTimer;
- uint32 m_uiShadronTimer;
- uint32 m_uiVesperonTimer;
-
- uint32 m_uiFlameTsunamiTimer;
- uint32 m_uiFlameBreathTimer;
- uint32 m_uiTailSweepTimer;
- uint32 m_uiCleaveTimer;
- uint32 m_uiLavaStrikeTimer;
-
- bool m_bHasCalledTenebron;
- bool m_bHasCalledShadron;
- bool m_bHasCalledVesperon;
-
- uint8 drakeCount;
+ boss_sartharionAI(Creature* creature) : BossAI(creature, DATA_SARTHARION) { }
void Reset() OVERRIDE
{
- m_bIsBerserk = false;
- m_bIsSoftEnraged = false;
-
- m_uiEnrageTimer = 15*MINUTE*IN_MILLISECONDS;
- m_bIsHardEnraged = false;
-
- m_uiTenebronTimer = 30000;
- m_uiShadronTimer = 75000;
- m_uiVesperonTimer = 120000;
-
- m_uiFlameTsunamiTimer = 30000;
- m_uiFlameBreathTimer = 20000;
- m_uiTailSweepTimer = 20000;
- m_uiCleaveTimer = 7000;
- m_uiLavaStrikeTimer = 5000;
-
- m_bHasCalledTenebron = false;
- m_bHasCalledShadron = false;
- m_bHasCalledVesperon = false;
+ _isBerserk = false;
+ _isSoftEnraged = false;
+ _isHardEnraged = false;
+ drakeCount = 0;
if (me->HasAura(SPELL_TWILIGHT_REVENGE))
me->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE);
me->SetHomePosition(3246.57f, 551.263f, 58.6164f, 4.66003f);
- drakeCount = 0;
-
- // Drakes respawning system
if (instance)
{
- Creature* pTenebron = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON));
- Creature* pShadron = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON));
- Creature* pVesperon = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON));
- if (pTenebron)
- {
- pTenebron->SetHomePosition(3239.07f, 657.235f, 86.8775f, 4.74729f);
- if (pTenebron->IsAlive())
- {
- if (pTenebron->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pTenebron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- pTenebron->GetMotionMaster()->MoveTargetedHome();
- }else
- {
- if (instance->GetData(TYPE_TENEBRON_PREKILLED) == false)
- {
- pTenebron->Respawn();
- pTenebron->GetMotionMaster()->MoveTargetedHome();
- pTenebron->AI()->SetData(DATA_CAN_LOOT, 0);
- }
- }
- }
- if (pShadron)
- {
- pShadron->SetHomePosition(3363.06f, 525.28f, 98.362f, 4.76475f);
- if (pShadron->IsAlive())
- {
- if (pShadron->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pShadron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- pShadron->GetMotionMaster()->MoveTargetedHome();
- }else
- {
- if (instance->GetData(TYPE_SHADRON_PREKILLED) == false)
- {
- pShadron->Respawn();
- pShadron->GetMotionMaster()->MoveTargetedHome();
- pShadron->AI()->SetData(DATA_CAN_LOOT, 0);
- }
- }
- }
- if (pVesperon)
- {
- pVesperon->SetHomePosition(3145.68f, 520.71f, 89.7f, 4.64258f);
- if (pVesperon->IsAlive())
- {
- if (pVesperon->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pVesperon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- pVesperon->GetMotionMaster()->MoveTargetedHome();
- }else
- {
- if (instance->GetData(TYPE_VESPERON_PREKILLED) == false)
- {
- pVesperon->Respawn();
- pVesperon->GetMotionMaster()->MoveTargetedHome();
- pVesperon->AI()->SetData(DATA_CAN_LOOT, 0);
- }
- }
- }
+ DrakeRespawn();
+ instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED);
}
}
void JustReachedHome() OVERRIDE
{
- if (instance)
- instance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED);
+ _Reset();
}
void EnterCombat(Unit* /*who*/) OVERRIDE
{
Talk(SAY_SARTHARION_AGGRO);
+ _EnterCombat();
DoZoneInCombat();
if (instance)
- {
- instance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS);
FetchDragons();
- }
+
+ events.ScheduleEvent(EVENT_LAVA_STRIKE, 5000);
+ events.ScheduleEvent(EVENT_CLEAVE_ATTACK, 7000);
+ events.ScheduleEvent(EVENT_FLAME_BREATH, 20000);
+ events.ScheduleEvent(EVENT_TAIL_SWEEP, 20000);
+ events.ScheduleEvent(EVENT_FLAME_TSUNAMI, 30000);
+ events.ScheduleEvent(EVENT_CALL_TENEBRON, 30000);
+ events.ScheduleEvent(EVENT_CALL_SHADRON, 75000);
+ events.ScheduleEvent(EVENT_CALL_VESPERON, 120000);
}
void JustDied(Unit* /*killer*/) OVERRIDE
{
Talk(SAY_SARTHARION_DEATH);
+ _JustDied();
if (instance)
{
- Creature* pTenebron = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON));
- Creature* pShadron = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON));
- Creature* pVesperon = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON));
- if (pTenebron && pTenebron->IsAlive())
- pTenebron->DisappearAndDie();
- if (pShadron && pShadron->IsAlive())
- pShadron->DisappearAndDie();
- if (pVesperon && pVesperon->IsAlive())
- pVesperon->DisappearAndDie();
-
- instance->SetData(TYPE_SARTHARION_EVENT, DONE);
+ if (Creature* tenebron = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON)))
+ if (tenebron->IsAlive())
+ tenebron->DisappearAndDie();
+
+ if (Creature* shadron = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON)))
+ if (shadron->IsAlive())
+ shadron->DisappearAndDie();
+
+ if (Creature* vesperon = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON)))
+ if (vesperon->IsAlive())
+ vesperon->DisappearAndDie();
}
}
@@ -402,83 +228,140 @@ public:
me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode
}
- uint32 GetData(uint32 type) const OVERRIDE
+ void DrakeRespawn() // Drakes respawning system
{
- if (type == TWILIGHT_ACHIEVEMENTS)
- return drakeCount;
+ if (Creature* tenebron = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON)))
+ {
+ tenebron->SetHomePosition(3239.07f, 657.235f, 86.8775f, 4.74729f);
+ if (tenebron->IsAlive())
+ {
+ if (tenebron->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ tenebron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ tenebron->GetMotionMaster()->MoveTargetedHome();
+ }
+ else
+ {
+ if (instance->GetBossState(DATA_TENEBRON) != DONE)
+ {
+ tenebron->Respawn();
+ tenebron->GetMotionMaster()->MoveTargetedHome();
+ tenebron->AI()->SetData(DATA_CAN_LOOT, 0);
+ }
+ }
+ }
- return 0;
+ if (Creature* shadron = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON)))
+ {
+ shadron->SetHomePosition(3363.06f, 525.28f, 98.362f, 4.76475f);
+ if (shadron->IsAlive())
+ {
+ if (shadron->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ shadron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ shadron->GetMotionMaster()->MoveTargetedHome();
+ }
+ else
+ {
+ if (instance->GetBossState(DATA_SHADRON) != DONE)
+ {
+ shadron->Respawn();
+ shadron->GetMotionMaster()->MoveTargetedHome();
+ shadron->AI()->SetData(DATA_CAN_LOOT, 0);
+ }
+ }
+ }
+
+ if (Creature* vesperon = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON)))
+ {
+ vesperon->SetHomePosition(3145.68f, 520.71f, 89.7f, 4.64258f);
+ if (vesperon->IsAlive())
+ {
+ if (vesperon->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ vesperon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ vesperon->GetMotionMaster()->MoveTargetedHome();
+ }
+ else
+ {
+ if (instance->GetBossState(DATA_VESPERON) != DONE)
+ {
+ vesperon->Respawn();
+ vesperon->GetMotionMaster()->MoveTargetedHome();
+ vesperon->AI()->SetData(DATA_CAN_LOOT, 0);
+ }
+ }
+ }
}
void FetchDragons()
{
- if (!instance)
- return;
-
me->ResetLootMode();
drakeCount = 0;
- Creature* pFetchTene = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON));
- Creature* pFetchShad = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON));
- Creature* pFetchVesp = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON));
-
//if at least one of the dragons are alive and are being called
- bool bCanUseWill = false;
+ bool _canUseWill = false;
- if (pFetchTene && pFetchTene->IsAlive() && !pFetchTene->GetVictim())
+ if (Creature* fetchTene = Unit::GetCreature(*me, instance->GetData64(DATA_TENEBRON)))
{
- bCanUseWill = true;
- if (!pFetchTene->IsInCombat())
+ if (fetchTene->IsAlive() && !fetchTene->GetVictim())
{
- DoCast(me, SPELL_POWER_OF_TENEBRON);
- AddDrakeLootMode();
- ++drakeCount;
- }
- pFetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ);
+ _canUseWill = true;
+ if (!fetchTene->IsInCombat())
+ {
+ DoCast(me, SPELL_POWER_OF_TENEBRON);
+ AddDrakeLootMode();
+ ++drakeCount;
+ }
+ fetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ);
- if (!pFetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pFetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if (!fetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ fetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
}
- if (pFetchShad && pFetchShad->IsAlive() && !pFetchShad->GetVictim())
+ if (Creature* fetchShad = Unit::GetCreature(*me, instance->GetData64(DATA_SHADRON)))
{
- bCanUseWill = true;
- if (!pFetchShad->IsInCombat())
+ if (fetchShad->IsAlive() && !fetchShad->GetVictim())
{
- DoCast(me, SPELL_POWER_OF_SHADRON);
- AddDrakeLootMode();
- ++drakeCount;
- }
- pFetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ);
+ _canUseWill = true;
+ if (!fetchShad->IsInCombat())
+ {
+ DoCast(me, SPELL_POWER_OF_SHADRON);
+ AddDrakeLootMode();
+ ++drakeCount;
+ }
+ fetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ);
- if (!pFetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pFetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if (!fetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ fetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
}
- if (pFetchVesp && pFetchVesp->IsAlive() && !pFetchVesp->GetVictim())
+ if (Creature* fetchVesp = Unit::GetCreature(*me, instance->GetData64(DATA_VESPERON)))
{
- bCanUseWill = true;
- if (!pFetchVesp->IsInCombat())
+ if (fetchVesp && fetchVesp->IsAlive() && !fetchVesp->GetVictim())
{
- DoCast(me, SPELL_POWER_OF_VESPERON);
- AddDrakeLootMode();
- ++drakeCount;
- }
- pFetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ);
+ _canUseWill = true;
+ if (!fetchVesp->IsInCombat())
+ {
+ DoCast(me, SPELL_POWER_OF_VESPERON);
+ AddDrakeLootMode();
+ ++drakeCount;
+ }
+ fetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ);
- if (!pFetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- pFetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if (!fetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ fetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
}
- if (bCanUseWill)
+ if (_canUseWill)
DoCast(me, SPELL_WILL_OF_SARTHARION);
}
- void CallDragon(uint32 uiDataId)
+ void CallDragon(uint32 dataId)
{
if (instance)
{
- if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(uiDataId)))
+ if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(dataId)))
{
if (temp->IsAlive() && !temp->GetVictim())
{
@@ -487,33 +370,41 @@ public:
if (temp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- int32 iTextId = 0;
+ int32 textId = 0;
switch (temp->GetEntry())
{
case NPC_TENEBRON:
- iTextId = SAY_SARTHARION_CALL_TENEBRON;
+ textId = SAY_SARTHARION_CALL_TENEBRON;
temp->AddAura(SPELL_POWER_OF_TENEBRON, temp);
temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ);
break;
case NPC_SHADRON:
- iTextId = SAY_SARTHARION_CALL_SHADRON;
+ textId = SAY_SARTHARION_CALL_SHADRON;
temp->AddAura(SPELL_POWER_OF_SHADRON, temp);
temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ);
break;
case NPC_VESPERON:
- iTextId = SAY_SARTHARION_CALL_VESPERON;
+ textId = SAY_SARTHARION_CALL_VESPERON;
temp->AddAura(SPELL_POWER_OF_VESPERON, temp);
temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ);
break;
}
- Talk(iTextId);
+ Talk(textId);
}
}
}
}
+ uint32 GetData(uint32 type) const OVERRIDE
+ {
+ if (type == TWILIGHT_ACHIEVEMENTS)
+ return drakeCount;
+
+ return 0;
+ }
+
void SendFlameTsunami()
{
if (Map* map = me->GetMap())
@@ -532,16 +423,16 @@ public:
// FIXME: Frequency of the casts reduced to compensate 100% chance of spawning a Lava Blaze add
void CastLavaStrikeOnTarget(Unit* target)
{
- std::list<Creature*> pFireCyclonesList;
+ std::list<Creature*> fireCyclonesList;
Trinity::AllCreaturesOfEntryInRange checker(me, NPC_FIRE_CYCLONE, 200.0f);
- Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, pFireCyclonesList, checker);
+ Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, fireCyclonesList, checker);
me->VisitNearbyObject(200.0f, searcher);
- if (pFireCyclonesList.empty())
+ if (fireCyclonesList.empty())
return;
- std::list<Creature*>::iterator itr = pFireCyclonesList.begin();
- uint32 rnd = rand()%pFireCyclonesList.size();
+ std::list<Creature*>::iterator itr = fireCyclonesList.begin();
+ uint32 rnd = rand()%fireCyclonesList.size();
for (uint32 i = 0; i < rnd; ++i)
++itr;
@@ -549,1224 +440,121 @@ public:
(*itr)->CastSpell(target, SPELL_LAVA_STRIKE, true);
}
- void UpdateAI(uint32 uiDiff) OVERRIDE
+ void UpdateAI(uint32 diff) OVERRIDE
{
- //Return since we have no target
if (!UpdateVictim())
return;
- Unit* pTene = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_TENEBRON) : 0);
- Unit* pShad = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_SHADRON) : 0);
- Unit* pVesp = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_VESPERON) : 0);
-
- //spell will target dragons, if they are still alive at 35%
- if (!m_bIsBerserk && !HealthAbovePct(35)
- && ((pTene && pTene->IsAlive()) || (pShad && pShad->IsAlive()) || (pVesp && pVesp->IsAlive())))
- {
- Talk(SAY_SARTHARION_BERSERK);
- DoCast(me, SPELL_BERSERK);
- m_bIsBerserk = true;
- }
+ events.Update(diff);
- //soft enrage
- if (!m_bIsSoftEnraged && HealthBelowPct(10))
+ while (uint32 eventId = events.ExecuteEvent())
{
- // m_bIsSoftEnraged is used while determining Lava Strike cooldown.
- m_bIsSoftEnraged = true;
- }
-
- // hard enrage
- if (!m_bIsHardEnraged)
- {
- if (m_uiEnrageTimer <= uiDiff)
+ switch (eventId)
{
- DoCast(me, SPELL_PYROBUFFET, true);
- m_bIsHardEnraged = true;
- }
- else
- m_uiEnrageTimer -= uiDiff;
- }
-
- // flame tsunami
- if (m_uiFlameTsunamiTimer <= uiDiff)
- {
- SendFlameTsunami();
- switch (urand(0, 1))
- {
- case 0:
- {
- Creature* Right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y, FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000);
- Creature* Right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y, FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000);
- Creature* Right3 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight3Spawn.x, FlameRight3Spawn.y, FlameRight3Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000);
- Right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z);
- Right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z);
- Right3->GetMotionMaster()->MovePoint(0, FlameRight3Direction.x, FlameRight3Direction.y, FlameRight3Direction.z);
+ case EVENT_HARD_ENRAGE:
+ if (!_isHardEnraged)
+ {
+ DoCast(me, SPELL_PYROBUFFET, true);
+ _isHardEnraged = true;
+ }
break;
- }
- case 1:
- {
- Creature* Left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y, FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000);
- Creature* Left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y, FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000);
- Left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z);
- Left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z);
+ case EVENT_FLAME_TSUNAMI:
+ SendFlameTsunami();
+ switch (urand(0, 1))
+ {
+ case 0:
+ {
+ if (Creature* right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y, FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000))
+ right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z);
+ if (Creature* right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y, FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000))
+ right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z);
+ if (Creature* right3 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight3Spawn.x, FlameRight3Spawn.y, FlameRight3Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000))
+ right3->GetMotionMaster()->MovePoint(0, FlameRight3Direction.x, FlameRight3Direction.y, FlameRight3Direction.z);
+ break;
+ }
+ case 1:
+ {
+ if (Creature* left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y, FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000))
+ left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z);
+ if (Creature* left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y, FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN, 12000))
+ left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z);
+ break;
+ }
+ }
+ events.ScheduleEvent(EVENT_FLAME_TSUNAMI, 30000);
break;
- }
- }
-
- m_uiFlameTsunamiTimer = 30000;
- }
- else
- m_uiFlameTsunamiTimer -= uiDiff;
-
- // flame breath
- if (m_uiFlameBreathTimer <= uiDiff)
- {
- Talk(SAY_SARTHARION_BREATH);
- DoCastVictim(RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H));
- m_uiFlameBreathTimer = urand(25000, 35000);
- }
- else
- m_uiFlameBreathTimer -= uiDiff;
-
- // Tail Sweep
- if (m_uiTailSweepTimer <= uiDiff)
- {
- DoCastVictim(RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H));
- m_uiTailSweepTimer = urand(15000, 20000);
- }
- else
- m_uiTailSweepTimer -= uiDiff;
-
- // Cleave
- if (m_uiCleaveTimer <= uiDiff)
- {
- DoCastVictim(SPELL_CLEAVE);
- m_uiCleaveTimer = urand(7000, 10000);
- }
- else
- m_uiCleaveTimer -= uiDiff;
-
- // Lavas Strike
- if (m_uiLavaStrikeTimer <= uiDiff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- {
- CastLavaStrikeOnTarget(target);
-
- if (urand(0, 5) == 0)
- Talk(SAY_SARTHARION_SPECIAL);
- }
- m_uiLavaStrikeTimer = (m_bIsSoftEnraged ? urand(1400, 2000) : urand(5000, 20000));
- }
- else
- m_uiLavaStrikeTimer -= uiDiff;
-
- // call tenebron
- if (!m_bHasCalledTenebron && m_uiTenebronTimer <= uiDiff)
- {
- CallDragon(DATA_TENEBRON);
- m_bHasCalledTenebron = true;
- }
- else
- m_uiTenebronTimer -= uiDiff;
-
- // call shadron
- if (!m_bHasCalledShadron && m_uiShadronTimer <= uiDiff)
- {
- CallDragon(DATA_SHADRON);
- m_bHasCalledShadron = true;
- }
- else
- m_uiShadronTimer -= uiDiff;
-
- // call vesperon
- if (!m_bHasCalledVesperon && m_uiVesperonTimer <= uiDiff)
- {
- CallDragon(DATA_VESPERON);
- m_bHasCalledVesperon = true;
- }
- else
- m_uiVesperonTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
-
- EnterEvadeIfOutOfCombatArea(uiDiff);
- }
- };
-
-};
-
-enum TeneText
-{
- SAY_TENEBRON_AGGRO = 0,
- SAY_TENEBRON_SLAY = 1,
- SAY_TENEBRON_DEATH = 2,
- SAY_TENEBRON_BREATH = 3,
- SAY_TENEBRON_RESPOND = 4,
- SAY_TENEBRON_SPECIAL = 5
-};
-
-enum ShadText
-{
- SAY_SHADRON_AGGRO = 0,
- SAY_SHADRON_SLAY = 1,
- SAY_SHADRON_DEATH = 2,
- SAY_SHADRON_BREATH = 3,
- SAY_SHADRON_RESPOND = 4,
- SAY_SHADRON_SPECIAL = 5
-};
-
-enum VespText
-{
- SAY_VESPERON_AGGRO = 0,
- SAY_VESPERON_SLAY = 1,
- SAY_VESPERON_DEATH = 2,
- SAY_VESPERON_BREATH = 3,
- SAY_VESPERON_RESPOND = 4,
- SAY_VESPERON_SPECIAL = 5,
-};
-
-//to control each dragons common abilities
-struct dummy_dragonAI : public ScriptedAI
-{
- dummy_dragonAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
-
- uint32 m_uiWaypointId;
- uint32 m_uiMoveNextTimer;
- int32 m_iPortalRespawnTime;
- bool m_bCanMoveFree;
- bool m_bCanLoot;
-
- void Reset() OVERRIDE
- {
- if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
- m_uiWaypointId = 0;
- m_uiMoveNextTimer = 500;
- m_iPortalRespawnTime = 30000;
- m_bCanMoveFree = false;
- m_bCanLoot = true;
- }
-
- void SetData(uint32 type, uint32 value) OVERRIDE
- {
- if (type == DATA_CAN_LOOT)
- m_bCanLoot = value;
- }
-
- void MovementInform(uint32 uiType, uint32 uiPointId) OVERRIDE
- {
- if (!instance || uiType != POINT_MOTION_TYPE)
- return;
-
-// debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId);
-
- //if healers messed up the raid and we was already initialized
- if (instance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS)
- {
- EnterEvadeMode();
- return;
- }
-
- //this is end, if we reach this, don't do much
- if (uiPointId == POINT_ID_LAND)
- {
- me->GetMotionMaster()->Clear();
- me->SetInCombatWithZone();
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
- {
- me->AddThreat(target, 1.0f);
- me->Attack(target, true);
- me->GetMotionMaster()->MoveChase(target);
- }
-
- m_bCanMoveFree = false;
- return;
- }
-
- //get amount of common points
- uint32 uiCommonWPCount = sizeof(m_aDragonCommon)/sizeof(Waypoint);
-
- //increase
- m_uiWaypointId = uiPointId+1;
-
- //if we have reached a point bigger or equal to count, it mean we must reset to point 0
- if (m_uiWaypointId >= uiCommonWPCount)
- {
- if (!m_bCanMoveFree)
- m_bCanMoveFree = true;
-
- m_uiWaypointId = 0;
- }
-
- m_uiMoveNextTimer = 500;
- }
-
- //used when open portal and spawn mobs in phase
- void DoRaidWhisper(int32 iTextId)
- {
- Map* map = me->GetMap();
-
- if (map && map->IsDungeon())
- {
- Map::PlayerList const &PlayerList = map->GetPlayers();
-
- if (!PlayerList.isEmpty())
- {
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- Talk(iTextId, i->GetSource()->GetGUID());
- }
- }
- }
-
- //"opens" the portal and does the "opening" whisper
- void OpenPortal()
- {
- int32 iTextId = 0;
-
- //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database
-
- //using a grid search here seem to be more efficient than caching all four guids
- //in instance script and calculate range to each.
- GameObject* pPortal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL, 50.0f);
-
- switch (me->GetEntry())
- {
- case NPC_TENEBRON:
- {
- iTextId = WHISPER_HATCH_EGGS;
- if (instance && !instance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS)
- {
- for (uint32 i = 0; i < 6; ++i)
- me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[i].x, TwilightEggs[i].y, TwilightEggs[i].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
- }
- else
- {
- for (uint32 i = 0; i < 6; ++i)
- me->SummonCreature(NPC_SARTHARION_TWILIGHT_EGG, TwilightEggsSarth[i].x, TwilightEggsSarth[i].y, TwilightEggsSarth[i].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
- }
- break;
- }
- case NPC_SHADRON:
- {
- iTextId = WHISPER_OPEN_PORTAL;
- if (instance && !instance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS)
- me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y, AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
- else
- me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y, AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
-
- break;
- }
- case NPC_VESPERON:
- {
- iTextId = WHISPER_OPEN_PORTAL;
- if (instance && !instance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS)
- {
- if (Creature* Acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y, AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
- {
- me->InterruptNonMeleeSpells(true);
- Acolyte->InterruptNonMeleeSpells(true);
- me->CastSpell(me, 32747, false);
- }
- }
- else
- {
- if (Creature* Acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y, AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
- {
- me->InterruptNonMeleeSpells(true);
- Acolyte->InterruptNonMeleeSpells(true);
- me->CastSpell(me, 32747, false);
- }
- }
-
- break;
- }
- }
-
- DoRaidWhisper(iTextId);
-
- //By using SetRespawnTime() we will actually "spawn" the object with our defined time.
- //Once time is up, portal will disappear again.
- if (pPortal && !pPortal->isSpawned())
- pPortal->SetRespawnTime(m_iPortalRespawnTime);
-
- //Unclear what are expected to happen if one drake has a portal open already
- //Refresh respawnTime so time again are set to 30secs?
- }
-
- void JustDied(Unit* /*killer*/) OVERRIDE
- {
- if (!m_bCanLoot)
- me->SetLootRecipient(NULL);
-
- int32 iTextId = 0;
- uint32 uiSpellId = 0;
-
- switch (me->GetEntry())
- {
- case NPC_TENEBRON:
- iTextId = SAY_TENEBRON_DEATH;
- uiSpellId = SPELL_POWER_OF_TENEBRON;
- if (instance && instance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS)
- instance->SetData(TYPE_TENEBRON_PREKILLED, 1);
- break;
- case NPC_SHADRON:
- iTextId = SAY_SHADRON_DEATH;
- uiSpellId = SPELL_POWER_OF_SHADRON;
- if (instance && instance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS)
- instance->SetData(TYPE_SHADRON_PREKILLED, 1);
- if (Creature* pAcolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_SHADRON, 100.0f))
- pAcolyte->Kill(pAcolyte);
- break;
- case NPC_VESPERON:
- iTextId = SAY_VESPERON_DEATH;
- uiSpellId = SPELL_POWER_OF_VESPERON;
- if (instance && instance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS)
- instance->SetData(TYPE_VESPERON_PREKILLED, 1);
- if (Creature* pAcolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_VESPERON, 100.0f))
- pAcolyte->Kill(pAcolyte);
- break;
- }
-
- Talk(iTextId);
-
- me->RemoveAurasDueToSpell(uiSpellId);
-
- if (instance)
- {
- instance->DoRemoveAurasDueToSpellOnPlayers(uiSpellId);
-
- // not if solo mini-boss fight
- if (instance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS)
- return;
-
- // Twilight Revenge to main boss
- if (Unit* pSartharion = Unit::GetUnit(*me, instance->GetData64(DATA_SARTHARION)))
- if (pSartharion->IsAlive())
- {
- pSartharion->RemoveAurasDueToSpell(uiSpellId);
- DoCast(pSartharion, SPELL_TWILIGHT_REVENGE, true);
- }
- }
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- if (m_bCanMoveFree && m_uiMoveNextTimer)
- {
- if (m_uiMoveNextTimer <= uiDiff)
- {
- if (m_uiWaypointId < MAX_WAYPOINT)
- me->GetMotionMaster()->MovePoint(m_uiWaypointId,
- m_aDragonCommon[m_uiWaypointId].m_fX, m_aDragonCommon[m_uiWaypointId].m_fY, m_aDragonCommon[m_uiWaypointId].m_fZ);
-
-// debug_log("dummy_dragonAI: %s moving to point %u", me->GetName(), m_uiWaypointId);
- m_uiMoveNextTimer = 0;
- }
- else
- m_uiMoveNextTimer -= uiDiff;
- }
- }
-};
-
-/*######
-## Mob Tenebron
-######*/
-
-class npc_tenebron : public CreatureScript
-{
-public:
- npc_tenebron() : CreatureScript("npc_tenebron") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_tenebronAI(creature);
- }
-
- struct npc_tenebronAI : public dummy_dragonAI
- {
- npc_tenebronAI(Creature* creature) : dummy_dragonAI(creature) { }
-
- uint32 m_uiShadowBreathTimer;
- uint32 m_uiShadowFissureTimer;
- uint32 m_uiHatchEggTimer;
-
- bool m_bHasPortalOpen;
-
- void Reset() OVERRIDE
- {
- dummy_dragonAI::Reset();
-
- m_uiShadowBreathTimer = 20000;
- m_uiShadowFissureTimer = 5000;
- m_uiHatchEggTimer = 30000;
-
- m_bHasPortalOpen = false;
- }
-
- void EnterCombat(Unit* /*who*/) OVERRIDE
- {
- Talk(SAY_TENEBRON_AGGRO);
- DoZoneInCombat();
- }
-
- void KilledUnit(Unit* /*victim*/) OVERRIDE
- {
- Talk(SAY_TENEBRON_SLAY);
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- //if no target, update dummy and return
- if (!UpdateVictim())
- {
- dummy_dragonAI::UpdateAI(uiDiff);
- return;
- }
-
- // shadow fissure
- if (m_uiShadowFissureTimer <= uiDiff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE));
-
- m_uiShadowFissureTimer = urand(15000, 20000);
- }
- else
- m_uiShadowFissureTimer -= uiDiff;
-
- // Hatch Egg
- if (m_uiHatchEggTimer <= uiDiff)
- {
- OpenPortal();
- m_uiHatchEggTimer = 30000;
- }
- else
- m_uiHatchEggTimer -= uiDiff;
-
- // shadow breath
- if (m_uiShadowBreathTimer <= uiDiff)
- {
- Talk(SAY_TENEBRON_BREATH);
- DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
- m_uiShadowBreathTimer = urand(20000, 25000);
- }
- else
- m_uiShadowBreathTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## Mob Shadron
-######*/
-
-class npc_shadron : public CreatureScript
-{
-public:
- npc_shadron() : CreatureScript("npc_shadron") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_shadronAI(creature);
- }
-
- struct npc_shadronAI : public dummy_dragonAI
- {
- npc_shadronAI(Creature* creature) : dummy_dragonAI(creature) { }
-
- uint32 m_uiShadowBreathTimer;
- uint32 m_uiShadowFissureTimer;
- uint32 m_uiAcolyteShadronTimer;
-
- bool m_bHasPortalOpen;
-
- void Reset() OVERRIDE
- {
- dummy_dragonAI::Reset();
-
- m_uiShadowBreathTimer = 20000;
- m_uiShadowFissureTimer = 5000;
- m_uiAcolyteShadronTimer = 60000;
-
- if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP))
- me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
-
- if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
- me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA);
-
- m_bHasPortalOpen = false;
- }
-
- void EnterCombat(Unit* /*who*/) OVERRIDE
- {
- Talk(SAY_SHADRON_AGGRO);
- DoZoneInCombat();
- }
-
- void KilledUnit(Unit* /*victim*/) OVERRIDE
- {
- Talk(SAY_SHADRON_SLAY);
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- //if no target, update dummy and return
- if (!UpdateVictim())
- {
- dummy_dragonAI::UpdateAI(uiDiff);
- return;
- }
-
- // shadow fissure
- if (m_uiShadowFissureTimer <= uiDiff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H));
-
- m_uiShadowFissureTimer = urand(15000, 20000);
- }
- else
- m_uiShadowFissureTimer -= uiDiff;
-
- // Portal Event
- if (m_uiAcolyteShadronTimer <= uiDiff)
- {
- if (m_bHasPortalOpen)
- m_uiAcolyteShadronTimer = 10000;
- else
- {
- if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
- return;
-
- OpenPortal();
- m_bHasPortalOpen = true;
- m_uiAcolyteShadronTimer = urand(60000, 65000);
- }
- }
- else
- m_uiAcolyteShadronTimer -= uiDiff;
-
- // shadow breath
- if (m_uiShadowBreathTimer <= uiDiff)
- {
- Talk(SAY_SHADRON_BREATH);
- DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
- m_uiShadowBreathTimer = urand(20000, 25000);
- }
- else
- m_uiShadowBreathTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## Mob Vesperon
-######*/
-
-class npc_vesperon : public CreatureScript
-{
-public:
- npc_vesperon() : CreatureScript("npc_vesperon") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_vesperonAI(creature);
- }
-
- struct npc_vesperonAI : public dummy_dragonAI
- {
- npc_vesperonAI(Creature* creature) : dummy_dragonAI(creature) { }
-
- uint32 m_uiShadowBreathTimer;
- uint32 m_uiShadowFissureTimer;
- uint32 m_uiAcolyteVesperonTimer;
-
- bool m_bHasPortalOpen;
-
- void Reset() OVERRIDE
- {
- dummy_dragonAI::Reset();
-
- m_uiShadowBreathTimer = 20000;
- m_uiShadowFissureTimer = 5000;
- m_uiAcolyteVesperonTimer = 60000;
-
- m_bHasPortalOpen = false;
- }
-
- void EnterCombat(Unit* /*who*/) OVERRIDE
- {
- Talk(SAY_VESPERON_AGGRO);
- DoZoneInCombat();
- }
-
- void KilledUnit(Unit* /*victim*/) OVERRIDE
- {
- Talk(SAY_VESPERON_SLAY);
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- //if no target, update dummy and return
- if (!UpdateVictim())
- {
- dummy_dragonAI::UpdateAI(uiDiff);
- return;
- }
-
- // shadow fissure
- if (m_uiShadowFissureTimer <= uiDiff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H));
-
- m_uiShadowFissureTimer = urand(15000, 20000);
- }
- else
- m_uiShadowFissureTimer -= uiDiff;
-
- // Portal Event
- if (m_uiAcolyteVesperonTimer <= uiDiff)
- {
- if (m_bHasPortalOpen)
- m_uiAcolyteVesperonTimer = 10000;
- else
- {
- OpenPortal();
- DoCastVictim(SPELL_TWILIGHT_TORMENT_VESP);
- m_uiAcolyteVesperonTimer = urand(60000, 70000);
- }
- }
- else
- m_uiAcolyteVesperonTimer -= uiDiff;
-
- // shadow breath
- if (m_uiShadowBreathTimer <= uiDiff)
- {
- Talk(SAY_VESPERON_BREATH);
- DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
- m_uiShadowBreathTimer = urand(20000, 25000);
- }
- else
- m_uiShadowBreathTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## Mob Acolyte of Shadron
-######*/
-
-class npc_acolyte_of_shadron : public CreatureScript
-{
-public:
- npc_acolyte_of_shadron() : CreatureScript("npc_acolyte_of_shadron") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_acolyte_of_shadronAI(creature);
- }
-
- struct npc_acolyte_of_shadronAI : public ScriptedAI
- {
- npc_acolyte_of_shadronAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
- uint32 uiDespawnTimer;
-
- void Reset() OVERRIDE
- {
- uiDespawnTimer = 28000;
- if (instance)
- {
- Creature* target = NULL;
- //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT
- if (instance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS)
- {
- target = Unit::GetCreature((*me), instance->GetData64(DATA_SARTHARION));
- if (target)
- target->AddAura(SPELL_GIFT_OF_TWILIGTH_SAR, target);
- }
- else
- {
- target = Unit::GetCreature((*me), instance->GetData64(DATA_SHADRON));
- if (target)
- target->AddAura(SPELL_GIFT_OF_TWILIGTH_SHA, target);
- }
- }
-
- me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
- }
-
- void JustDied(Unit* /*killer*/) OVERRIDE
- {
- if (instance)
- {
- Creature* Shadron = instance->instance->GetCreature(instance->GetData64(DATA_SHADRON));
- if (Shadron)
- {
- (CAST_AI(npc_shadron::npc_shadronAI, Shadron->AI()))->m_bHasPortalOpen = false;
- }
-
- Creature* pDebuffTarget = NULL;
- Map* map = me->GetMap();
- if (map->IsDungeon())
- {
- Map::PlayerList const &PlayerList = map->GetPlayers();
-
- if (PlayerList.isEmpty())
- return;
-
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT, 0) && !i->GetSource()->GetVictim())
+ case EVENT_FLAME_BREATH:
+ Talk(SAY_SARTHARION_BREATH);
+ DoCastVictim(RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H));
+ events.ScheduleEvent(EVENT_FLAME_BREATH, urand(25000, 35000));
+ break;
+ case EVENT_TAIL_SWEEP:
+ DoCastVictim(RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H));
+ events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(15000, 20000));
+ break;
+ case EVENT_CLEAVE_ATTACK:
+ DoCastVictim(SPELL_CLEAVE);
+ events.ScheduleEvent(EVENT_CLEAVE_ATTACK, urand(7000, 10000));
+ break;
+ case EVENT_LAVA_STRIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
- i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true);
- i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true);
- i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT);
- i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER);
+ CastLavaStrikeOnTarget(target);
+ if (urand(0, 5) == 0)
+ Talk(SAY_SARTHARION_SPECIAL);
}
- }
+ events.ScheduleEvent(EVENT_LAVA_STRIKE, (_isSoftEnraged ? urand(1400, 2000) : urand(5000, 20000)));
+ break;
+ case EVENT_CALL_TENEBRON:
+ CallDragon(DATA_TENEBRON);
+ break;
+ case EVENT_CALL_SHADRON:
+ CallDragon(DATA_SHADRON);
+ break;
+ case EVENT_CALL_VESPERON:
+ CallDragon(DATA_VESPERON);
+ break;
+ default:
+ break;
}
-
- //not solo fight, so main boss has deduff
- pDebuffTarget = instance->instance->GetCreature(instance->GetData64(DATA_SARTHARION));
- if (pDebuffTarget && pDebuffTarget->IsAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR))
- pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR);
-
- //event not in progress, then solo fight and must remove debuff mini-boss
- pDebuffTarget = instance->instance->GetCreature(instance->GetData64(DATA_SHADRON));
- if (pDebuffTarget && pDebuffTarget->IsAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
- pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA);
}
- }
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- if (uiDespawnTimer < uiDiff)
+ // At 35% spell will target dragons, if they are still alive.
+ if (!_isBerserk && !HealthAbovePct(35))
{
- me->SetVisible(false);
- me->Kill(me);
- uiDespawnTimer = 28000;
- return;
- }else uiDespawnTimer -= uiDiff;
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## Mob Acolyte of Vesperon
-######*/
-
-class npc_acolyte_of_vesperon : public CreatureScript
-{
-public:
- npc_acolyte_of_vesperon() : CreatureScript("npc_acolyte_of_vesperon") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_acolyte_of_vesperonAI(creature);
- }
-
- struct npc_acolyte_of_vesperonAI : public ScriptedAI
- {
- npc_acolyte_of_vesperonAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- InstanceScript* instance;
- uint32 uiDespawnTimer;
-
- void Reset() OVERRIDE
- {
- uiDespawnTimer = 28000;
- if (instance)
- me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
- DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO);
- }
-
- void JustDied(Unit* /*killer*/) OVERRIDE
- {
- me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP_ACO);
-
- // remove twilight torment on Vesperon
- if (instance)
- {
- Creature* pVesperon = instance->instance->GetCreature(instance->GetData64(DATA_VESPERON));
- if (pVesperon)
- (CAST_AI(npc_vesperon::npc_vesperonAI, pVesperon->AI()))->m_bHasPortalOpen = false;
-
- if (pVesperon && pVesperon->IsAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP))
- pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
-
- Map* map = me->GetMap();
- if (map->IsDungeon())
+ if (instance->GetBossState(DATA_TENEBRON) != DONE || instance->GetBossState(DATA_SHADRON) != DONE || instance->GetBossState(DATA_VESPERON) != DONE)
{
- Map::PlayerList const &PlayerList = map->GetPlayers();
-
- if (PlayerList.isEmpty())
- return;
-
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT, 0) && !i->GetSource()->GetVictim())
- {
- i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true);
- i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true);
- i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT);
- i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER);
- }
- if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP, 0) && !i->GetSource()->GetVictim())
- i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
- }
+ Talk(SAY_SARTHARION_BERSERK);
+ DoCast(me, SPELL_BERSERK);
+ _isBerserk = true;
}
-
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_VESP_ACO);
- instance->DoRemoveAurasDueToSpellOnPlayers(57935);
- instance->DoRemoveAurasDueToSpellOnPlayers(58835); // Components of spell Twilight Torment
}
- }
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- if (uiDespawnTimer < uiDiff)
+ // Soft Enrage used while determining Lava Strike cooldown.
+ if (!_isSoftEnraged && HealthBelowPct(10))
{
- me->SetVisible(false);
- me->Kill(me);
- uiDespawnTimer = 28000;
- return;
- }else uiDespawnTimer -= uiDiff;
-
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-/*######
-## Mob Twilight Eggs
-######*/
-
-class npc_twilight_eggs : public CreatureScript
-{
-public:
- npc_twilight_eggs() : CreatureScript("npc_twilight_eggs") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_twilight_eggsAI(creature);
- }
-
- struct npc_twilight_eggsAI : public ScriptedAI
- {
- npc_twilight_eggsAI(Creature* creature) : ScriptedAI(creature)
- {
- SetCombatMovement(false);
- instance = creature->GetInstanceScript();
- }
-
- uint32 m_uiFadeArmorTimer;
- uint32 m_uiHatchEggTimer;
-
- InstanceScript* instance;
-
- void Reset() OVERRIDE
- {
- if (instance)
- me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
- m_uiFadeArmorTimer = 1000;
- m_uiHatchEggTimer = 20000;
- }
-
- void SpawnWhelps()
- {
- me->RemoveAllAuras();
-
- if (!instance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS)
- me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
- else
- me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
- me->DealDamage(me, me->GetHealth());
- }
-
- void JustSummoned(Creature* who) OVERRIDE
- {
- who->SetInCombatWithZone();
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- if (m_uiHatchEggTimer <= uiDiff)
- {
- Creature* Tenebron = instance->instance->GetCreature(instance->GetData64(DATA_TENEBRON));
- if (Tenebron)
- (CAST_AI(npc_tenebron::npc_tenebronAI, Tenebron->AI()))->m_bHasPortalOpen = false;
- SpawnWhelps();
+ _isSoftEnraged = true;
}
- else
- m_uiHatchEggTimer -= uiDiff;
- }
-
- void AttackStart(Unit* /*who*/) OVERRIDE { }
- void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { }
-
- };
-
-};
-
-/*######
-## Mob Flame Tsunami
-######*/
-class npc_flame_tsunami : public CreatureScript
-{
-public:
- npc_flame_tsunami() : CreatureScript("npc_flame_tsunami") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_flame_tsunamiAI(creature);
- }
-
- struct npc_flame_tsunamiAI : public ScriptedAI
- {
- npc_flame_tsunamiAI(Creature* creature) : ScriptedAI(creature)
- {
- me->SetDisplayId(11686);
- me->AddAura(SPELL_FLAME_TSUNAMI, me);
- }
-
- uint32 Tsunami_Timer;
- uint32 TsunamiBuff_timer;
- uint32 entry;
-
- void Reset() OVERRIDE
- {
- me->SetReactState(REACT_PASSIVE);
- Tsunami_Timer = 100;
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- TsunamiBuff_timer = 1000;
- entry = 0;
- }
-
- void UpdateAI(uint32 diff) OVERRIDE
- {
- if (Tsunami_Timer <= diff)
- {
- DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA);
- Tsunami_Timer = 500;
- }else Tsunami_Timer -= diff;
-
- if (TsunamiBuff_timer <= diff)
- {
- if (Unit* LavaBlaze = GetClosestCreatureWithEntry(me, NPC_LAVA_BLAZE, 10.0f, true))
- LavaBlaze->CastSpell(LavaBlaze, SPELL_FLAME_TSUNAMI_BUFF, true);
- TsunamiBuff_timer = 1000;
- }else TsunamiBuff_timer -= diff;
- }
- };
-
-};
-
-// Twilight Fissure
-class npc_twilight_fissure : public CreatureScript
-{
-public:
- npc_twilight_fissure() : CreatureScript("npc_twilight_fissure") { }
-
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_twilight_fissureAI(creature);
- }
-
- struct npc_twilight_fissureAI : public ScriptedAI
- {
- npc_twilight_fissureAI(Creature* creature) : ScriptedAI(creature)
- {
- SetCombatMovement(false);
- }
- uint32 VoidBlast_Timer;
+ DoMeleeAttackIfReady();
- void Reset() OVERRIDE
- {
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->AddAura( 46265, me ); // Wrong, can't find proper visual
- me->AddAura( 69422, me );
- VoidBlast_Timer = 5000;
+ EnterEvadeIfOutOfCombatArea(diff);
}
- void UpdateAI(uint32 diff) OVERRIDE
- {
- if (VoidBlast_Timer <= diff)
- {
- DoCastAOE(RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H));
- ////twilight realm
- //DoCastVictim(57620, true);
- //DoCastVictim(57874, true);
- VoidBlast_Timer = 9000;
- me->RemoveAllAuras();
- me->Kill(me);
- } else VoidBlast_Timer -= diff;
- }
+ private:
+ bool _isBerserk;
+ bool _isSoftEnraged;
+ bool _isHardEnraged;
+ uint8 drakeCount;
};
-};
-
-/*######
-## Mob Twilight Whelps
-######*/
-
-class npc_twilight_whelp : public CreatureScript
-{
-public:
- npc_twilight_whelp() : CreatureScript("npc_twilight_whelp") { }
-
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- return new npc_twilight_whelpAI(creature);
+ return new boss_sartharionAI(creature);
}
-
- struct npc_twilight_whelpAI : public ScriptedAI
- {
- npc_twilight_whelpAI(Creature* creature) : ScriptedAI(creature)
- {
- Reset();
- }
-
- uint32 m_uiFadeArmorTimer;
-
- void Reset() OVERRIDE
- {
- me->RemoveAllAuras();
- me->SetInCombatWithZone();
- m_uiFadeArmorTimer = 1000;
- }
-
- void UpdateAI(uint32 uiDiff) OVERRIDE
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- // twilight torment
- if (m_uiFadeArmorTimer <= uiDiff)
- {
- DoCastVictim(SPELL_FADE_ARMOR);
- m_uiFadeArmorTimer = urand(5000, 10000);
- }
- else
- m_uiFadeArmorTimer -= uiDiff;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-class achievement_twilight_assist : public AchievementCriteriaScript
-{
- public:
- achievement_twilight_assist() : AchievementCriteriaScript("achievement_twilight_assist")
- {
- }
-
- bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
- {
- if (!target)
- return false;
-
- if (Creature* Sartharion = target->ToCreature())
- if (Sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 1)
- return true;
-
- return false;
- }
-};
-
-class achievement_twilight_duo : public AchievementCriteriaScript
-{
- public:
- achievement_twilight_duo() : AchievementCriteriaScript("achievement_twilight_duo")
- {
- }
-
- bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
- {
- if (!target)
- return false;
-
- if (Creature* Sartharion = target->ToCreature())
- if (Sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 2)
- return true;
-
- return false;
- }
-};
-
-class achievement_twilight_zone : public AchievementCriteriaScript
-{
- public:
- achievement_twilight_zone() : AchievementCriteriaScript("achievement_twilight_zone")
- {
- }
-
- bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
- {
- if (!target)
- return false;
-
- if (Creature* Sartharion = target->ToCreature())
- if (Sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) == 3)
- return true;
-
- return false;
- }
};
void AddSC_boss_sartharion()
{
new boss_sartharion();
- new npc_vesperon();
- new npc_shadron();
- new npc_tenebron();
- new npc_acolyte_of_shadron();
- new npc_acolyte_of_vesperon();
- new npc_twilight_eggs();
- new npc_flame_tsunami();
- new npc_twilight_fissure();
- new npc_twilight_whelp();
- new achievement_twilight_assist();
- new achievement_twilight_duo();
- new achievement_twilight_zone();
}
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp
index ace2258ac9f..ad1346e7f37 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp
@@ -19,8 +19,6 @@
#include "InstanceScript.h"
#include "obsidian_sanctum.h"
-#define MAX_ENCOUNTER 1
-
/* Obsidian Sanctum encounters:
0 - Sartharion
*/
@@ -28,48 +26,18 @@
class instance_obsidian_sanctum : public InstanceMapScript
{
public:
- instance_obsidian_sanctum() : InstanceMapScript("instance_obsidian_sanctum", 615) { }
-
- InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE
- {
- return new instance_obsidian_sanctum_InstanceMapScript(map);
- }
+ instance_obsidian_sanctum() : InstanceMapScript(OSScriptName, 615) { }
struct instance_obsidian_sanctum_InstanceMapScript : public InstanceScript
{
instance_obsidian_sanctum_InstanceMapScript(Map* map) : InstanceScript(map) { }
- uint32 m_auiEncounter[MAX_ENCOUNTER];
- uint64 m_uiSartharionGUID;
- uint64 m_uiTenebronGUID;
- uint64 m_uiShadronGUID;
- uint64 m_uiVesperonGUID;
-
- bool m_bTenebronKilled;
- bool m_bShadronKilled;
- bool m_bVesperonKilled;
-
void Initialize() OVERRIDE
{
- memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
-
- m_uiSartharionGUID = 0;
- m_uiTenebronGUID = 0;
- m_uiShadronGUID = 0;
- m_uiVesperonGUID = 0;
-
- m_bTenebronKilled = false;
- m_bShadronKilled = false;
- m_bVesperonKilled = false;
- }
-
- bool IsEncounterInProgress() const OVERRIDE
- {
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS)
- return true;
-
- return false;
+ sartharionGUID = 0;
+ tenebronGUID = 0;
+ shadronGUID = 0;
+ vesperonGUID = 0;
}
void OnCreatureCreate(Creature* creature) OVERRIDE
@@ -77,68 +45,113 @@ public:
switch (creature->GetEntry())
{
case NPC_SARTHARION:
- m_uiSartharionGUID = creature->GetGUID();
+ sartharionGUID = creature->GetGUID();
break;
- //three dragons below set to active state once created.
- //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences
+ // Three dragons below set to active state once created.
+ // We must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences
case NPC_TENEBRON:
- m_uiTenebronGUID = creature->GetGUID();
+ tenebronGUID = creature->GetGUID();
creature->setActive(true);
break;
case NPC_SHADRON:
- m_uiShadronGUID = creature->GetGUID();
+ shadronGUID = creature->GetGUID();
creature->setActive(true);
break;
case NPC_VESPERON:
- m_uiVesperonGUID = creature->GetGUID();
+ vesperonGUID = creature->GetGUID();
creature->setActive(true);
break;
}
}
- void SetData(uint32 uiType, uint32 uiData) OVERRIDE
- {
- if (uiType == TYPE_SARTHARION_EVENT)
- m_auiEncounter[0] = uiData;
- else if (uiType == TYPE_TENEBRON_PREKILLED)
- m_bTenebronKilled = true;
- else if (uiType == TYPE_SHADRON_PREKILLED)
- m_bShadronKilled = true;
- else if (uiType == TYPE_VESPERON_PREKILLED)
- m_bVesperonKilled = true;
- }
-
- uint32 GetData(uint32 uiType) const OVERRIDE
+ bool SetBossState(uint32 type, EncounterState state) OVERRIDE
{
- if (uiType == TYPE_SARTHARION_EVENT)
- return m_auiEncounter[0];
- else if (uiType == TYPE_TENEBRON_PREKILLED)
- return m_bTenebronKilled;
- else if (uiType == TYPE_SHADRON_PREKILLED)
- return m_bShadronKilled;
- else if (uiType == TYPE_VESPERON_PREKILLED)
- return m_bVesperonKilled;
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
- return 0;
+ switch (type)
+ {
+ case DATA_SARTHARION:
+ case DATA_TENEBRON:
+ case DATA_SHADRON:
+ case DATA_VESPERON:
+ break;
+ default:
+ break;
+ }
+ return true;
}
- uint64 GetData64(uint32 uiData) const OVERRIDE
+ uint64 GetData64(uint32 Data) const OVERRIDE
{
- switch (uiData)
+ switch (Data)
{
case DATA_SARTHARION:
- return m_uiSartharionGUID;
+ return sartharionGUID;
case DATA_TENEBRON:
- return m_uiTenebronGUID;
+ return tenebronGUID;
case DATA_SHADRON:
- return m_uiShadronGUID;
+ return shadronGUID;
case DATA_VESPERON:
- return m_uiVesperonGUID;
+ return vesperonGUID;
}
return 0;
}
+
+ std::string GetSaveData() OVERRIDE
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "O S " << GetBossSaveData();
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
+ }
+
+ void Load(const char* str) OVERRIDE
+ {
+ if (!str)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(str);
+
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(str);
+ loadStream >> dataHead1 >> dataHead2;
+
+ if (dataHead1 == 'O' && dataHead2 == 'S')
+ {
+ for (uint32 i = 0; i < EncounterCount; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+ SetBossState(i, EncounterState(tmpState));
+ }
+ }
+ else
+ OUT_LOAD_INST_DATA_FAIL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ protected:
+ uint64 sartharionGUID;
+ uint64 tenebronGUID;
+ uint64 shadronGUID;
+ uint64 vesperonGUID;
};
+ InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE
+ {
+ return new instance_obsidian_sanctum_InstanceMapScript(map);
+ }
};
void AddSC_instance_obsidian_sanctum()
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
new file mode 100644
index 00000000000..f8d8b0106c5
--- /dev/null
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
@@ -0,0 +1,1183 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "Cell.h"
+#include "CellImpl.h"
+#include "obsidian_sanctum.h"
+
+enum Enums
+{
+ WHISPER_HATCH_EGGS = 6,
+ WHISPER_OPEN_PORTAL = 6, // whisper, shared by two dragons
+
+ //Mini bosses common spells
+ SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase
+
+ //Miniboses (Vesperon, Shadron, Tenebron)
+ SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster.
+ SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster.
+
+ SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec.
+ SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec.
+
+ //Vesperon
+ //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
+ NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon
+ SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%.
+ SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988
+ SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988
+
+ //Shadron
+ //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
+ NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron
+ SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%.
+ SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron
+ SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion
+ SPELL_VOID_BLAST = 57581, // Twilight Fissure
+ SPELL_VOID_BLAST_H = 59128,
+
+ //Tenebron
+ //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708
+ SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%.
+ //Tenebron, dummy spell
+ SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP
+ SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP
+ SPELL_TWILIGHT_REVENGE = 60639,
+ SPELL_HATCH_EGGS_H = 59189,
+ SPELL_HATCH_EGGS = 58542,
+ SPELL_HATCH_EGGS_EFFECT_H = 59190,
+ SPELL_HATCH_EGGS_EFFECT = 58685,
+ NPC_TWILIHT_WHELP = 31214,
+ NPC_TWILIGHT_EGG = 30882,
+ NPC_SARTHARION_TWILIGHT_EGG = 31204,
+
+ SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO
+ SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura
+ SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase
+ SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave)
+
+ //Whelps
+ NPC_TWILIGHT_WHELP = 30890,
+ NPC_SHARTHARION_TWILIGHT_WHELP = 31214,
+ SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s
+
+ //flame tsunami
+ SPELL_FLAME_TSUNAMI = 57494, // the visual dummy
+ SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction
+
+ SPELL_FLAME_TSUNAMI_DMG_AURA = 57491, // periodic damage, npc has this aura
+ SPELL_FLAME_TSUNAMI_BUFF = 60430,
+ NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike
+
+ //using these custom points for dragons start and end
+ POINT_ID_INIT = 100,
+ POINT_ID_LAND = 200
+};
+
+enum Misc
+{
+ DATA_CAN_LOOT = 0
+};
+
+struct Location
+{
+ float x, y, z;
+};
+
+struct Locations
+{
+ float x, y, z;
+};
+
+struct Waypoint
+{
+ float m_fX, m_fY, m_fZ;
+};
+
+#define MAX_WAYPOINT 6
+//points around raid "isle", counter clockwise. should probably be adjusted to be more alike
+Waypoint dragonCommon[MAX_WAYPOINT]=
+{
+ {3214.012f, 468.932f, 98.652f},
+ {3244.950f, 468.427f, 98.652f},
+ {3283.520f, 496.869f, 98.652f},
+ {3287.316f, 555.875f, 98.652f},
+ {3250.479f, 585.827f, 98.652f},
+ {3209.969f, 566.523f, 98.652f}
+};
+
+static Location AcolyteofShadron = { 3363.92f, 534.703f, 97.2683f };
+static Location AcolyteofShadron2 = { 3246.57f, 551.263f, 58.6164f };
+static Location AcolyteofVesperon = { 3145.68f, 520.71f, 89.7f };
+static Location AcolyteofVesperon2 = { 3246.57f, 551.263f, 58.6164f };
+
+Locations TwilightEggs[] =
+{
+ {3219.28f, 669.121f, 88.5549f},
+ {3221.55f, 682.852f, 90.5361f},
+ {3239.77f, 685.94f, 90.3168f},
+ {3250.33f, 669.749f, 88.7637f},
+ {3246.6f, 642.365f, 84.8752f},
+ {3233.68f, 653.117f, 85.7051f}
+};
+Locations TwilightEggsSarth[] =
+{
+ {3252.73f, 515.762f, 58.5501f},
+ {3256.56f, 521.119f, 58.6061f},
+ {3255.63f, 527.513f, 58.7568f},
+ {3264.90f, 525.865f, 58.6436f},
+ {3264.26f, 516.364f, 58.8011f},
+ {3257.54f, 502.285f, 58.2077f}
+};
+
+enum SharedTextIDs
+{
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_DEATH = 2,
+ SAY_BREATH = 3,
+ SAY_RESPOND = 4,
+ SAY_SPECIAL = 5
+};
+
+enum DummyDragonEvents
+{
+ EVENT_FREE_MOVEMENT = 1
+};
+
+//to control each dragons common abilities
+struct dummy_dragonAI : public ScriptedAI
+{
+ dummy_dragonAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ waypointId = 0;
+ portalRespawnTime = 30000;
+ _canMoveFree = false;
+ _canLoot = true;
+ }
+
+ void SetData(uint32 type, uint32 value) OVERRIDE
+ {
+ if (type == DATA_CAN_LOOT)
+ _canLoot = value;
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE
+ {
+ if (!instance || type != POINT_MOTION_TYPE)
+ return;
+
+ // debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId);
+
+ // if healers messed up the raid and we was already initialized
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ // this is end, if we reach this, don't do much
+ if (pointId == POINT_ID_LAND)
+ {
+ me->GetMotionMaster()->Clear();
+ me->SetInCombatWithZone();
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
+ {
+ me->AddThreat(target, 1.0f);
+ me->Attack(target, true);
+ me->GetMotionMaster()->MoveChase(target);
+ }
+
+ _canMoveFree = false;
+ return;
+ }
+
+ // get amount of common points
+ uint32 commonWPCount = sizeof(dragonCommon)/sizeof(Waypoint);
+
+ // increase
+ waypointId = pointId+1;
+
+ // if we have reached a point bigger or equal to count, it mean we must reset to point 0
+ if (waypointId >= commonWPCount)
+ {
+ if (!_canMoveFree)
+ _canMoveFree = true;
+
+ waypointId = 0;
+ }
+
+ events.ScheduleEvent(EVENT_FREE_MOVEMENT, 500);
+ }
+
+ // used when open portal and spawn mobs in phase
+ void DoRaidWhisper(int32 iTextId)
+ {
+ Map* map = me->GetMap();
+
+ if (map && map->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+
+ if (!PlayerList.isEmpty())
+ {
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ Talk(iTextId, i->GetSource()->GetGUID());
+ }
+ }
+ }
+
+ // "opens" the portal and does the "opening" whisper
+ void OpenPortal()
+ {
+ int32 textId = 0;
+
+ // there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database
+
+ // using a grid search here seem to be more efficient than caching all four guids
+ // in instance script and calculate range to each.
+ GameObject* portal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL, 50.0f);
+
+ switch (me->GetEntry())
+ {
+ case NPC_TENEBRON:
+ {
+ textId = WHISPER_HATCH_EGGS;
+ if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ {
+ for (uint32 i = 0; i < 6; ++i)
+ me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[i].x, TwilightEggs[i].y, TwilightEggs[i].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ }
+ else
+ {
+ for (uint32 i = 0; i < 6; ++i)
+ me->SummonCreature(NPC_SARTHARION_TWILIGHT_EGG, TwilightEggsSarth[i].x, TwilightEggsSarth[i].y, TwilightEggsSarth[i].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ }
+ break;
+ }
+ case NPC_SHADRON:
+ {
+ textId = WHISPER_OPEN_PORTAL;
+ if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y, AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
+ else
+ me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y, AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 28000);
+
+ break;
+ }
+ case NPC_VESPERON:
+ {
+ textId = WHISPER_OPEN_PORTAL;
+ if (instance && !instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ {
+ if (Creature* acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y, AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
+ {
+ me->InterruptNonMeleeSpells(true);
+ acolyte->InterruptNonMeleeSpells(true);
+ me->CastSpell(me, 32747, false);
+ }
+ }
+ else
+ {
+ if (Creature* acolyte = me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y, AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
+ {
+ me->InterruptNonMeleeSpells(true);
+ acolyte->InterruptNonMeleeSpells(true);
+ me->CastSpell(me, 32747, false);
+ }
+ }
+
+ break;
+ }
+ }
+
+ DoRaidWhisper(textId);
+
+ // By using SetRespawnTime() we will actually "spawn" the object with our defined time.
+ // Once time is up, portal will disappear again.
+ if (portal && !portal->isSpawned())
+ portal->SetRespawnTime(portalRespawnTime);
+
+ // Unclear what are expected to happen if one drake has a portal open already
+ // Refresh respawnTime so time again are set to 30secs?
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (!_canLoot)
+ me->SetLootRecipient(NULL);
+
+ uint32 spellId = 0;
+
+ switch (me->GetEntry())
+ {
+ case NPC_TENEBRON:
+ spellId = SPELL_POWER_OF_TENEBRON;
+ if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
+ instance->SetBossState(DATA_TENEBRON, DONE);
+ break;
+ case NPC_SHADRON:
+ spellId = SPELL_POWER_OF_SHADRON;
+ if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
+ instance->SetBossState(DATA_SHADRON, DONE);
+ if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_SHADRON, 100.0f))
+ acolyte->Kill(acolyte);
+ break;
+ case NPC_VESPERON:
+ spellId = SPELL_POWER_OF_VESPERON;
+ if (instance && instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
+ instance->SetBossState(DATA_VESPERON, DONE);
+ if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_VESPERON, 100.0f))
+ acolyte->Kill(acolyte);
+ break;
+ }
+
+ Talk(SAY_DEATH);
+ me->RemoveAurasDueToSpell(spellId);
+
+ if (instance)
+ {
+ instance->DoRemoveAurasDueToSpellOnPlayers(spellId);
+
+ // not if solo mini-boss fight
+ if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS)
+ return;
+
+ // Twilight Revenge to main boss
+ if (Unit* sartharion = Unit::GetUnit(*me, instance->GetData64(DATA_SARTHARION)))
+ if (sartharion->IsAlive())
+ {
+ sartharion->RemoveAurasDueToSpell(spellId);
+ DoCast(sartharion, SPELL_TWILIGHT_REVENGE, true);
+ }
+ }
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ if (events.ExecuteEvent() == EVENT_FREE_MOVEMENT)
+ {
+ if (_canMoveFree && waypointId < MAX_WAYPOINT)
+ me->GetMotionMaster()->MovePoint(waypointId, dragonCommon[waypointId].m_fX, dragonCommon[waypointId].m_fY, dragonCommon[waypointId].m_fZ);
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ uint32 waypointId;
+ int32 portalRespawnTime;
+ bool _canMoveFree;
+ bool _canLoot;
+};
+
+/*######
+## Tenebron
+######*/
+
+enum TenebronEvents
+{
+ EVENT_SHADOW_FISSURE_TENEBRON = 2,
+ EVENT_HATCH_EGGS = 3,
+ EVENT_SHADOW_BREATH_TENEBRON = 4
+};
+
+class npc_tenebron : public CreatureScript
+{
+public:
+ npc_tenebron() : CreatureScript("npc_tenebron") { }
+
+ struct npc_tenebronAI : public dummy_dragonAI
+ {
+ npc_tenebronAI(Creature* creature) : dummy_dragonAI(creature) { }
+
+ void Reset() OVERRIDE
+ {
+ dummy_dragonAI::Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_TENEBRON, 5000);
+ events.ScheduleEvent(EVENT_HATCH_EGGS, 30000);
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_TENEBRON, 20000);
+ }
+
+ void KilledUnit(Unit* /*victim*/) OVERRIDE
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ //if no target, update dummy and return
+ if (!UpdateVictim())
+ {
+ dummy_dragonAI::UpdateAI(diff);
+ return;
+ }
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_FISSURE_TENEBRON:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE));
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_TENEBRON, urand(15000, 20000));
+ break;
+ case EVENT_HATCH_EGGS:
+ OpenPortal();
+ events.ScheduleEvent(EVENT_HATCH_EGGS, 30000);
+ break;
+ case EVENT_SHADOW_BREATH_TENEBRON:
+ Talk(SAY_BREATH);
+ DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_TENEBRON, urand(20000, 25000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_tenebronAI(creature);
+ }
+};
+
+/*######
+## Shadron
+######*/
+
+enum ShadronEvents
+{
+ EVENT_SHADOW_FISSURE_SHADRON = 5,
+ EVENT_ACOLYTE_SHADRON = 6,
+ EVENT_SHADOW_BREATH_SHADRON = 7
+};
+
+class npc_shadron : public CreatureScript
+{
+public:
+ npc_shadron() : CreatureScript("npc_shadron") { }
+
+ struct npc_shadronAI : public dummy_dragonAI
+ {
+ npc_shadronAI(Creature* creature) : dummy_dragonAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ dummy_dragonAI::Reset();
+
+ if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP))
+ me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
+
+ if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
+ me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA);
+
+ if (instance)
+ instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_SHADRON, 5000);
+ events.ScheduleEvent(EVENT_ACOLYTE_SHADRON, 60000);
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_SHADRON, 20000);
+ }
+
+ void KilledUnit(Unit* /*victim*/) OVERRIDE
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ //if no target, update dummy and return
+ if (!UpdateVictim())
+ {
+ dummy_dragonAI::UpdateAI(diff);
+ return;
+ }
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_FISSURE_SHADRON:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H));
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_SHADRON, urand(15000, 20000));
+ break;
+ case EVENT_ACOLYTE_SHADRON:
+ if (instance->GetBossState(DATA_PORTAL_OPEN) == NOT_STARTED)
+ events.ScheduleEvent(EVENT_ACOLYTE_SHADRON, 10000);
+ else
+ {
+ if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
+ return;
+
+ OpenPortal();
+
+ if (instance)
+ instance->SetBossState(DATA_PORTAL_OPEN, IN_PROGRESS);
+
+ events.ScheduleEvent(EVENT_ACOLYTE_SHADRON, urand(60000, 65000));
+ }
+ break;
+ case EVENT_SHADOW_BREATH_SHADRON:
+ Talk(SAY_BREATH);
+ DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_SHADRON, urand(20000, 25000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_shadronAI(creature);
+ }
+};
+
+/*######
+## Vesperon
+######*/
+
+enum VesperonEvents
+{
+ EVENT_SHADOW_FISSURE_VESPERON = 8,
+ EVENT_ACOLYTE_VESPERON = 9,
+ EVENT_SHADOW_BREATH_VESPERON = 10
+};
+
+class npc_vesperon : public CreatureScript
+{
+public:
+ npc_vesperon() : CreatureScript("npc_vesperon") { }
+
+ struct npc_vesperonAI : public dummy_dragonAI
+ {
+ npc_vesperonAI(Creature* creature) : dummy_dragonAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ dummy_dragonAI::Reset();
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_VESPERON, 5000);
+ events.ScheduleEvent(EVENT_ACOLYTE_VESPERON, 60000);
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_VESPERON, 20000);
+ }
+
+ void KilledUnit(Unit* /*victim*/) OVERRIDE
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ //if no target, update dummy and return
+ if (!UpdateVictim())
+ {
+ dummy_dragonAI::UpdateAI(diff);
+ return;
+ }
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_FISSURE_VESPERON:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H));
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE_VESPERON, urand(15000, 20000));
+ break;
+ case EVENT_ACOLYTE_VESPERON:
+ if (instance->GetBossState(DATA_PORTAL_OPEN) == IN_PROGRESS)
+ events.ScheduleEvent(EVENT_ACOLYTE_VESPERON, 10000);
+ else
+ {
+ OpenPortal();
+ DoCastVictim(SPELL_TWILIGHT_TORMENT_VESP);
+ events.ScheduleEvent(EVENT_ACOLYTE_VESPERON, urand(60000, 70000));
+ }
+ break;
+ case EVENT_SHADOW_BREATH_VESPERON:
+ Talk(SAY_BREATH);
+ DoCastVictim(RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H));
+ events.ScheduleEvent(EVENT_SHADOW_BREATH_VESPERON, urand(20000, 25000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_vesperonAI(creature);
+ }
+};
+
+/*######
+## Acolyte of Shadron
+######*/
+
+class npc_acolyte_of_shadron : public CreatureScript
+{
+public:
+ npc_acolyte_of_shadron() : CreatureScript("npc_acolyte_of_shadron") { }
+
+ struct npc_acolyte_of_shadronAI : public ScriptedAI
+ {
+ npc_acolyte_of_shadronAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ // Despawn the NPC automatically after 28 seconds
+ me->DespawnOrUnsummon(28000);
+
+ if (instance)
+ {
+ Creature* target = NULL;
+ //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT
+ if (instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ {
+ if (target = Unit::GetCreature((*me), instance->GetData64(DATA_SARTHARION)))
+ target->AddAura(SPELL_GIFT_OF_TWILIGTH_SAR, target);
+ }
+ else
+ {
+ if (target = Unit::GetCreature((*me), instance->GetData64(DATA_SHADRON)))
+ target->AddAura(SPELL_GIFT_OF_TWILIGTH_SHA, target);
+ }
+ }
+
+ me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (instance)
+ {
+ if (Creature* shadron = instance->instance->GetCreature(instance->GetData64(DATA_SHADRON)))
+ instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED);
+
+ Map* map = me->GetMap();
+ if (map->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+
+ if (PlayerList.isEmpty())
+ return;
+
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT, 0) && !i->GetSource()->GetVictim())
+ {
+ i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true);
+ i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true);
+ i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT);
+ i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER);
+ }
+ }
+ }
+
+ //not solo fight, so main boss has deduff
+ if (Creature* debuffTarget = instance->instance->GetCreature(instance->GetData64(DATA_SARTHARION)))
+ if (debuffTarget->IsAlive() && debuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR))
+ debuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR);
+
+ //event not in progress, then solo fight and must remove debuff mini-boss
+ if (Creature* debuffTarget = instance->instance->GetCreature(instance->GetData64(DATA_SHADRON)))
+ if (debuffTarget->IsAlive() && debuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA))
+ debuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA);
+ }
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_acolyte_of_shadronAI(creature);
+ }
+};
+
+/*######
+## Acolyte of Vesperon
+######*/
+
+class npc_acolyte_of_vesperon : public CreatureScript
+{
+public:
+ npc_acolyte_of_vesperon() : CreatureScript("npc_acolyte_of_vesperon") { }
+
+ struct npc_acolyte_of_vesperonAI : public ScriptedAI
+ {
+ npc_acolyte_of_vesperonAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ // Despawn the NPC automatically after 28 seconds
+ me->DespawnOrUnsummon(28000);
+
+ if (instance)
+ me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
+
+ DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP_ACO);
+
+ // remove twilight torment on Vesperon
+ if (instance)
+ {
+ if (Creature* vesperon = instance->instance->GetCreature(instance->GetData64(DATA_VESPERON)))
+ {
+ instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED);
+
+ if (vesperon->IsAlive() && vesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP))
+ vesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
+ }
+
+ Map* map = me->GetMap();
+ if (map->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+
+ if (PlayerList.isEmpty())
+ return;
+
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT, 0) && !i->GetSource()->GetVictim())
+ {
+ i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true);
+ i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true);
+ i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT);
+ i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER);
+ }
+ if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP, 0) && !i->GetSource()->GetVictim())
+ i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP);
+ }
+ }
+
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_VESP_ACO);
+ instance->DoRemoveAurasDueToSpellOnPlayers(57935);
+ instance->DoRemoveAurasDueToSpellOnPlayers(58835); // Components of spell Twilight Torment
+ }
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_acolyte_of_vesperonAI(creature);
+ }
+};
+
+/*######
+## Twilight Eggs
+######*/
+
+enum TwilightEggs
+{
+ EVENT_TWILIGHT_EGGS = 11
+};
+
+class npc_twilight_eggs : public CreatureScript
+{
+public:
+ npc_twilight_eggs() : CreatureScript("npc_twilight_eggs") { }
+
+ struct npc_twilight_eggsAI : public ScriptedAI
+ {
+ npc_twilight_eggsAI(Creature* creature) : ScriptedAI(creature)
+ {
+ SetCombatMovement(false);
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE
+ {
+ if (instance)
+ me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
+
+ events.ScheduleEvent(EVENT_TWILIGHT_EGGS, 20000);
+ }
+
+ void SpawnWhelps()
+ {
+ me->RemoveAllAuras();
+
+ if (!instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ else
+ me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ me->DealDamage(me, me->GetHealth());
+ }
+
+ void JustSummoned(Creature* who) OVERRIDE
+ {
+ who->SetInCombatWithZone();
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ if (events.ExecuteEvent() == EVENT_TWILIGHT_EGGS)
+ {
+ if (Creature* tenebron = instance->instance->GetCreature(instance->GetData64(DATA_TENEBRON)))
+ instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED);
+
+ SpawnWhelps();
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_twilight_eggsAI(creature);
+ }
+};
+
+/*######
+## Flame Tsunami
+######*/
+
+enum FlameTsunami
+{
+ EVENT_TSUNAMI_TIMER = 12,
+ EVENT_TSUNAMI_BUFF = 13
+};
+
+class npc_flame_tsunami : public CreatureScript
+{
+public:
+ npc_flame_tsunami() : CreatureScript("npc_flame_tsunami") { }
+
+ struct npc_flame_tsunamiAI : public ScriptedAI
+ {
+ npc_flame_tsunamiAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetDisplayId(11686);
+ me->AddAura(SPELL_FLAME_TSUNAMI, me);
+ }
+
+ void Reset() OVERRIDE
+ {
+ me->SetReactState(REACT_PASSIVE);
+ events.ScheduleEvent(EVENT_TSUNAMI_TIMER, 100);
+ events.ScheduleEvent(EVENT_TSUNAMI_BUFF, 1000);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_TSUNAMI_TIMER:
+ DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA);
+ events.ScheduleEvent(EVENT_TSUNAMI_TIMER, 500);
+ break;
+ case EVENT_TSUNAMI_BUFF:
+ if (Unit* lavaBlaze = GetClosestCreatureWithEntry(me, NPC_LAVA_BLAZE, 10.0f, true))
+ lavaBlaze->CastSpell(lavaBlaze, SPELL_FLAME_TSUNAMI_BUFF, true);
+ events.ScheduleEvent(EVENT_TSUNAMI_BUFF, 1000);
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_flame_tsunamiAI(creature);
+ }
+};
+
+/*######
+## Twilight Fissure
+######*/
+
+enum TwilightFissure
+{
+ EVENT_VOID_BLAST = 14
+};
+
+class npc_twilight_fissure : public CreatureScript
+{
+public:
+ npc_twilight_fissure() : CreatureScript("npc_twilight_fissure") { }
+
+ struct npc_twilight_fissureAI : public ScriptedAI
+ {
+ npc_twilight_fissureAI(Creature* creature) : ScriptedAI(creature)
+ {
+ SetCombatMovement(false);
+ }
+
+ void Reset() OVERRIDE
+ {
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->AddAura( 46265, me ); // Wrong, can't find proper visual
+ me->AddAura( 69422, me );
+ events.ScheduleEvent(EVENT_VOID_BLAST, 5000);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ if (events.ExecuteEvent() == EVENT_VOID_BLAST)
+ {
+ DoCastAOE(RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H));
+ ////twilight realm
+ //DoCastVictim(57620, true);
+ //DoCastVictim(57874, true);
+ me->RemoveAllAuras();
+ me->Kill(me);
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_twilight_fissureAI(creature);
+ }
+};
+
+/*######
+## Twilight Whelps
+######*/
+
+enum TwilightWhelps
+{
+ EVENT_FADE_ARMOR = 15
+};
+
+class npc_twilight_whelp : public CreatureScript
+{
+public:
+ npc_twilight_whelp() : CreatureScript("npc_twilight_whelp") { }
+
+ struct npc_twilight_whelpAI : public ScriptedAI
+ {
+ npc_twilight_whelpAI(Creature* creature) : ScriptedAI(creature)
+ {
+ Reset();
+ }
+
+ void Reset() OVERRIDE
+ {
+ me->RemoveAllAuras();
+ me->SetInCombatWithZone();
+ events.ScheduleEvent(EVENT_FADE_ARMOR, 1000);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
+
+ // twilight torment
+ events.Update(diff);
+
+ if (events.ExecuteEvent() == EVENT_FADE_ARMOR)
+ {
+ DoCastVictim(SPELL_FADE_ARMOR);
+ events.ScheduleEvent(EVENT_FADE_ARMOR, urand(5000, 10000));
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_twilight_whelpAI(creature);
+ }
+};
+
+class achievement_twilight_assist : public AchievementCriteriaScript
+{
+ public:
+ achievement_twilight_assist() : AchievementCriteriaScript("achievement_twilight_assist") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
+ {
+ if (!target)
+ return false;
+
+ if (Creature* sartharion = target->ToCreature())
+ if (sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 1)
+ return true;
+
+ return false;
+ }
+};
+
+class achievement_twilight_duo : public AchievementCriteriaScript
+{
+ public:
+ achievement_twilight_duo() : AchievementCriteriaScript("achievement_twilight_duo") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
+ {
+ if (!target)
+ return false;
+
+ if (Creature* sartharion = target->ToCreature())
+ if (sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 2)
+ return true;
+
+ return false;
+ }
+};
+
+class achievement_twilight_zone : public AchievementCriteriaScript
+{
+ public:
+ achievement_twilight_zone() : AchievementCriteriaScript("achievement_twilight_zone") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
+ {
+ if (!target)
+ return false;
+
+ if (Creature* sartharion = target->ToCreature())
+ if (sartharion->AI()->GetData(TWILIGHT_ACHIEVEMENTS) == 3)
+ return true;
+
+ return false;
+ }
+};
+
+void AddSC_obsidian_sanctum()
+{
+ new npc_vesperon();
+ new npc_shadron();
+ new npc_tenebron();
+ new npc_acolyte_of_shadron();
+ new npc_acolyte_of_vesperon();
+ new npc_twilight_eggs();
+ new npc_flame_tsunami();
+ new npc_twilight_fissure();
+ new npc_twilight_whelp();
+ new achievement_twilight_assist();
+ new achievement_twilight_duo();
+ new achievement_twilight_zone();
+}
+
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h
index 7d2403be469..8cfb3931372 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h
@@ -18,17 +18,18 @@
#ifndef DEF_OBSIDIAN_SANCTUM_H
#define DEF_OBSIDIAN_SANCTUM_H
+#define OSScriptName "instance_obsidian_sanctum"
+
+uint32 const EncounterCount = 5;
+
enum DataTypes
{
- TYPE_SARTHARION_EVENT = 1,
- TYPE_TENEBRON_PREKILLED = 2,
- TYPE_SHADRON_PREKILLED = 3,
- TYPE_VESPERON_PREKILLED = 4,
-
- DATA_SARTHARION = 10,
- DATA_TENEBRON = 11,
- DATA_SHADRON = 12,
- DATA_VESPERON = 13
+ DATA_SARTHARION = 0,
+ DATA_TENEBRON = 1,
+ DATA_SHADRON = 2,
+ DATA_VESPERON = 3,
+ DATA_PORTAL_OPEN = 4,
+ TWILIGHT_ACHIEVEMENTS = 5
};
enum CreaturesIds