Script HoR instance. 1st part.

Fixes issue #1311.

- Intro event.
- 10 waves including Falric and Marwyn.
- Script based on proposal of Synric on trinitycore forum (submitted by Skarabex on GC).

--HG--
branch : trunk
This commit is contained in:
Trazom62
2010-05-20 20:09:18 +02:00
parent ce7886aeb0
commit d2cad4b14e
14 changed files with 1907 additions and 35 deletions
+8
View File
@@ -416,6 +416,10 @@ void AddSC_pit_of_saron();
void AddSC_boss_garfrost();
void AddSC_boss_ick();
void AddSC_boss_tyrannus();
void AddSC_instance_halls_of_reflection(); // Halls of Reflection
void AddSC_halls_of_reflection();
void AddSC_boss_falric();
void AddSC_boss_marwyn();
void AddSC_dalaran();
void AddSC_borean_tundra();
@@ -912,6 +916,10 @@ void AddScripts()
AddSC_boss_garfrost();
AddSC_boss_ick();
AddSC_boss_tyrannus();
AddSC_instance_halls_of_reflection(); // Halls of Reflection
AddSC_halls_of_reflection();
AddSC_boss_falric();
AddSC_boss_marwyn();
AddSC_dalaran();
AddSC_borean_tundra();
+20 -3
View File
@@ -1089,9 +1089,26 @@ void Aura::HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster,
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
// Remove the immunity shield marker on Avenging Wrath removal if Forbearance is not present
if (GetId() == 61987 && target->HasAura(61988) && !target->HasAura(25771))
target->RemoveAura(61988);
switch(GetId())
{
case 61987: // Avenging Wrath
// Remove the immunity shield marker on Avenging Wrath removal if Forbearance is not present
if (target->HasAura(61988) && !target->HasAura(25771))
target->RemoveAura(61988);
break;
case 72368: // Shared Suffering
case 72369:
if (caster)
{
if (AuraEffect* aurEff = GetEffect(0))
{
int32 remainingDamage = aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber());
if (remainingDamage > 0)
caster->CastCustomSpell(caster, 72373, NULL, &remainingDamage, NULL, true);
}
}
break;
}
break;
case SPELLFAMILY_MAGE:
switch(GetId())
+1
View File
@@ -3629,6 +3629,7 @@ void SpellMgr::LoadSpellCustomAttr()
case 42384: // Brutal Swipe
case 45150: // Meteor Slash
case 64422: case 64688: // Sonic Screech
case 72373: // Shared Suffering
// ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE
mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE;
count++;
+3
View File
@@ -346,7 +346,10 @@ SET(scripts_STAT_SRCS
northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp
northrend/frozen_halls/forge_of_souls/forge_of_souls.h
northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp
northrend/frozen_halls/halls_of_reflection/boss_falric.cpp
northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp
northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp
northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp
northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h
northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp
northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp
@@ -0,0 +1,142 @@
/* Copyright (C) 2006 - 2010 TrinityCore <https://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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ScriptedPch.h"
#include "halls_of_reflection.h"
enum Yells
{
SAY_AGGRO = -1668050,
SAY_SLAY_1 = -1668051,
SAY_SLAY_2 = -1668052,
SAY_DEATH = -1668053,
SAY_IMPENDING_DESPAIR = -1668054,
SAY_DEFILING_HORROR = -1668055,
};
enum Spells
{
SPELL_QUIVERING_STRIKE = 72422,
SPELL_IMPENDING_DESPAIR = 72426,
SPELL_DEFILING_HORROR = 72435,
SPELL_HOPELESSNESS = 72395,
H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB.
};
enum Events
{
EVENT_NONE,
EVENT_QUIVERING_STRIKE,
EVENT_IMPENDING_DESPAIR,
EVENT_DEFILING_HORROR,
};
struct boss_falricAI : public boss_horAI
{
boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {}
uint8 uiHopelessnessCount;
void Reset()
{
boss_horAI::Reset();
uiHopelessnessCount = 0;
if (pInstance)
pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* who)
{
DoScriptText(SAY_AGGRO, me);
if (pInstance)
pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS);
events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000);
events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000);
events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer.
}
void JustDied(Unit* killer)
{
DoScriptText(SAY_DEATH, me);
if (pInstance)
pInstance->SetData(DATA_FALRIC_EVENT, DONE);
}
void KilledUnit(Unit *victim)
{
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void UpdateAI(const uint32 diff)
{
// Return since we have no target
if (!UpdateVictim())
return;
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_QUIVERING_STRIKE:
DoCast(SPELL_QUIVERING_STRIKE);
events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000);
break;
case EVENT_IMPENDING_DESPAIR:
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM))
{
DoScriptText(SAY_IMPENDING_DESPAIR, me);
DoCast(pTarget, SPELL_IMPENDING_DESPAIR);
}
events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000);
break;
case EVENT_DEFILING_HORROR:
DoCast(SPELL_DEFILING_HORROR);
events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer.
break;
}
if ((uiHopelessnessCount < 1 && HealthBelowPct(66))
|| (uiHopelessnessCount < 2 && HealthBelowPct(33))
|| (uiHopelessnessCount < 3 && HealthBelowPct(10)))
{
uiHopelessnessCount++;
DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS));
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_falric(Creature* pCreature)
{
return new boss_falricAI(pCreature);
}
void AddSC_boss_falric()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_falric";
newscript->GetAI = &GetAI_boss_falric;
newscript->RegisterSelf();
}
@@ -0,0 +1,133 @@
/* Copyright (C) 2006 - 2010 TrinityCore <https://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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ScriptedPch.h"
#include "halls_of_reflection.h"
enum Yells
{
SAY_AGGRO = -1668060,
SAY_SLAY_1 = -1668061,
SAY_SLAY_2 = -1668062,
SAY_DEATH = -1668063,
SAY_CORRUPTED_FLESH_1 = -1668064,
SAY_CORRUPTED_FLESH_2 = -1668065,
};
enum Spells
{
SPELL_OBLITERATE = 72360,
SPELL_WELL_OF_CORRUPTION = 72362,
SPELL_CORRUPTED_FLESH = 72363,
SPELL_SHARED_SUFFERING = 72368,
};
enum Events
{
EVENT_NONE,
EVENT_OBLITERATE,
EVENT_WELL_OF_CORRUPTION,
EVENT_CORRUPTED_FLESH,
EVENT_SHARED_SUFFERING,
};
struct boss_marwynAI : public boss_horAI
{
boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {}
void Reset()
{
boss_horAI::Reset();
if (pInstance)
pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* who)
{
DoScriptText(SAY_AGGRO, me);
if (pInstance)
pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS);
events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer
events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer
}
void JustDied(Unit* killer)
{
DoScriptText(SAY_DEATH, me);
if (pInstance)
pInstance->SetData(DATA_MARWYN_EVENT, DONE);
}
void KilledUnit(Unit *victim)
{
DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me);
}
void UpdateAI(const uint32 diff)
{
// Return since we have no target
if (!UpdateVictim())
return;
events.Update(diff);
if (me->hasUnitState(UNIT_STAT_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_OBLITERATE:
DoCast(SPELL_OBLITERATE);
events.ScheduleEvent(EVENT_OBLITERATE, 30000);
break;
case EVENT_WELL_OF_CORRUPTION:
DoCast(SPELL_WELL_OF_CORRUPTION);
events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
break;
case EVENT_CORRUPTED_FLESH:
DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me);
DoCast(SPELL_CORRUPTED_FLESH);
events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
break;
case EVENT_SHARED_SUFFERING:
if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM))
DoCast(pTarget, SPELL_SHARED_SUFFERING);
events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000);
break;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_marwyn(Creature* pCreature)
{
return new boss_marwynAI(pCreature);
}
void AddSC_boss_marwyn()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_marwyn";
newscript->GetAI = &GetAI_boss_marwyn;
newscript->RegisterSelf();
}
File diff suppressed because it is too large Load Diff
@@ -16,16 +16,141 @@
#ifndef DEF_HALLS_OF_REFLECTION_H
#define DEF_HALLS_OF_REFLECTION_H
enum Data
{
DATA_FALRIC_EVENT,
DATA_MARWYN_EVENT,
DATA_LICHKING_EVENT
DATA_LICHKING_EVENT,
DATA_WAVE_COUNT,
DATA_TEAM_IN_INSTANCE,
};
enum Data64
{
DATA_FALRIC,
DATA_MARWYN,
DATA_LICHKING,
DATA_FROSTMOURNE,
};
enum Creatures
{
CREATURE_FALRIC = 36494,
CREATURE_MARWYN = 36476,
CREATURE_LICHKING = 36658
NPC_FALRIC = 38112,
NPC_MARWYN = 38113,
NPC_LICH_KING_EVENT = 37226,
NPC_LICH_KING_BOSS = 36954,
NPC_UTHER = 37225,
NPC_JAINA_PART1 = 37221,
NPC_JAINA_PART2 = 36955,
NPC_SYLVANAS_PART1 = 37223,
NPC_SYLVANAS_PART2 = 37554,
NPC_WAVE_MERCENARY = 38177,
NPC_WAVE_FOOTMAN = 38173,
NPC_WAVE_RIFLEMAN = 38176,
NPC_WAVE_PRIEST = 38175,
NPC_WAVE_MAGE = 38172,
};
enum GameObjects
{
GO_FROSTMOURNE = 202302,
GO_FROSTMOURNE_ALTAR = 202236,
GO_FRONT_DOOR = 201976,
GO_ARTHAS_DOOR = 197341,
};
enum HorWorldStates
{
WORLD_STATE_HOR = 4884,
WORLD_STATE_HOR_WAVE_COUNT = 4882,
};
// Common actions from Instance Script to Boss Script
enum Actions
{
ACTION_ENTER_COMBAT,
};
// Base class for FALRIC and MARWYN
// handled the summonList and the notification events to/from the InstanceData
struct boss_horAI : ScriptedAI
{
boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature)
{
pInstance = me->GetInstanceData();
}
InstanceData* pInstance;
EventMap events;
SummonList summons;
void Reset()
{
events.Reset();
me->SetVisibility(VISIBILITY_OFF);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_PASSIVE);
}
void DamageTaken(Unit *pWho, uint32 &uiDamage)
{
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
uiDamage = 0;
}
void DoAction(const int32 actionID)
{
switch(actionID)
{
case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat.
// Just in case. Should have been done by InstanceData
me->SetVisibility(VISIBILITY_ON);
// Reset flags
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
if (Unit *pUnit = me->SelectNearestTarget())
AttackStart(pUnit);
DoZoneInCombat();
break;
}
}
void JustSummoned(Creature *pSummoned)
{
summons.Summon(pSummoned);
if (Unit *pUnit = pSummoned->SelectNearestTarget())
{
if (pSummoned->AI())
pSummoned->AI()->AttackStart(pUnit);
else
{
pSummoned->GetMotionMaster()->MoveChase(pUnit);
pSummoned->Attack(pUnit, true);
}
}
if (pSummoned->AI())
pSummoned->AI()->DoZoneInCombat();
}
void SummonedCreatureDespawn(Creature *pSummoned)
{
summons.Despawn(pSummoned);
if (summons.empty())
{
if (pSummoned->isAlive())
pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
else
pInstance->SetData(DATA_WAVE_COUNT, SPECIAL);
}
}
};
#endif
@@ -25,61 +25,212 @@
2- The Lich King
*/
enum eEnum
{
ENCOUNTER_WAVE_MERCENARY = 6,
ENCOUNTER_WAVE_FOOTMAN = 10,
ENCOUNTER_WAVE_RIFLEMAN = 6,
ENCOUNTER_WAVE_PRIEST = 6,
ENCOUNTER_WAVE_MAGE = 6,
};
enum Events
{
EVENT_NONE,
EVENT_NEXT_WAVE,
EVENT_START_LICH_KING,
};
static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] =
{
{5277.74,2016.88,707.778,5.96903},
{5295.88,2040.34,707.778,5.07891},
{5320.37,1980.13,707.778,2.00713},
{5280.51,1997.84,707.778,0.296706},
{5302.45,2042.22,707.778,4.90438},
{5306.57,1977.47,707.778,1.50098},
};
static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] =
{
{5312.75,2037.12,707.778,4.59022},
{5309.58,2042.67,707.778,4.69494},
{5275.08,2008.72,707.778,6.21337},
{5279.65,2004.66,707.778,0.069813},
{5275.48,2001.14,707.778,0.174533},
{5316.7,2041.55,707.778,4.50295},
};
static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] =
{
{5302.25,1972.41,707.778,1.37881},
{5311.03,1972.23,707.778,1.64061},
{5277.36,1993.23,707.778,0.401426},
{5318.7,2036.11,707.778,4.2237},
{5335.72,1996.86,707.778,2.74017},
{5299.43,1979.01,707.778,1.23918},
};
static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] =
{
{5306.06,2037,707.778,4.81711},
{5344.15,2007.17,707.778,3.15905},
{5337.83,2010.06,707.778,3.22886},
{5343.29,1999.38,707.778,2.9147},
{5340.84,1992.46,707.778,2.75762},
{5325.07,1977.6,707.778,2.07694},
{5336.6,2017.28,707.778,3.47321},
{5313.82,1978.15,707.778,1.74533},
{5280.63,2012.16,707.778,6.05629},
{5322.96,2040.29,707.778,4.34587},
};
static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] =
{
{5343.47,2015.95,707.778,3.49066},
{5337.86,2003.4,707.778,2.98451},
{5319.16,1974,707.778,1.91986},
{5299.25,2036,707.778,5.02655},
{5295.64,1973.76,707.778,1.18682},
{5282.9,2019.6,707.778,5.88176},
};
struct instance_halls_of_reflection : public ScriptedInstance
{
instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {};
uint64 uiFalric;
uint64 uiMarwyn;
uint64 uiLichKing;
uint64 uiLichKingEvent;
uint64 uiJainaPart1;
uint64 uiSylvanasPart1;
uint32 m_auiEncounter[MAX_ENCOUNTER];
uint64 uiFrostmourne;
uint64 uiFrostmourneAltar;
uint64 uiArthasDoor;
uint64 uiFrontDoor;
uint32 uiEncounter[MAX_ENCOUNTER];
uint32 uiTeamInInstance;
uint32 uiWaveCount;
bool bIntroDone;
EventMap events;
void Initialize()
{
events.Reset();
uiFalric = 0;
uiMarwyn = 0;
uiLichKing = 0;
uiLichKingEvent = 0;
uiJainaPart1 = 0;
uiSylvanasPart1 = 0;
uiFrostmourne = 0;
uiFrostmourneAltar = 0;
uiArthasDoor = 0;
uiFrontDoor = 0;
uiTeamInInstance = 0;
uiWaveCount = 0;
bIntroDone = false;
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
m_auiEncounter[i] = NOT_STARTED;
uiEncounter[i] = NOT_STARTED;
}
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
void OnCreatureCreate(Creature* pCreature, bool add)
{
if (!add)
return;
Map::PlayerList const &players = instance->GetPlayers();
if (!players.isEmpty())
if (Player* pPlayer = players.begin()->getSource())
uiTeamInInstance = pPlayer->GetTeam();
switch(pCreature->GetEntry())
{
case CREATURE_FALRIC:
case NPC_FALRIC:
uiFalric = pCreature->GetGUID();
break;
case CREATURE_MARWYN:
case NPC_MARWYN:
uiMarwyn = pCreature->GetGUID();
break;
case CREATURE_LICHKING:
uiLichKing = pCreature->GetGUID();
case NPC_LICH_KING_EVENT:
uiLichKingEvent = pCreature->GetGUID();
break;
case NPC_JAINA_PART1:
uiJainaPart1 = pCreature->GetGUID();
break;
case NPC_SYLVANAS_PART1:
uiSylvanasPart1 = pCreature->GetGUID();
break;
}
}
/*
void OnGameObjectCreate(GameObject* pGo, bool add)
{
if (!add)
return;
// TODO: init state depending on encounters
switch(pGo->GetEntry())
{
case GO_FROSTMOURNE:
uiFrostmourne = pGo->GetGUID();
pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
HandleGameObject(0, false, pGo);
break;
case GO_FROSTMOURNE_ALTAR:
uiFrostmourneAltar = pGo->GetGUID();
pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
HandleGameObject(0, true, pGo);
break;
case GO_FRONT_DOOR:
uiFrontDoor = pGo->GetGUID();
pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
HandleGameObject(0, true, pGo);
break;
case GO_ARTHAS_DOOR:
uiArthasDoor = pGo->GetGUID();
pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
if (uiEncounter[1] == DONE)
HandleGameObject(0, true, pGo);
else
HandleGameObject(0, false, pGo);
break;
}
}
*/
void SetData(uint32 type, uint32 data)
{
if (type == DATA_WAVE_COUNT && data == SPECIAL)
{
bIntroDone = true;
events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
return;
}
if (uiWaveCount && data == NOT_STARTED)
DoWipe();
switch(type)
{
case DATA_FALRIC_EVENT:
m_auiEncounter[0] = data;
uiEncounter[0] = data;
if (data == DONE)
events.ScheduleEvent(EVENT_NEXT_WAVE, 60000);
break;
case DATA_MARWYN_EVENT:
m_auiEncounter[1] = data;
uiEncounter[1] = data;
if (data == DONE)
HandleGameObject(uiArthasDoor, true);
break;
case DATA_LICHKING_EVENT:
m_auiEncounter[2] = data;
uiEncounter[2] = data;
break;
}
@@ -91,29 +242,35 @@ struct instance_halls_of_reflection : public ScriptedInstance
{
switch(type)
{
case DATA_FALRIC_EVENT: return m_auiEncounter[0];
case DATA_MARWYN_EVENT: return m_auiEncounter[1];
case DATA_LICHKING_EVENT: return m_auiEncounter[2];
case DATA_FALRIC_EVENT: return uiEncounter[0];
case DATA_MARWYN_EVENT: return uiEncounter[1];
case DATA_LICHKING_EVENT: return uiEncounter[2];
case DATA_WAVE_COUNT: return uiWaveCount;
case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance;
}
return 0;
}
/*
uint64 GetData64(uint32 identifier)
{
switch(identifier)
{
case DATA_FALRIC: return uiFalric;
case DATA_MARWYN: return uiMarwyn;
case DATA_LICHKING: return uiLichKingEvent;
case DATA_FROSTMOURNE: return uiFrostmourne;
}
return 0;
}
*/
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << "H R " << m_auiEncounter[0] << " " << m_auiEncounter[1] << m_auiEncounter[2];
saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2];
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
@@ -130,25 +287,133 @@ struct instance_halls_of_reflection : public ScriptedInstance
OUT_LOAD_INST_DATA(in);
char dataHead1, dataHead2;
uint16 version;
uint16 data0, data1, data2;
std::istringstream loadStream(in);
loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2;
loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2;
if (dataHead1 == 'H' && dataHead2 == 'R')
{
m_auiEncounter[0] = data0;
m_auiEncounter[1] = data1;
m_auiEncounter[2] = data2;
uiEncounter[0] = data0;
uiEncounter[1] = data1;
uiEncounter[2] = data2;
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
if (uiEncounter[i] == IN_PROGRESS)
uiEncounter[i] = NOT_STARTED;
} else OUT_LOAD_INST_DATA_FAIL;
if (uiEncounter[0] == DONE || uiEncounter[1] == DONE)
bIntroDone = true;
OUT_LOAD_INST_DATA_COMPLETE;
}
void AddWave()
{
DoUpdateWorldState(WORLD_STATE_HOR, 1);
DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount);
switch(uiWaveCount)
{
case 1:
case 2:
case 3:
case 4:
if (Creature *pFalric = instance->GetCreature(uiFalric))
SpawnWave(pFalric);
break;
case 5:
if (GetData(DATA_FALRIC_EVENT) == DONE)
events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
else if (Creature *pFalric = instance->GetCreature(uiFalric))
if (pFalric->AI())
pFalric->AI()->DoAction(ACTION_ENTER_COMBAT);
break;
case 6:
case 7:
case 8:
case 9:
if (Creature *pMarwyn = instance->GetCreature(uiMarwyn))
SpawnWave(pMarwyn);
break;
case 10:
if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit!
if (Creature *pMarwyn = instance->GetCreature(uiMarwyn))
if (pMarwyn->AI())
pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT);
break;
}
}
// Wipe has been detected. Perform cleanup and reset.
void DoWipe()
{
uiWaveCount = 0;
events.Reset();
DoUpdateWorldState(WORLD_STATE_HOR, 1);
DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount);
HandleGameObject(uiFrontDoor, true);
// TODO
// in case of wipe, the event is normally restarted by jumping into the center of the room.
// As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted.
if (Creature* pJaina = instance->GetCreature(uiJainaPart1))
pJaina->Respawn();
if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1))
pSylvanas->Respawn();
if (Creature* pFalric = instance->GetCreature(uiFalric))
pFalric->SetVisibility(VISIBILITY_OFF);
if (Creature* pMarwyn = instance->GetCreature(uiMarwyn))
pMarwyn->SetVisibility(VISIBILITY_OFF);
}
// spawn a wave on behalf of the summoner.
void SpawnWave(Creature *pSummoner)
{
uint32 index;
pSummoner->SetVisibility(VISIBILITY_ON);
// TODO: do composition at random. # of spawn also depends on uiWaveCount
// As of now, it is just one of each.
index = urand(0,ENCOUNTER_WAVE_MERCENARY-1);
pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1);
pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1);
pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
index = urand(0,ENCOUNTER_WAVE_PRIEST-1);
pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
index = urand(0,ENCOUNTER_WAVE_MAGE-1);
pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
}
void Update(uint32 diff)
{
if (!instance->HavePlayers())
return;
events.Update(diff);
switch(uint32 eventId = events.ExecuteEvent())
{
case EVENT_NEXT_WAVE:
uiWaveCount++;
AddWave();
break;
case EVENT_START_LICH_KING:
// TODO
break;
}
}
};
InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap)
@@ -156,7 +421,7 @@ InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap)
return new instance_halls_of_reflection(pMap);
}
void AddSC_halls_of_reflection()
void AddSC_instance_halls_of_reflection()
{
Script *newscript;
newscript = new Script;