Added some additional defense checks around isHostile and unit/target (#2056)

Needs second pair of eyes, they appear in crash logs here and there. Its
merely a patch on a open wound.

----
As in aslong there multithreads in mapupdate, which we need for decent
performance and core calls are not done correctly due various reasons.
These type of issues remain.

Although i am planning to experiment a little with threadsafe execution
of our strategies vs performance.

The most effective thing we could do is check every single action and
check its stateless and where it does effect the state or read the state
of a core object its done in the safest way. flags, worldthread where
possible and/ot simply taking into account the state might be invalid.
This commit is contained in:
bashermens
2026-01-24 20:41:12 +01:00
committed by GitHub
parent 3e21563669
commit 3d467ce3bb
8 changed files with 62 additions and 22 deletions

View File

@@ -28,7 +28,7 @@ bool TravelAction::Execute(Event event)
for (Unit* unit : targets)
{
newTarget = unit;
if (!newTarget)
if (!newTarget || !newTarget->IsInWorld() || newTarget->IsDuringRemoveFromWorld())
continue;
if (newTarget->GetMapId() != bot->GetMapId())

View File

@@ -245,8 +245,10 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget, Uni
{
packet << unitTarget->GetGUID();
targetSelected = true;
// If the target is bot or is an enemy, say "on self"
if (unitTarget == bot || (unitTarget->IsHostileTo(bot)))
if (unitTarget == bot || !unitTarget->IsInWorld() || unitTarget->IsDuringRemoveFromWorld())
out << " on self";
else if (unitTarget->IsHostileTo(bot))
out << " on self";
else
out << " on " << unitTarget->GetName();

View File

@@ -258,6 +258,9 @@ bool PossibleAddsValue::Calculate()
if (Unit* add = botAI->GetUnit(guid))
{
if (!add->IsInWorld() || add->IsDuringRemoveFromWorld())
continue;
if (!add->GetTarget() && !add->GetThreatMgr().getCurrentVictim() && add->IsHostileTo(bot))
{
for (ObjectGuid const attackerGUID : attackers)

View File

@@ -59,26 +59,22 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
for (ObjectGuid const guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit)
continue;
if (!unit->IsInWorld() || unit->IsDuringRemoveFromWorld())
continue;
auto& rep = bot->ToPlayer()->GetReputationMgr();
if (unit->ToCreature() && !unit->ToCreature()->GetCreatureTemplate()->lootid &&
bot->GetReactionTo(unit) >= REP_NEUTRAL)
{
continue;
}
if (!bot->IsHostileTo(unit) && unit->GetNpcFlags() != UNIT_NPC_FLAG_NONE)
{
continue;
}
if (!bot->isHonorOrXPTarget(unit))
{
continue;
}
if (abs(bot->GetPositionZ() - unit->GetPositionZ()) > INTERACTION_DISTANCE)
continue;

View File

@@ -27,7 +27,16 @@ void NearestHostileNpcsValue::FindUnits(std::list<Unit*>& targets)
Cell::VisitObjects(bot, searcher, range);
}
bool NearestHostileNpcsValue::AcceptUnit(Unit* unit) { return unit->IsHostileTo(bot) && !unit->IsPlayer(); }
bool NearestHostileNpcsValue::AcceptUnit(Unit* unit)
{
if (!unit || !unit->IsInWorld() || unit->IsDuringRemoveFromWorld())
return false;
if (unit->IsPlayer())
return false;
return unit->IsHostileTo(bot);
}
void NearestVehiclesValue::FindUnits(std::list<Unit*>& targets)
{

View File

@@ -54,6 +54,9 @@ void PossibleRpgTargetsValue::FindUnits(std::list<Unit*>& targets)
bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit)
{
if (!unit || !unit->IsInWorld() || unit->IsDuringRemoveFromWorld())
return false;
if (unit->IsHostileTo(bot) || unit->IsPlayer())
return false;
@@ -70,7 +73,8 @@ bool PossibleRpgTargetsValue::AcceptUnit(Unit* unit)
}
TravelTarget* travelTarget = context->GetValue<TravelTarget*>("travel target")->Get();
if (travelTarget->getDestination() && travelTarget->getDestination()->getEntry() == unit->GetEntry())
if (travelTarget && travelTarget->getDestination() &&
travelTarget->getDestination()->getEntry() == unit->GetEntry())
return true;
if (urand(1, 100) < 25 && unit->IsFriendlyTo(bot))
@@ -145,6 +149,9 @@ void PossibleNewRpgTargetsValue::FindUnits(std::list<Unit*>& targets)
bool PossibleNewRpgTargetsValue::AcceptUnit(Unit* unit)
{
if (!unit || !unit->IsInWorld() || unit->IsDuringRemoveFromWorld())
return false;
if (unit->IsHostileTo(bot) || unit->IsPlayer())
return false;

View File

@@ -99,7 +99,10 @@ bool IccGunshipCannonNearTrigger::IsActive()
bool IccGunshipTeleportAllyTrigger::IsActive()
{
Unit* boss = bot->FindNearestCreature(NPC_HIGH_OVERLORD_SAURFANG, 100.0f);
if (!boss)
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))
@@ -111,7 +114,10 @@ bool IccGunshipTeleportAllyTrigger::IsActive()
bool IccGunshipTeleportHordeTrigger::IsActive()
{
Unit* boss = bot->FindNearestCreature(NPC_MURADIN_BRONZEBEARD, 100.0f);
if (!boss)
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))

View File

@@ -765,9 +765,13 @@ bool FreyaMoveToHealingSporeTrigger::IsActive()
bool ThorimUnbalancingStrikeTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
// Check boss and it is alive
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))
return false;
return bot->HasAura(SPELL_UNBALANCING_STRIKE);
@@ -804,8 +808,13 @@ bool ThorimMarkDpsTargetTrigger::IsActive()
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
// Check boss and it is alive
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD && (!currentSkullUnit || !currentSkullUnit->IsAlive()))
@@ -982,9 +991,13 @@ bool ThorimGauntletPositioningTrigger::IsActive()
bool ThorimArenaPositioningTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
// Check boss and it is alive
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD)
@@ -1080,9 +1093,13 @@ bool ThorimPhase2PositioningTrigger::IsActive()
return false;
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
if (!boss || !boss->IsInWorld() || boss->IsDuringRemoveFromWorld())
return false;
// Check boss and it is alive
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
if (!boss->IsAlive())
return false;
if (!boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD)