fix(Scripts/World): Precious and Simone use safer calls (#25728)

This commit is contained in:
sogladev
2026-05-06 05:26:30 +02:00
committed by GitHub
parent c96d48c299
commit 95e4d8a423
2 changed files with 90 additions and 62 deletions

View File

@@ -70,14 +70,14 @@ Player* NPCStaveQuestAI::GetGossipPlayer()
return ObjectAccessor::GetPlayer(*me, gossipPlayerGUID); return ObjectAccessor::GetPlayer(*me, gossipPlayerGUID);
} }
bool NPCStaveQuestAI::IsAllowedEntry(uint32 entry) bool NPCStaveQuestAI::IsAllowedEntry(uint32 entry) const
{ {
uint32 allowedEntries[4] = { 0, 12999, 19833, 19921 }; //player, World Invisible Trigger(traps) and snake trap snakes uint32 allowedEntries[4] = { 0, 12999, 19833, 19921 }; //player, World Invisible Trigger(traps) and snake trap snakes
bool isAllowed = std::find(std::begin(allowedEntries), std::end(allowedEntries), entry) != std::end(allowedEntries); bool isAllowed = std::find(std::begin(allowedEntries), std::end(allowedEntries), entry) != std::end(allowedEntries);
return isAllowed; return isAllowed;
} }
bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit) bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit) const
{ {
if (!unit || playerGUID.IsEmpty()) if (!unit || playerGUID.IsEmpty())
{ {
@@ -108,7 +108,7 @@ bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit)
return false; return false;
} }
bool NPCStaveQuestAI::IsFairFight() bool NPCStaveQuestAI::IsFairFight() const
{ {
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList()) for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
{ {
@@ -128,12 +128,10 @@ bool NPCStaveQuestAI::IsFairFight()
return true; return true;
} }
bool NPCStaveQuestAI::ValidThreatlist() bool NPCStaveQuestAI::ValidThreatlist() const
{ {
if (me->GetThreatMgr().GetThreatListSize() == 1) if (me->GetThreatMgr().GetThreatListSize() == 1)
{
return true; return true;
}
bool isFair = IsFairFight(); bool isFair = IsFairFight();
@@ -463,10 +461,10 @@ public:
struct npc_preciousAI : public NPCStaveQuestAI struct npc_preciousAI : public NPCStaveQuestAI
{ {
npc_preciousAI(Creature *creature) : NPCStaveQuestAI(creature) { } explicit npc_preciousAI(Creature *creature) : NPCStaveQuestAI(creature) { }
EventMap events; EventMap events;
bool flaggedForDespawn; bool flaggedForDespawn{};
void InitializeAI() override void InitializeAI() override
{ {
@@ -512,6 +510,37 @@ public:
{ {
flaggedForDespawn = true; flaggedForDespawn = true;
} }
uint32 GetData(uint32 type) const override
{
if (type == DATA_SIMONE_VALID_THREATLIST)
return ValidThreatlist() ? 1 : 0;
return 0;
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case DATA_SIMONE_REVEAL:
if (data)
RevealForm();
break;
case DATA_SIMONE_PREPARE_ENCOUNTER:
PrepareForEncounter();
break;
case DATA_SIMONE_SET_HOME:
SetHomePosition();
break;
case DATA_SIMONE_CORPSE_REMOVED:
EnterEvadeMode();
FlagForDespawn();
break;
default:
break;
}
}
}; };
}; };
@@ -527,7 +556,7 @@ public:
struct npc_simoneAI : public NPCStaveQuestAI struct npc_simoneAI : public NPCStaveQuestAI
{ {
npc_simoneAI(Creature *creature) : NPCStaveQuestAI(creature) { } explicit npc_simoneAI(Creature *creature) : NPCStaveQuestAI(creature) { }
EventMap events; EventMap events;
ObjectGuid preciousGUID; ObjectGuid preciousGUID;
@@ -535,39 +564,18 @@ public:
void SetPreciousGUID() void SetPreciousGUID()
{ {
if (CreatureGroup* formation = me->GetFormation()) if (CreatureGroup* formation = me->GetFormation())
{ for ([[maybe_unused]] auto const& [member, info] : formation->GetMembers())
const CreatureGroup::CreatureGroupMemberType& members = formation->GetMembers(); if (member && member->GetOriginalEntry() == PRECIOUS_NORMAL_ENTRY)
for (CreatureGroup::CreatureGroupMemberType::const_iterator itr = members.begin(); itr != members.end(); ++itr) preciousGUID = member->GetGUID();
{
if (itr->first && itr->first->GetOriginalEntry() == PRECIOUS_NORMAL_ENTRY)
{
preciousGUID = itr->first->GetGUID();
}
}
}
} }
Creature* Precious() Creature* Precious()
{ {
if (preciousGUID.IsEmpty()) if (preciousGUID.IsEmpty())
{
SetPreciousGUID(); SetPreciousGUID();
}
if (!preciousGUID.IsEmpty()) if (!preciousGUID.IsEmpty())
{
return ObjectAccessor::GetCreature(*me, preciousGUID); return ObjectAccessor::GetCreature(*me, preciousGUID);
}
return nullptr;
}
npc_precious::npc_preciousAI* PreciousAI()
{
if (Precious())
{
return CAST_AI(npc_precious::npc_preciousAI, Precious()->AI());
}
return nullptr; return nullptr;
} }
@@ -632,21 +640,20 @@ public:
void CorpseRemoved(uint32& /*respawnDelay*/) override void CorpseRemoved(uint32& /*respawnDelay*/) override
{ {
if (!Precious()) Creature* creature = Precious();
{ if (!creature)
return; return;
}
if (Precious()->IsInCombat()) if (creature->IsInCombat())
{ {
// If Simone corpse is removed but pet is InCombat, EnterEvadeMode and auto despawn on pet reaching home // If Simone corpse is removed but pet is InCombat, ask pet AI to enter evade and flag for despawn
PreciousAI()->EnterEvadeMode(); if (creature->AI())
PreciousAI()->FlagForDespawn(); creature->AI()->SetData(DATA_SIMONE_CORPSE_REMOVED, 1);
else
creature->DespawnOrUnsummon(0ms);
} }
else else
{ creature->DespawnOrUnsummon(0ms);
Precious()->DespawnOrUnsummon(0ms);
}
} }
void Reset() override void Reset() override
@@ -704,10 +711,9 @@ public:
break; break;
case EVENT_REVEAL: case EVENT_REVEAL:
RevealForm(); RevealForm();
if (PreciousAI()) if (Creature* creature = Precious())
{ if (creature->AI())
PreciousAI()->RevealForm(); creature->AI()->SetData(DATA_SIMONE_REVEAL, 1);
}
break; break;
// Prevent hunters from figthing Simone alone // Prevent hunters from figthing Simone alone
case SIMONE_EVENT_CHECK_PET_STATE: case SIMONE_EVENT_CHECK_PET_STATE:
@@ -721,6 +727,8 @@ public:
events.ScheduleEvent(SIMONE_EVENT_CHECK_PET_STATE, 1s); events.ScheduleEvent(SIMONE_EVENT_CHECK_PET_STATE, 1s);
} }
break; break;
default:
break;
} }
if (UpdateVictim()) if (UpdateVictim())
@@ -760,23 +768,32 @@ public:
} }
break; break;
case EVENT_UNFAIR_FIGHT: case EVENT_UNFAIR_FIGHT:
if (!ValidThreatlist() || (PreciousAI() && !PreciousAI()->ValidThreatlist())) {
Creature* creature = Precious();
bool isPreciousThreatListValid = creature && creature->AI() && creature->AI()->GetData(DATA_SIMONE_VALID_THREATLIST) == 1;
if (!ValidThreatlist() || !isPreciousThreatListValid)
{ {
SetHomePosition(); SetHomePosition();
PreciousAI()->SetHomePosition(); me->DespawnOrUnsummon(5s);
Precious()->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
Precious()->SetImmuneToAll(true);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1); me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
me->SetImmuneToAll(true); me->SetImmuneToAll(true);
Precious()->DespawnOrUnsummon(5s); if (creature)
{
if (creature->AI())
creature->AI()->SetData(DATA_SIMONE_SET_HOME, 1);
creature->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
creature->SetImmuneToAll(true);
creature->DespawnOrUnsummon(5s);
}
me->DespawnOrUnsummon(5s);
break; break;
} }
events.Repeat(2s); events.Repeat(2s);
break; break;
}
case SIMONE_EVENT_CHAIN_LIGHTNING: case SIMONE_EVENT_CHAIN_LIGHTNING:
me->CastSpell(me->GetVictim(), SIMONE_SPELL_CHAIN_LIGHTNING, false); me->CastSpell(me->GetVictim(), SIMONE_SPELL_CHAIN_LIGHTNING, false);
events.Repeat(7s); events.Repeat(7s);
@@ -785,6 +802,8 @@ public:
me->CastSpell(me->GetVictim(), SIMONE_SPELL_TEMPTRESS_KISS, false); me->CastSpell(me->GetVictim(), SIMONE_SPELL_TEMPTRESS_KISS, false);
events.Repeat(45s); events.Repeat(45s);
break; break;
default:
break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
@@ -805,10 +824,10 @@ public:
void ScheduleEncounterStart(ObjectGuid playerGUID) void ScheduleEncounterStart(ObjectGuid playerGUID)
{ {
PrepareForEncounter(); PrepareForEncounter();
if (PreciousAI()) if (Creature* creature = Precious())
{ if (creature->AI())
PreciousAI()->PrepareForEncounter(); creature->AI()->SetData(DATA_SIMONE_PREPARE_ENCOUNTER, 1);
}
gossipPlayerGUID = playerGUID; gossipPlayerGUID = playerGUID;
events.ScheduleEvent(EVENT_ENCOUNTER_START, 1s); events.ScheduleEvent(EVENT_ENCOUNTER_START, 1s);
} }

