Scripts/Ulduar: Algalon the Observer

This commit is contained in:
Shauren
2012-04-19 23:19:27 +02:00
parent 9231f04d0f
commit 3c2dd7c5ed
13 changed files with 1981 additions and 483 deletions

View File

@@ -119,6 +119,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Maps
${CMAKE_SOURCE_DIR}/src/server/game/Movement
${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators
${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline
${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints
${CMAKE_SOURCE_DIR}/src/server/game/Opcodes
${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP

View File

@@ -22,7 +22,7 @@ set(scripts_STAT_SRCS
Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp
Northrend/Ulduar/Ulduar/boss_thorim.cpp
Northrend/Ulduar/Ulduar/boss_ignis.cpp
Northrend/Ulduar/Ulduar/boss_algalon.cpp
Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
Northrend/Ulduar/Ulduar/instance_ulduar.cpp
Northrend/Ulduar/Ulduar/boss_auriaya.cpp
Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp

View File

@@ -1,376 +0,0 @@
/*
* Copyright (C) 2008-2012 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 "ulduar.h"
#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821
enum Spells
{
SPELL_ASCEND = 64487,
SPELL_BERSERK = 47008,
SPELL_BIG_BANG = 64443,
H_SPELL_BIG_BANG = 64584,
SPELL_COSMIC_SMASH = 62301,
H_SPELL_COSMIC_SMASH = 64598,
SPELL_PHASE_PUNCH = 64412,
SPELL_QUANTUM_STRIKE = 64395,
H_SPELL_QUANTUM_STRIKE = 64592,
SPELL_BLACK_HOLE_EXPLOSION = 64122,
SPELL_ARCANE_BARAGE = 64599,
H_SPELL_ARCANE_BARAGE = 64607
};
enum Creatures
{
CREATURE_COLLAPSING_STAR = 32955,
CREATURE_BLACK_HOLE = 32953,
CREATURE_LIVING_CONSTELLATION = 33052,
CREATURE_DARK_MATTER = 33089
};
enum Yells
{
SAY_AGGRO = -1603000,
SAY_SLAY_1 = -1603001,
SAY_SLAY_2 = -1603002,
SAY_ENGADED_FOR_FIRTS_TIME = -1603003,
SAY_PHASE_2 = -1603004,
SAY_SUMMON_COLLAPSING_STAR = -1603005,
SAY_DEATH_1 = -1603006,
SAY_DEATH_2 = -1603007,
SAY_DEATH_3 = -1603008,
SAY_DEATH_4 = -1603009,
SAY_DEATH_5 = -1603010,
SAY_BERSERK = -1603011,
SAY_BIG_BANG_1 = -1603012,
SAY_BIG_BANG_2 = -1603013,
SAY_TIMER_1 = -1603014,
SAY_TIMER_2 = -1603015,
SAY_TIMER_3 = -1603016,
SAY_SUMMON_1 = -1603017,
SAY_SUMMON_2 = -1603018,
SAY_SUMMON_3 = -1603019,
};
class boss_algalon : public CreatureScript
{
public:
boss_algalon() : CreatureScript("boss_algalon") { }
CreatureAI* GetAI(Creature* creature) const
{
return GetUlduarAI<boss_algalonAI>(creature);
}
struct boss_algalonAI : public ScriptedAI
{
boss_algalonAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
Summon = false; // not in reset. intro speech done only once.
}
InstanceScript* instance;
std::list<uint64> m_lCollapsingStarGUIDList;
uint32 Phase;
uint32 Ascend_Timer;
uint32 Berserk_Timer;
uint32 BigBang_Timer;
uint32 CosmicSmash_Timer;
uint32 PhasePunch_Timer;
uint32 QuantumStrike_Timer;
uint32 CollapsingStar_Timer;
uint32 uiPhase_timer;
uint32 uiStep;
uint64 BlackHoleGUID;
bool Enrage;
bool Summon;
void EnterCombat(Unit* who)
{
if (Summon)
{
DoScriptText(SAY_AGGRO, me);
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
DoZoneInCombat(who->ToCreature());
}
else
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
uiStep = 1;
}
if (instance)
instance->SetData(BOSS_ALGALON, IN_PROGRESS);
}
void KilledUnit(Unit* /*victim*/)
{
DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me);
}
void Reset()
{
Phase = 1;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
if (instance)
instance->SetData(BOSS_ALGALON, NOT_STARTED);
BlackHoleGUID = 0;
uiPhase_timer = 0;
Ascend_Timer = 480000; //8 minutes
QuantumStrike_Timer = urand(4000, 14000);
Berserk_Timer = 360000; //6 minutes
CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds
BigBang_Timer = 90000;
PhasePunch_Timer = 8000;
CosmicSmash_Timer = urand(30000, 60000);
Enrage = false;
}
void JumpToNextStep(uint32 uiTimer)
{
uiPhase_timer = uiTimer;
++uiStep;
}
void DespawnCollapsingStar()
{
if (m_lCollapsingStarGUIDList.empty())
return;
for (std::list<uint64>::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr)
{
if (Creature* temp = Unit::GetCreature(*me, *itr))
{
if (temp->isAlive())
temp->DespawnOrUnsummon();
}
}
m_lCollapsingStarGUIDList.clear();
}
void JustSummoned(Creature* summoned)
{
if (summoned->GetEntry() == CREATURE_COLLAPSING_STAR)
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
if (me->getVictim())
summoned->AI()->AttackStart(target ? target : me->getVictim());
m_lCollapsingStarGUIDList.push_back(summoned->GetGUID());
}
}
void SummonCollapsingStar(Unit* target)
{
DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me);
me->SummonCreature(CREATURE_COLLAPSING_STAR, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 100000);
me->SummonCreature(CREATURE_BLACK_HOLE, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 27000);
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (Phase == 1 && HealthBelowPct(20))
{
Phase = 2;
DoScriptText(SAY_PHASE_2, me);
}
if (HealthBelowPct(2))
{
me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667f, -295.101166f, 417.321381f, 0, 0, 0, 0, 0, 0);
// All of them. or random?
DoScriptText(SAY_DEATH_1, me);
DoScriptText(SAY_DEATH_2, me);
DoScriptText(SAY_DEATH_3, me);
DoScriptText(SAY_DEATH_4, me);
DoScriptText(SAY_DEATH_5, me);
me->DisappearAndDie();
if (instance)
instance->SetData(BOSS_ALGALON, DONE);
return;
}
if (Phase == 1)
{
if (!Summon)
{
if (uiPhase_timer <= diff)
{
switch (uiStep)
{
case 1:
DoScriptText(SAY_SUMMON_1, me);
JumpToNextStep(3000);
break;
case 2:
DoScriptText(SAY_SUMMON_2, me);
JumpToNextStep(3000);
break;
case 3:
DoScriptText(SAY_SUMMON_3, me);
JumpToNextStep(3000);
break;
case 4:
DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me);
JumpToNextStep(3000);
break;
case 5:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_AGGRESSIVE);
Summon = true;
break;
}
} else uiPhase_timer -= diff;
return;
}
if (QuantumStrike_Timer <= diff)
{
DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE, H_SPELL_QUANTUM_STRIKE), true);
QuantumStrike_Timer = urand(4000, 14000);
} else QuantumStrike_Timer -= diff;
if (BigBang_Timer <= diff)
{
DoScriptText(RAND(SAY_BIG_BANG_1, SAY_BIG_BANG_2), me);
DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG, H_SPELL_BIG_BANG), true);
BigBang_Timer = 90000;
} else BigBang_Timer -= diff;
if (Ascend_Timer <= diff)
{
DoCast(me->getVictim(), SPELL_ASCEND, true);
Ascend_Timer = 480000;
} else Ascend_Timer -= diff;
if (PhasePunch_Timer <= diff)
{
DoCast(me->getVictim(), SPELL_PHASE_PUNCH, true);
PhasePunch_Timer = 8000;
} else PhasePunch_Timer -= diff;
if (CosmicSmash_Timer <= diff)
{
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH, H_SPELL_COSMIC_SMASH), true);
CosmicSmash_Timer = urand(30000, 60000);
} else CosmicSmash_Timer -= diff;
if (Berserk_Timer <= diff)
{
DoScriptText(SAY_BERSERK, me);
DoCast(me->getVictim(), SPELL_BERSERK, true);
Berserk_Timer = 360000;
} else Berserk_Timer -= diff;
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea(diff);
}
if (Phase == 2)
{
if (Enrage)
{
if (Ascend_Timer <= diff)
{
DoCast(me, SPELL_ASCEND);
DoScriptText(SAY_BERSERK, me);
Ascend_Timer = urand(360000, 365000);
Enrage = false;
} else Ascend_Timer -= diff;
}
}
DoMeleeAttackIfReady();
}
};
};
//Collapsing Star
class mob_collapsing_star : public CreatureScript
{
public:
mob_collapsing_star() : CreatureScript("mob_collapsing_star") { }
CreatureAI* GetAI(Creature* creature) const
{
return new mob_collapsing_starAI(creature);
}
struct mob_collapsing_starAI : public ScriptedAI
{
mob_collapsing_starAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 BlackHoleExplosion_Timer;
void Reset()
{
BlackHoleExplosion_Timer = 0;
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
if (BlackHoleExplosion_Timer <= diff)
{
me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false);
BlackHoleExplosion_Timer = 0;
} else BlackHoleExplosion_Timer -= diff;
}
};
};
void AddSC_boss_Algalon()
{
new boss_algalon();
new mob_collapsing_star();
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,9 +22,14 @@
static DoorData const doorData[] =
{
{ GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
{ GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W },
{GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
{GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
{GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
};
class instance_ulduar : public InstanceMapScript
@@ -36,7 +41,6 @@ class instance_ulduar : public InstanceMapScript
{
instance_ulduar_InstanceMapScript(InstanceMap* map) : InstanceScript(map) { }
uint32 Encounter[MAX_ENCOUNTER];
std::string m_strInstData;
// Creatures
@@ -72,6 +76,12 @@ class instance_ulduar : public InstanceMapScript
uint64 HodirDoorGUID;
uint64 HodirIceDoorGUID;
uint64 ArchivumDoorGUID;
uint64 AlgalonSigilDoorGUID[3];
uint64 AlgalonFloorGUID[2];
uint64 AlgalonUniverseGUID;
uint64 AlgalonTrapdoorGUID;
uint64 BrannBronzebeardAlgGUID;
uint64 GiftOfTheObserverGUID;
// Miscellaneous
uint32 TeamInInstance;
@@ -111,35 +121,49 @@ class instance_ulduar : public InstanceMapScript
HodirDoorGUID = 0;
HodirIceDoorGUID = 0;
ArchivumDoorGUID = 0;
AlgalonUniverseGUID = 0;
AlgalonTrapdoorGUID = 0;
BrannBronzebeardAlgGUID = 0;
GiftOfTheObserverGUID = 0;
_algalonTimer = 61;
_maxArmorItemLevel = 0;
_maxWeaponItemLevel = 0;
TeamInInstance = 0;
HodirRareCacheData = 0;
ColossusData = 0;
elderCount = 0;
conSpeedAtory = false;
Unbroken = true;
_summonAlgalon = false;
memset(Encounter, 0, sizeof(Encounter));
memset(AlgalonSigilDoorGUID, 0, sizeof(AlgalonSigilDoorGUID));
memset(AlgalonFloorGUID, 0, sizeof(AlgalonFloorGUID));
memset(XTToyPileGUIDs, 0, sizeof(XTToyPileGUIDs));
memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs));
memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs));
memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs));
}
bool IsEncounterInProgress() const
void FillInitialWorldStates(WorldPacket& packet)
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (Encounter[i] == IN_PROGRESS)
return true;
}
return false;
packet << uint32(WORLD_STATE_ALGALON_TIMER_ENABLED) << uint32(_algalonTimer && _algalonTimer <= 60);
packet << uint32(WORLD_STATE_ALGALON_DESPAWN_TIMER) << uint32(std::min<uint32>(_algalonTimer, 60));
}
void OnPlayerEnter(Player* player)
{
if (!TeamInInstance)
TeamInInstance = player->GetTeam();
if (_summonAlgalon)
{
_summonAlgalon = false;
TempSummon* algalon = instance->SummonCreature(NPC_ALGALON, AlgalonLandPos);
if (_algalonTimer && _algalonTimer <= 60)
algalon->AI()->DoAction(ACTION_INIT_ALGALON);
else
algalon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
}
void OnCreatureCreate(Creature* creature)
@@ -267,9 +291,32 @@ class instance_ulduar : public InstanceMapScript
if (TeamInInstance == HORDE)
creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA, HORDE);
break;
case NPC_BRANN_BRONZBEARD_ALG:
BrannBronzebeardAlgGUID = creature->GetGUID();
break;
//! These creatures are summoned by something else than Algalon
//! but need to be controlled/despawned by him - so they need to be
//! registered in his summon list
case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
case NPC_UNLEASHED_DARK_MATTER:
if (Creature* algalon = instance->GetCreature(AlgalonGUID))
algalon->AI()->JustSummoned(creature);
break;
}
}
}
void OnCreatureRemove(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_BRANN_BRONZBEARD_ALG:
if (BrannBronzebeardAlgGUID == creature->GetGUID())
BrannBronzebeardAlgGUID = 0;
break;
}
}
void OnGameObjectCreate(GameObject* gameObject)
{
@@ -340,6 +387,45 @@ class instance_ulduar : public InstanceMapScript
if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE)
HandleGameObject(ArchivumDoorGUID, false);
break;
case GO_CELESTIAL_PLANETARIUM_ACCESS_10:
case GO_CELESTIAL_PLANETARIUM_ACCESS_25:
if (_algalonSummoned)
gameObject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
break;
case GO_DOODAD_UL_SIGILDOOR_01:
AlgalonSigilDoorGUID[0] = gameObject->GetGUID();
if (_algalonSummoned)
gameObject->SetGoState(GO_STATE_ACTIVE);
break;
case GO_DOODAD_UL_SIGILDOOR_02:
AlgalonSigilDoorGUID[1] = gameObject->GetGUID();
if (_algalonSummoned)
gameObject->SetGoState(GO_STATE_ACTIVE);
break;
case GO_DOODAD_UL_SIGILDOOR_03:
AlgalonSigilDoorGUID[2] = gameObject->GetGUID();
AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_UNIVERSEFLOOR_01:
AlgalonFloorGUID[0] = gameObject->GetGUID();
AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_UNIVERSEFLOOR_02:
AlgalonFloorGUID[1] = gameObject->GetGUID();
AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_UNIVERSEGLOBE01:
AlgalonUniverseGUID = gameObject->GetGUID();
AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
AlgalonTrapdoorGUID = gameObject->GetGUID();
AddDoor(gameObject, true);
break;
case GO_GIFT_OF_THE_OBSERVER_10:
case GO_GIFT_OF_THE_OBSERVER_25:
GiftOfTheObserverGUID = gameObject->GetGUID();
break;
}
}
@@ -348,10 +434,14 @@ class instance_ulduar : public InstanceMapScript
switch (gameObject->GetEntry())
{
case GO_LEVIATHAN_DOOR:
case GO_XT_002_DOOR:
case GO_DOODAD_UL_SIGILDOOR_03:
case GO_DOODAD_UL_UNIVERSEFLOOR_01:
case GO_DOODAD_UL_UNIVERSEFLOOR_02:
case GO_DOODAD_UL_UNIVERSEGLOBE01:
case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
AddDoor(gameObject, false);
break;
case GO_XT_002_DOOR:
AddDoor(gameObject, false);
default:
break;
}
@@ -389,6 +479,7 @@ class instance_ulduar : public InstanceMapScript
// Flame Leviathan's Tower Event triggers
Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID);
if (FlameLeviathan && FlameLeviathan->isAlive()) // No leviathan, no event triggering ;)
{
switch (eventId)
{
case EVENT_TOWER_OF_STORM_DESTROYED:
@@ -404,6 +495,7 @@ class instance_ulduar : public InstanceMapScript
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED);
break;
}
}
}
@@ -464,6 +556,52 @@ class instance_ulduar : public InstanceMapScript
if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID))
gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
break;
case BOSS_ALGALON:
if (state == DONE)
{
_events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
_events.CancelEvent(EVENT_DESPAWN_ALGALON);
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_algalonTimer = 61;
if (GameObject* gameObject = instance->GetGameObject(GiftOfTheObserverGUID))
gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
// get item level (recheck weapons)
Map::PlayerList const& players = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->getSource())
for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot)
if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel)
_maxWeaponItemLevel = item->GetTemplate()->ItemLevel;
}
else if (state == IN_PROGRESS)
{
// get item level (armor cannot be swapped in combat)
Map::PlayerList const& players = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
if (Player* player = itr->getSource())
{
for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
{
if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
continue;
if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
{
if (slot >= EQUIPMENT_SLOT_MAINHAND && slot <= EQUIPMENT_SLOT_RANGED)
{
if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel)
_maxWeaponItemLevel = item->GetTemplate()->ItemLevel;
}
else if (item->GetTemplate()->ItemLevel > _maxArmorItemLevel)
_maxArmorItemLevel = item->GetTemplate()->ItemLevel;
}
}
}
}
}
break;
}
return true;
@@ -496,6 +634,16 @@ class instance_ulduar : public InstanceMapScript
case DATA_UNBROKEN:
Unbroken = bool(data);
break;
case EVENT_DESPAWN_ALGALON:
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60);
_algalonTimer = 60;
_events.ScheduleEvent(EVENT_DESPAWN_ALGALON, 3600000);
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
break;
case DATA_ALGALON_SUMMON_STATE:
_algalonSummoned = true;
break;
default:
break;
}
@@ -570,6 +718,22 @@ class instance_ulduar : public InstanceMapScript
return KeeperGUIDs[1];
case BOSS_STONEBARK:
return KeeperGUIDs[2];
case DATA_SIGILDOOR_01:
return AlgalonSigilDoorGUID[0];
case DATA_SIGILDOOR_02:
return AlgalonSigilDoorGUID[1];
case DATA_SIGILDOOR_03:
return AlgalonSigilDoorGUID[2];
case DATA_UNIVERSE_FLOOR_01:
return AlgalonFloorGUID[0];
case DATA_UNIVERSE_FLOOR_02:
return AlgalonFloorGUID[1];
case DATA_UNIVERSE_GLOBE:
return AlgalonUniverseGUID;
case DATA_ALGALON_TRAPDOOR:
return AlgalonTrapdoorGUID;
case DATA_BRANN_BRONZEBEARD_ALG:
return BrannBronzebeardAlgGUID;
}
return 0;
@@ -592,12 +756,23 @@ class instance_ulduar : public InstanceMapScript
return 0;
}
bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* , Unit const* /* = NULL */, uint32 /* = 0 */)
{
switch (criteriaId)
{
case CRITERIA_HERALD_OF_TITANS:
return _maxArmorItemLevel <= MAX_HERALD_ARMOR_ITEMLEVEL && _maxWeaponItemLevel <= MAX_HERALD_WEAPON_ITEMLEVEL;
}
return false;
}
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS);
saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS) << ' ' << _algalonTimer << ' ' << (_algalonSummoned ? 1 : 0);
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
@@ -627,15 +802,68 @@ class instance_ulduar : public InstanceMapScript
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
if (i == DATA_COLOSSUS)
SetData(i, tmpState);
else
SetBossState(i, EncounterState(tmpState));
SetBossState(i, EncounterState(tmpState));
}
uint32 tempState;
loadStream >> tempState;
if (tempState == IN_PROGRESS || tempState > SPECIAL)
tempState = NOT_STARTED;
SetData(DATA_COLOSSUS, tempState);
loadStream >> _algalonTimer;
loadStream >> tempState;
_algalonSummoned = tempState != 0;
if (_algalonSummoned && GetBossState(BOSS_ALGALON) != DONE)
{
_summonAlgalon = true;
if (_algalonTimer && _algalonTimer <= 60)
{
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer);
}
}
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 diff)
{
if (_events.Empty())
return;
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_UPDATE_ALGALON_TIMER:
SaveToDB();
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, --_algalonTimer);
if (_algalonTimer)
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000);
else
{
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
if (Creature* algalon = instance->GetCreature(AlgalonGUID))
algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON);
}
break;
}
}
}
private:
EventMap _events;
uint32 _algalonTimer;
bool _summonAlgalon;
bool _algalonSummoned;
uint32 _maxArmorItemLevel;
uint32 _maxWeaponItemLevel;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const

