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

View File

@@ -18,6 +18,7 @@
#include "CreatureScript.h"
#include "InstanceMapScript.h"
#include "ScriptedCreature.h"
#include "TaskScheduler.h"
#include "nexus.h"
#include "Player.h"
#include "Group.h"
@@ -44,6 +45,8 @@ public:
{
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {}
GuidVector _frayerGUIDs;
void Initialize() override
{
SetHeaders(DataHeader);
@@ -80,6 +83,23 @@ public:
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG);
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))
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;
BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB);
@@ -156,9 +182,17 @@ enum eFrayer
{
SPELL_SUMMON_SEED_POD = 52796,
SPELL_SEED_POD = 48082,
SPELL_AURA_OF_REGENERATION = 52067,
SPELL_AURA_OF_REGENERATION = 57056,
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
@@ -166,27 +200,44 @@ struct npc_crystalline_frayer : public ScriptedAI
npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { }
bool _allowDeath;
uint32 restoreTimer;
uint32 abilityTimer1;
uint32 abilityTimer2;
bool _inSeedPod;
TaskScheduler _scheduler;
void Reset() override
{
restoreTimer = 0;
abilityTimer1 = 0;
abilityTimer2 = 30000;
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
_allowDeath = false;
_inSeedPod = false;
_scheduler.CancelAll();
me->RemoveAllAuras();
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 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
{
if (me->isRegeneratingHealth())
if (!_inSeedPod)
ScriptedAI::EnterEvadeMode(why);
}
@@ -196,57 +247,67 @@ struct npc_crystalline_frayer : public ScriptedAI
{
if (!_allowDeath)
{
me->RemoveAllAuras();
me->GetThreatMgr().ClearAllThreat();
me->CombatStop(true);
damage = 0;
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;
EnterSeedPod();
}
}
}
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
{
if (restoreTimer)
{
restoreTimer += diff;
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);
}
_scheduler.Update(diff);
if (_inSeedPod)
return;
}
if (!UpdateVictim())
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;
}
}
};

View File

@@ -50,6 +50,7 @@ enum Npcs
NPC_COMMANDER_STOUTBEARD = 26796,
NPC_COMMANDER_KOLURG = 26798,
NPC_CRYSTALLINE_FRAYER = 26793,
GO_TELESTRA_SPHERE = 188526,
GO_ANOMALUS_SPHERE = 188527,