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

View File

@@ -88,6 +88,15 @@ enum NPCPrecious
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
{
NELSON_EVENT_DREADFUL_FRIGHT = 6,
@@ -189,10 +198,10 @@ struct NPCStaveQuestAI : public ScriptedAI
void RevealForm();
void StorePlayerGUID();
Player* GetGossipPlayer();
bool IsAllowedEntry(uint32 /*entry*/);
bool UnitIsUnfair(Unit* unit);
bool IsFairFight();
bool ValidThreatlist();
bool IsAllowedEntry(uint32 /*entry*/) const;
bool UnitIsUnfair(Unit* unit) const;
bool IsFairFight() const;
bool ValidThreatlist() const;
void SetHomePosition();
void PrepareForEncounter();
void ClearLootIfUnfair(Unit* killer);