refactor(Scripts/Onyxia): Update Onyxia's script (#9371)

This commit is contained in:
Skjalf
2021-11-27 13:33:50 -03:00
committed by GitHub
parent 849839c688
commit 08580defd0
4 changed files with 479 additions and 606 deletions
@@ -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);
@@ -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,23 +481,23 @@ 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;
@@ -550,55 +505,43 @@ public:
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;
@@ -648,60 +589,9 @@ 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;
@@ -151,11 +120,16 @@ public:
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