Review of Onyxia's Lair

Make it 95% perfect to LK version (fixes spawns, eruption, achievements and some more)

Fixes issue #1706
Fixes issue #1736d

--HG--
branch : trunk
This commit is contained in:
John Holiver
2010-05-22 15:26:38 -03:00
parent d1099c345d
commit b3bd094785
7 changed files with 564 additions and 155 deletions
+2
View File
@@ -262,6 +262,7 @@ void AddSC_boss_landslide();
void AddSC_boss_noxxion();
void AddSC_boss_ptheradras();
void AddSC_boss_onyxia(); //Onyxia's Lair
void AddSC_instance_onyxias_lair();
void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs
void AddSC_razorfen_downs();
void AddSC_instance_razorfen_downs();
@@ -763,6 +764,7 @@ void AddScripts()
AddSC_boss_noxxion();
AddSC_boss_ptheradras();
AddSC_boss_onyxia(); //Onyxia's Lair
AddSC_instance_onyxias_lair();
AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs
AddSC_razorfen_downs();
AddSC_instance_razorfen_downs();
+1
View File
@@ -262,6 +262,7 @@ SET(scripts_STAT_SRCS
kalimdor/maraudon/boss_noxxion.cpp
kalimdor/maraudon/boss_princess_theradras.cpp
kalimdor/onyxias_lair/boss_onyxia.cpp
kalimdor/onyxias_lair/instance_onyxias_lair.cpp
kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp
kalimdor/razorfen_downs/razorfen_downs.cpp
kalimdor/razorfen_downs/instance_razorfen_downs.cpp
+244 -155
View File
@@ -1,44 +1,52 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
/* Copyright (C) 2008 - 2010 Trinity <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,
* 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
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
SDName: Boss_Onyxia
SD%Complete: 90
SDComment: Phase 3 need additianal code. Phase 2 requires entries in spell_target_position with specific locations. See bottom of file.
SD%Complete: 95
SDComment: <Known bugs>
Ground visual for Deep Breath effect;
Wing Buffet not ignoring armor;
Not summoning whelps on phase 3 (lacks info)
</Known bugs>
SDCategory: Onyxia's Lair
EndScriptData */
#include "ScriptedPch.h"
#include "onyxias_lair.h"
enum
enum eYells
{
SAY_AGGRO = -1249000,
SAY_KILL = -1249001,
SAY_PHASE_2_TRANS = -1249002,
SAY_PHASE_3_TRANS = -1249003,
EMOTE_BREATH = -1249004,
};
SPELL_WINGBUFFET = 18500,
SPELL_FLAMEBREATH = 18435,
SPELL_CLEAVE = 19983,
SPELL_TAILSWEEP = 15847,
SPELL_KNOCK_AWAY = 19633,
enum eSpells
{
// Phase 1 spells
SPELL_WING_BUFFET = 18500,
SPELL_FLAME_BREATH = 18435,
SPELL_CLEAVE = 68868,
SPELL_TAIL_SWEEP = 68867,
SPELL_ENGULFINGFLAMES = 20019,
SPELL_DEEPBREATH = 23461,
// Phase 2 spells
SPELL_DEEP_BREATH = 23461,
SPELL_FIREBALL = 18392,
//Not much choise about these. We have to make own defintion on the direction/start-end point
@@ -55,20 +63,8 @@ enum
//SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays
SPELL_BELLOWINGROAR = 18431,
SPELL_HEATED_GROUND = 22191,
SPELL_SUMMONWHELP = 17646,
SPELL_SUMMONLAIRGUARD = 68968,
NPC_WHELP = 11262,
MAX_WHELP = 20,
NPC_LAIRGUARD = 36561,
PHASE_START = 1,
PHASE_BREATH = 2,
PHASE_END = 3,
ACHIEV_TIMED_START_EVENT = 6601,
// Phase 3 spells
SPELL_BELLOWING_ROAR = 18431,
};
struct sOnyxMove
@@ -81,30 +77,37 @@ struct sOnyxMove
static sOnyxMove aMoveData[]=
{
{0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -60.9457f},//west
{1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -60.1278f},//east
{2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -60.896f},//north-west
{3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -60.896f},//north-east
{4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -60.477f},//south-east
{5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -60.790f},//south-west
{6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -60.2985f},//south
{7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -60.0548f},//north
{0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f},//west
{1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f},//east
{2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -55.896f},//north-west
{3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -55.896f},//north-east
{4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -55.477f},//south-east
{5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -55.790f},//south-west
{6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -55.2985f},//south
{7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f},//north
};
static float afSpawnLocations[2][3]=
const Position MiddleRoomLocation = {-23.6155, -215.357, -55.7344};
static Position aSpawnLocations[3]=
{
//Whelps
{-30.127, -254.463, -89.440},
{-30.817, -177.106, -89.258}
{-30.817, -177.106, -89.258},
//Lair Guard
{-145.950, -212.831, -68.659}
};
struct boss_onyxiaAI : public ScriptedAI
{
boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature)
boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me)
{
instance = me->GetInstanceData();
m_pInstance = pCreature->GetInstanceData();
Reset();
}
InstanceData *instance;
ScriptedInstance* m_pInstance;
SummonList Summons;
uint32 m_uiPhase;
@@ -117,21 +120,19 @@ struct boss_onyxiaAI : public ScriptedAI
uint32 m_uiMovementTimer;
sOnyxMove* m_pPointData;
uint32 m_uiEngulfingFlamesTimer;
uint32 m_uiSummonWhelpsTimer;
uint32 m_uiBellowingRoarTimer;
uint32 m_uiFireballTimer;
uint32 m_uiWhelpTimer;
uint32 m_uiLairGuardTimer;
uint32 m_uiDeepBreathTimer;
uint8 m_uiSummonCount;
bool m_bIsSummoningWhelps;
bool m_bIsSummoningLairGuards;
uint32 m_uiBellowingRoarTimer;
uint8 m_uiSummonWhelpCount;
uint8 m_uiSummonLairGuardCount;
bool m_bIsMoving;
void Reset()
{
if (instance)
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
if (!IsCombatMovement())
SetCombatMovement(true);
@@ -146,40 +147,77 @@ struct boss_onyxiaAI : public ScriptedAI
m_uiMovementTimer = 20000;
m_pPointData = GetMoveData();
m_uiEngulfingFlamesTimer = 15000;
m_uiSummonWhelpsTimer = 45000;
m_uiBellowingRoarTimer = 30000;
m_uiFireballTimer = 15000;
m_uiWhelpTimer = 1000;
m_uiLairGuardTimer = 1000;
m_uiLairGuardTimer = 15000;
m_uiDeepBreathTimer = 85000;
m_uiSummonCount = 0;
m_bIsSummoningWhelps = false;
m_bIsSummoningLairGuards = false;
m_uiBellowingRoarTimer = 30000;
Summons.DespawnAll();
m_uiSummonWhelpCount = 0;
m_uiSummonLairGuardCount = 0;
m_bIsMoving = false;
if (m_pInstance)
{
m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED);
m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase);
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
}
void EnterCombat(Unit* /*pWho*/)
void EnterCombat(Unit* pWho)
{
DoScriptText(SAY_AGGRO, me);
me->SetInCombatWithZone();
if (m_pInstance)
{
m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS);
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
sLog.outBasic("[Onyxia] DoStartTimedAchievement(%u,%u)",ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
}
if (instance)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
void JustDied(Unit* killer)
{
if (m_pInstance)
m_pInstance->SetData(DATA_ONYXIA, DONE);
Summons.DespawnAll();
}
void JustSummoned(Creature *pSummoned)
{
pSummoned->SetInCombatWithZone();
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0))
pSummoned->AI()->AttackStart(pTarget);
++m_uiSummonCount;
switch (pSummoned->GetEntry())
{
case NPC_WHELP:
++m_uiSummonWhelpCount;
break;
case NPC_LAIRGUARD:
pSummoned->setActive(true);
++m_uiSummonLairGuardCount;
break;
}
Summons.Summon(pSummoned);
}
void KilledUnit(Unit* /*pVictim*/)
void SummonedCreatureDespawn(Creature *summon)
{
Summons.Despawn(summon);
}
void KilledUnit(Unit* pVictim)
{
DoScriptText(SAY_KILL, me);
}
void SpellHit(Unit * /*pCaster*/, const SpellEntry* pSpell)
void SpellHit(Unit *pCaster, const SpellEntry* pSpell)
{
if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST ||
pSpell->Id == SPELL_BREATH_WEST_TO_EAST ||
@@ -188,11 +226,58 @@ struct boss_onyxiaAI : public ScriptedAI
pSpell->Id == SPELL_BREATH_SW_TO_NE ||
pSpell->Id == SPELL_BREATH_NE_TO_SW)
{
if (m_pPointData)
{
me->GetMap()->CreatureRelocation(me, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ, 0.0f);
me->GetMotionMaster()->MovePoint(0, -10.6155, -219.357, -87.7344);
m_pPointData = GetMoveData();
m_uiMovePoint = m_pPointData->uiLocIdEnd;
me->SetSpeed(MOVE_FLIGHT, 1.5f);
me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation);
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type == POINT_MOTION_TYPE)
{
switch (id)
{
case 8:
m_pPointData = GetMoveData();
if (m_pPointData)
{
me->SetSpeed(MOVE_FLIGHT, 1.0f);
me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
}
break;
case 9:
me->GetMotionMaster()->MoveChase(me->getVictim());
m_uiBellowingRoarTimer = 1000;
break;
default:
m_bIsMoving = false;
break;
}
}
}
void SpellHitTarget(Unit* target, const SpellEntry* pSpell)
{
//Workaround - Couldn't find a way to group this spells (All Eruption)
if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) ||
(pSpell->Id == 17097) ||
(pSpell->Id >= 18351 && pSpell->Id <= 18361) ||
(pSpell->Id >= 18564 && pSpell->Id <= 18576) ||
(pSpell->Id >= 18578 && pSpell->Id <= 18607) ||
(pSpell->Id == 18609) ||
(pSpell->Id >= 18611 && pSpell->Id <= 18628) ||
(pSpell->Id >= 21132 && pSpell->Id <= 21133) ||
(pSpell->Id >= 21135 && pSpell->Id <= 21139) ||
(pSpell->Id >= 22191 && pSpell->Id <= 22202) ||
(pSpell->Id >= 22267 && pSpell->Id <= 22268)) &&
(target->GetTypeId() == TYPEID_PLAYER))
{
if (m_pInstance)
{
m_pInstance->SetData(DATA_SHE_DEEP_BREATH_MORE, FAIL);
}
}
}
@@ -227,11 +312,54 @@ struct boss_onyxiaAI : public ScriptedAI
if (!UpdateVictim())
return;
//Common to PHASE_START && PHASE_END
if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END)
{
//Specific to PHASE_START || PHASE_END
if (m_uiPhase == PHASE_START)
{
if (me->GetHealth()*100 / me->GetMaxHealth() < 60)
{
m_uiPhase = PHASE_BREATH;
if (m_pInstance)
m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase);
SetCombatMovement(false);
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
me->SetFlying(true);
DoScriptText(SAY_PHASE_2_TRANS, me);
if (m_pPointData)
me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
m_uiWhelpTimer = 1000;
return;
}
}
else
{
if (m_uiBellowingRoarTimer <= uiDiff)
{
DoCastVictim(SPELL_BELLOWING_ROAR);
// Eruption
GameObject* pFloor = NULL;
Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15);
Trinity::GameObjectLastSearcher<Trinity::GameObjectInRangeCheck> searcher(me, pFloor, check);
me->VisitNearbyGridObject(30, searcher);
if (m_pInstance && pFloor)
m_pInstance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID());
m_uiBellowingRoarTimer = 30000;
}
else
m_uiBellowingRoarTimer -= uiDiff;
}
if (m_uiFlameBreathTimer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_FLAMEBREATH);
DoCastVictim(SPELL_FLAME_BREATH);
m_uiFlameBreathTimer = urand(10000, 20000);
}
else
@@ -239,7 +367,7 @@ struct boss_onyxiaAI : public ScriptedAI
if (m_uiTailSweepTimer <= uiDiff)
{
DoCast(me, SPELL_TAILSWEEP);
DoCastAOE(SPELL_TAIL_SWEEP);
m_uiTailSweepTimer = urand(15000, 20000);
}
else
@@ -247,7 +375,7 @@ struct boss_onyxiaAI : public ScriptedAI
if (m_uiCleaveTimer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_CLEAVE);
DoCastVictim(SPELL_CLEAVE);
m_uiCleaveTimer = urand(2000, 5000);
}
else
@@ -255,43 +383,12 @@ struct boss_onyxiaAI : public ScriptedAI
if (m_uiWingBuffetTimer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_WINGBUFFET);
DoCastVictim(SPELL_WING_BUFFET);
m_uiWingBuffetTimer = urand(15000, 30000);
}
else
m_uiWingBuffetTimer -= uiDiff;
if (m_uiPhase == PHASE_END)
{
if (m_uiBellowingRoarTimer <= uiDiff)
{
DoCast(me->getVictim(), SPELL_BELLOWINGROAR);
m_uiBellowingRoarTimer = 30000;
}
else
m_uiBellowingRoarTimer -= uiDiff;
}
else
{
if (me->GetHealth()*100 / me->GetMaxHealth() < 60)
{
m_uiPhase = PHASE_BREATH;
SetCombatMovement(false);
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
DoScriptText(SAY_PHASE_2_TRANS, me);
if (m_pPointData)
me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
SetNextRandomPoint();
return;
}
}
DoMeleeAttackIfReady();
}
else
@@ -299,99 +396,91 @@ struct boss_onyxiaAI : public ScriptedAI
if (me->GetHealth()*100 / me->GetMaxHealth() < 40)
{
m_uiPhase = PHASE_END;
if (m_pInstance)
m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase);
DoScriptText(SAY_PHASE_3_TRANS, me);
SetCombatMovement(true);
me->GetMotionMaster()->MoveChase(me->getVictim());
me->SetFlying(false);
m_bIsMoving = false;
me->GetMotionMaster()->MovePoint(9,me->GetHomePosition());
return;
}
if (m_uiMovementTimer <= uiDiff)
if (m_uiDeepBreathTimer <= uiDiff)
{
m_pPointData = GetMoveData();
SetNextRandomPoint();
m_uiMovementTimer = 25000;
if (!m_pPointData)
return;
if (m_uiMovePoint == m_pPointData->uiLocIdEnd)
if (!m_bIsMoving)
{
if (me->IsNonMeleeSpellCasted(false))
me->InterruptNonMeleeSpells(false);
DoScriptText(EMOTE_BREATH, me);
DoCast(me, m_pPointData->uiSpellId);
m_uiDeepBreathTimer = 70000;
}
else
}
else
m_uiDeepBreathTimer -= uiDiff;
if (m_uiMovementTimer <= uiDiff)
{
if (!m_bIsMoving)
{
SetNextRandomPoint();
m_pPointData = GetMoveData();
if (!m_pPointData)
return;
me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
m_bIsMoving = true;
m_uiMovementTimer = 25000;
}
}
else
m_uiMovementTimer -= uiDiff;
if (m_uiEngulfingFlamesTimer <= uiDiff)
if (m_uiFireballTimer <= uiDiff)
{
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)
{
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
DoCast(pTarget, SPELL_FIREBALL);
m_uiEngulfingFlamesTimer = 8000;
m_uiFireballTimer = 8000;
}
}
else
m_uiEngulfingFlamesTimer -= uiDiff; //engulfingflames is supposed to be activated by a fireball but haven't come by
m_uiFireballTimer -= uiDiff;
if (m_bIsSummoningWhelps)
if (m_uiLairGuardTimer <= uiDiff)
{
if (m_uiSummonCount < MAX_WHELP)
me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN);
if (m_uiSummonLairGuardCount >= RAID_MODE(1,2))
{
if (m_uiWhelpTimer <= uiDiff)
{
me->SummonCreature(NPC_WHELP, afSpawnLocations[0][0], afSpawnLocations[0][1], afSpawnLocations[0][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
me->SummonCreature(NPC_WHELP, afSpawnLocations[1][0], afSpawnLocations[1][1], afSpawnLocations[1][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
m_uiWhelpTimer = 1000;
}
else
m_uiWhelpTimer -= uiDiff;
}
else
{
m_bIsSummoningWhelps = false;
m_uiSummonCount = 0;
m_uiSummonWhelpsTimer = 30000;
}
}
else
{
if (m_uiSummonWhelpsTimer <= uiDiff)
m_bIsSummoningWhelps = true;
else
m_uiSummonWhelpsTimer -= uiDiff;
}
if (m_bIsSummoningLairGuards)
{
if (m_uiLairGuardTimer <= uiDiff)
{
me->SummonCreature(NPC_LAIRGUARD, afSpawnLocations[0][0], afSpawnLocations[0][1], afSpawnLocations[0][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
me->SummonCreature(NPC_LAIRGUARD, afSpawnLocations[1][0], afSpawnLocations[1][1], afSpawnLocations[1][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
m_uiSummonLairGuardCount = 0;
m_uiLairGuardTimer = 30000;
}
else
m_uiLairGuardTimer -= uiDiff;
m_uiLairGuardTimer = 2000;
}
else
m_uiLairGuardTimer -= uiDiff;
if (m_uiWhelpTimer <= uiDiff)
{
if (m_uiLairGuardTimer <= uiDiff)
m_bIsSummoningLairGuards = true;
me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN);
me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN);
if (m_uiSummonWhelpCount >= RAID_MODE(20,40))
{
m_uiSummonWhelpCount = 0;
m_uiWhelpTimer = 90000;
}
else
m_uiLairGuardTimer -= uiDiff;
m_uiWhelpTimer = 500;
}
else
m_uiWhelpTimer -= uiDiff;
}
}
};
@@ -0,0 +1,249 @@
/* Copyright (C) 2008 - 2010 Trinity <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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* ScriptData
SDName: Instance_Onyxias_Lair
SD%Complete: 100
SDComment:
SDCategory: Onyxia's Lair
EndScriptData */
#include "ScriptedPch.h"
#include "onyxias_lair.h"
struct instance_onyxias_lair : public ScriptedInstance
{
instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
//Eruption is a BFS graph problem
//One map to remember all floor, one map to keep floor that still need to erupt and one queue to know what needs to be removed
std::map<uint64,uint32> FloorEruptionGUID[2];
std::queue<uint64> FloorEruptionGUIDQueue;
uint64 m_uiOnyxiasGUID;
uint32 m_uiOnyxiaLiftoffTimer;
uint32 m_uiManyWhelpsCounter;
uint32 m_uiEruptTimer;
uint8 m_auiEncounter[MAX_ENCOUNTER];
bool m_bAchievManyWhelpsHandleIt;
bool m_bAchievSheDeepBreathMore;
void Initialize()
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
m_uiOnyxiasGUID = 0;
m_uiOnyxiaLiftoffTimer = 0;
m_uiManyWhelpsCounter = 0;
m_bAchievManyWhelpsHandleIt = false;
m_bAchievSheDeepBreathMore = true;
m_uiEruptTimer = 0;
}
void OnCreatureCreate(Creature* pCreature, bool add)
{
switch (pCreature->GetEntry())
{
case NPC_ONYXIA:
m_uiOnyxiasGUID = pCreature->GetGUID();
break;
}
}
void OnGameObjectCreate(GameObject* pGo, bool add)
{
if ((pGo->GetGOInfo()->displayId == 4392 || pGo->GetGOInfo()->displayId == 4472) && pGo->GetGOInfo()->trap.spellId == 17731)
{
if (add)
FloorEruptionGUID[0].insert(std::make_pair(pGo->GetGUID(),0));
else
FloorEruptionGUID[0].erase(pGo->GetGUID());
return;
}
switch(pGo->GetEntry())
{
case GO_WHELP_SPAWNER:
Position pGoPos;
pGo->GetPosition(&pGoPos);
if (Creature* pTemp = pGo->SummonCreature(NPC_WHELP,pGoPos,TEMPSUMMON_CORPSE_DESPAWN))
{
pTemp->SetInCombatWithZone();
++m_uiManyWhelpsCounter;
}
break;
}
}
void FloorEruption(uint64 floorEruptedGUID)
{
if (GameObject *pFloorEruption = instance->GetGameObject(floorEruptedGUID))
{
//THIS GOB IS A TRAP - What shall i do? =(
//Cast it spell? Copyed Heigan method
pFloorEruption->SendCustomAnim();
pFloorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId
//Get all immediatly nearby floors
std::list<GameObject*> nearFloorList;
Trinity::GameObjectInRangeCheck check(pFloorEruption->GetPositionX(), pFloorEruption->GetPositionY(), pFloorEruption->GetPositionZ(), 15);
Trinity::GameObjectListSearcher<Trinity::GameObjectInRangeCheck> searcher(pFloorEruption, nearFloorList, check);
pFloorEruption->VisitNearbyGridObject(999, searcher);
//remove all that are not present on FloorEruptionGUID[1] and update treeLen on each GUID
for (std::list<GameObject*>::const_iterator itr = nearFloorList.begin(); itr != nearFloorList.end(); ++itr)
{
if (((*itr)->GetGOInfo()->displayId == 4392 || (*itr)->GetGOInfo()->displayId == 4472) && (*itr)->GetGOInfo()->trap.spellId == 17731)
{
uint64 nearFloorGUID = (*itr)->GetGUID();
if (FloorEruptionGUID[1].find(nearFloorGUID) != FloorEruptionGUID[1].end() && (*FloorEruptionGUID[1].find(nearFloorGUID)).second == 0)
{
(*FloorEruptionGUID[1].find(nearFloorGUID)).second = (*FloorEruptionGUID[1].find(floorEruptedGUID)).second+1;
FloorEruptionGUIDQueue.push(nearFloorGUID);
}
}
}
}
FloorEruptionGUID[1].erase(floorEruptedGUID);
}
void SetData(uint32 uiType, uint32 uiData)
{
switch(uiType)
{
case DATA_ONYXIA:
m_auiEncounter[0] = uiData;
if (uiData == IN_PROGRESS)
SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS);
break;
case DATA_ONYXIA_PHASE:
if (uiData == PHASE_BREATH) //Used to mark the liftoff phase
{
m_bAchievManyWhelpsHandleIt = false;
m_uiManyWhelpsCounter = 0;
m_uiOnyxiaLiftoffTimer = 10*IN_MILISECONDS;
}
break;
case DATA_SHE_DEEP_BREATH_MORE:
if (uiData == IN_PROGRESS)
{
m_bAchievSheDeepBreathMore = true;
}
else if (uiData == FAIL)
{
m_bAchievSheDeepBreathMore = false;
}
break;
}
if (uiType < MAX_ENCOUNTER && uiData == DONE)
SaveToDB();
}
void SetData64(uint32 uiType, uint64 uiData)
{
switch(uiType)
{
case DATA_FLOOR_ERUPTION_GUID:
FloorEruptionGUID[1] = FloorEruptionGUID[0];
FloorEruptionGUIDQueue.push(uiData);
m_uiEruptTimer = 2500;
break;
}
}
uint32 GetData(uint32 uiType)
{
switch(uiType)
{
case DATA_ONYXIA:
return m_auiEncounter[0];
}
return 0;
}
uint64 GetData64(uint32 uiData)
{
switch(uiData)
{
case DATA_ONYXIA_GUID:
return m_uiOnyxiasGUID;
}
return 0;
}
void Update(uint32 uiDiff)
{
if (GetData(DATA_ONYXIA) == IN_PROGRESS)
{
if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff)
{
m_uiOnyxiaLiftoffTimer = 0;
if (m_uiManyWhelpsCounter >= 50)
m_bAchievManyWhelpsHandleIt = true;
} else m_uiOnyxiaLiftoffTimer -= uiDiff;
}
if (!FloorEruptionGUIDQueue.empty())
{
if (m_uiEruptTimer <= uiDiff)
{
uint32 treeHeight = 0;
do
{
treeHeight = (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second;
FloorEruption(FloorEruptionGUIDQueue.front());
FloorEruptionGUIDQueue.pop();
} while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight);
m_uiEruptTimer = 1000;
}
else
m_uiEruptTimer -= uiDiff;
}
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0)
{
switch(criteria_id)
{
case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s
case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s
return m_bAchievManyWhelpsHandleIt;
case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath
case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath
return m_bAchievSheDeepBreathMore;
}
return false;
}
};
InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap)
{
return new instance_onyxias_lair(pMap);
}
void AddSC_instance_onyxias_lair()
{
Script *newscript;
newscript = new Script;
newscript->Name = "instance_onyxias_lair";
newscript->GetInstanceData = &GetInstanceData_instance_onyxias_lair;
newscript->RegisterSelf();
}
@@ -0,0 +1,65 @@
/* Copyright (C) 2008 - 2010 Trinity <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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DEF_ONYXIAS_LAIR_H
#define DEF_ONYXIAS_LAIR_H
enum eData64
{
DATA_ONYXIA_GUID,
DATA_FLOOR_ERUPTION_GUID
};
enum eInstanceData
{
DATA_ONYXIA,
MAX_ENCOUNTER,
DATA_ONYXIA_PHASE,
DATA_SHE_DEEP_BREATH_MORE,
DATA_MANY_WHELPS_COUNT
};
enum eCreatures
{
NPC_WHELP = 11262,
NPC_LAIRGUARD = 36561,
NPC_ONYXIA = 10184
};
enum eOnyxiaPhases
{
PHASE_START = 1,
PHASE_BREATH = 2,
PHASE_END = 3
};
enum eGameObjects
{
GO_WHELP_SPAWNER = 176510,
GO_WHELP_EGG = 176511
};
enum eAchievementData
{
ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s
ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s
ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER = 12566, // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath
ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER = 12569, // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath
ACHIEV_TIMED_START_EVENT = 6601, // Timed event for achievement 4402, 4005: More Dots! (10,25 player) 5 min kill
};
#endif