aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent_Michael <Vincent_Michael@gmx.de>2013-12-11 20:34:44 +0100
committerVincent_Michael <Vincent_Michael@gmx.de>2013-12-11 20:34:44 +0100
commit07024d3ea84db832e5bdd221c293e5daf297181a (patch)
tree663c0412bd112c0bef4f9b106c597e2bc0d05eb5 /src
parent70445f34a6b66b603662716371c6f6a873a95855 (diff)
parentfb26e1852394a1aa6e7695030eabcf8e85b1c5c8 (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/game/DataStores/DBCEnums.h src/server/scripts/Commands/cs_wp.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp124
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h20
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp2
-rw-r--r--src/server/game/DataStores/DBCEnums.h60
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp11
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Events/GameEventMgr.cpp2
-rw-r--r--src/server/game/Pools/PoolMgr.cpp2
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_wp.cpp17
-rw-r--r--src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/zone_ghostlands.cpp6
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp11
-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.cpp1159
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h19
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp379
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp27
-rw-r--r--src/server/scripts/Outland/zone_netherstorm.cpp38
27 files changed, 1882 insertions, 1906 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 1f312de73f6..18daf1ef8de 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -409,7 +409,7 @@ Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect)
{
if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay())
- if (Unit* nearTarget = me->ToCreature()->SelectNearestHostileUnitInAggroRange(true))
+ if (Unit* nearTarget = me->SelectNearestHostileUnitInAggroRange(true))
return nearTarget;
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index e98c196d6e3..a1042a25c01 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -525,9 +525,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell);
int32 mana = me->GetPower(POWER_MANA);
- if (me->GetDistance((*itr)->ToUnit()) > spellInfo->GetMaxRange(true) ||
- me->GetDistance((*itr)->ToUnit()) < spellInfo->GetMinRange(true) ||
- !me->ToUnit()->IsWithinLOSInMap((*itr)->ToUnit()) ||
+ if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) ||
+ me->GetDistance(*itr) < spellInfo->GetMinRange(true) ||
+ !me->IsWithinLOSInMap(*itr) ||
mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()))
_allowMove = true;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 74d2d5c49a1..3835220b453 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -107,6 +107,8 @@ SmartWaypointMgr::~SmartWaypointMgr()
void SmartAIMgr::LoadSmartAIFromDB()
{
+ LoadHelperStores();
+
uint32 oldMSTime = getMSTime();
for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; i++)
@@ -118,7 +120,6 @@ void SmartAIMgr::LoadSmartAIFromDB()
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 SmartAI scripts. DB table `smartai_scripts` is empty.");
-
return;
}
@@ -236,6 +237,7 @@ void SmartAIMgr::LoadSmartAIFromDB()
TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ UnLoadHelperStores();
}
bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
@@ -769,27 +771,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break;
}
case SMART_ACTION_SUMMON_CREATURE:
+ {
if (!IsCreatureValid(e, e.action.summonCreature.creature))
return false;
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
- if (!spellInfo)
- continue;
-
- for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
- {
- if (spellInfo->Effects[j].Effect == SPELL_EFFECT_SUMMON)
- {
- uint32 creatureSummonEntry = spellInfo->Effects[j].MiscValue;
-
- if (e.action.summonCreature.creature == creatureSummonEntry)
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u creature summon: There is a summon spell for creature entry %u (SpellId: %u, effect: %u)",
- e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.creature, spellInfo->Id, j);
- }
- }
- }
+ CacheSpellContainerBounds sBounds = GetSummonCreatureSpellContainerBounds(e.action.summonCreature.creature);
+ for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u creature summon: There is a summon spell for creature entry %u (SpellId: %u, effect: %u)",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.creature, itr->second.first, itr->second.second);
if (e.action.summonCreature.type < TEMPSUMMON_TIMED_OR_DEAD_DESPAWN || e.action.summonCreature.type > TEMPSUMMON_MANUAL_DESPAWN)
{
@@ -797,27 +786,16 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
break;
+ }
case SMART_ACTION_CALL_KILLEDMONSTER:
+ {
if (!IsCreatureValid(e, e.action.killedMonster.creature))
return false;
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
- if (!spellInfo)
- continue;
-
- for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
- {
- if (spellInfo->Effects[j].Effect == SPELL_EFFECT_KILL_CREDIT || spellInfo->Effects[j].Effect == SPELL_EFFECT_KILL_CREDIT2)
- {
- uint32 killCredit = spellInfo->Effects[j].MiscValue;
-
- if (e.action.killedMonster.creature == killCredit)
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Kill Credit: %u has already spell kill credit (SpellId: %u effect: %u)", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.killedMonster.creature, spellInfo->Id, j);
- }
- }
- }
+ CacheSpellContainerBounds sBounds = GetKillCreditSpellContainerBounds(e.action.killedMonster.creature);
+ for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Kill Credit: There is a killcredit spell for creatureEntry %u (SpellId: %u effect: %u)",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.killedMonster.creature, itr->second.first, itr->second.second);
if (e.GetTargetType() == SMART_TARGET_POSITION)
{
@@ -825,6 +803,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
break;
+ }
case SMART_ACTION_UPDATE_TEMPLATE:
if (e.action.updateTemplate.creature && !IsCreatureValid(e, e.action.updateTemplate.creature))
return false;
@@ -846,28 +825,16 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break;
}
case SMART_ACTION_SUMMON_GO:
+ {
if (!IsGameObjectValid(e, e.action.summonGO.entry))
return false;
- for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
- if (!spellInfo)
- continue;
-
- for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
- {
- if (spellInfo->Effects[j].Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD)
- {
- uint32 goSummonEntry = spellInfo->Effects[j].MiscValue;
-
- if (e.action.summonGO.entry == goSummonEntry)
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u gameobject summon: There is a summon spell for gameobject entry %u (SpellId: %u, effect: %u)",
- e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonGO.entry, spellInfo->Id, j);
- }
- }
- }
+ CacheSpellContainerBounds sBounds = GetSummonGameObjectSpellContainerBounds(e.action.summonGO.entry);
+ for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr)
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u gameobject summon: There is a summon spell for gameobject entry %u (SpellId: %u, effect: %u)",
+ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonGO.entry, itr->second.first, itr->second.second);
break;
+ }
case SMART_ACTION_ADD_ITEM:
case SMART_ACTION_REMOVE_ITEM:
if (!IsItemValid(e, e.action.item.entry))
@@ -1073,3 +1040,52 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
}
return true;
}*/
+
+void SmartAIMgr::LoadHelperStores()
+{
+ uint32 oldMSTime = getMSTime();
+
+ SpellInfo const* spellInfo = NULL;
+ for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
+ {
+ spellInfo = sSpellMgr->GetSpellInfo(i);
+ if (!spellInfo)
+ continue;
+
+ for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
+ {
+ if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_SUMMON))
+ SummonCreatureSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j))));
+
+ else if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD))
+ SummonGameObjectSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j))));
+
+ else if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2))
+ KillCreditSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j))));
+ }
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded SmartAIMgr Helpers in %u ms", GetMSTimeDiffToNow(oldMSTime));
+}
+
+void SmartAIMgr::UnLoadHelperStores()
+{
+ SummonCreatureSpellStore.clear();
+ SummonGameObjectSpellStore.clear();
+ KillCreditSpellStore.clear();
+}
+
+CacheSpellContainerBounds SmartAIMgr::GetSummonCreatureSpellContainerBounds(uint32 creatureEntry) const
+{
+ return SummonCreatureSpellStore.equal_range(creatureEntry);
+}
+
+CacheSpellContainerBounds SmartAIMgr::GetSummonGameObjectSpellContainerBounds(uint32 gameObjectEntry) const
+{
+ return SummonGameObjectSpellStore.equal_range(gameObjectEntry);
+}
+
+CacheSpellContainerBounds SmartAIMgr::GetKillCreditSpellContainerBounds(uint32 killCredit) const
+{
+ return KillCreditSpellStore.equal_range(killCredit);
+}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 093f71ad1bd..2ad68474f8a 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1346,12 +1346,16 @@ typedef std::vector<SmartScriptHolder> SmartAIEventList;
// all events for all entries / guids
typedef UNORDERED_MAP<int32, SmartAIEventList> SmartAIEventMap;
+// Helper Stores
+typedef std::map<uint32 /*entry*/, std::pair<uint32 /*spellId*/, SpellEffIndex /*effIndex*/> > CacheSpellContainer;
+typedef std::pair<CacheSpellContainer::const_iterator, CacheSpellContainer::const_iterator> CacheSpellContainerBounds;
+
class SmartAIMgr
{
friend class ACE_Singleton<SmartAIMgr, ACE_Null_Mutex>;
- SmartAIMgr(){ }
+ SmartAIMgr() { }
public:
- ~SmartAIMgr(){ }
+ ~SmartAIMgr() { }
void LoadSmartAIFromDB();
@@ -1506,6 +1510,18 @@ class SmartAIMgr
}
//bool IsTextValid(SmartScriptHolder const& e, uint32 id);
+
+ // Helpers
+ void LoadHelperStores();
+ void UnLoadHelperStores();
+
+ CacheSpellContainerBounds GetSummonCreatureSpellContainerBounds(uint32 creatureEntry) const;
+ CacheSpellContainerBounds GetSummonGameObjectSpellContainerBounds(uint32 gameObjectEntry) const;
+ CacheSpellContainerBounds GetKillCreditSpellContainerBounds(uint32 killCredit) const;
+
+ CacheSpellContainer SummonCreatureSpellStore;
+ CacheSpellContainer SummonGameObjectSpellStore;
+ CacheSpellContainer KillCreditSpellStore;
};
#define sSmartScriptMgr ACE_Singleton<SmartAIMgr, ACE_Null_Mutex>::instance()
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index f5a5d02e7ac..1e21b640ddb 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -825,7 +825,7 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
return 0;
}
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, 0, team, x, y, z, o))
{
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry);
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index e3aff877319..473303dc5ee 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1648,7 +1648,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
if (!map)
return NULL;
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, 0, teamval, x, y, z, o))
{
TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!",
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index b8a52152202..0d7d520b4fa 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -290,36 +290,36 @@ enum AchievementCriteriaTypes
enum AreaFlags
{
- AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
- AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
- AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
- AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
- AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
- AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
- AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
- AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
- AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
- AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
- AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
- AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
- AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
- AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
- AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
- AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
- AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
- AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
- AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
- AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
- AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
- AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
- AREA_FLAG_UNK7 = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion (Something to do with team?)
- AREA_FLAG_UNK8 = 0x00800000, // Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion (Something to do with team?)
- AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
- AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
- AREA_FLAG_NO_FLY_ZONE = 0x20000000, // Marks zones where you cannot fly
- AREA_FLAG_UNK9 = 0x40000000,
+ AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
+ AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
+ AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
+ AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
+ AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
+ AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
+ AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
+ AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
+ AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
+ AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
+ AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
+ AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
+ AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
+ AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
+ AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
+ AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
+ AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
+ AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
+ AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
+ AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
+ AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
+ AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
+ AREA_FLAG_REST_ZONE_HORDE = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion (Something to do with team?)
+ AREA_FLAG_REST_ZONE_ALLIANCE = 0x00800000, // Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion (Something to do with team?)
+ AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
+ AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
+ AREA_FLAG_NO_FLY_ZONE = 0x20000000, // Marks zones where you cannot fly
+ AREA_FLAG_UNK9 = 0x40000000
};
enum Difficulty
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 7d89b90c5dc..70c932da272 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1344,7 +1344,7 @@ bool Creature::IsInvisibleDueToDespawn() const
if (Unit::IsInvisibleDueToDespawn())
return true;
- if (IsAlive() || m_corpseRemoveTime > time(NULL))
+ if (IsAlive() || isDying() || m_corpseRemoveTime > time(NULL))
return false;
return true;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index cd4fa2139f9..18732984559 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -10640,6 +10640,9 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
void Unit::setDeathState(DeathState s)
{
+ // Death state needs to be updated before RemoveAllAurasOnDeath() is called, to prevent entering combat
+ m_deathState = s;
+
if (s != ALIVE && s != JUST_RESPAWNED)
{
CombatStop();
@@ -10688,8 +10691,6 @@ void Unit::setDeathState(DeathState s)
}
else if (s == JUST_RESPAWNED)
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)
-
- m_deathState = s;
}
/*########################################
@@ -10697,14 +10698,14 @@ void Unit::setDeathState(DeathState s)
######## AGGRO SYSTEM ########
######## ########
########################################*/
-bool Unit::CanHaveThreatList() const
+bool Unit::CanHaveThreatList(bool skipAliveCheck) const
{
// only creatures can have threat list
if (GetTypeId() != TYPEID_UNIT)
return false;
// only alive units can have threat list
- if (!IsAlive() || isDying())
+ if (!skipAliveCheck && !IsAlive())
return false;
// totems can not have threat list
@@ -10747,7 +10748,7 @@ void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, Sp
void Unit::DeleteThreatList()
{
- if (CanHaveThreatList() && !m_ThreatManager.isThreatListEmpty())
+ if (CanHaveThreatList(true) && !m_ThreatManager.isThreatListEmpty())
SendClearThreatListOpcode();
m_ThreatManager.clearReferences();
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index cb228bd135d..416a2257b92 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1906,7 +1906,7 @@ class Unit : public WorldObject
uint32 m_lastSanctuaryTime;
// Threat related methods
- bool CanHaveThreatList() const;
+ bool CanHaveThreatList(bool skipAliveCheck = false) const;
void AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = NULL);
float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL);
void DeleteThreatList();
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index e3d15728297..a09500cb67e 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -1181,7 +1181,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
// We use spawn coords to spawn
if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
{
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
//TC_LOG_DEBUG("misc", "Spawning creature %u", *itr);
if (!creature->LoadCreatureFromDB(*itr, map))
delete creature;
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index d4211f83a11..1eed9feb289 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -364,7 +364,7 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
// We use spawn coords to spawn
if (!map->Instanceable() && map->IsGridLoaded(data->posX, data->posY))
{
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
//TC_LOG_DEBUG("pool", "Spawning creature %u", guid);
if (!creature->LoadCreatureFromDB(obj->guid, map))
{
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 976a3e6fb7a..82c6cbdf0b5 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -452,6 +452,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();
@@ -1299,6 +1300,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/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 05b56e7b25d..63fe3e91433 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -924,7 +924,7 @@ public:
if (!ve)
return false;
- Creature* v = new Creature;
+ Creature* v = new Creature();
Map* map = handler->GetSession()->GetPlayer()->GetMap();
diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp
index 86d079f53e4..711e40b0659 100644
--- a/src/server/scripts/Commands/cs_wp.cpp
+++ b/src/server/scripts/Commands/cs_wp.cpp
@@ -693,8 +693,13 @@ public:
wpCreature->AddObjectToRemoveList();
}
// re-create
+<<<<<<< HEAD
Creature* wpCreature2 = new Creature;
if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
+=======
+ Creature* wpCreature2 = new Creature();
+ if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
+>>>>>>> fb26e1852394a1aa6e7695030eabcf8e85b1c5c8
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
@@ -917,8 +922,13 @@ public:
Map* map = chr->GetMap();
float o = chr->GetOrientation();
+<<<<<<< HEAD
Creature* wpCreature = new Creature;
if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+=======
+ Creature* wpCreature = new Creature();
+ if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+>>>>>>> fb26e1852394a1aa6e7695030eabcf8e85b1c5c8
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -981,8 +991,13 @@ public:
float o = chr->GetOrientation();
Map* map = chr->GetMap();
+<<<<<<< HEAD
Creature* creature = new Creature;
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+=======
+ Creature* creature = new Creature();
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+>>>>>>> fb26e1852394a1aa6e7695030eabcf8e85b1c5c8
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
@@ -1030,7 +1045,7 @@ public:
Player* chr = handler->GetSession()->GetPlayer();
Map* map = chr->GetMap();
- Creature* creature = new Creature;
+ Creature* creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp
index 451fd46938d..f93f0a94414 100644
--- a/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp
+++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp
@@ -69,7 +69,7 @@ public:
DoCast(me, SPELL_ICEARMOR, true);
}
- void EnterCombat(Unit* /*who*/)OVERRIDE { }
+ void EnterCombat(Unit* /*who*/) OVERRIDE { }
void UpdateAI(uint32 diff) OVERRIDE
{
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
index ca5dcf5360e..80b4b98b0a4 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
@@ -351,8 +351,7 @@ public:
break;
}
case 6:
- me->SetOrientation(me->GetAngle(breathX, breathY));
- me->StopMoving();
+ me->SetFacingTo(me->GetAngle(breathX, breathY));
//DoTextEmote("takes a deep breath.", NULL);
events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000);
break;
diff --git a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
index 76c2e635a82..1606b59e786 100644
--- a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
@@ -125,7 +125,7 @@ public:
break;
case 11:
Talk(SAY_PROGRESS2, player->GetGUID());
- me->SetOrientation(4.762841f);
+ me->SetFacingTo(4.762841f);
break;
case 18:
{
@@ -150,11 +150,11 @@ public:
player->GroupEventHappens(QUEST_ESCAPE_FROM_THE_CATACOMBS, me);
break;
case 32:
- me->SetOrientation(2.978281f);
+ me->SetFacingTo(2.978281f);
Talk(SAY_END1, player->GetGUID());
break;
case 33:
- me->SetOrientation(5.858011f);
+ me->SetFacingTo(5.858011f);
Talk(SAY_END2, player->GetGUID());
Creature* CaptainHelios = me->FindNearestCreature(NPC_CAPTAIN_HELIOS, 50);
if (CaptainHelios)
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
index 53e09c918ea..8dd009cdb32 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp
@@ -308,18 +308,15 @@ public:
{
if (instance)
{
- Unit* pKri = Unit::GetUnit(*me, instance->GetData64(DATA_KRI));
- Unit* pVem = Unit::GetUnit(*me, instance->GetData64(DATA_VEM));
-
switch (urand(0, 2))
{
case 0:
- if (pKri)
- DoCast(pKri, SPELL_HEAL);
+ if (Creature* kri = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KRI)))
+ DoCast(kri, SPELL_HEAL);
break;
case 1:
- if (pVem)
- DoCast(pVem, SPELL_HEAL);
+ if (Creature* vem = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VEM)))
+ DoCast(vem, SPELL_HEAL);
break;
case 2:
DoCast(me, SPELL_HEAL);
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..5fc4869c4af
--- /dev/null
+++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp
@@ -0,0 +1,1159 @@
+/*
+ * 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)
+ {
+ //if not solo fight, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT
+ if (instance->GetBossState(DATA_SARTHARION) == IN_PROGRESS)
+ {
+ if (Creature* sartharion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SARTHARION)))
+ sartharion->AddAura(SPELL_GIFT_OF_TWILIGTH_SAR, sartharion);
+ }
+ else
+ {
+ if (Creature* shadron = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADRON)))
+ shadron->AddAura(SPELL_GIFT_OF_TWILIGTH_SHA, shadron);
+ }
+ }
+
+ me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (instance)
+ {
+ if (ObjectAccessor::GetCreature(*me, 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 debuff
+ if (Creature* debuffTarget = ObjectAccessor::GetCreature(*me, 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 = ObjectAccessor::GetCreature(*me, 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 = ObjectAccessor::GetCreature(*me, 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 (ObjectAccessor::GetCreature(*me, 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 | 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 | 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
+ {
+ return target && target->GetAI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 1;
+ }
+};
+
+class achievement_twilight_duo : public AchievementCriteriaScript
+{
+ public:
+ achievement_twilight_duo() : AchievementCriteriaScript("achievement_twilight_duo") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
+ {
+ return target && target->GetAI()->GetData(TWILIGHT_ACHIEVEMENTS) >= 2;
+ }
+};
+
+class achievement_twilight_zone : public AchievementCriteriaScript
+{
+ public:
+ achievement_twilight_zone() : AchievementCriteriaScript("achievement_twilight_zone") { }
+
+ bool OnCheck(Player* /*player*/, Unit* target) OVERRIDE
+ {
+ return target && target->GetAI()->GetData(TWILIGHT_ACHIEVEMENTS) == 3;
+ }
+};
+
+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
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
index d518747a462..f7e8d9ea7d6 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
@@ -81,15 +81,40 @@ enum Creatures
NPC_SCOURGE_HULK = 26555
};
-enum SvalaPhase
+enum Phases
{
- IDLE,
+ IDLE = 1,
INTRO,
NORMAL,
SACRIFICING,
SVALADEAD
};
+enum Events
+{
+ //INTRO
+ EVENT_INTRO_SVALA_TALK_0 = 1,
+ EVENT_INTRO_ARTHAS_TALK_0,
+ EVENT_INTRO_TRANSFORM_0,
+ EVENT_INTRO_TRANSFORM_1,
+ EVENT_INTRO_TRANSFORM_2,
+ EVENT_INTRO_SVALA_TALK_1,
+ EVENT_INTRO_ARTHAS_TALK_1,
+ EVENT_INTRO_SVALA_TALK_2,
+ EVENT_INTRO_RELOCATE_SVALA,
+ EVENT_INTRO_DESPAWN_ARTHAS,
+
+ //NORMAL
+ EVENT_SINISTER_STRIKE,
+ EVENT_CALL_FLAMES,
+ EVENT_RITUAL_PREPARATION,
+
+ //SACRIFICING
+ EVENT_SPAWN_RITUAL_CHANNELERS,
+ EVENT_RITUAL_STRIKE,
+ EVENT_RITUAL_DISARM
+};
+
enum Misc
{
DATA_INCREDIBLE_HULK = 2043
@@ -112,38 +137,23 @@ class boss_svala : public CreatureScript
{
boss_svalaAI(Creature* creature) : BossAI(creature, DATA_SVALA_SORROWGRAVE)
{
- Phase = IDLE;
+ _introCompleted = false;
}
- SvalaPhase Phase;
-
- uint32 introTimer;
- uint8 introPhase;
- uint8 sacrePhase;
-
- uint64 arthasGUID;
-
- uint32 sinsterStrikeTimer;
- uint32 callFlamesTimer;
- uint32 sacrificeTimer;
-
- bool sacrificed;
-
void Reset() OVERRIDE
{
_Reset();
- sacrificed = false;
+ _sacrificed = false;
SetCombatMovement(true);
- if (Phase > NORMAL)
- Phase = NORMAL;
+ if (_introCompleted)
+ events.SetPhase(NORMAL);
+ else
+ events.SetPhase(IDLE);
- me->SetDisableGravity(Phase == NORMAL);
+ me->SetDisableGravity(events.IsInPhase(NORMAL));
- introTimer = 1 * IN_MILLISECONDS;
- introPhase = 0;
- sacrePhase = 0;
- arthasGUID = 0;
+ _arthasGUID = 0;
instance->SetData64(DATA_SACRIFICED_PLAYER, 0);
}
@@ -152,16 +162,12 @@ class boss_svala : public CreatureScript
{
_EnterCombat();
Talk(SAY_AGGRO);
-
- sinsterStrikeTimer = 7 * IN_MILLISECONDS;
- callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
}
void JustSummoned(Creature* summon) OVERRIDE
{
if (summon->GetEntry() == NPC_RITUAL_CHANNELER)
summon->CastSpell(summon, SPELL_SUMMONED_VIS, true);
-
summons.Summon(summon);
}
@@ -170,9 +176,9 @@ class boss_svala : public CreatureScript
if (!who)
return;
- if (Phase == IDLE && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40))
+ if (events.IsInPhase(IDLE) && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40))
{
- Phase = INTRO;
+ events.SetPhase(INTRO);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (GameObject* mirror = ObjectAccessor::GetGameObject(*me, DATA_UTGARDE_MIRROR))
@@ -181,8 +187,9 @@ class boss_svala : public CreatureScript
if (Creature* arthas = me->SummonCreature(NPC_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN))
{
arthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- arthasGUID = arthas->GetGUID();
+ _arthasGUID = arthas->GetGUID();
}
+ events.ScheduleEvent(EVENT_INTRO_SVALA_TALK_0, 1 * IN_MILLISECONDS, 0, INTRO);
}
}
@@ -194,20 +201,20 @@ class boss_svala : public CreatureScript
void JustDied(Unit* /*killer*/) OVERRIDE
{
- if (Phase == SACRIFICING)
+ if (events.IsInPhase(SACRIFICING))
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
-
me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH);
-
_JustDied();
Talk(SAY_DEATH);
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spellInfo) OVERRIDE
{
- if (spellInfo->Id == SPELL_RITUAL_STRIKE_EFF_1 && Phase != NORMAL && Phase != SVALADEAD)
+ if (spellInfo->Id == SPELL_RITUAL_STRIKE_EFF_1 && !events.IsInPhase(NORMAL) && !events.IsInPhase(SVALADEAD))
{
- Phase = NORMAL;
+ events.SetPhase(NORMAL);
+ events.ScheduleEvent(EVENT_SINISTER_STRIKE, 7 * IN_MILLISECONDS, 0, NORMAL);
+ events.ScheduleEvent(EVENT_CALL_FLAMES, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, NORMAL);
SetCombatMovement(true);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f, true))
@@ -217,199 +224,163 @@ class boss_svala : public CreatureScript
void UpdateAI(uint32 diff) OVERRIDE
{
- if (Phase == IDLE)
+ if (events.IsInPhase(IDLE))
return;
- if (Phase == INTRO)
+ if (events.IsInPhase(NORMAL) && !UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (!_sacrificed && HealthBelowPct(50))
{
- if (introTimer <= diff)
- {
- Creature* arthas = ObjectAccessor::GetCreature(*me, arthasGUID);
- if (!arthas)
- return;
+ _sacrificed = true;
+ events.SetPhase(SACRIFICING);
+ events.ScheduleEvent(EVENT_RITUAL_PREPARATION, 0, 0, SACRIFICING);
+ }
- switch (introPhase)
- {
- case 0:
- Talk(SAY_SVALA_INTRO_0);
- ++introPhase;
- introTimer = 8100;
- break;
- case 1:
+ if (events.IsInPhase(NORMAL))
+ DoMeleeAttackIfReady();
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INTRO_SVALA_TALK_0:
+ Talk(SAY_SVALA_INTRO_0);
+ events.ScheduleEvent(EVENT_INTRO_ARTHAS_TALK_0, 8.1 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_ARTHAS_TALK_0:
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_1);
- ++introPhase;
- introTimer = 10000;
- break;
- case 2:
- {
+ events.ScheduleEvent(EVENT_INTRO_TRANSFORM_0, 10 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_TRANSFORM_0:
+ {
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false);
- Position pos;
- pos.Relocate(me);
- pos.m_positionZ += 8.0f;
- me->GetMotionMaster()->MoveTakeoff(0, pos);
- // spectators flee event
- std::list<Creature*> lspectatorList;
- GetCreatureListWithEntryInGrid(lspectatorList, me, NPC_SPECTATOR, 100.0f);
- for (std::list<Creature*>::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr)
+ Position pos;
+ pos.Relocate(me);
+ pos.m_positionZ += 8.0f;
+ me->GetMotionMaster()->MoveTakeoff(0, pos);
+ // spectators flee event
+ std::list<Creature*> lspectatorList;
+ GetCreatureListWithEntryInGrid(lspectatorList, me, NPC_SPECTATOR, 100.0f);
+ for (std::list<Creature*>::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr)
+ {
+ if ((*itr)->IsAlive())
{
- if ((*itr)->IsAlive())
- {
- (*itr)->SetStandState(UNIT_STAND_STATE_STAND);
- (*itr)->SetWalk(false);
- (*itr)->GetMotionMaster()->MovePoint(1, spectatorWP[0]);
- }
+ (*itr)->SetStandState(UNIT_STAND_STATE_STAND);
+ (*itr)->SetWalk(false);
+ (*itr)->GetMotionMaster()->MovePoint(1, spectatorWP[0]);
}
-
- ++introPhase;
- introTimer = 4200;
- break;
}
- case 3:
- me->CastSpell(me, SPELL_SVALA_TRANSFORMING1, false);
- ++introPhase;
- introTimer = 6200;
- break;
- case 4:
- me->CastSpell(me, SPELL_SVALA_TRANSFORMING2, false);
+ events.ScheduleEvent(EVENT_INTRO_TRANSFORM_1, 4.2 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ }
+ case EVENT_INTRO_TRANSFORM_1:
+ me->CastSpell(me, SPELL_SVALA_TRANSFORMING1, false);
+ events.ScheduleEvent(EVENT_INTRO_TRANSFORM_2, 6.2 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_TRANSFORM_2:
+ me->CastSpell(me, SPELL_SVALA_TRANSFORMING2, false);
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
+ {
arthas->InterruptNonMeleeSpells(true);
- me->RemoveAllAuras();
- me->UpdateEntry(NPC_SVALA_SORROWGRAVE);
me->SetFacingToObject(arthas);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- ++introPhase;
- introTimer = 3200;
- break;
- case 5:
- Talk(SAY_SVALA_INTRO_1);
- ++introPhase;
- introTimer = 10000;
- break;
- case 6:
+ }
+ me->RemoveAllAuras();
+ me->UpdateEntry(NPC_SVALA_SORROWGRAVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ events.ScheduleEvent(EVENT_INTRO_SVALA_TALK_1, 10 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_SVALA_TALK_1:
+ Talk(SAY_SVALA_INTRO_1);
+ events.ScheduleEvent(EVENT_INTRO_ARTHAS_TALK_1, 3.2 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_ARTHAS_TALK_1:
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
arthas->AI()->Talk(SAY_DIALOG_OF_ARTHAS_2);
- ++introPhase;
- introTimer = 7200;
- break;
- case 7:
- Talk(SAY_SVALA_INTRO_2);
- me->SetFacingTo(1.58f);
+ events.ScheduleEvent(EVENT_INTRO_SVALA_TALK_2, 7.2 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_SVALA_TALK_2:
+ Talk(SAY_SVALA_INTRO_2);
+ me->SetFacingTo(1.58f);
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
arthas->SetVisible(false);
- ++introPhase;
- introTimer = 13800;
- break;
- case 8:
- {
- Position pos;
- pos.Relocate(me);
- pos.m_positionX = me->GetHomePosition().GetPositionX();
- pos.m_positionY = me->GetHomePosition().GetPositionY();
- pos.m_positionZ = 90.6065f;
- me->GetMotionMaster()->MoveLand(0, pos);
- me->SetDisableGravity(false, true);
- me->SetHover(true);
- ++introPhase;
- introTimer = 3000;
- break;
- }
- case 9:
- if (GameObject* mirror = ObjectAccessor::GetGameObject(*me, DATA_UTGARDE_MIRROR))
- mirror->SetGoState(GO_STATE_ACTIVE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- arthas->DespawnOrUnsummon();
- arthasGUID = 0;
- Phase = NORMAL;
- break;
- }
- }
- else
- introTimer -= diff;
-
- return;
- }
-
- if (Phase == NORMAL)
- {
- if (!UpdateVictim())
- return;
-
- if (sinsterStrikeTimer <= diff)
- {
- DoCastVictim(SPELL_SINSTER_STRIKE);
- sinsterStrikeTimer = urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS);
- }
- else
- sinsterStrikeTimer -= diff;
-
- if (callFlamesTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ events.ScheduleEvent(EVENT_INTRO_RELOCATE_SVALA, 13.8 * IN_MILLISECONDS, 0, INTRO);
+ break;
+ case EVENT_INTRO_RELOCATE_SVALA:
{
- DoCast(target, SPELL_CALL_FLAMES);
- callFlamesTimer = urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
+ Position pos;
+ pos.Relocate(me);
+ pos.m_positionX = me->GetHomePosition().GetPositionX();
+ pos.m_positionY = me->GetHomePosition().GetPositionY();
+ pos.m_positionZ = 90.6065f;
+ me->GetMotionMaster()->MoveLand(0, pos);
+ me->SetDisableGravity(false, true);
+ me->SetHover(true);
+ events.ScheduleEvent(EVENT_INTRO_DESPAWN_ARTHAS, 3 * IN_MILLISECONDS, 0, INTRO);
+ break;
}
- }
- else
- callFlamesTimer -= diff;
-
- if (!sacrificed)
- {
- if (HealthBelowPct(50))
- {
+ case EVENT_INTRO_DESPAWN_ARTHAS:
+ if (GameObject* mirror = ObjectAccessor::GetGameObject(*me, DATA_UTGARDE_MIRROR))
+ mirror->SetGoState(GO_STATE_ACTIVE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if (Creature* arthas = ObjectAccessor::GetCreature(*me, _arthasGUID))
+ arthas->DespawnOrUnsummon();
+ _arthasGUID = 0;
+ events.SetPhase(NORMAL);
+ _introCompleted = true;
+ events.ScheduleEvent(EVENT_SINISTER_STRIKE, 7 * IN_MILLISECONDS, 0, NORMAL);
+ events.ScheduleEvent(EVENT_CALL_FLAMES, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, NORMAL);
+ break;
+ case EVENT_SINISTER_STRIKE:
+ DoCastVictim(SPELL_SINSTER_STRIKE);
+ events.ScheduleEvent(EVENT_SINISTER_STRIKE, urand(5 * IN_MILLISECONDS, 9 * IN_MILLISECONDS), 0, NORMAL);
+ break;
+ case EVENT_CALL_FLAMES:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_CALL_FLAMES);
+ events.ScheduleEvent(EVENT_CALL_FLAMES, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, NORMAL);
+ break;
+ case EVENT_RITUAL_PREPARATION:
if (Unit* sacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true))
{
instance->SetData64(DATA_SACRIFICED_PLAYER, sacrificeTarget->GetGUID());
-
Talk(SAY_SACRIFICE_PLAYER);
-
DoCast(sacrificeTarget, SPELL_RITUAL_PREPARATION);
-
SetCombatMovement(false);
-
- Phase = SACRIFICING;
- sacrePhase = 0;
- sacrificeTimer = 1 * IN_MILLISECONDS;
-
DoCast(me, SPELL_RITUAL_OF_THE_SWORD);
- sacrificed = true;
}
- }
- }
-
- DoMeleeAttackIfReady();
- }
- else // SACRIFICING
- {
- if (sacrificeTimer <= diff)
- {
- switch (sacrePhase)
- {
- case 0:
- // spawn ritual channelers
- DoCast(me, SPELL_RITUAL_CHANNELER_1, true);
- DoCast(me, SPELL_RITUAL_CHANNELER_2, true);
- DoCast(me, SPELL_RITUAL_CHANNELER_3, true);
- ++sacrePhase;
- sacrificeTimer = 2 * IN_MILLISECONDS;
- break;
- case 1:
- me->StopMoving();
- me->GetMotionMaster()->MoveIdle();
- me->InterruptNonMeleeSpells(true);
- DoCast(me, SPELL_RITUAL_STRIKE_TRIGGER, true);
- ++sacrePhase;
- sacrificeTimer = 200;
- break;
- case 2:
- DoCast(me, SPELL_RITUAL_DISARM);
- ++sacrePhase;
- break;
- case 3:
- break;
- }
+ events.ScheduleEvent(EVENT_SPAWN_RITUAL_CHANNELERS, 1 * IN_MILLISECONDS, 0, SACRIFICING);
+ break;
+ case EVENT_SPAWN_RITUAL_CHANNELERS:
+ DoCast(me, SPELL_RITUAL_CHANNELER_1, true);
+ DoCast(me, SPELL_RITUAL_CHANNELER_2, true);
+ DoCast(me, SPELL_RITUAL_CHANNELER_3, true);
+ events.ScheduleEvent(EVENT_RITUAL_STRIKE, 2 * IN_MILLISECONDS, 0, SACRIFICING);
+ break;
+ case EVENT_RITUAL_STRIKE:
+ me->StopMoving();
+ me->GetMotionMaster()->MoveIdle();
+ me->InterruptNonMeleeSpells(true);
+ DoCast(me, SPELL_RITUAL_STRIKE_TRIGGER, true);
+ events.ScheduleEvent(EVENT_RITUAL_DISARM, 200, 0, SACRIFICING);
+ break;
+ case EVENT_RITUAL_DISARM:
+ DoCast(me, SPELL_RITUAL_DISARM);
+ break;
+ default:
+ break;
}
- else
- sacrificeTimer -= diff;
}
}
+
+ private:
+ uint64 _arthasGUID;
+ bool _sacrificed;
+ bool _introCompleted;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 9209969ce45..7a2afe5505f 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -452,14 +452,14 @@ enum BrannBronzebeard
EVENT_SCRIPT_13 = 13
};
-class npc_brann_bronzebeard : public CreatureScript
+class npc_brann_bronzebeard_keystone : public CreatureScript
{
public:
- npc_brann_bronzebeard() : CreatureScript("npc_brann_bronzebeard") { }
+ npc_brann_bronzebeard_keystone() : CreatureScript("npc_brann_bronzebeard_keystone") { }
- struct npc_brann_bronzebeardAI : public ScriptedAI
+ struct npc_brann_bronzebeard_keystoneAI : public ScriptedAI
{
- npc_brann_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() OVERRIDE
{
@@ -583,7 +583,7 @@ public:
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- return new npc_brann_bronzebeardAI(creature);
+ return new npc_brann_bronzebeard_keystoneAI(creature);
}
};
@@ -642,6 +642,10 @@ enum JokkumScriptcast
{
SPELL_JOKKUM_KILL_CREDIT = 56545,
SPELL_JOKKUM_SUMMON = 56541,
+ SPELL_RIDE_JOKKUM = 56606,
+ NPC_KINGJOKKUM = 30331,
+ SAY_HOLD_ON = 0,
+ PATH_JOKKUM = 2072200
};
class spell_jokkum_scriptcast : public SpellScriptLoader
@@ -665,6 +669,17 @@ class spell_jokkum_scriptcast : public SpellScriptLoader
{
player->CastSpell(player, SPELL_JOKKUM_KILL_CREDIT, true);
player->CastSpell(player, SPELL_JOKKUM_SUMMON, true);
+
+ if (Creature* kingjokkum = GetClosestCreatureWithEntry(player, NPC_KINGJOKKUM, 10.0f))
+ {
+ kingjokkum->setFaction(player->getFaction());
+ player->CastSpell(kingjokkum, SPELL_RIDE_JOKKUM, true);
+ player->SetUInt64Value(PLAYER_FARSIGHT, player->GetGUID());
+ kingjokkum->AI()->Talk(0, player->GetGUID());
+ kingjokkum->ToPlayer()->SetClientControl(kingjokkum, 1);
+ kingjokkum->GetMotionMaster()->MovePath(PATH_JOKKUM, false);
+ kingjokkum->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
+ }
}
}
@@ -688,7 +703,7 @@ void AddSC_storm_peaks()
new npc_freed_protodrake();
new npc_icefang();
new npc_hyldsmeet_protodrake();
- new npc_brann_bronzebeard();
+ new npc_brann_bronzebeard_keystone();
new spell_close_rift();
new spell_jokkum_scriptcast();
}
diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp
index 5cf152bd6e2..e1b95aea972 100644
--- a/src/server/scripts/Outland/zone_netherstorm.cpp
+++ b/src/server/scripts/Outland/zone_netherstorm.cpp
@@ -400,7 +400,7 @@ public:
struct npc_commander_dawnforgeAI : public ScriptedAI
{
- npc_commander_dawnforgeAI(Creature* creature) : ScriptedAI(creature) { Reset(); }
+ npc_commander_dawnforgeAI(Creature* creature) : ScriptedAI(creature) { }
uint64 PlayerGUID;
uint64 ardonisGUID;
@@ -411,9 +411,6 @@ public:
uint32 Phase_Timer;
bool isEvent;
- float angle_dawnforge;
- float angle_ardonis;
-
void Reset() OVERRIDE
{
PlayerGUID = 0;
@@ -438,21 +435,15 @@ public:
{
Creature* ardonis = ObjectAccessor::GetCreature(*me, ardonisGUID);
Creature* pathaleon = ObjectAccessor::GetCreature(*me, pathaleonGUID);
- Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
- if (!ardonis || !pathaleon || !player)
+ if (!ardonis || !pathaleon)
return;
- //Calculate the angle to Pathaleon
- angle_dawnforge = me->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY());
- angle_ardonis = ardonis->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY());
+ // Turn Dawnforge
+ me->SetFacingToObject(pathaleon);
- //Turn Dawnforge and update
- me->SetOrientation(angle_dawnforge);
- me->SendUpdateToPlayer(player);
- //Turn Ardonis and update
- ardonis->SetOrientation(angle_ardonis);
- ardonis->SendUpdateToPlayer(player);
+ // Turn Ardonis
+ ardonis->SetFacingToObject(pathaleon);
//Set them to kneel
me->SetStandState(UNIT_STAND_STATE_KNEEL);
@@ -464,20 +455,11 @@ public:
{
if (Unit* ardonis = ObjectAccessor::GetUnit(*me, ardonisGUID))
{
- Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
-
- if (!player)
- return;
-
- angle_dawnforge = me->GetAngle(ardonis->GetPositionX(), ardonis->GetPositionY());
- angle_ardonis = ardonis->GetAngle(me->GetPositionX(), me->GetPositionY());
+ // Turn Dawnforge
+ me->SetFacingToObject(ardonis);
- //Turn Dawnforge and update
- me->SetOrientation(angle_dawnforge);
- me->SendUpdateToPlayer(player);
- //Turn Ardonis and update
- ardonis->SetOrientation(angle_ardonis);
- ardonis->SendUpdateToPlayer(player);
+ // Turn Ardonis
+ ardonis->SetFacingToObject(me);
//Set state
me->SetStandState(UNIT_STAND_STATE_STAND);