fix(Scripts/MagtheridonsLair): prevent Hellfire Channelers from respawning during boss fight (#25603)
Co-authored-by: sogla <sogladev@gmail.com>
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
-- Hellfire Channelers formation: groupAI = 3 (MEMBER_ASSIST_LEADER | LEADER_ASSIST_MEMBER), pack-aggro only. Wipe handling lives in the instance script's hard reset.
|
||||||
|
DELETE FROM `creature_formations` WHERE `leaderGUID`=90978;
|
||||||
|
INSERT INTO `creature_formations`
|
||||||
|
(`leaderGUID`,`memberGUID`,`dist`,`angle`,`groupAI`,`point_1`,`point_2`)
|
||||||
|
VALUES
|
||||||
|
(90978, 90978, 0, 0, 3, 0, 0),
|
||||||
|
(90978, 90979, 0, 0, 3, 0, 0),
|
||||||
|
(90978, 90980, 0, 0, 3, 0, 0),
|
||||||
|
(90978, 90981, 0, 0, 3, 0, 0),
|
||||||
|
(90978, 90982, 0, 0, 3, 0, 0);
|
||||||
|
|
||||||
|
-- Hellfire Channeler SAI: drop id=6. Death tracking moved to the instance script (OnUnitDeath).
|
||||||
|
DELETE FROM `smart_scripts` WHERE `entryorguid`=17256 AND `source_type`=0 AND `id`=6;
|
||||||
@@ -70,12 +70,6 @@ enum Groups
|
|||||||
GROUP_EARLY_RELEASE_CHECK = 0
|
GROUP_EARLY_RELEASE_CHECK = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Actions
|
|
||||||
{
|
|
||||||
ACTION_INCREASE_HELLFIRE_CHANNELER_DEATH_COUNT = 1,
|
|
||||||
ACTION_BANISH_SELF = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
struct boss_magtheridon : public BossAI
|
struct boss_magtheridon : public BossAI
|
||||||
{
|
{
|
||||||
boss_magtheridon(Creature* creature) : BossAI(creature, DATA_MAGTHERIDON)
|
boss_magtheridon(Creature* creature) : BossAI(creature, DATA_MAGTHERIDON)
|
||||||
@@ -84,7 +78,6 @@ struct boss_magtheridon : public BossAI
|
|||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
_channelersKilled = 0;
|
|
||||||
_currentPhase = 0;
|
_currentPhase = 0;
|
||||||
_castingQuake = false;
|
_castingQuake = false;
|
||||||
_recentlySpoken = false;
|
_recentlySpoken = false;
|
||||||
@@ -194,21 +187,19 @@ struct boss_magtheridon : public BossAI
|
|||||||
|
|
||||||
void DoAction(int32 action) override
|
void DoAction(int32 action) override
|
||||||
{
|
{
|
||||||
if (action == ACTION_INCREASE_HELLFIRE_CHANNELER_DEATH_COUNT)
|
if (action == ACTION_RELEASE_MAGTHERIDON)
|
||||||
{
|
{
|
||||||
_channelersKilled++;
|
if (_magReleased)
|
||||||
|
return;
|
||||||
|
|
||||||
if (_channelersKilled >= 5 && !_magReleased)
|
Talk(SAY_EMOTE_FREE);
|
||||||
|
Talk(SAY_FREE);
|
||||||
|
scheduler.CancelGroup(GROUP_EARLY_RELEASE_CHECK); //cancel regular countdown
|
||||||
|
_magReleased = true;
|
||||||
|
scheduler.Schedule(3s, [this](TaskContext)
|
||||||
{
|
{
|
||||||
Talk(SAY_EMOTE_FREE);
|
ScheduleCombatEvents();
|
||||||
Talk(SAY_FREE);
|
});
|
||||||
scheduler.CancelGroup(GROUP_EARLY_RELEASE_CHECK); //cancel regular countdown
|
|
||||||
_magReleased = true;
|
|
||||||
scheduler.Schedule(3s, [this](TaskContext)
|
|
||||||
{
|
|
||||||
ScheduleCombatEvents();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (action == ACTION_BANISH_SELF)
|
else if (action == ACTION_BANISH_SELF)
|
||||||
{
|
{
|
||||||
@@ -222,10 +213,6 @@ struct boss_magtheridon : public BossAI
|
|||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
Talk(SAY_EMOTE_BEGIN);
|
Talk(SAY_EMOTE_BEGIN);
|
||||||
|
|
||||||
instance->DoForAllMinions(DATA_MAGTHERIDON, [&](Creature* creature) {
|
|
||||||
creature->SetInCombatWithZone();
|
|
||||||
});
|
|
||||||
|
|
||||||
scheduler.Schedule(60s, GROUP_EARLY_RELEASE_CHECK, [this](TaskContext /*context*/)
|
scheduler.Schedule(60s, GROUP_EARLY_RELEASE_CHECK, [this](TaskContext /*context*/)
|
||||||
{
|
{
|
||||||
Talk(SAY_EMOTE_NEARLY);
|
Talk(SAY_EMOTE_NEARLY);
|
||||||
@@ -260,7 +247,6 @@ private:
|
|||||||
bool _recentlySpoken;
|
bool _recentlySpoken;
|
||||||
bool _magReleased;
|
bool _magReleased;
|
||||||
uint8 _currentPhase;
|
uint8 _currentPhase;
|
||||||
uint8 _channelersKilled;
|
|
||||||
TaskScheduler _interruptScheduler;
|
TaskScheduler _interruptScheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+60
-14
@@ -15,6 +15,7 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "CreatureAI.h"
|
||||||
#include "InstanceMapScript.h"
|
#include "InstanceMapScript.h"
|
||||||
#include "InstanceScript.h"
|
#include "InstanceScript.h"
|
||||||
#include "magtheridons_lair.h"
|
#include "magtheridons_lair.h"
|
||||||
@@ -30,12 +31,6 @@ DoorData const doorData[] =
|
|||||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||||
};
|
};
|
||||||
|
|
||||||
MinionData const minionData[] =
|
|
||||||
{
|
|
||||||
{ NPC_HELLFIRE_CHANNELER, DATA_MAGTHERIDON },
|
|
||||||
{ 0, 0 } // END
|
|
||||||
};
|
|
||||||
|
|
||||||
class instance_magtheridons_lair : public InstanceMapScript
|
class instance_magtheridons_lair : public InstanceMapScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -48,17 +43,28 @@ public:
|
|||||||
SetHeaders(DataHeader);
|
SetHeaders(DataHeader);
|
||||||
SetBossNumber(MAX_ENCOUNTER);
|
SetBossNumber(MAX_ENCOUNTER);
|
||||||
LoadDoorData(doorData);
|
LoadDoorData(doorData);
|
||||||
LoadMinionData(minionData);
|
|
||||||
LoadBossBoundaries(boundaries);
|
LoadBossBoundaries(boundaries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize() override
|
void Initialize() override
|
||||||
{
|
{
|
||||||
|
_channelersSet.clear();
|
||||||
_wardersSet.clear();
|
_wardersSet.clear();
|
||||||
|
_burningAbyssalsSet.clear();
|
||||||
_cubesSet.clear();
|
_cubesSet.clear();
|
||||||
_columnSet.clear();
|
_columnSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsAnyChannelerAlive()
|
||||||
|
{
|
||||||
|
return std::ranges::any_of(_channelersSet, [&](ObjectGuid const& guid)
|
||||||
|
{
|
||||||
|
if (Creature* channeler = instance->GetCreature(guid))
|
||||||
|
return channeler->IsAlive();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void OnCreatureCreate(Creature* creature) override
|
void OnCreatureCreate(Creature* creature) override
|
||||||
{
|
{
|
||||||
switch (creature->GetEntry())
|
switch (creature->GetEntry())
|
||||||
@@ -67,22 +73,42 @@ public:
|
|||||||
_magtheridonGUID = creature->GetGUID();
|
_magtheridonGUID = creature->GetGUID();
|
||||||
break;
|
break;
|
||||||
case NPC_HELLFIRE_CHANNELER:
|
case NPC_HELLFIRE_CHANNELER:
|
||||||
AddMinion(creature);
|
_channelersSet.insert(creature->GetGUID());
|
||||||
break;
|
break;
|
||||||
case NPC_HELLFIRE_WARDER:
|
case NPC_HELLFIRE_WARDER:
|
||||||
_wardersSet.insert(creature->GetGUID());
|
_wardersSet.insert(creature->GetGUID());
|
||||||
break;
|
break;
|
||||||
|
case NPC_BURNING_ABYSSAL:
|
||||||
|
_burningAbyssalsSet.insert(creature->GetGUID());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCreatureRemove(Creature* creature) override
|
void OnCreatureRemove(Creature* creature) override
|
||||||
{
|
{
|
||||||
switch (creature->GetEntry())
|
if (creature->GetEntry() == NPC_BURNING_ABYSSAL)
|
||||||
{
|
_burningAbyssalsSet.erase(creature->GetGUID());
|
||||||
case NPC_HELLFIRE_CHANNELER:
|
}
|
||||||
RemoveMinion(creature);
|
|
||||||
break;
|
void OnUnitDeath(Unit* unit) override
|
||||||
}
|
{
|
||||||
|
Creature* creature = unit ? unit->ToCreature() : nullptr;
|
||||||
|
if (!creature || creature->GetEntry() != NPC_HELLFIRE_CHANNELER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// IN_PROGRESS guard: stays inert during the hard-reset Respawn(true) cycle.
|
||||||
|
if (GetBossState(DATA_MAGTHERIDON) != IN_PROGRESS || IsAnyChannelerAlive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Creature* magtheridon = instance->GetCreature(_magtheridonGUID))
|
||||||
|
magtheridon->AI()->DoAction(ACTION_RELEASE_MAGTHERIDON);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCreatureEvade(Creature* creature) override
|
||||||
|
{
|
||||||
|
// Phase-1 wipe signal: Mag is ImmuneToPC so BossAI evade does not fire; a Channeler evade is the trigger.
|
||||||
|
if (creature->GetEntry() == NPC_HELLFIRE_CHANNELER && GetBossState(DATA_MAGTHERIDON) == IN_PROGRESS)
|
||||||
|
SetBossState(DATA_MAGTHERIDON, NOT_STARTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* go) override
|
void OnGameObjectCreate(GameObject* go) override
|
||||||
@@ -154,6 +180,18 @@ public:
|
|||||||
|
|
||||||
if (state == NOT_STARTED)
|
if (state == NOT_STARTED)
|
||||||
SetData(DATA_COLLAPSE, GO_READY);
|
SetData(DATA_COLLAPSE, GO_READY);
|
||||||
|
|
||||||
|
// Hard reset: vanish Channelers and their lingering Burning Abyssal summons.
|
||||||
|
if (state == NOT_STARTED || state == FAIL)
|
||||||
|
{
|
||||||
|
for (ObjectGuid const& guid : _channelersSet)
|
||||||
|
if (Creature* channeler = instance->GetCreature(guid))
|
||||||
|
channeler->Respawn(true);
|
||||||
|
|
||||||
|
for (ObjectGuid const& guid : _burningAbyssalsSet)
|
||||||
|
if (Creature* abyssal = instance->GetCreature(guid))
|
||||||
|
abyssal->DespawnOrUnsummon();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -164,9 +202,13 @@ public:
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DATA_CHANNELER_COMBAT:
|
case DATA_CHANNELER_COMBAT:
|
||||||
|
// Force the encounter start: Mag is ImmuneToPC so SetInCombatWithZone alone may miss JustEngagedWith.
|
||||||
if (GetBossState(DATA_MAGTHERIDON) != IN_PROGRESS)
|
if (GetBossState(DATA_MAGTHERIDON) != IN_PROGRESS)
|
||||||
|
{
|
||||||
|
SetBossState(DATA_MAGTHERIDON, IN_PROGRESS);
|
||||||
if (Creature* magtheridon = instance->GetCreature(_magtheridonGUID))
|
if (Creature* magtheridon = instance->GetCreature(_magtheridonGUID))
|
||||||
magtheridon->SetInCombatWithZone();
|
magtheridon->SetInCombatWithZone();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DATA_ACTIVATE_CUBES:
|
case DATA_ACTIVATE_CUBES:
|
||||||
for (ObjectGuid const& guid : _cubesSet)
|
for (ObjectGuid const& guid : _cubesSet)
|
||||||
@@ -178,12 +220,16 @@ public:
|
|||||||
if (GameObject* column = instance->GetGameObject(guid))
|
if (GameObject* column = instance->GetGameObject(guid))
|
||||||
column->SetGoState(GOState(data));
|
column->SetGoState(GOState(data));
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ObjectGuid _magtheridonGUID;
|
ObjectGuid _magtheridonGUID;
|
||||||
|
GuidSet _channelersSet;
|
||||||
GuidSet _wardersSet;
|
GuidSet _wardersSet;
|
||||||
|
GuidSet _burningAbyssalsSet;
|
||||||
GuidSet _cubesSet;
|
GuidSet _cubesSet;
|
||||||
GuidSet _columnSet;
|
GuidSet _columnSet;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,14 @@ enum NpcIds
|
|||||||
NPC_HELLFIRE_CHANNELER = 17256,
|
NPC_HELLFIRE_CHANNELER = 17256,
|
||||||
NPC_HELLFIRE_WARDER = 18829,
|
NPC_HELLFIRE_WARDER = 18829,
|
||||||
NPC_HELLFIRE_RAID_TRIGGER = 17376,
|
NPC_HELLFIRE_RAID_TRIGGER = 17376,
|
||||||
NPC_TARGET_TRIGGER = 17474
|
NPC_TARGET_TRIGGER = 17474,
|
||||||
|
NPC_BURNING_ABYSSAL = 17454
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MagtheridonActions
|
||||||
|
{
|
||||||
|
ACTION_RELEASE_MAGTHERIDON = 1,
|
||||||
|
ACTION_BANISH_SELF = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GoIds
|
enum GoIds
|
||||||
|
|||||||
Reference in New Issue
Block a user