View File

@@ -18,9 +18,12 @@
#ifndef DEF_ULDUAR_H
#define DEF_ULDUAR_H
#include "ObjectMgr.h"
#include "Creature.h"
#include "GameObject.h"
#define UlduarScriptName "instance_ulduar"
extern Position const AlgalonLandPos;
enum UlduarBosses
{
MAX_ENCOUNTER = 20,
@@ -50,98 +53,124 @@ enum UlduarBosses
enum UlduarNPCs
{
// General
NPC_LEVIATHAN = 33113,
NPC_SALVAGED_DEMOLISHER = 33109,
NPC_SALVAGED_SIEGE_ENGINE = 33060,
NPC_IGNIS = 33118,
NPC_RAZORSCALE = 33186,
NPC_RAZORSCALE_CONTROLLER = 33233,
NPC_STEELFORGED_DEFFENDER = 33236,
NPC_EXPEDITION_COMMANDER = 33210,
NPC_XT002 = 33293,
NPC_XT_TOY_PILE = 33337,
NPC_STEELBREAKER = 32867,
NPC_MOLGEIM = 32927,
NPC_BRUNDIR = 32857,
NPC_KOLOGARN = 32930,
NPC_FOCUSED_EYEBEAM = 33632,
NPC_FOCUSED_EYEBEAM_RIGHT = 33802,
NPC_LEFT_ARM = 32933,
NPC_RIGHT_ARM = 32934,
NPC_RUBBLE = 33768,
NPC_AURIAYA = 33515,
NPC_MIMIRON = 33350,
NPC_HODIR = 32845,
NPC_THORIM = 32865,
NPC_FREYA = 32906,
NPC_VEZAX = 33271,
NPC_YOGGSARON = 33288,
NPC_ALGALON = 32871,
NPC_LEVIATHAN = 33113,
NPC_SALVAGED_DEMOLISHER = 33109,
NPC_SALVAGED_SIEGE_ENGINE = 33060,
NPC_IGNIS = 33118,
NPC_RAZORSCALE = 33186,
NPC_RAZORSCALE_CONTROLLER = 33233,
NPC_STEELFORGED_DEFFENDER = 33236,
NPC_EXPEDITION_COMMANDER = 33210,
NPC_XT002 = 33293,
NPC_XT_TOY_PILE = 33337,
NPC_STEELBREAKER = 32867,
NPC_MOLGEIM = 32927,
NPC_BRUNDIR = 32857,
NPC_KOLOGARN = 32930,
NPC_FOCUSED_EYEBEAM = 33632,
NPC_FOCUSED_EYEBEAM_RIGHT = 33802,
NPC_LEFT_ARM = 32933,
NPC_RIGHT_ARM = 32934,
NPC_RUBBLE = 33768,
NPC_AURIAYA = 33515,
NPC_MIMIRON = 33350,
NPC_HODIR = 32845,
NPC_THORIM = 32865,
NPC_FREYA = 32906,
NPC_VEZAX = 33271,
NPC_YOGGSARON = 33288,
NPC_ALGALON = 32871,
// Mimiron
NPC_LEVIATHAN_MKII = 33432,
NPC_VX_001 = 33651,
NPC_AERIAL_COMMAND_UNIT = 33670,
NPC_LEVIATHAN_MKII = 33432,
NPC_VX_001 = 33651,
NPC_AERIAL_COMMAND_UNIT = 33670,
// Freya's Keepers
NPC_IRONBRANCH = 32913,
NPC_BRIGHTLEAF = 32915,
NPC_STONEBARK = 32914,
NPC_IRONBRANCH = 32913,
NPC_BRIGHTLEAF = 32915,
NPC_STONEBARK = 32914,
// Hodir's Helper NPCs
NPC_TOR_GREYCLOUD = 32941,
NPC_KAR_GREYCLOUD = 33333,
NPC_EIVI_NIGHTFEATHER = 33325,
NPC_ELLIE_NIGHTFEATHER = 32901,
NPC_SPIRITWALKER_TARA = 33332,
NPC_SPIRITWALKER_YONA = 32950,
NPC_ELEMENTALIST_MAHFUUN = 33328,
NPC_ELEMENTALIST_AVUUN = 32900,
NPC_AMIRA_BLAZEWEAVER = 33331,
NPC_VEESHA_BLAZEWEAVER = 32946,
NPC_MISSY_FLAMECUFFS = 32893,
NPC_SISSY_FLAMECUFFS = 33327,
NPC_BATTLE_PRIEST_ELIZA = 32948,
NPC_BATTLE_PRIEST_GINA = 33330,
NPC_FIELD_MEDIC_PENNY = 32897,
NPC_FIELD_MEDIC_JESSI = 33326,
NPC_TOR_GREYCLOUD = 32941,
NPC_KAR_GREYCLOUD = 33333,
NPC_EIVI_NIGHTFEATHER = 33325,
NPC_ELLIE_NIGHTFEATHER = 32901,
NPC_SPIRITWALKER_TARA = 33332,
NPC_SPIRITWALKER_YONA = 32950,
NPC_ELEMENTALIST_MAHFUUN = 33328,
NPC_ELEMENTALIST_AVUUN = 32900,
NPC_AMIRA_BLAZEWEAVER = 33331,
NPC_VEESHA_BLAZEWEAVER = 32946,
NPC_MISSY_FLAMECUFFS = 32893,
NPC_SISSY_FLAMECUFFS = 33327,
NPC_BATTLE_PRIEST_ELIZA = 32948,
NPC_BATTLE_PRIEST_GINA = 33330,
NPC_FIELD_MEDIC_PENNY = 32897,
NPC_FIELD_MEDIC_JESSI = 33326,
// Freya's trash NPCs
NPC_CORRUPTED_SERVITOR = 33354,
NPC_MISGUIDED_NYMPH = 33355,
NPC_GUARDIAN_LASHER = 33430,
NPC_FOREST_SWARMER = 33431,
NPC_MANGROVE_ENT = 33525,
NPC_IRONROOT_LASHER = 33526,
NPC_NATURES_BLADE = 33527,
NPC_GUARDIAN_OF_LIFE = 33528,
NPC_CORRUPTED_SERVITOR = 33354,
NPC_MISGUIDED_NYMPH = 33355,
NPC_GUARDIAN_LASHER = 33430,
NPC_FOREST_SWARMER = 33431,
NPC_MANGROVE_ENT = 33525,
NPC_IRONROOT_LASHER = 33526,
NPC_NATURES_BLADE = 33527,
NPC_GUARDIAN_OF_LIFE = 33528,
// Algalon the Observer
NPC_BRANN_BRONZBEARD_ALG = 34064,
NPC_AZEROTH = 34246,
NPC_LIVING_CONSTELLATION = 33052,
NPC_ALGALON_STALKER = 33086,
NPC_COLLAPSING_STAR = 32955,
NPC_BLACK_HOLE = 32953,
NPC_WORM_HOLE = 34099,
NPC_ALGALON_VOID_ZONE_VISUAL_STALKER = 34100,
NPC_ALGALON_STALKER_ASTEROID_TARGET_01 = 33104,
NPC_ALGALON_STALKER_ASTEROID_TARGET_02 = 33105,
NPC_UNLEASHED_DARK_MATTER = 34097,
};
enum UlduarGameObjects
{
GO_KOLOGARN_CHEST_HERO = 195047,
GO_KOLOGARN_CHEST = 195046,
GO_KOLOGARN_BRIDGE = 194232,
GO_KOLOGARN_DOOR = 194553,
GO_THORIM_CHEST_HERO = 194315,
GO_THORIM_CHEST = 194314,
GO_HODIR_RARE_CACHE_OF_WINTER = 194200,
GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201,
GO_HODIR_CHEST_HERO = 194308,
GO_HODIR_CHEST = 194307,
GO_LEVIATHAN_DOOR = 194905,
GO_LEVIATHAN_GATE = 194630,
GO_XT_002_DOOR = 194631,
GO_VEZAX_DOOR = 194750,
GO_MOLE_MACHINE = 194316,
GO_RAZOR_HARPOON_1 = 194542,
GO_RAZOR_HARPOON_2 = 194541,
GO_RAZOR_HARPOON_3 = 194543,
GO_RAZOR_HARPOON_4 = 194519,
GO_RAZOR_BROKEN_HARPOON = 194565,
GO_HODIR_DOOR = 194634,
GO_HODIR_ICE_DOOR = 194441,
GO_ARCHIVUM_DOOR = 194556,
GO_KOLOGARN_CHEST_HERO = 195047,
GO_KOLOGARN_CHEST = 195046,
GO_KOLOGARN_BRIDGE = 194232,
GO_KOLOGARN_DOOR = 194553,
GO_THORIM_CHEST_HERO = 194315,
GO_THORIM_CHEST = 194314,
GO_HODIR_RARE_CACHE_OF_WINTER = 194200,
GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201,
GO_HODIR_CHEST_HERO = 194308,
GO_HODIR_CHEST = 194307,
GO_LEVIATHAN_DOOR = 194905,
GO_LEVIATHAN_GATE = 194630,
GO_XT_002_DOOR = 194631,
GO_VEZAX_DOOR = 194750,
GO_MOLE_MACHINE = 194316,
GO_RAZOR_HARPOON_1 = 194542,
GO_RAZOR_HARPOON_2 = 194541,
GO_RAZOR_HARPOON_3 = 194543,
GO_RAZOR_HARPOON_4 = 194519,
GO_RAZOR_BROKEN_HARPOON = 194565,
GO_HODIR_DOOR = 194634,
GO_HODIR_ICE_DOOR = 194441,
GO_ARCHIVUM_DOOR = 194556,
// Algalon the Observer
GO_CELESTIAL_PLANETARIUM_ACCESS_10 = 194628,
GO_CELESTIAL_PLANETARIUM_ACCESS_25 = 194752,
GO_DOODAD_UL_SIGILDOOR_01 = 194767,
GO_DOODAD_UL_SIGILDOOR_02 = 194911,
GO_DOODAD_UL_SIGILDOOR_03 = 194910,
GO_DOODAD_UL_UNIVERSEFLOOR_01 = 194715,
GO_DOODAD_UL_UNIVERSEFLOOR_02 = 194716,
GO_DOODAD_UL_UNIVERSEGLOBE01 = 194148,
GO_DOODAD_UL_ULDUAR_TRAPDOOR_03 = 194253,
GO_GIFT_OF_THE_OBSERVER_10 = 194821,
GO_GIFT_OF_THE_OBSERVER_25 = 194822,
};
enum LeviathanData
@@ -161,6 +190,7 @@ enum UlduarAchievementCriteriaIds
{
CRITERIA_CON_SPEED_ATORY = 21597,
CRITERIA_DISARMED = 21687,
CRITERIA_HERALD_OF_TITANS = 10678,
};
enum UlduarData
@@ -180,12 +210,38 @@ enum UlduarData
// Hodir
DATA_HODIR_RARE_CACHE,
// Algalon the Observer
DATA_ALGALON_SUMMON_STATE,
DATA_SIGILDOOR_01,
DATA_SIGILDOOR_02,
DATA_SIGILDOOR_03,
DATA_UNIVERSE_FLOOR_01,
DATA_UNIVERSE_FLOOR_02,
DATA_UNIVERSE_GLOBE,
DATA_ALGALON_TRAPDOOR,
DATA_BRANN_BRONZEBEARD_ALG,
};
enum UlduarWorldStates
{
WORLD_STATE_ALGALON_DESPAWN_TIMER = 4131,
WORLD_STATE_ALGALON_TIMER_ENABLED = 4132,
};
enum UlduarAchievementData
{
// FL Achievement boolean
DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs,
MAX_HERALD_ARMOR_ITEMLEVEL = 226,
MAX_HERALD_WEAPON_ITEMLEVEL = 232,
};
enum UlduarEvents
{
EVENT_DESPAWN_ALGALON = 1,
EVENT_UPDATE_ALGALON_TIMER = 2,
ACTION_INIT_ALGALON = 6,
};
template<class AI>
@@ -199,6 +255,17 @@ CreatureAI* GetUlduarAI(Creature* creature)
return NULL;
}
template<class AI>
GameObjectAI* GetUlduarAI(GameObject* go)
{
if (InstanceMap* instance = go->GetMap()->ToInstanceMap())
if (instance->GetInstanceScript())
if (instance->GetScriptId() == sObjectMgr->GetScriptId(UlduarScriptName))
return new AI(go);
return NULL;
}
class PlayerOrPetCheck
{
public: