fix(Scripts/BlackwingLair): Solve the issue with Nefarian occasionall… (#11398)

This commit is contained in:
Skjalf
2022-04-14 17:27:04 -03:00
committed by GitHub
parent 6800f79c00
commit 2f5a5dffcb
2 changed files with 84 additions and 124 deletions

View File

@@ -242,11 +242,10 @@ public:
// Victor Nefarius weekly mechanic drakonid spawn // Victor Nefarius weekly mechanic drakonid spawn
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated). // Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER }; std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
_nefarianRightTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners); Acore::Containers::RandomResize(nefarianDrakonidSpawners, 2);
// delete the previous picked one so we don't get any repeated.
nefarianDrakonidSpawners.erase(std::remove(nefarianDrakonidSpawners.begin(), nefarianDrakonidSpawners.end(), _nefarianRightTunnel), nefarianDrakonidSpawners.end()); _nefarianRightTunnel = nefarianDrakonidSpawners[0];
// Pick another one _nefarianLeftTunnel = nefarianDrakonidSpawners[1];
_nefarianLeftTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// save it to instance // save it to instance
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel); instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
@@ -293,6 +292,23 @@ public:
Reset(); Reset();
} }
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() != NPC_NEFARIAN)
{
BossAI::JustSummoned(summon);
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
{
if (summon->GetEntry() == NPC_NEFARIAN)
{
summons.DespawnAll();
Unit::Kill(me, me);
}
}
void DoAction(int32 action) override void DoAction(int32 action) override
{ {
if (action == ACTION_RESET) if (action == ACTION_RESET)
@@ -304,12 +320,26 @@ public:
if (action == ACTION_ADD_KILLED) if (action == ACTION_ADD_KILLED)
{ {
KilledAdds++; KilledAdds++;
}
if (action == ACTION_KILLED) if (KilledAdds == MAX_DRAKONID_KILLED)
{ {
summons.DespawnEntry(NPC_BONE_CONSTRUCT); if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
Unit::Kill(me, me); {
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.Reset();
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Stop spawning adds
EntryCheckPredicate pred(_nefarianRightTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred);
EntryCheckPredicate pred2(_nefarianLeftTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
}
} }
} }
@@ -335,14 +365,11 @@ public:
events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000)); events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000));
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000)); events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10000); events.ScheduleEvent(EVENT_SPAWN_ADDS, 10000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 10000);
} }
void JustSummoned(Creature* summon) override { summons.Summon(summon); }
void SetData(uint32 type, uint32 data) override void SetData(uint32 type, uint32 data) override
{ {
if ( type == 1 && data == 1) if (type == 1 && data == 1)
{ {
me->StopMoving(); me->StopMoving();
events.ScheduleEvent(EVENT_PATH_2, 9000); events.ScheduleEvent(EVENT_PATH_2, 9000);
@@ -428,8 +455,7 @@ public:
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 19000, 25000); events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 19000, 25000);
break; break;
case EVENT_FEAR: case EVENT_FEAR:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true)) DoCastRandomTarget(SPELL_FEAR, 0, 40.0f);
DoCast(target, SPELL_FEAR);
events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000)); events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000));
break; break;
case EVENT_SILENCE: case EVENT_SILENCE:
@@ -437,8 +463,7 @@ public:
events.ScheduleEvent(EVENT_SILENCE, urand(14000, 23000)); events.ScheduleEvent(EVENT_SILENCE, urand(14000, 23000));
break; break;
case EVENT_MIND_CONTROL: case EVENT_MIND_CONTROL:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true)) DoCastRandomTarget(SPELL_SHADOW_COMMAND, 0, 40.0f);
DoCast(target, SPELL_SHADOW_COMMAND);
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(24000, 30000)); events.ScheduleEvent(EVENT_MIND_CONTROL, urand(24000, 30000));
break; break;
case EVENT_SHADOWBLINK: case EVENT_SHADOWBLINK:
@@ -450,32 +475,6 @@ public:
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]); me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]); me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
break; break;
case EVENT_CHECK_PHASE_2:
if (KilledAdds >= MAX_DRAKONID_KILLED)
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SHADOW_BOLT_VOLLEY);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Stop spawning adds
EntryCheckPredicate pred(_nefarianRightTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred);
EntryCheckPredicate pred2(_nefarianLeftTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
return;
}
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 1000);
break;
} }
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
@@ -500,8 +499,6 @@ public:
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->SetStandState(UNIT_STAND_STATE_STAND); me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
// Due to Nefarius despawning himself on Vael, we need to update the guid on instance to prevent unwanted behaviours as encounter not resetting at all.
instance->SetGuidData(DATA_LORD_VICTOR_NEFARIUS, me->GetGUID());
} }
} }
@@ -556,14 +553,6 @@ struct boss_nefarian : public BossAI
{ {
_JustDied(); _JustDied();
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (Creature* victor = me->FindNearestCreature(NPC_VICTOR_NEFARIUS, 200.f, true))
{
if (victor->AI())
{
victor->AI()->DoAction(ACTION_KILLED);
}
}
} }
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
@@ -620,6 +609,29 @@ struct boss_nefarian : public BossAI
_introDone = true; _introDone = true;
} }
void DamageTaken(Unit* /*unit*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (me->HealthBelowPctDamaged(20, damage) && !Phase3)
{
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
for (Creature* const& summon : constructList)
{
if (summon && !summon->IsAlive())
{
summon->Respawn();
summon->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_AGGRESSIVE);
summon->SetStandState(UNIT_STAND_STATE_STAND);
DoZoneInCombat(summon);
}
}
Phase3 = true;
Talk(SAY_RAISE_SKELETONS);
}
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (!UpdateVictim())
@@ -734,27 +746,6 @@ struct boss_nefarian : public BossAI
} }
} }
// Phase3 begins when health below 20 pct
if (!Phase3 && HealthBelowPct(20))
{
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
{
if ((*itr) && !(*itr)->IsAlive())
{
(*itr)->Respawn();
DoZoneInCombat((*itr));
(*itr)->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
(*itr)->SetReactState(REACT_AGGRESSIVE);
(*itr)->SetStandState(UNIT_STAND_STATE_STAND);
}
}
Phase3 = true;
Talk(SAY_RAISE_SKELETONS);
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
@@ -818,17 +809,19 @@ struct npc_corrupted_totem : public ScriptedAI
return; return;
} }
std::vector<uint32> mobsEntries; std::vector<uint32> mobsEntries =
mobsEntries.push_back(NPC_NEFARIAN); {
mobsEntries.push_back(NPC_BONE_CONSTRUCT); NPC_NEFARIAN,
mobsEntries.push_back(NPC_BRONZE_DRAKONID); NPC_BONE_CONSTRUCT,
mobsEntries.push_back(NPC_BLUE_DRAKONID); NPC_BRONZE_DRAKONID,
mobsEntries.push_back(NPC_RED_DRAKONID); NPC_BLUE_DRAKONID,
mobsEntries.push_back(NPC_GREEN_DRAKONID); NPC_RED_DRAKONID,
mobsEntries.push_back(NPC_BLACK_DRAKONID); NPC_GREEN_DRAKONID,
mobsEntries.push_back(NPC_CHROMATIC_DRAKONID); NPC_BLACK_DRAKONID,
NPC_CHROMATIC_DRAKONID
};
for (auto& entry : mobsEntries) for (auto const& entry : mobsEntries)
{ {
std::list<Creature*> tmpMobList; std::list<Creature*> tmpMobList;
GetCreatureListWithEntryInGrid(tmpMobList, me, entry, 100.f); GetCreatureListWithEntryInGrid(tmpMobList, me, entry, 100.f);

View File

@@ -45,8 +45,9 @@ DoorData const doorData[] =
ObjectData const creatureData[] = ObjectData const creatureData[] =
{ {
{ NPC_GRETHOK, DATA_GRETHOK }, { NPC_GRETHOK, DATA_GRETHOK },
{ NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS } { NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS },
{ NPC_VICTOR_NEFARIUS, DATA_LORD_VICTOR_NEFARIUS }
}; };
Position const SummonPosition[8] = Position const SummonPosition[8] =
@@ -127,26 +128,19 @@ public:
case NPC_NEFARIAN: case NPC_NEFARIAN:
nefarianGUID = creature->GetGUID(); nefarianGUID = creature->GetGUID();
break; break;
case NPC_VICTOR_NEFARIUS:
victorNefariusGUID = creature->GetGUID();
break;
case NPC_BLACK_DRAKONID: case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID: case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID: case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID: case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID: case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID: case NPC_RED_DRAKONID:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID)) if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{ {
if (CreatureAI* nefariusAI = nefarius->AI()) if (CreatureAI* nefariusAI = nefarius->AI())
{ {
nefariusAI->JustSummoned(creature); nefariusAI->JustSummoned(creature);
} }
} }
if (creature->AI())
{
creature->AI()->DoZoneInCombat();
}
break; break;
default: default:
break; break;
@@ -369,8 +363,6 @@ public:
{ {
case DATA_RAZORGORE_THE_UNTAMED: case DATA_RAZORGORE_THE_UNTAMED:
return razorgoreGUID; return razorgoreGUID;
case DATA_LORD_VICTOR_NEFARIUS:
return victorNefariusGUID;
case DATA_CHROMAGGUS: case DATA_CHROMAGGUS:
return chromaggusGUID; return chromaggusGUID;
case DATA_GO_CHROMAGGUS_DOOR: case DATA_GO_CHROMAGGUS_DOOR:
@@ -382,18 +374,6 @@ public:
return ObjectGuid::Empty; return ObjectGuid::Empty;
} }
void SetGuidData(uint32 type, ObjectGuid data) override
{
switch (type)
{
case DATA_LORD_VICTOR_NEFARIUS:
victorNefariusGUID = data;
break;
default:
break;
}
}
void OnUnitDeath(Unit* unit) override void OnUnitDeath(Unit* unit) override
{ {
switch (unit->GetEntry()) switch (unit->GetEntry())
@@ -413,25 +393,13 @@ public:
summon->SetStandState(UNIT_STAND_STATE_DEAD); summon->SetStandState(UNIT_STAND_STATE_DEAD);
summon->SetHomePosition(summon->GetPosition()); summon->SetHomePosition(summon->GetPosition());
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID)) if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{ {
if (nefarius->AI()) if (nefarius->AI())
{ {
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED); nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
} }
} }
else // Something happened, try another way
{
if (Creature* nefarius = summon->FindNearestCreature(NPC_VICTOR_NEFARIUS, 500.f, true))
{
victorNefariusGUID = nefarius->GetGUID();
if (nefarius->AI())
{
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
}
}
} }
break; break;
case NPC_BLACKWING_DRAGON: case NPC_BLACKWING_DRAGON:
@@ -514,7 +482,7 @@ public:
razor->AI()->DoAction(ACTION_PHASE_TWO); razor->AI()->DoAction(ACTION_PHASE_TWO);
break; break;
case EVENT_RESPAWN_NEFARIUS: case EVENT_RESPAWN_NEFARIUS:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID)) if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{ {
nefarius->SetPhaseMask(1, true); nefarius->SetPhaseMask(1, true);
nefarius->setActive(true); nefarius->setActive(true);
@@ -580,7 +548,6 @@ public:
ObjectGuid chromaggusDoorGUID; ObjectGuid chromaggusDoorGUID;
ObjectGuid nefarianGUID; ObjectGuid nefarianGUID;
ObjectGuid nefarianDoorGUID; ObjectGuid nefarianDoorGUID;
ObjectGuid victorNefariusGUID;
// Razorgore // Razorgore
uint8 EggCount; uint8 EggCount;