fix(Scripts/Naxx): fix Gothik the Harvester evading during phase 2 teleport (#25265)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: offl <11556157+offl@users.noreply.github.com>
This commit is contained in:
@@ -111,7 +111,9 @@ enum Events
|
|||||||
// Intro
|
// Intro
|
||||||
EVENT_INTRO_2 = 15,
|
EVENT_INTRO_2 = 15,
|
||||||
EVENT_INTRO_3 = 16,
|
EVENT_INTRO_3 = 16,
|
||||||
EVENT_INTRO_4 = 17
|
EVENT_INTRO_4 = 17,
|
||||||
|
// Resume after teleport
|
||||||
|
EVENT_RESUME_ATTACK = 18
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 gothikWaves[24][2] =
|
const uint32 gothikWaves[24][2] =
|
||||||
@@ -172,21 +174,6 @@ const Position PosSummonDead[5] =
|
|||||||
#define POS_X_SOUTH 2633.84f
|
#define POS_X_SOUTH 2633.84f
|
||||||
#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE)
|
#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE)
|
||||||
|
|
||||||
// Predicate function to check that the r efzr unit is NOT on the same side as the source.
|
|
||||||
struct NotOnSameSide
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit NotOnSameSide(Unit* pSource) : m_inLiveSide(IN_LIVE_SIDE(pSource)) { }
|
|
||||||
|
|
||||||
bool operator() (Unit const* pTarget)
|
|
||||||
{
|
|
||||||
return (m_inLiveSide != IN_LIVE_SIDE(pTarget));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_inLiveSide;
|
|
||||||
};
|
|
||||||
|
|
||||||
class boss_gothik : public CreatureScript
|
class boss_gothik : public CreatureScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -206,6 +193,7 @@ public:
|
|||||||
SummonList summons;
|
SummonList summons;
|
||||||
bool secondPhase{};
|
bool secondPhase{};
|
||||||
bool gateOpened{};
|
bool gateOpened{};
|
||||||
|
bool lastTeleportDead{};
|
||||||
uint8 waveCount{};
|
uint8 waveCount{};
|
||||||
|
|
||||||
bool IsInRoom()
|
bool IsInRoom()
|
||||||
@@ -228,6 +216,7 @@ public:
|
|||||||
me->SetReactState(REACT_PASSIVE);
|
me->SetReactState(REACT_PASSIVE);
|
||||||
secondPhase = false;
|
secondPhase = false;
|
||||||
gateOpened = false;
|
gateOpened = false;
|
||||||
|
lastTeleportDead = false;
|
||||||
waveCount = 0;
|
waveCount = 0;
|
||||||
me->NearTeleportTo(2642.139f, -3386.959f, 285.492f, 6.265f);
|
me->NearTeleportTo(2642.139f, -3386.959f, 285.492f, 6.265f);
|
||||||
}
|
}
|
||||||
@@ -366,6 +355,18 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGate()
|
||||||
|
{
|
||||||
|
if (gateOpened)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GameObject* go = instance->GetGameObject(DATA_GOTHIK_INNER_GATE))
|
||||||
|
go->SetGoState(GO_STATE_ACTIVE);
|
||||||
|
|
||||||
|
gateOpened = true;
|
||||||
|
Talk(EMOTE_GATE_OPENED);
|
||||||
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||||
{
|
{
|
||||||
if (!secondPhase)
|
if (!secondPhase)
|
||||||
@@ -382,6 +383,35 @@ public:
|
|||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Safety net: if our victim is on the wrong side, find a
|
||||||
|
// same-side target or open the gate
|
||||||
|
if (secondPhase && me->HasReactState(REACT_AGGRESSIVE) && !gateOpened
|
||||||
|
&& !IN_LIVE_SIDE(me) != !IN_LIVE_SIDE(me->GetVictim()))
|
||||||
|
{
|
||||||
|
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
|
||||||
|
Player* newTarget = nullptr;
|
||||||
|
for (auto const& itr : pList)
|
||||||
|
{
|
||||||
|
Player* player = itr.GetSource();
|
||||||
|
if (player && player->IsAlive() && !player->IsGameMaster()
|
||||||
|
&& me->IsValidAttackTarget(player)
|
||||||
|
&& IN_LIVE_SIDE(me) == IN_LIVE_SIDE(player))
|
||||||
|
{
|
||||||
|
newTarget = player;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTarget)
|
||||||
|
{
|
||||||
|
me->GetThreatMgr().ResetAllThreat();
|
||||||
|
me->GetThreatMgr().AddThreat(newTarget, 1.0f);
|
||||||
|
AttackStart(newTarget);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
OpenGate();
|
||||||
|
}
|
||||||
|
|
||||||
events.Update(diff);
|
events.Update(diff);
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||||
return;
|
return;
|
||||||
@@ -407,32 +437,29 @@ public:
|
|||||||
break;
|
break;
|
||||||
case EVENT_TELEPORT:
|
case EVENT_TELEPORT:
|
||||||
{
|
{
|
||||||
|
if (me->HealthBelowPct(30))
|
||||||
|
break;
|
||||||
|
|
||||||
|
me->CastStop();
|
||||||
me->AttackStop();
|
me->AttackStop();
|
||||||
if (IN_LIVE_SIDE(me))
|
me->SetReactState(REACT_PASSIVE);
|
||||||
me->CastSpell(me, SPELL_TELEPORT_DEAD, false);
|
me->GetThreatMgr().ResetAllThreat();
|
||||||
else
|
me->CastSpell(me, lastTeleportDead ? SPELL_TELEPORT_LIVE : SPELL_TELEPORT_DEAD, false);
|
||||||
me->CastSpell(me, SPELL_TELEPORT_LIVE, false);
|
lastTeleportDead = !lastTeleportDead;
|
||||||
|
|
||||||
// Clear threat from targets not on the same side as Gothik
|
events.CancelEvent(EVENT_SHADOW_BOLT);
|
||||||
NotOnSameSide notOnSameSide(me);
|
events.ScheduleEvent(EVENT_RESUME_ATTACK, 2s);
|
||||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
|
||||||
if (notOnSameSide(ref->GetVictim()))
|
|
||||||
me->GetThreatMgr().ClearThreat(ref->GetVictim());
|
|
||||||
|
|
||||||
if (Unit* pTarget = SelectTarget(SelectTargetMethod::MaxDistance, 0))
|
|
||||||
{
|
|
||||||
me->GetThreatMgr().AddThreat(pTarget, 100.0f);
|
|
||||||
AttackStart(pTarget);
|
|
||||||
}
|
|
||||||
events.Repeat(20s);
|
events.Repeat(20s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVENT_RESUME_ATTACK:
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
events.ScheduleEvent(EVENT_SHADOW_BOLT, 0s);
|
||||||
|
return UpdateAI(0);
|
||||||
case EVENT_CHECK_HEALTH:
|
case EVENT_CHECK_HEALTH:
|
||||||
if (me->HealthBelowPct(30))
|
if (me->HealthBelowPct(30))
|
||||||
{
|
{
|
||||||
if (GameObject* go = instance->GetGameObject(DATA_GOTHIK_INNER_GATE))
|
OpenGate();
|
||||||
go->SetGoState(GO_STATE_ACTIVE);
|
|
||||||
|
|
||||||
events.CancelEvent(EVENT_TELEPORT);
|
events.CancelEvent(EVENT_TELEPORT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -464,10 +491,7 @@ public:
|
|||||||
case EVENT_CHECK_PLAYERS:
|
case EVENT_CHECK_PLAYERS:
|
||||||
if (!CheckGroupSplitted())
|
if (!CheckGroupSplitted())
|
||||||
{
|
{
|
||||||
if (GameObject* go = instance->GetGameObject(DATA_GOTHIK_INNER_GATE))
|
OpenGate();
|
||||||
go->SetGoState(GO_STATE_ACTIVE);
|
|
||||||
|
|
||||||
gateOpened = true;
|
|
||||||
summons.DoForAllSummons([&](WorldObject* summon)
|
summons.DoForAllSummons([&](WorldObject* summon)
|
||||||
{
|
{
|
||||||
if (Creature* gothikMinion = summon->ToCreature())
|
if (Creature* gothikMinion = summon->ToCreature())
|
||||||
@@ -481,7 +505,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Talk(EMOTE_GATE_OPENED);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user