Scripts/BWD: store Magmaw's body parts via guids instead of smelly pointers and validate the body parts on engage
This commit is contained in:
1 parent
d78cfb2843
commit
44f89c7dae
1 file changed
+101
-54
+101
-54
@@ -194,6 +194,15 @@ enum EncounterFramePriorities
|
||||
FRAME_PRIORITY_EXPOSED_HEAD_OF_MAGMAW = 2
|
||||
};
|
||||
|
||||
enum BodyParts : uint8
|
||||
{
|
||||
BODY_PART_EXPOSED_HEAD_1 = 0,
|
||||
BODY_PART_EXPOSED_HEAD_2,
|
||||
BODY_PART_PINCER_1,
|
||||
BODY_PART_PINCER_2,
|
||||
MAX_BODY_PARTS
|
||||
};
|
||||
|
||||
Position const ExposedHeadOfMagmawPos = { -299.0f, -28.9861f, 191.0293f, 4.118977f };
|
||||
Position const NefarianIntroSummonPos = { -390.1042f, 40.88411f, 207.8586f, 0.196609f };
|
||||
|
||||
@@ -203,8 +212,7 @@ Position const NefarianIntroSummonPos = { -390.1042f, 40.88411f, 207.8586f, 0
|
||||
struct boss_magmaw : public BossAI
|
||||
{
|
||||
boss_magmaw(Creature* creature) : BossAI(creature, DATA_MAGMAW),
|
||||
_exposedHead1(nullptr), _exposedHead2(nullptr), _pincer1(nullptr), _pincer2(nullptr), _magmaProjectileCount(0),
|
||||
_achievementEnligible(true), _headEngaged(false), _heroicPhaseTwoActive(!IsHeroic())
|
||||
_magmaProjectileCount(0), _achievementEnligible(true), _headEngaged(false), _heroicPhaseTwoActive(!IsHeroic())
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
@@ -217,6 +225,16 @@ struct boss_magmaw : public BossAI
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
// Sanity checks if the body has been successfully set up
|
||||
for (uint8 i = BODY_PART_EXPOSED_HEAD_1; i < MAX_BODY_PARTS; ++i)
|
||||
{
|
||||
if (!GetBodyPart(BodyParts(i)))
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_OTHER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BossAI::JustEngagedWith(who);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, FRAME_PRIORITY_MAGMAW);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
@@ -254,17 +272,21 @@ struct boss_magmaw : public BossAI
|
||||
{
|
||||
_EnterEvadeMode();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
if (_headEngaged)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, _exposedHead1);
|
||||
|
||||
Creature* head = GetBodyPart(BODY_PART_EXPOSED_HEAD_1);
|
||||
if (_headEngaged && head)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, head);
|
||||
|
||||
DoCastSelf(SPELL_EJECT_PASSENGER_3, true);
|
||||
_pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1, true);
|
||||
_pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1, true);
|
||||
for (BodyParts part : { BODY_PART_PINCER_1, BODY_PART_PINCER_2 })
|
||||
if (Creature* pincer = GetBodyPart(part))
|
||||
pincer->CastSpell(pincer, SPELL_EJECT_PASSENGER_1, true);
|
||||
|
||||
instance->SetBossState(DATA_MAGMAW, FAIL);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PARASITIC_INFECTION_VOMIT);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PARASITIC_INFECTION_PERIODIC_DAMAGE);
|
||||
_exposedHead1->DespawnOrUnsummon();
|
||||
if (head)
|
||||
head->DespawnOrUnsummon();
|
||||
summons.DespawnAll();
|
||||
|
||||
if (Creature* nefarian = instance->GetCreature(DATA_NEFARIAN_MAGMAW))
|
||||
@@ -274,8 +296,9 @@ struct boss_magmaw : public BossAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (_headEngaged)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, _exposedHead1);
|
||||
if (Creature* head = GetBodyPart(BODY_PART_EXPOSED_HEAD_1))
|
||||
if (_headEngaged)
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, head);
|
||||
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PARASITIC_INFECTION_VOMIT);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PARASITIC_INFECTION_PERIODIC_DAMAGE);
|
||||
@@ -320,10 +343,10 @@ struct boss_magmaw : public BossAI
|
||||
switch (type)
|
||||
{
|
||||
case DATA_FREE_PINCER:
|
||||
if (_pincer1->GetVehicleKit() && _pincer1->GetVehicleKit()->GetAvailableSeatCount())
|
||||
return _pincer1->GetGUID();
|
||||
else if (_pincer2->GetVehicleKit() && _pincer2->GetVehicleKit()->GetAvailableSeatCount())
|
||||
return _pincer2->GetGUID();
|
||||
for (BodyParts part : { BODY_PART_PINCER_1, BODY_PART_PINCER_2 })
|
||||
if (Creature* pincer = GetBodyPart(part))
|
||||
if (pincer->GetVehicleKit() && pincer->GetVehicleKit()->GetAvailableSeatCount())
|
||||
return pincer->GetGUID();
|
||||
break;
|
||||
default:
|
||||
return ObjectGuid::Empty;
|
||||
@@ -345,8 +368,10 @@ struct boss_magmaw : public BossAI
|
||||
{
|
||||
// Make sure we eject all passengers nicely before we die so they wont end up in the lava
|
||||
DoCastSelf(SPELL_EJECT_PASSENGER_3, true);
|
||||
_pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1, true);
|
||||
_pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1, true);
|
||||
|
||||
for (BodyParts part : { BODY_PART_PINCER_1, BODY_PART_PINCER_2 })
|
||||
if (Creature* pincer = GetBodyPart(part))
|
||||
pincer->CastSpell(pincer, SPELL_EJECT_PASSENGER_1, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,9 +396,13 @@ struct boss_magmaw : public BossAI
|
||||
case ACTION_ENABLE_MOUNTING:
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_ENEMY_INTERACT);
|
||||
_exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_HEAD, true);
|
||||
_pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1, true);
|
||||
_pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1, true);
|
||||
|
||||
if (Creature* head = GetBodyPart(BODY_PART_EXPOSED_HEAD_1))
|
||||
head->CastSpell(head, SPELL_RIDE_VEHICLE_HEAD, true);
|
||||
|
||||
for (BodyParts part : { BODY_PART_PINCER_1, BODY_PART_PINCER_2 })
|
||||
if (Creature* pincer = GetBodyPart(part))
|
||||
pincer->CastSpell(pincer, SPELL_EJECT_PASSENGER_1, true);
|
||||
events.ScheduleEvent(EVENT_ANNOUNCE_PINCERS_EXPOSED, 1s, 0, PHASE_COMBAT);
|
||||
break;
|
||||
case ACTION_DISABLE_MOUNTING:
|
||||
@@ -396,8 +425,12 @@ struct boss_magmaw : public BossAI
|
||||
case ACTION_COVER_HEAD:
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_FINISH_IMPALE_SELF, 3s, 0, PHASE_COMBAT);
|
||||
_exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true);
|
||||
_exposedHead1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
if (Creature* head = GetBodyPart(BODY_PART_EXPOSED_HEAD_1))
|
||||
{
|
||||
head->CastSpell(head, SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true);
|
||||
head->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
break;
|
||||
case ACTION_FAIL_ACHIEVEMT:
|
||||
_achievementEnligible = false;
|
||||
@@ -469,8 +502,9 @@ struct boss_magmaw : public BossAI
|
||||
break;
|
||||
case EVENT_MASSIVE_CRASH:
|
||||
DoCast(SPELL_MASSIVE_CRASH);
|
||||
_pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1, true);
|
||||
_pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1, true);
|
||||
for (BodyParts part : { BODY_PART_PINCER_1, BODY_PART_PINCER_2 })
|
||||
if (Creature* pincer = GetBodyPart(part))
|
||||
pincer->CastSpell(pincer, SPELL_EJECT_PASSENGER_1, true);
|
||||
break;
|
||||
case EVENT_ANNOUNCE_PINCERS_EXPOSED:
|
||||
Talk(SAY_ANNOUNCE_EXPOSE_PINCERS);
|
||||
@@ -480,13 +514,16 @@ struct boss_magmaw : public BossAI
|
||||
events.ScheduleEvent(EVENT_SHOW_HEAD, 5s, 0, PHASE_IMPALED);
|
||||
break;
|
||||
case EVENT_SHOW_HEAD:
|
||||
if (!_headEngaged)
|
||||
if (Creature* head = GetBodyPart(BODY_PART_EXPOSED_HEAD_1))
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, _exposedHead1, FRAME_PRIORITY_EXPOSED_HEAD_OF_MAGMAW);
|
||||
_headEngaged = true;
|
||||
if (!_headEngaged)
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, head, FRAME_PRIORITY_EXPOSED_HEAD_OF_MAGMAW);
|
||||
_headEngaged = true;
|
||||
}
|
||||
head->CastSpell(head, SPELL_RIDE_VEHICLE_HEAD, true);
|
||||
head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
_exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_HEAD, true);
|
||||
_exposedHead1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
case EVENT_FINISH_IMPALE_SELF:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
@@ -504,47 +541,55 @@ struct boss_magmaw : public BossAI
|
||||
private:
|
||||
void SetupBody()
|
||||
{
|
||||
_pincer1 = DoSummon(NPC_MAGMAWS_PINCER_1, me->GetPosition());
|
||||
if (_pincer1)
|
||||
Creature* pincer1 = DoSummon(NPC_MAGMAWS_PINCER_1, me->GetPosition());
|
||||
if (pincer1)
|
||||
{
|
||||
_pincer1->EnterVehicle(me, SEAT_MAGMAWS_PINCER_1);
|
||||
_pincer1->SetDisplayId(_pincer1->GetCreatureTemplate()->Modelid3);
|
||||
pincer1->EnterVehicle(me, SEAT_MAGMAWS_PINCER_1);
|
||||
pincer1->SetDisplayId(pincer1->GetCreatureTemplate()->Modelid3);
|
||||
_bodyPartGUIDs[BODY_PART_PINCER_1] = pincer1->GetGUID();
|
||||
}
|
||||
|
||||
_pincer2 = DoSummon(NPC_MAGMAWS_PINCER_2, me->GetPosition());
|
||||
if (_pincer2)
|
||||
Creature* pincer2 = DoSummon(NPC_MAGMAWS_PINCER_2, me->GetPosition());
|
||||
if (pincer2)
|
||||
{
|
||||
_pincer2->EnterVehicle(me, SEAT_MAGMAWS_PINCER_2);
|
||||
_pincer2->SetDisplayId(_pincer2->GetCreatureTemplate()->Modelid3);
|
||||
pincer2->EnterVehicle(me, SEAT_MAGMAWS_PINCER_2);
|
||||
pincer2->SetDisplayId(pincer2->GetCreatureTemplate()->Modelid3);
|
||||
_bodyPartGUIDs[BODY_PART_PINCER_2] = pincer2->GetGUID();
|
||||
}
|
||||
|
||||
_exposedHead1 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW, ExposedHeadOfMagmawPos);
|
||||
_exposedHead2 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW_2, me->GetPosition());
|
||||
Creature* exposedHead1 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW, ExposedHeadOfMagmawPos);
|
||||
Creature* exposedHead2 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW_2, me->GetPosition());
|
||||
|
||||
if (!_exposedHead1 || !_exposedHead2)
|
||||
if (!exposedHead1 || !exposedHead2)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
return;
|
||||
}
|
||||
|
||||
_exposedHead1->SetReactState(REACT_PASSIVE);
|
||||
_exposedHead2->SetReactState(REACT_PASSIVE);
|
||||
_bodyPartGUIDs[BODY_PART_EXPOSED_HEAD_1] = exposedHead1->GetGUID();
|
||||
_bodyPartGUIDs[BODY_PART_EXPOSED_HEAD_2] = exposedHead2->GetGUID();
|
||||
|
||||
_exposedHead2->EnterVehicle(me, SEAT_EXPOSED_HEAD_OF_MAGMAW_2);
|
||||
exposedHead1->SetReactState(REACT_PASSIVE);
|
||||
exposedHead2->SetReactState(REACT_PASSIVE);
|
||||
|
||||
exposedHead2->EnterVehicle(me, SEAT_EXPOSED_HEAD_OF_MAGMAW_2);
|
||||
DoCastSelf(SPELL_BIRTH);
|
||||
|
||||
// First we link the real exposed head
|
||||
_exposedHead1->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
_exposedHead1->CastSpell(_exposedHead1, SPELL_POINT_OF_VULNERABILITY);
|
||||
_exposedHead1->CastSpell(_exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
exposedHead1->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
exposedHead1->CastSpell(exposedHead1, SPELL_POINT_OF_VULNERABILITY);
|
||||
exposedHead1->CastSpell(exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
// ... now the dummy exposed head
|
||||
_exposedHead2->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
_exposedHead2->CastSpell(_exposedHead2, SPELL_POINT_OF_VULNERABILITY);
|
||||
exposedHead2->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
exposedHead2->CastSpell(exposedHead2, SPELL_POINT_OF_VULNERABILITY);
|
||||
// ... and now Magmaw
|
||||
DoCast(_exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
DoCast(_exposedHead1, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
DoCast(exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
DoCast(exposedHead1, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE);
|
||||
|
||||
_exposedHead2->CastSpell(_exposedHead2, SPELL_QUEST_INVIS_5);
|
||||
exposedHead2->CastSpell(exposedHead2, SPELL_QUEST_INVIS_5);
|
||||
|
||||
ObjectGuid guid = me->GetGUID();
|
||||
Unit* head = _exposedHead1;
|
||||
Unit* head = exposedHead1;
|
||||
head->m_Events.AddEventAtOffset([head, guid]()
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*head, guid))
|
||||
@@ -552,10 +597,12 @@ private:
|
||||
}, 1s + 200ms);
|
||||
}
|
||||
|
||||
Creature* _exposedHead1;
|
||||
Creature* _exposedHead2;
|
||||
Creature* _pincer1;
|
||||
Creature* _pincer2;
|
||||
Creature* GetBodyPart(BodyParts part) const
|
||||
{
|
||||
return ObjectAccessor::GetCreature(*me, _bodyPartGUIDs[part]);
|
||||
}
|
||||
|
||||
std::array<ObjectGuid, MAX_BODY_PARTS> _bodyPartGUIDs;
|
||||
uint8 _magmaProjectileCount;
|
||||
bool _achievementEnligible;
|
||||
bool _headEngaged;
|
||||
|
||||
Reference in new issue
Block a user