refactor(Scripts/Onyxia): Update Onyxia's script (#9371)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1637948987614040500');
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = `flags_extra` |128, `ScriptName` = '' WHERE `entry` = 12758;
|
||||||
|
UPDATE `creature_template` SET `ScriptName` = '' WHERE `entry` = 11262;
|
||||||
|
|
||||||
|
-- Remove taunt immunity
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = `flags_extra` &~ 256 WHERE `entry` = 10184;
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "SpellInfo.h"
|
#include "SpellInfo.h"
|
||||||
#include "onyxias_lair.h"
|
#include "onyxias_lair.h"
|
||||||
|
|
||||||
enum // Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
SPELL_WINGBUFFET = 18500,
|
SPELL_WINGBUFFET = 18500,
|
||||||
SPELL_FLAMEBREATH = 18435,
|
SPELL_FLAMEBREATH = 18435,
|
||||||
@@ -47,7 +47,7 @@ enum // Spells
|
|||||||
SPELL_BREATH_NE_TO_SW = 18617,
|
SPELL_BREATH_NE_TO_SW = 18617,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum // Events
|
enum Events
|
||||||
{
|
{
|
||||||
EVENT_SPELL_WINGBUFFET = 1,
|
EVENT_SPELL_WINGBUFFET = 1,
|
||||||
EVENT_SPELL_FLAMEBREATH = 2,
|
EVENT_SPELL_FLAMEBREATH = 2,
|
||||||
@@ -73,7 +73,15 @@ enum // Events
|
|||||||
EVENT_LIFTOFF = 31,
|
EVENT_LIFTOFF = 31,
|
||||||
EVENT_FLY_S_TO_N = 32,
|
EVENT_FLY_S_TO_N = 32,
|
||||||
EVENT_LAND = 33,
|
EVENT_LAND = 33,
|
||||||
EVENT_END_MANY_WHELPS_TIME,
|
EVENT_END_MANY_WHELPS_TIME
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Phases
|
||||||
|
{
|
||||||
|
PHASE_NONE,
|
||||||
|
PHASE_GROUNDED, // Phase 1
|
||||||
|
PHASE_AIRPHASE, // Phase 2 - Airphase - 60% health
|
||||||
|
PHASE_LANDED // Phase 3 - Landed after Airphase - 40% health
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sOnyxMove
|
struct sOnyxMove
|
||||||
@@ -108,52 +116,39 @@ enum Yells
|
|||||||
EMOTE_BREATH = 4
|
EMOTE_BREATH = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_onyxia : public CreatureScript
|
struct boss_onyxia : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
boss_onyxia() : CreatureScript("boss_onyxia") { }
|
boss_onyxia(Creature* pCreature) : BossAI(pCreature, DATA_ONYXIA)
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
{
|
||||||
return GetOnyxiasLairAI<boss_onyxiaAI>(pCreature);
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boss_onyxiaAI : public ScriptedAI
|
void Initialize()
|
||||||
{
|
{
|
||||||
boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature)
|
CurrentWP = 0;
|
||||||
{
|
whelpSpam = false;
|
||||||
m_pInstance = me->GetInstanceScript();
|
whelpCount = 0;
|
||||||
|
whelpSpamTimer = 0;
|
||||||
|
bManyWhelpsAvailable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventMap events;
|
|
||||||
|
|
||||||
InstanceScript* m_pInstance;
|
|
||||||
uint8 Phase;
|
|
||||||
int8 CurrentWP;
|
|
||||||
|
|
||||||
bool whelpSpam;
|
|
||||||
uint8 whelpCount;
|
|
||||||
int32 whelpSpamTimer;
|
|
||||||
bool bManyWhelpsAvailable;
|
|
||||||
|
|
||||||
void SetPhase(uint8 ph)
|
void SetPhase(uint8 ph)
|
||||||
{
|
{
|
||||||
events.Reset();
|
events.Reset();
|
||||||
Phase = ph;
|
Phase = ph;
|
||||||
switch (ph)
|
switch (ph)
|
||||||
{
|
{
|
||||||
case 0:
|
case PHASE_GROUNDED:
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_WINGBUFFET, urand(10000, 20000));
|
events.ScheduleEvent(EVENT_SPELL_WINGBUFFET, urand(10000, 20000));
|
||||||
events.ScheduleEvent(EVENT_SPELL_FLAMEBREATH, urand(10000, 20000));
|
events.ScheduleEvent(EVENT_SPELL_FLAMEBREATH, urand(10000, 20000));
|
||||||
events.ScheduleEvent(EVENT_SPELL_TAILSWEEP, urand(15000, 20000));
|
events.ScheduleEvent(EVENT_SPELL_TAILSWEEP, urand(15000, 20000));
|
||||||
events.ScheduleEvent(EVENT_SPELL_CLEAVE, urand(2000, 5000));
|
events.ScheduleEvent(EVENT_SPELL_CLEAVE, urand(2000, 5000));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case PHASE_AIRPHASE:
|
||||||
events.ScheduleEvent(EVENT_START_PHASE_2, 0);
|
events.ScheduleEvent(EVENT_START_PHASE_2, 0);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case PHASE_LANDED:
|
||||||
events.ScheduleEvent(EVENT_START_PHASE_3, 5000);
|
events.ScheduleEvent(EVENT_START_PHASE_3, 5000);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -161,41 +156,14 @@ public:
|
|||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
CurrentWP = 0;
|
Initialize();
|
||||||
SetPhase(0);
|
SetPhase(PHASE_NONE);
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
me->SetCanFly(false);
|
me->SetCanFly(false);
|
||||||
me->SetDisableGravity(false);
|
me->SetDisableGravity(false);
|
||||||
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run, false);
|
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run, false);
|
||||||
|
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
||||||
whelpSpam = false;
|
BossAI::Reset();
|
||||||
whelpCount = 0;
|
|
||||||
whelpSpamTimer = 0;
|
|
||||||
bManyWhelpsAvailable = false;
|
|
||||||
|
|
||||||
if (m_pInstance)
|
|
||||||
{
|
|
||||||
m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED);
|
|
||||||
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
m_pInstance->SetData(DATA_ONYXIA, DONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
|
||||||
{
|
|
||||||
if (me->GetVictim() || me->GetDistance(who) > 30.0f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
AttackStart(who);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoAction(int32 param) override
|
void DoAction(int32 param) override
|
||||||
@@ -203,66 +171,51 @@ public:
|
|||||||
switch (param)
|
switch (param)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
if (bManyWhelpsAvailable && m_pInstance)
|
if (bManyWhelpsAvailable)
|
||||||
{
|
{
|
||||||
m_pInstance->SetData(DATA_WHELP_SUMMONED, 1);
|
instance->SetData(DATA_WHELP_SUMMONED, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindPlayers()
|
void EnterCombat(Unit* who) override
|
||||||
{
|
|
||||||
me->GetMap()->ToInstanceMap()->PermBindAllPlayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
|
||||||
{
|
{
|
||||||
Talk(SAY_AGGRO);
|
Talk(SAY_AGGRO);
|
||||||
DoZoneInCombat();
|
SetPhase(PHASE_GROUNDED);
|
||||||
SetPhase(1);
|
|
||||||
|
|
||||||
if (m_pInstance)
|
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); // just in case at reset some players already left the instance
|
||||||
{
|
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
||||||
m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS);
|
BossAI::EnterCombat(who);
|
||||||
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); // just in case at reset some players already left the instance
|
|
||||||
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
|
|
||||||
}
|
|
||||||
BindPlayers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||||
{
|
{
|
||||||
switch (Phase)
|
if (me->HealthBelowPctDamaged(65, damage) && Phase == PHASE_GROUNDED)
|
||||||
{
|
{
|
||||||
case 1:
|
SetPhase(PHASE_AIRPHASE);
|
||||||
if (me->GetHealth() * 100 / me->GetMaxHealth() <= 65)
|
|
||||||
{
|
|
||||||
SetPhase(2);
|
|
||||||
}
|
}
|
||||||
break;
|
else if (me->HealthBelowPctDamaged(40, damage) && Phase == PHASE_AIRPHASE)
|
||||||
case 2:
|
|
||||||
if (me->GetHealth() * 100 / me->GetMaxHealth() <= 40)
|
|
||||||
{
|
{
|
||||||
me->InterruptNonMeleeSpells(false);
|
me->InterruptNonMeleeSpells(false);
|
||||||
SetPhase(3);
|
SetPhase(PHASE_LANDED);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* pSummoned) override
|
void JustSummoned(Creature* summon) override
|
||||||
{
|
{
|
||||||
if (pSummoned->GetEntry() != NPC_ONYXIAN_WHELP && pSummoned->GetEntry() != NPC_ONYXIAN_LAIR_GUARD)
|
if (summon->GetEntry() != NPC_ONYXIAN_WHELP && summon->GetEntry() != NPC_ONYXIAN_LAIR_GUARD)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Unit* target = pSummoned->SelectNearestTarget(300.0f))
|
if (Unit* target = summon->SelectNearestTarget(300.0f))
|
||||||
{
|
{
|
||||||
pSummoned->AI()->AttackStart(target);
|
summon->AI()->AttackStart(target);
|
||||||
DoZoneInCombat(pSummoned);
|
DoZoneInCombat(summon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
summons.Summon(summon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 id) override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
@@ -274,7 +227,7 @@ public:
|
|||||||
|
|
||||||
if (id < 9)
|
if (id < 9)
|
||||||
{
|
{
|
||||||
if (id > 0 && Phase == 2)
|
if (id > 0 && Phase == PHASE_AIRPHASE)
|
||||||
{
|
{
|
||||||
me->SetFacingTo(OnyxiaMoveData[id].o);
|
me->SetFacingTo(OnyxiaMoveData[id].o);
|
||||||
me->SetSpeed(MOVE_RUN, 1.6f, false);
|
me->SetSpeed(MOVE_RUN, 1.6f, false);
|
||||||
@@ -319,8 +272,8 @@ public:
|
|||||||
{
|
{
|
||||||
float angle = rand_norm() * 2 * M_PI;
|
float angle = rand_norm() * 2 * M_PI;
|
||||||
float dist = rand_norm() * 4.0f;
|
float dist = rand_norm() * 4.0f;
|
||||||
me->CastSpell(-33.18f + cos(angle)*dist, -258.80f + sin(angle)*dist, -89.0f, 17646, true);
|
me->CastSpell(-33.18f + cos(angle) * dist, -258.80f + sin(angle) * dist, -89.0f, 17646, true);
|
||||||
me->CastSpell(-32.535f + cos(angle)*dist, -170.190f + sin(angle)*dist, -89.0f, 17646, true);
|
me->CastSpell(-32.535f + cos(angle) * dist, -170.190f + sin(angle) * dist, -89.0f, 17646, true);
|
||||||
whelpCount += 2;
|
whelpCount += 2;
|
||||||
whelpSpamTimer += 600;
|
whelpSpamTimer += 600;
|
||||||
}
|
}
|
||||||
@@ -353,32 +306,30 @@ public:
|
|||||||
|
|
||||||
switch (events.ExecuteEvent())
|
switch (events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_WINGBUFFET:
|
case EVENT_SPELL_WINGBUFFET:
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_WINGBUFFET, false);
|
DoCastAOE(SPELL_WINGBUFFET);
|
||||||
events.RepeatEvent(urand(15000, 30000));
|
events.RepeatEvent(urand(15000, 30000));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_FLAMEBREATH:
|
case EVENT_SPELL_FLAMEBREATH:
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_FLAMEBREATH, false);
|
DoCastAOE(SPELL_FLAMEBREATH);
|
||||||
events.RepeatEvent(urand(10000, 20000));
|
events.RepeatEvent(urand(10000, 20000));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_TAILSWEEP:
|
case EVENT_SPELL_TAILSWEEP:
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_TAILSWEEP, false);
|
DoCastAOE(SPELL_TAILSWEEP);
|
||||||
events.RepeatEvent(urand(15000, 20000));
|
events.RepeatEvent(urand(15000, 20000));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_CLEAVE:
|
case EVENT_SPELL_CLEAVE:
|
||||||
{
|
{
|
||||||
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
|
DoCastVictim(SPELL_CLEAVE);
|
||||||
events.RepeatEvent(urand(2000, 5000));
|
events.RepeatEvent(urand(2000, 5000));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_START_PHASE_2:
|
case EVENT_START_PHASE_2:
|
||||||
{
|
{
|
||||||
me->AttackStop();
|
me->AttackStop();
|
||||||
@@ -386,8 +337,8 @@ public:
|
|||||||
me->StopMoving();
|
me->StopMoving();
|
||||||
DoResetThreat();
|
DoResetThreat();
|
||||||
me->GetMotionMaster()->MovePoint(10, OnyxiaMoveData[0].x, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z);
|
me->GetMotionMaster()->MovePoint(10, OnyxiaMoveData[0].x, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_LIFTOFF:
|
case EVENT_LIFTOFF:
|
||||||
{
|
{
|
||||||
Talk(SAY_PHASE_2_TRANS);
|
Talk(SAY_PHASE_2_TRANS);
|
||||||
@@ -402,8 +353,8 @@ public:
|
|||||||
bManyWhelpsAvailable = true;
|
bManyWhelpsAvailable = true;
|
||||||
|
|
||||||
events.RescheduleEvent(EVENT_END_MANY_WHELPS_TIME, 10000);
|
events.RescheduleEvent(EVENT_END_MANY_WHELPS_TIME, 10000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_END_MANY_WHELPS_TIME:
|
case EVENT_END_MANY_WHELPS_TIME:
|
||||||
bManyWhelpsAvailable = false;
|
bManyWhelpsAvailable = false;
|
||||||
break;
|
break;
|
||||||
@@ -415,45 +366,45 @@ public:
|
|||||||
whelpSpam = true;
|
whelpSpam = true;
|
||||||
events.ScheduleEvent(EVENT_WHELP_SPAM, 90000);
|
events.ScheduleEvent(EVENT_WHELP_SPAM, 90000);
|
||||||
events.ScheduleEvent(EVENT_SUMMON_LAIR_GUARD, 30000);
|
events.ScheduleEvent(EVENT_SUMMON_LAIR_GUARD, 30000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SUMMON_LAIR_GUARD:
|
case EVENT_SUMMON_LAIR_GUARD:
|
||||||
{
|
{
|
||||||
me->CastSpell(-101.654f, -214.491f, -80.70f, SPELL_SUMMON_LAIR_GUARD, true);
|
me->CastSpell(-101.654f, -214.491f, -80.70f, SPELL_SUMMON_LAIR_GUARD, true);
|
||||||
events.RepeatEvent(30000);
|
events.RepeatEvent(30000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_WHELP_SPAM:
|
case EVENT_WHELP_SPAM:
|
||||||
{
|
{
|
||||||
whelpSpam = true;
|
whelpSpam = true;
|
||||||
events.RepeatEvent(90000);
|
events.RepeatEvent(90000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_LAND:
|
case EVENT_LAND:
|
||||||
{
|
{
|
||||||
Talk(SAY_PHASE_3_TRANS);
|
Talk(SAY_PHASE_3_TRANS);
|
||||||
me->SendMeleeAttackStop(me->GetVictim());
|
me->SendMeleeAttackStop(me->GetVictim());
|
||||||
me->GetMotionMaster()->MoveLand(13, OnyxiaMoveData[0].x + 1.0f, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z, 12.0f);
|
me->GetMotionMaster()->MoveLand(13, OnyxiaMoveData[0].x + 1.0f, OnyxiaMoveData[0].y, OnyxiaMoveData[0].z, 12.0f);
|
||||||
DoResetThreat();
|
DoResetThreat();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_FIREBALL_FIRST:
|
case EVENT_SPELL_FIREBALL_FIRST:
|
||||||
{
|
{
|
||||||
if (Unit* v = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
|
if (Unit* v = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
|
||||||
{
|
{
|
||||||
me->SetFacingToObject(v);
|
me->SetFacingToObject(v);
|
||||||
me->CastSpell(v, SPELL_FIREBALL, false);
|
DoCast(v, SPELL_FIREBALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL_SECOND, 4000);
|
events.ScheduleEvent(EVENT_SPELL_FIREBALL_SECOND, 4000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_FIREBALL_SECOND:
|
case EVENT_SPELL_FIREBALL_SECOND:
|
||||||
{
|
{
|
||||||
if (Unit* v = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
|
if (Unit* v = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
|
||||||
{
|
{
|
||||||
me->SetFacingToObject(v);
|
me->SetFacingToObject(v);
|
||||||
me->CastSpell(v, SPELL_FIREBALL, false);
|
DoCast(v, SPELL_FIREBALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 rand = urand(0, 99);
|
uint8 rand = urand(0, 99);
|
||||||
@@ -469,8 +420,8 @@ public:
|
|||||||
{
|
{
|
||||||
events.ScheduleEvent(EVENT_PHASE_2_STEP_ACROSS, 4000);
|
events.ScheduleEvent(EVENT_PHASE_2_STEP_ACROSS, 4000);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_PHASE_2_STEP_CW:
|
case EVENT_PHASE_2_STEP_CW:
|
||||||
{
|
{
|
||||||
uint8 newWP = CurrentWP + 1;
|
uint8 newWP = CurrentWP + 1;
|
||||||
@@ -479,8 +430,8 @@ public:
|
|||||||
newWP = 1;
|
newWP = 1;
|
||||||
}
|
}
|
||||||
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_PHASE_2_STEP_ACW:
|
case EVENT_PHASE_2_STEP_ACW:
|
||||||
{
|
{
|
||||||
uint8 newWP = CurrentWP - 1;
|
uint8 newWP = CurrentWP - 1;
|
||||||
@@ -489,35 +440,39 @@ public:
|
|||||||
newWP = 8;
|
newWP = 8;
|
||||||
}
|
}
|
||||||
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_PHASE_2_STEP_ACROSS:
|
case EVENT_PHASE_2_STEP_ACROSS:
|
||||||
{
|
{
|
||||||
|
Talk(EMOTE_BREATH);
|
||||||
me->SetFacingTo(OnyxiaMoveData[CurrentWP].o);
|
me->SetFacingTo(OnyxiaMoveData[CurrentWP].o);
|
||||||
me->TextEmote("Onyxia takes in a deep breath...", nullptr, true);
|
DoCastAOE(OnyxiaMoveData[CurrentWP].spellId);
|
||||||
me->CastSpell(me, OnyxiaMoveData[CurrentWP].spellId, false);
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_BREATH, 8250);
|
events.ScheduleEvent(EVENT_SPELL_BREATH, 8250);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_BREATH:
|
case EVENT_SPELL_BREATH:
|
||||||
{
|
{
|
||||||
uint8 newWP = OnyxiaMoveData[CurrentWP].DestId;
|
uint8 newWP = OnyxiaMoveData[CurrentWP].DestId;
|
||||||
me->SetSpeed(MOVE_RUN, 2.95f, false);
|
me->SetSpeed(MOVE_RUN, 2.95f, false);
|
||||||
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
me->GetMotionMaster()->MovePoint(newWP, OnyxiaMoveData[newWP].x, OnyxiaMoveData[newWP].y, OnyxiaMoveData[newWP].z);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_START_PHASE_3:
|
case EVENT_START_PHASE_3:
|
||||||
{
|
{
|
||||||
me->SetSpeed(MOVE_RUN, 2.95f, false);
|
me->SetSpeed(MOVE_RUN, 2.95f, false);
|
||||||
me->GetMotionMaster()->MovePoint(12, OnyxiaMoveData[1].x, OnyxiaMoveData[1].y, OnyxiaMoveData[1].z);
|
me->GetMotionMaster()->MovePoint(12, OnyxiaMoveData[1].x, OnyxiaMoveData[1].y, OnyxiaMoveData[1].z);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_PHASE_3_ATTACK:
|
case EVENT_PHASE_3_ATTACK:
|
||||||
{
|
{
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 0, false));
|
|
||||||
me->CastSpell(me, SPELL_BELLOWINGROAR, false);
|
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 0, false))
|
||||||
|
{
|
||||||
|
AttackStart(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCastAOE(SPELL_BELLOWINGROAR);
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_ERUPTION, 0);
|
events.ScheduleEvent(EVENT_ERUPTION, 0);
|
||||||
events.ScheduleEvent(EVENT_SPELL_WINGBUFFET, urand(10000, 20000));
|
events.ScheduleEvent(EVENT_SPELL_WINGBUFFET, urand(10000, 20000));
|
||||||
@@ -526,79 +481,67 @@ public:
|
|||||||
events.ScheduleEvent(EVENT_SPELL_CLEAVE, urand(2000, 5000));
|
events.ScheduleEvent(EVENT_SPELL_CLEAVE, urand(2000, 5000));
|
||||||
events.ScheduleEvent(EVENT_SPELL_BELLOWINGROAR, 15000);
|
events.ScheduleEvent(EVENT_SPELL_BELLOWINGROAR, 15000);
|
||||||
events.ScheduleEvent(EVENT_SUMMON_WHELP, 10000);
|
events.ScheduleEvent(EVENT_SUMMON_WHELP, 10000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SPELL_BELLOWINGROAR:
|
case EVENT_SPELL_BELLOWINGROAR:
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_BELLOWINGROAR, false);
|
DoCastAOE(SPELL_BELLOWINGROAR);
|
||||||
events.RepeatEvent(22000);
|
events.RepeatEvent(22000);
|
||||||
events.ScheduleEvent(EVENT_ERUPTION, 0);
|
events.ScheduleEvent(EVENT_ERUPTION, 0);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_ERUPTION:
|
case EVENT_ERUPTION:
|
||||||
{
|
{
|
||||||
if (Creature* trigger = me->SummonCreature(12758, *me, TEMPSUMMON_TIMED_DESPAWN, 1000))
|
if (Creature* trigger = me->SummonCreature(12758, *me, TEMPSUMMON_TIMED_DESPAWN, 1000))
|
||||||
{
|
{
|
||||||
trigger->CastSpell(trigger, 17731, false);
|
trigger->CastSpell(trigger, 17731, false);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EVENT_SUMMON_WHELP:
|
case EVENT_SUMMON_WHELP:
|
||||||
{
|
{
|
||||||
float angle = rand_norm() * 2 * M_PI;
|
float angle = rand_norm() * 2 * M_PI;
|
||||||
float dist = rand_norm() * 4.0f;
|
float dist = rand_norm() * 4.0f;
|
||||||
me->CastSpell(-33.18f + cos(angle)*dist, -258.80f + sin(angle)*dist, -89.0f, 17646, true);
|
me->CastSpell(-33.18f + cos(angle) * dist, -258.80f + sin(angle) * dist, -89.0f, 17646, true);
|
||||||
me->CastSpell(-32.535f + cos(angle)*dist, -170.190f + sin(angle)*dist, -89.0f, 17646, true);
|
me->CastSpell(-32.535f + cos(angle) * dist, -170.190f + sin(angle) * dist, -89.0f, 17646, true);
|
||||||
events.RepeatEvent(30000);
|
events.RepeatEvent(30000);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpellHitTarget(Unit* target, const SpellInfo* spell) override
|
void SpellHitTarget(Unit* target, const SpellInfo* spell) override
|
||||||
{
|
{
|
||||||
if (target->IsPlayer() && spell->DurationEntry && spell->DurationEntry->ID == 328 && spell->Effects[EFFECT_1].TargetA.GetTarget() == 1 && (spell->Effects[EFFECT_1].Amplitude == 50 || spell->Effects[EFFECT_1].Amplitude == 215)) // Deep Breath
|
if (target->IsPlayer() && spell->DurationEntry && spell->DurationEntry->ID == 328 && spell->Effects[EFFECT_1].TargetA.GetTarget() == 1 && (spell->Effects[EFFECT_1].Amplitude == 50 || spell->Effects[EFFECT_1].Amplitude == 215)) // Deep Breath
|
||||||
{
|
{
|
||||||
m_pInstance->SetData(DATA_DEEP_BREATH_FAILED, 1);
|
instance->SetData(DATA_DEEP_BREATH_FAILED, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
private:
|
||||||
|
uint8 Phase;
|
||||||
|
int8 CurrentWP;
|
||||||
|
|
||||||
|
bool whelpSpam;
|
||||||
|
uint8 whelpCount;
|
||||||
|
int32 whelpSpamTimer;
|
||||||
|
bool bManyWhelpsAvailable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class npc_onyxian_lair_guard : public CreatureScript
|
struct npc_onyxian_lair_guard : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
npc_onyxian_lair_guard() : CreatureScript("npc_onyxian_lair_guard") { }
|
npc_onyxian_lair_guard(Creature* creature) : ScriptedAI(creature) {}
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
EventMap events;
|
||||||
{
|
|
||||||
return GetOnyxiasLairAI<npc_onyxian_lair_guardAI>(pCreature);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct npc_onyxian_lair_guardAI : public ScriptedAI
|
void EnterCombat(Unit* /*who*/) override
|
||||||
{
|
|
||||||
npc_onyxian_lair_guardAI(Creature* pCreature) : ScriptedAI(pCreature)
|
|
||||||
{
|
{
|
||||||
events.Reset();
|
events.Reset();
|
||||||
events.ScheduleEvent(EVENT_OLG_SPELL_BLASTNOVA, 15000);
|
events.ScheduleEvent(EVENT_OLG_SPELL_BLASTNOVA, 15000);
|
||||||
events.ScheduleEvent(EVENT_OLG_SPELL_IGNITEWEAPON, 10000);
|
events.ScheduleEvent(EVENT_OLG_SPELL_IGNITEWEAPON, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventMap events;
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
|
||||||
{
|
|
||||||
if (me->GetVictim() || me->GetDistance(who) > 20.0f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
AttackStart(who);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
@@ -615,10 +558,8 @@ public:
|
|||||||
|
|
||||||
switch (events.ExecuteEvent())
|
switch (events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case EVENT_OLG_SPELL_BLASTNOVA:
|
case EVENT_OLG_SPELL_BLASTNOVA:
|
||||||
me->CastSpell(me, SPELL_OLG_BLASTNOVA, false);
|
DoCastAOE(SPELL_OLG_BLASTNOVA);
|
||||||
events.RepeatEvent(15000);
|
events.RepeatEvent(15000);
|
||||||
break;
|
break;
|
||||||
case EVENT_OLG_SPELL_IGNITEWEAPON:
|
case EVENT_OLG_SPELL_IGNITEWEAPON:
|
||||||
@@ -628,7 +569,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
me->CastSpell(me, SPELL_OLG_IGNITEWEAPON, false);
|
DoCastSelf(SPELL_OLG_IGNITEWEAPON);
|
||||||
events.RepeatEvent(urand(18000, 21000));
|
events.RepeatEvent(urand(18000, 21000));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -647,61 +588,10 @@ public:
|
|||||||
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class npc_onyxia_whelp : public CreatureScript
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
npc_onyxia_whelp() : CreatureScript("npc_onyxia_whelp") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
|
||||||
return GetOnyxiasLairAI<npc_onyxia_whelpAI>(pCreature);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct npc_onyxia_whelpAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
npc_onyxia_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) {}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
|
||||||
{
|
|
||||||
if (me->GetVictim() || me->GetDistance(who) > 20.0f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
AttackStart(who);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class npc_onyxia_trigger : public CreatureScript
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
npc_onyxia_trigger() : CreatureScript("npc_onyxia_trigger") { }
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* pCreature) const override
|
|
||||||
{
|
|
||||||
return GetOnyxiasLairAI<npc_onyxia_triggerAI>(pCreature);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct npc_onyxia_triggerAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
npc_onyxia_triggerAI(Creature* pCreature) : ScriptedAI(pCreature) {}
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
|
||||||
void UpdateAI(uint32 /*diff*/) override {}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_onyxia()
|
void AddSC_boss_onyxia()
|
||||||
{
|
{
|
||||||
new boss_onyxia();
|
RegisterOnyxiasLairCreatureAI(boss_onyxia);
|
||||||
new npc_onyxian_lair_guard();
|
RegisterOnyxiasLairCreatureAI(npc_onyxian_lair_guard);
|
||||||
new npc_onyxia_whelp();
|
|
||||||
new npc_onyxia_trigger();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,33 +38,18 @@ public:
|
|||||||
{
|
{
|
||||||
instance_onyxias_lair_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();};
|
instance_onyxias_lair_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();};
|
||||||
|
|
||||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
|
||||||
std::string str_data;
|
std::string str_data;
|
||||||
uint16 ManyWhelpsCounter;
|
uint16 ManyWhelpsCounter;
|
||||||
GuidVector minions;
|
|
||||||
bool bDeepBreath;
|
bool bDeepBreath;
|
||||||
|
|
||||||
void Initialize() override
|
void Initialize() override
|
||||||
{
|
{
|
||||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
SetBossNumber(MAX_ENCOUNTER);
|
||||||
ManyWhelpsCounter = 0;
|
ManyWhelpsCounter = 0;
|
||||||
bDeepBreath = true;
|
bDeepBreath = true;
|
||||||
LoadObjectData(creatureData, nullptr);
|
LoadObjectData(creatureData, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCreatureCreate(Creature* creature) override
|
|
||||||
{
|
|
||||||
switch (creature->GetEntry())
|
|
||||||
{
|
|
||||||
case NPC_ONYXIAN_WHELP:
|
|
||||||
case NPC_ONYXIAN_LAIR_GUARD:
|
|
||||||
minions.push_back(creature->GetGUID());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
InstanceScript::OnCreatureCreate(creature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* go) override
|
void OnGameObjectCreate(GameObject* go) override
|
||||||
{
|
{
|
||||||
switch (go->GetEntry())
|
switch (go->GetEntry())
|
||||||
@@ -79,26 +64,26 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetData(uint32 uiType, uint32 uiData) override
|
bool SetBossState(uint32 type, EncounterState state) override
|
||||||
|
{
|
||||||
|
if (!InstanceScript::SetBossState(type, state))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == DATA_ONYXIA && state == NOT_STARTED)
|
||||||
|
{
|
||||||
|
ManyWhelpsCounter = 0;
|
||||||
|
bDeepBreath = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetData(uint32 uiType, uint32 /*uiData*/) override
|
||||||
{
|
{
|
||||||
switch (uiType)
|
switch (uiType)
|
||||||
{
|
{
|
||||||
case DATA_ONYXIA:
|
|
||||||
m_auiEncounter[0] = uiData;
|
|
||||||
ManyWhelpsCounter = 0;
|
|
||||||
bDeepBreath = true;
|
|
||||||
if(uiData == NOT_STARTED)
|
|
||||||
{
|
|
||||||
for (ObjectGuid const& guid : minions)
|
|
||||||
{
|
|
||||||
if (Creature* c = instance->GetCreature(guid))
|
|
||||||
{
|
|
||||||
c->DespawnOrUnsummon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
minions.clear();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DATA_WHELP_SUMMONED:
|
case DATA_WHELP_SUMMONED:
|
||||||
++ManyWhelpsCounter;
|
++ManyWhelpsCounter;
|
||||||
break;
|
break;
|
||||||
@@ -106,29 +91,13 @@ public:
|
|||||||
bDeepBreath = false;
|
bDeepBreath = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uiType < MAX_ENCOUNTER && uiData == DONE)
|
|
||||||
{
|
|
||||||
SaveToDB();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 GetData(uint32 uiType) const override
|
|
||||||
{
|
|
||||||
switch (uiType)
|
|
||||||
{
|
|
||||||
case DATA_ONYXIA:
|
|
||||||
return m_auiEncounter[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetSaveData() override
|
std::string GetSaveData() override
|
||||||
{
|
{
|
||||||
OUT_SAVE_INST_DATA;
|
OUT_SAVE_INST_DATA;
|
||||||
std::ostringstream saveStream;
|
std::ostringstream saveStream;
|
||||||
saveStream << "O L " << m_auiEncounter[0];
|
saveStream << "O L " << GetBossSaveData();
|
||||||
str_data = saveStream.str();
|
str_data = saveStream.str();
|
||||||
OUT_SAVE_INST_DATA_COMPLETE;
|
OUT_SAVE_INST_DATA_COMPLETE;
|
||||||
return str_data;
|
return str_data;
|
||||||
@@ -136,7 +105,7 @@ public:
|
|||||||
|
|
||||||
void Load(const char* in) override
|
void Load(const char* in) override
|
||||||
{
|
{
|
||||||
if( !in )
|
if (!in)
|
||||||
{
|
{
|
||||||
OUT_LOAD_INST_DATA_FAIL;
|
OUT_LOAD_INST_DATA_FAIL;
|
||||||
return;
|
return;
|
||||||
@@ -149,13 +118,18 @@ public:
|
|||||||
std::istringstream loadStream(in);
|
std::istringstream loadStream(in);
|
||||||
loadStream >> dataHead1 >> dataHead2 >> data0;
|
loadStream >> dataHead1 >> dataHead2 >> data0;
|
||||||
|
|
||||||
if( dataHead1 == 'O' && dataHead2 == 'L' )
|
if (dataHead1 == 'O' && dataHead2 == 'L')
|
||||||
{
|
{
|
||||||
m_auiEncounter[0] = data0;
|
for (uint32 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||||
|
{
|
||||||
for( uint8 i = 0; i < MAX_ENCOUNTER; ++i )
|
uint32 tmpState;
|
||||||
if( m_auiEncounter[i] == IN_PROGRESS )
|
loadStream >> tmpState;
|
||||||
m_auiEncounter[i] = NOT_STARTED;
|
if (tmpState == IN_PROGRESS || tmpState == FAIL || tmpState > SPECIAL)
|
||||||
|
{
|
||||||
|
tmpState = NOT_STARTED;
|
||||||
|
}
|
||||||
|
SetBossState(i, EncounterState(tmpState));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
OUT_LOAD_INST_DATA_FAIL;
|
OUT_LOAD_INST_DATA_FAIL;
|
||||||
|
|||||||
@@ -58,4 +58,6 @@ inline AI* GetOnyxiasLairAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, OnyxiasLairScriptName);
|
return GetInstanceAI<AI>(obj, OnyxiasLairScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterOnyxiasLairCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetOnyxiasLairAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user