fix(Scripts/Nexus): Improve Crystalline Frayer (#24480)

This commit is contained in:
Gultask
2026-01-20 19:47:49 -03:00
committed by GitHub
parent e062d26ff5
commit 73f4bfd713
3 changed files with 161 additions and 52 deletions
@@ -0,0 +1,47 @@
--
DELETE FROM `linked_respawn` WHERE `linkedGuid` = 126663 AND `linkType` = 0;
INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`) VALUES
(126619, 126663, 0),
(126620, 126663, 0),
(126621, 126663, 0),
(126622, 126663, 0),
(126623, 126663, 0),
(126624, 126663, 0),
(126625, 126663, 0),
(126626, 126663, 0),
(126627, 126663, 0),
(126628, 126663, 0),
(126629, 126663, 0),
(126630, 126663, 0),
(126631, 126663, 0),
(126632, 126663, 0),
(126633, 126663, 0),
(126634, 126663, 0),
(126635, 126663, 0),
(126636, 126663, 0),
(126637, 126663, 0),
(126638, 126663, 0),
(126639, 126663, 0),
(126640, 126663, 0),
(126641, 126663, 0),
(126642, 126663, 0),
(126643, 126663, 0),
(126644, 126663, 0),
(126645, 126663, 0),
(126646, 126663, 0),
(126647, 126663, 0),
(126648, 126663, 0),
(126649, 126663, 0),
(126650, 126663, 0),
(126651, 126663, 0),
(126652, 126663, 0),
(126653, 126663, 0),
(126654, 126663, 0),
(126655, 126663, 0),
(126656, 126663, 0),
(126657, 126663, 0),
(126658, 126663, 0),
(126659, 126663, 0),
(126660, 126663, 0),
(126661, 126663, 0),
(126662, 126663, 0);
@@ -18,6 +18,7 @@
#include "CreatureScript.h" #include "CreatureScript.h"
#include "InstanceMapScript.h" #include "InstanceMapScript.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "TaskScheduler.h"
#include "nexus.h" #include "nexus.h"
#include "Player.h" #include "Player.h"
#include "Group.h" #include "Group.h"
@@ -44,6 +45,8 @@ public:
{ {
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {} instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {}
GuidVector _frayerGUIDs;
void Initialize() override void Initialize() override
{ {
SetHeaders(DataHeader); SetHeaders(DataHeader);
@@ -80,6 +83,23 @@ public:
if (GetTeamIdInInstance() == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG); creature->UpdateEntry(NPC_COMMANDER_KOLURG);
break; break;
case NPC_CRYSTALLINE_FRAYER:
_frayerGUIDs.push_back(creature->GetGUID());
break;
}
}
void KillAllFrayers()
{
for (ObjectGuid const& guid : _frayerGUIDs)
{
if (Creature* frayer = instance->GetCreature(guid))
{
frayer->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
Unit::Kill(frayer, frayer);
}
} }
} }
@@ -141,7 +161,13 @@ public:
if (!InstanceScript::SetBossState(id, state)) if (!InstanceScript::SetBossState(id, state))
return false; return false;
if (state != DONE || id > DATA_ORMOROK_EVENT) if (state != DONE)
return true;
if (id == DATA_ORMOROK_EVENT)
KillAllFrayers();
if (id > DATA_ORMOROK_EVENT)
return true; return true;
BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB); BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB);
@@ -156,9 +182,17 @@ enum eFrayer
{ {
SPELL_SUMMON_SEED_POD = 52796, SPELL_SUMMON_SEED_POD = 52796,
SPELL_SEED_POD = 48082, SPELL_SEED_POD = 48082,
SPELL_AURA_OF_REGENERATION = 52067, SPELL_AURA_OF_REGENERATION = 57056,
SPELL_CRYSTAL_BLOOM = 48058, SPELL_CRYSTAL_BLOOM = 48058,
SPELL_ENSNARE = 48053 SPELL_ENSNARE = 48053,
SAY_EMOTE = 0
};
enum FrayerGroups
{
GROUP_COMBAT = 1,
GROUP_SEED_POD = 2
}; };
struct npc_crystalline_frayer : public ScriptedAI struct npc_crystalline_frayer : public ScriptedAI
@@ -166,27 +200,44 @@ struct npc_crystalline_frayer : public ScriptedAI
npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { } npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { }
bool _allowDeath; bool _allowDeath;
uint32 restoreTimer; bool _inSeedPod;
uint32 abilityTimer1; TaskScheduler _scheduler;
uint32 abilityTimer2;
void Reset() override void Reset() override
{ {
restoreTimer = 0; _allowDeath = false;
abilityTimer1 = 0; _inSeedPod = false;
abilityTimer2 = 30000; _scheduler.CancelAll();
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveAllAuras();
me->SetObjectScale(1.0f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
me->GetMotionMaster()->MoveRandom(10.0f);
} }
void JustEngagedWith(Unit*) override void JustEngagedWith(Unit*) override
{ {
_allowDeath = me->GetInstanceScript()->GetBossState(DATA_ORMOROK_EVENT) == DONE; if (InstanceScript* instance = me->GetInstanceScript())
_allowDeath = instance->GetBossState(DATA_ORMOROK_EVENT) == DONE;
_scheduler.Schedule(5s, GROUP_COMBAT, [this](TaskContext context)
{
DoCastVictim(SPELL_ENSNARE);
context.Repeat(5s);
}).Schedule(0s, GROUP_COMBAT, [this](TaskContext context)
{
DoCastVictim(SPELL_CRYSTAL_BLOOM);
context.Repeat(30s);
});
} }
void EnterEvadeMode(EvadeReason why) override void EnterEvadeMode(EvadeReason why) override
{ {
if (me->isRegeneratingHealth()) if (!_inSeedPod)
ScriptedAI::EnterEvadeMode(why); ScriptedAI::EnterEvadeMode(why);
} }
@@ -196,57 +247,67 @@ struct npc_crystalline_frayer : public ScriptedAI
{ {
if (!_allowDeath) if (!_allowDeath)
{ {
me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
damage = 0; damage = 0;
EnterSeedPod();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetRegeneratingHealth(false);
me->CastSpell(me, SPELL_SUMMON_SEED_POD, true);
me->CastSpell(me, SPELL_SEED_POD, true);
me->CastSpell(me, SPELL_AURA_OF_REGENERATION, false);
restoreTimer = 1;
} }
} }
} }
void EnterSeedPod()
{
_inSeedPod = true;
_scheduler.CancelGroup(GROUP_COMBAT);
me->AttackStop();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(false);
me->SetObjectScale(0.6f);
DoCastSelf(SPELL_SEED_POD, true);
DoCastSelf(SPELL_SUMMON_SEED_POD, true);
DoCastSelf(SPELL_AURA_OF_REGENERATION, true);
_scheduler.Schedule(90s, GROUP_SEED_POD, [this](TaskContext /*context*/)
{
LeaveSeedPod();
});
}
void LeaveSeedPod()
{
_inSeedPod = false;
Talk(SAY_EMOTE);
me->RemoveAurasDueToSpell(SPELL_SEED_POD);
me->RemoveAurasDueToSpell(SPELL_AURA_OF_REGENERATION);
me->SetObjectScale(1.0f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
me->GetMotionMaster()->MoveRandom(10.0f);
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (restoreTimer) _scheduler.Update(diff);
{
restoreTimer += diff; if (_inSeedPod)
if (restoreTimer >= 90 * IN_MILLISECONDS)
{
Talk(0);
me->SetRegeneratingHealth(true);
restoreTimer = 0;
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
return; return;
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
abilityTimer1 += diff;
abilityTimer2 += diff;
if (abilityTimer1 >= 5000)
{
me->CastSpell(me->GetVictim(), SPELL_ENSNARE, false);
abilityTimer1 = 0;
}
if (abilityTimer2 >= 30000)
{
me->CastSpell(me->GetVictim(), SPELL_CRYSTAL_BLOOM, false);
abilityTimer2 = 0;
}
} }
}; };
@@ -50,6 +50,7 @@ enum Npcs
NPC_COMMANDER_STOUTBEARD = 26796, NPC_COMMANDER_STOUTBEARD = 26796,
NPC_COMMANDER_KOLURG = 26798, NPC_COMMANDER_KOLURG = 26798,
NPC_CRYSTALLINE_FRAYER = 26793,
GO_TELESTRA_SPHERE = 188526, GO_TELESTRA_SPHERE = 188526,
GO_ANOMALUS_SPHERE = 188527, GO_ANOMALUS_SPHERE = 188527,