View File

@@ -88,6 +88,15 @@ enum NPCPrecious
PRECIOUS_EVIL_ENTRY = 14538 PRECIOUS_EVIL_ENTRY = 14538
}; };
enum SimoneAIData
{
DATA_SIMONE_REVEAL = 1,
DATA_SIMONE_PREPARE_ENCOUNTER = 2,
DATA_SIMONE_VALID_THREATLIST = 3,
DATA_SIMONE_SET_HOME = 4,
DATA_SIMONE_CORPSE_REMOVED = 5
};
enum NPCNelson enum NPCNelson
{ {
NELSON_EVENT_DREADFUL_FRIGHT = 6, NELSON_EVENT_DREADFUL_FRIGHT = 6,
@@ -189,10 +198,10 @@ struct NPCStaveQuestAI : public ScriptedAI
void RevealForm(); void RevealForm();
void StorePlayerGUID(); void StorePlayerGUID();
Player* GetGossipPlayer(); Player* GetGossipPlayer();
bool IsAllowedEntry(uint32 /*entry*/); bool IsAllowedEntry(uint32 /*entry*/) const;
bool UnitIsUnfair(Unit* unit); bool UnitIsUnfair(Unit* unit) const;
bool IsFairFight(); bool IsFairFight() const;
bool ValidThreatlist(); bool ValidThreatlist() const;
void SetHomePosition(); void SetHomePosition();
void PrepareForEncounter(); void PrepareForEncounter();
void ClearLootIfUnfair(Unit* killer); void ClearLootIfUnfair(Unit* killer);