fix(Scripts/OnyxiasLair): Match Onyxia's air phase to retail (#27848)

This commit is contained in:
Andrew
2026-09-28 00:26:07 -03:00
committed by GitHub
parent e849efedb6
commit 2945ef1892
2 changed files with 168 additions and 73 deletions
@@ -0,0 +1,96 @@
-- Onyxia's Deep Breath trails
DELETE FROM `spell_target_position` WHERE `ID` IN (17086, 17087, 17088, 17089, 17090, 17091, 17092, 17093, 17094, 17095, 17097, 18351, 18352, 18353, 18354, 18355, 18356, 18357, 18358, 18359, 18360, 18361, 18564, 18565, 18566, 18567, 18568, 18569, 18570, 18571, 18572, 18573, 18574, 18575, 18576, 18578, 18579, 18580, 18581, 18582, 18583, 18584, 18585, 18586, 18587, 18588, 18589, 18590, 18591, 18592, 18593, 18594, 18595, 18596, 18597, 18598, 18599, 18600, 18601, 18602, 18603, 18604, 18605, 18606, 18607, 18609, 18611, 18612, 18613, 18614, 18615, 18616, 18617, 18618, 18619, 18620, 18621, 18622, 18623, 18624, 18625, 18626, 18627, 18628, 21132, 21133, 21135, 21136, 21137, 21138, 21139, 22267, 22268);
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES
(17086, 0, 249, 25, -216.025, -84.874, 3.142, 69933),
(17087, 0, 249, 15, -216.025, -85.8052, 3.142, 69933),
(17088, 0, 249, 5, -216.025, -86.0683, 3.142, 69933),
(17089, 0, 249, -5, -216.025, -86.9675, 3.142, 69933),
(17090, 0, 249, -15, -216.025, -88.3522, 3.142, 69933),
(17091, 0, 249, -25, -216.025, -89.2463, 3.142, 69933),
(17092, 0, 249, -35, -216.025, -87.4351, 3.142, 69933),
(17093, 0, 249, -45, -216.025, -86.4653, 3.142, 69933),
(17094, 0, 249, -55, -216.025, -85.3717, 3.142, 69933),
(17095, 0, 249, -65, -216.025, -84.3052, 3.142, 69933),
(17097, 0, 249, -75, -216.025, -83.395, 3.142, 69933),
(18351, 0, 249, -75, -216.025, -83.395, 0.0, 69933),
(18352, 0, 249, -65, -216.025, -84.3052, 0.0, 69933),
(18353, 0, 249, -55, -216.025, -85.3717, 0.0, 69933),
(18354, 0, 249, -45, -216.025, -86.4653, 0.0, 69933),
(18355, 0, 249, -35, -216.025, -87.4351, 0.0, 69933),
(18356, 0, 249, -25, -216.025, -89.2463, 0.0, 69933),
(18357, 0, 249, -15, -216.025, -88.3522, 0.0, 69933),
(18358, 0, 249, -5, -216.025, -86.9675, 0.0, 69933),
(18359, 0, 249, 5, -216.025, -86.0683, 0.0, 69933),
(18360, 0, 249, 15, -216.025, -85.8052, 0.0, 69933),
(18361, 0, 249, 25, -216.025, -84.874, 0.0, 69933),
(18564, 0, 249, 12, -243, -85.8115, 2.509, 69933),
(18565, 0, 249, 5, -238, -83.5463, 2.509, 69933),
(18566, 0, 249, -2, -233, -87.0423, 2.509, 69933),
(18567, 0, 249, -9, -228, -87.2249, 2.509, 69933),
(18568, 0, 249, -16, -223, -88.4193, 2.509, 69933),
(18569, 0, 249, -23, -218, -89.118, 2.509, 69933),
(18570, 0, 249, -30, -213, -88.7968, 2.509, 69933),
(18571, 0, 249, -37, -208, -85.7672, 2.509, 69933),
(18572, 0, 249, -42, -203, -85.7496, 2.509, 69933),
(18573, 0, 249, -49, -198, -86.0707, 2.509, 69933),
(18574, 0, 249, -56, -193, -95.3709, 2.509, 69933),
(18575, 0, 249, -63, -188, -84.9507, 2.509, 69933),
(18576, 0, 249, -15, -245, -87.5753, 1.571, 69933),
(18578, 0, 249, -15, -235, -88.0806, 1.571, 69933),
(18579, 0, 249, -15, -225, -88.2034, 1.571, 69933),
(18580, 0, 249, -15, -215, -88.3604, 1.571, 69933),
(18581, 0, 249, -15, -205, -88.2501, 1.571, 69933),
(18582, 0, 249, -15, -195, -87.9789, 1.571, 69933),
(18583, 0, 249, -15, -185, -87.619, 1.571, 69933),
(18584, 0, 249, -63, -235, -84.7973, 0.633, 69933),
(18585, 0, 249, -56, -230, -85.3849, 0.633, 69933),
(18586, 0, 249, -49, -225, -85.9159, 0.633, 69933),
(18587, 0, 249, -42, -220, -86.5724, 0.633, 69933),
(18588, 0, 249, -37, -215, -86.8173, 0.633, 69933),
(18589, 0, 249, -30, -210, -88.7968, 0.633, 69933),
(18590, 0, 249, -23, -205, -89.0804, 0.633, 69933),
(18591, 0, 249, -16, -200, -88.152, 0.633, 69933),
(18592, 0, 249, -9, -195, -87.5513, 0.633, 69933),
(18593, 0, 249, -2, -190, -87.1019, 0.633, 69933),
(18594, 0, 249, 5, -185, -86.8609, 0.633, 69933),
(18595, 0, 249, 12, -180, -85.7109, 0.633, 69933),
(18596, 0, 249, -63, -188, -84.9507, 5.65, 69933),
(18597, 0, 249, -56, -193, -95.3709, 5.65, 69933),
(18598, 0, 249, -49, -198, -86.0707, 5.65, 69933),
(18599, 0, 249, -42, -203, -85.7496, 5.65, 69933),
(18600, 0, 249, -37, -208, -85.7672, 5.65, 69933),
(18601, 0, 249, -30, -213, -88.7968, 5.65, 69933),
(18602, 0, 249, -23, -218, -89.118, 5.65, 69933),
(18603, 0, 249, -16, -223, -88.4193, 5.65, 69933),
(18604, 0, 249, -9, -228, -87.2249, 5.65, 69933),
(18605, 0, 249, -2, -233, -87.0423, 5.65, 69933),
(18606, 0, 249, 5, -238, -83.5463, 5.65, 69933),
(18607, 0, 249, 12, -243, -85.8115, 5.65, 69933),
(18609, 0, 249, -15, -185, -87.619, 4.712, 69933),
(18611, 0, 249, -15, -195, -87.9789, 4.712, 69933),
(18612, 0, 249, -15, -205, -88.2501, 4.712, 69933),
(18613, 0, 249, -15, -215, -88.3604, 4.712, 69933),
(18614, 0, 249, -15, -225, -88.2034, 4.712, 69933),
(18615, 0, 249, -15, -235, -88.0806, 4.712, 69933),
(18616, 0, 249, -15, -245, -87.5753, 4.712, 69933),
(18617, 0, 249, 12, -180, -85.7109, 3.774, 69933),
(18618, 0, 249, -63, -235, -84.7873, 3.774, 69933),
(18619, 0, 249, 5, -185, -86.8609, 3.774, 69933),
(18620, 0, 249, -2, -190, -87.1019, 3.774, 69933),
(18621, 0, 249, -9, -195, -87.5513, 3.774, 69933),
(18622, 0, 249, -16, -200, -88.152, 3.774, 69933),
(18623, 0, 249, -23, -205, -89.0804, 3.774, 69933),
(18624, 0, 249, -30, -210, -88.7968, 3.774, 69933),
(18625, 0, 249, -37, -215, -86.8173, 3.774, 69933),
(18626, 0, 249, -42, -220, -86.5724, 3.774, 69933),
(18627, 0, 249, -49, -225, -85.9159, 3.774, 69933),
(18628, 0, 249, -56, -230, -85.3849, 3.774, 69933),
(21132, 0, 249, -120.471, -214.335, -71.9481, 3.142, 69933),
(21133, 0, 249, -142.719, -213.206, -68.8335, 3.142, 69933),
(21135, 0, 249, -162.585, -205.683, -68.7282, 3.142, 69933),
(21136, 0, 249, -194.92, -206.546, -68.7282, 3.142, 69933),
(21137, 0, 249, -173.573, -186.406, -66.1293, 3.142, 69933),
(21138, 0, 249, -164.067, -164.104, -59.5405, 3.142, 69933),
(21139, 0, 249, -144.485, -149.742, -53.8462, 3.142, 69933),
(22267, 0, 249, -85, -216.025, -82.5516, 3.142, 69933),
(22268, 0, 249, -96.8227, -214.425, -82.2065, 3.142, 69933);
@@ -34,6 +34,7 @@ enum Spells
SPELL_TAILSWEEP = 68867,
SPELL_FIREBALL = 18392,
SPELL_BELLOWINGROAR = 18431,
SPELL_DEEP_BREATH_TIMER = 68800,
SPELL_SUMMON_LAIR_GUARD = 68968,
@@ -47,10 +48,10 @@ enum Spells
SPELL_BREATH_S_TO_N = 18351,
SPELL_BREATH_E_TO_W = 18576,
SPELL_BREATH_W_TO_E = 18609,
SPELL_BREATH_SE_TO_NW = 18564,
SPELL_BREATH_NW_TO_SE = 18584,
SPELL_BREATH_NE_TO_SW = 18564,
SPELL_BREATH_SE_TO_NW = 18584,
SPELL_BREATH_SW_TO_NE = 18596,
SPELL_BREATH_NE_TO_SW = 18617,
SPELL_BREATH_NW_TO_SE = 18617,
// Each patch triggers the next one, up to 22202
SPELL_HEATED_GROUND = 22191,
@@ -63,11 +64,8 @@ enum Events
EVENT_SPELL_TAILSWEEP = 3,
EVENT_SPELL_CLEAVE = 4,
EVENT_START_PHASE_2 = 5,
EVENT_SPELL_FIREBALL_FIRST = 6,
EVENT_SPELL_FIREBALL_SECOND = 7,
EVENT_PHASE_2_STEP_CW = 8,
EVENT_PHASE_2_STEP_ACW = 9,
EVENT_PHASE_2_STEP_ACROSS = 10,
EVENT_AIR_PHASE_ACTION = 6,
EVENT_DEEP_BREATH_TIMER = 7,
EVENT_SPELL_BREATH = 11,
EVENT_START_PHASE_3 = 12,
EVENT_PHASE_3_ATTACK = 13,
@@ -111,17 +109,18 @@ struct OnyxiaMove
float X, Y, Z, O;
};
// O is her facing on arrival and for Deep Breath
static OnyxiaMove const OnyxiaMoveData[] =
{
{0, 0, 0, -64.496f, -214.906f, -84.4f, 0.0f}, // south ground
{1, 5, SPELL_BREATH_S_TO_N, -64.496f, -214.906f, -60.0f, 0.0f}, // south
{2, 6, SPELL_BREATH_SW_TO_NE, -59.809f, -190.758f, -60.0f, 7 * M_PI / 4}, // south-west
{3, 7, SPELL_BREATH_W_TO_E, -29.450f, -180.600f, -60.0f, M_PI + M_PI / 2}, // west
{4, 8, SPELL_BREATH_NW_TO_SE, 6.895f, -180.246f, -60.0f, M_PI + M_PI / 4}, // north-west
{5, 1, SPELL_BREATH_N_TO_S, 22.876f, -217.152f, -60.0f, M_PI}, // north
{6, 2, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -60.0f, 3 * M_PI / 4}, // north-east
{7, 3, SPELL_BREATH_E_TO_W, -31.496f, -250.123f, -60.0f, M_PI / 2}, // east
{8, 4, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -60.0f, M_PI / 4}, // south-east
{0, 0, 0, -66.3589f, -215.928f, -84.23904f, 0.0f}, // south ground
{1, 5, SPELL_BREATH_S_TO_N, -75.387505f, -215.21892f, -58.02298f, 0.0075448f}, // south
{2, 6, SPELL_BREATH_SW_TO_NE, -64.04101f, -188.51236f, -59.439896f, 5.549744f}, // south-west
{3, 7, SPELL_BREATH_W_TO_E, -15.713689f, -181.3027f, -62.038284f, 4.2037554f}, // west
{4, 8, SPELL_BREATH_NW_TO_SE, 11.944992f, -180.16212f, -60.27321f, 3.9242017f}, // north-west
{5, 1, SPELL_BREATH_N_TO_S, 25.16067f, -216.08244f, -58.92215f, 3.2004213f}, // north
{6, 2, SPELL_BREATH_NE_TO_SW, 12.422047f, -242.43831f, -60.561646f, 2.6292219f}, // north-east
{7, 3, SPELL_BREATH_E_TO_W, -14.978153f, -245.48346f, -60.375755f, 2.0324559f}, // east
{8, 4, SPELL_BREATH_SE_TO_NW, -63.786427f, -235.2712f, -60.19681f, 0.5779157f}, // south-east
};
static_assert(std::size(OnyxiaMoveData) == WP_SOUTH_EAST + 1);
@@ -174,6 +173,9 @@ struct boss_onyxia : public BossAI
{
_phase = PHASE_NONE;
_currentWP = WP_GROUND_SOUTH;
_fireballsCast = 0;
_fireballsBeforeMoving = 0;
_landingPending = false;
_manyWhelpsAvailable = false;
_whelpsRespawn = false;
_pointWhelpGUIDs.fill(ObjectGuid::Empty);
@@ -210,7 +212,6 @@ struct boss_onyxia : public BossAI
me->SetReactState(REACT_AGGRESSIVE);
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run, false);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
BossAI::Reset();
}
@@ -243,10 +244,10 @@ struct boss_onyxia : public BossAI
{
SetPhase(PHASE_AIRPHASE);
});
// She keeps flying her route and lands at the next waypoint where she has cast a Fireball
ScheduleHealthCheckEvent(40, [&]
{
summons.DespawnEntry(NPC_WORLD_TRIGGER);
SetPhase(PHASE_LANDED);
_landingPending = true;
});
me->SummonCreature(NPC_ONYXIAN_LAIR_GUARD, -167.837936f, -200.549332f, -66.343231f, 5.598287f, TEMPSUMMON_MANUAL_DESPAWN);
@@ -321,16 +322,17 @@ struct boss_onyxia : public BossAI
if (id >= WP_SOUTH && _phase == PHASE_AIRPHASE)
{
me->SetFacingTo(OnyxiaMoveData[id].O);
me->SetSpeed(MOVE_RUN, 1.6f, false);
// The first stop, after the long flight north, waits longer before its first Fireball
events.ScheduleEvent(EVENT_AIR_PHASE_ACTION, _currentWP == WP_GROUND_SOUTH ? 3250ms : 1400ms);
_currentWP = id;
events.ScheduleEvent(EVENT_SPELL_FIREBALL_FIRST, 1s);
_fireballsCast = 0;
_fireballsBeforeMoving = urand(3, 5);
}
return;
}
switch (id)
{
// The landing replaces an unfinished walk or takeoff, and the replaced movement still reports its point
case POINT_GROUND_SOUTH:
if (_phase != PHASE_AIRPHASE)
break;
@@ -346,7 +348,6 @@ struct boss_onyxia : public BossAI
case POINT_LAND:
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run, false);
events.ScheduleEvent(EVENT_PHASE_3_ATTACK, 2s);
break;
default:
@@ -354,10 +355,10 @@ struct boss_onyxia : public BossAI
}
}
void MoveToWaypoint(uint8 wp)
void MoveToWaypoint(uint8 wp, float speed)
{
OnyxiaMove const& point = OnyxiaMoveData[wp];
me->GetMotionMaster()->MovePoint(wp, point.X, point.Y, point.Z);
me->GetMotionMaster()->MovePoint(wp, point.X, point.Y, point.Z, FORCED_MOVEMENT_NONE, speed);
}
void SummonPointWhelp(uint8 point)
@@ -454,6 +455,7 @@ struct boss_onyxia : public BossAI
_lairGuardTriggerGUID = trigger->GetGUID();
events.ScheduleEvent(EVENT_SUMMON_LAIR_GUARD, 46s);
events.ScheduleEvent(EVENT_DEEP_BREATH_TIMER, 25s, 35s);
break;
}
case EVENT_LIFTOFF:
@@ -465,7 +467,8 @@ struct boss_onyxia : public BossAI
me->SetDisableGravity(true);
me->SetOrientation(OnyxiaMoveData[WP_GROUND_SOUTH].O);
me->SendMovementFlagUpdate();
me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, OnyxiaMoveData[WP_SOUTH].X + 1.0f, OnyxiaMoveData[WP_SOUTH].Y, OnyxiaMoveData[WP_SOUTH].Z, 12.0f);
// Straight up, 20y in 2s
me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, OnyxiaMoveData[WP_GROUND_SOUTH].X, OnyxiaMoveData[WP_GROUND_SOUTH].Y, OnyxiaMoveData[WP_GROUND_SOUTH].Z + 20.0f, 10.0f);
_manyWhelpsAvailable = true;
// On the scheduler: reaching 40% during takeoff resets the event map before the window would close
scheduler.Schedule(10s, [this](TaskContext)
@@ -481,8 +484,7 @@ struct boss_onyxia : public BossAI
}
case EVENT_FLY_S_TO_N:
{
me->SetSpeed(MOVE_RUN, 2.95f, false);
MoveToWaypoint(WP_NORTH);
MoveToWaypoint(WP_NORTH, 8.0f);
break;
}
case EVENT_SUMMON_LAIR_GUARD:
@@ -494,61 +496,55 @@ struct boss_onyxia : public BossAI
events.Repeat(46s);
break;
}
case EVENT_SPELL_FIREBALL_FIRST:
case EVENT_DEEP_BREATH_TIMER:
{
DoCastSelf(SPELL_DEEP_BREATH_TIMER, true);
events.Repeat(37s, 62s);
break;
}
// At a waypoint: Fireballs back to back, a pending Deep Breath once two are out, then on to a neighbour
case EVENT_AIR_PHASE_ACTION:
{
if (_landingPending && _fireballsCast > 0)
{
summons.DespawnEntry(NPC_WORLD_TRIGGER);
SetPhase(PHASE_LANDED);
break;
}
if (_fireballsCast >= _fireballsBeforeMoving)
{
if (urand(0, 1))
MoveToWaypoint(_currentWP == WP_SOUTH_EAST ? WP_SOUTH : _currentWP + 1, 8.0f);
else
MoveToWaypoint(_currentWP == WP_SOUTH ? WP_SOUTH_EAST : _currentWP - 1, 8.0f);
break;
}
if (_fireballsCast >= 2 && me->HasAura(SPELL_DEEP_BREATH_TIMER))
{
me->RemoveAurasDueToSpell(SPELL_DEEP_BREATH_TIMER);
Talk(EMOTE_BREATH);
me->SetFacingTo(OnyxiaMoveData[_currentWP].O);
DoCastAOE(OnyxiaMoveData[_currentWP].SpellId);
events.ScheduleEvent(EVENT_SPELL_BREATH, 8250ms);
break;
}
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.0f, true))
{
me->SetFacingToObject(target);
DoCast(target, SPELL_FIREBALL);
}
events.ScheduleEvent(EVENT_SPELL_FIREBALL_SECOND, 4s);
break;
}
case EVENT_SPELL_FIREBALL_SECOND:
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.0f, true))
{
me->SetFacingToObject(target);
DoCast(target, SPELL_FIREBALL);
}
switch (urand(0, 2))
{
case 0:
events.ScheduleEvent(EVENT_PHASE_2_STEP_CW, 4s);
break;
case 1:
events.ScheduleEvent(EVENT_PHASE_2_STEP_ACW, 4s);
break;
default:
events.ScheduleEvent(EVENT_PHASE_2_STEP_ACROSS, 4s);
break;
}
break;
}
case EVENT_PHASE_2_STEP_CW:
{
MoveToWaypoint(_currentWP == WP_SOUTH_EAST ? WP_SOUTH : _currentWP + 1);
break;
}
case EVENT_PHASE_2_STEP_ACW:
{
MoveToWaypoint(_currentWP == WP_SOUTH ? WP_SOUTH_EAST : _currentWP - 1);
break;
}
case EVENT_PHASE_2_STEP_ACROSS:
{
Talk(EMOTE_BREATH);
me->SetFacingTo(OnyxiaMoveData[_currentWP].O);
DoCastAOE(OnyxiaMoveData[_currentWP].SpellId);
events.ScheduleEvent(EVENT_SPELL_BREATH, 8250ms);
++_fireballsCast;
// The 3s cast plus a 0.6s pause
events.Repeat(3600ms);
break;
}
case EVENT_SPELL_BREATH:
{
me->SetSpeed(MOVE_RUN, 2.95f, false);
MoveToWaypoint(OnyxiaMoveData[_currentWP].DestId);
MoveToWaypoint(OnyxiaMoveData[_currentWP].DestId, 24.0f);
break;
}
case EVENT_START_PHASE_3:
@@ -626,6 +622,9 @@ struct boss_onyxia : public BossAI
private:
Phases _phase;
uint8 _currentWP;
uint8 _fireballsCast;
uint8 _fireballsBeforeMoving;
bool _landingPending;
bool _manyWhelpsAvailable;
bool _whelpsRespawn;
std::array<ObjectGuid, std::size(WhelpSpawnPoints)> _pointWhelpGUIDs;