mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
fix(Core/AI): validate stored targets (#12489)
Co-authored-by: Meji <meji46@users.noreply.github.com> Co-authored-by: Ariel Silva <ariel-@users.noreply.github.com> Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Meji <meji46@users.noreply.github.com> Co-authored-by: Ariel Silva <ariel-@users.noreply.github.com> Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
@@ -297,7 +297,7 @@ void SmartAI::EndPath(bool fail)
|
|||||||
mEscortNPCFlags = 0;
|
mEscortNPCFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS);
|
ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me);
|
||||||
if (targets && mEscortQuestID)
|
if (targets && mEscortQuestID)
|
||||||
{
|
{
|
||||||
if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
|
if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
|
||||||
@@ -535,7 +535,7 @@ void SmartAI::UpdateAI(uint32 diff)
|
|||||||
|
|
||||||
bool SmartAI::IsEscortInvokerInRange()
|
bool SmartAI::IsEscortInvokerInRange()
|
||||||
{
|
{
|
||||||
if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS))
|
if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me))
|
||||||
{
|
{
|
||||||
float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST;
|
float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST;
|
||||||
if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
|
if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin())))
|
||||||
|
|||||||
@@ -2051,7 +2051,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
|||||||
}
|
}
|
||||||
case SMART_ACTION_SEND_TARGET_TO_TARGET:
|
case SMART_ACTION_SEND_TARGET_TO_TARGET:
|
||||||
{
|
{
|
||||||
ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id);
|
WorldObject* ref = GetBaseObject();
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
ref = unit;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id, *ref);
|
||||||
if (!storedTargets)
|
if (!storedTargets)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2919,6 +2927,17 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
break;
|
break;
|
||||||
case SMART_TARGET_CREATURE_RANGE:
|
case SMART_TARGET_CREATURE_RANGE:
|
||||||
{
|
{
|
||||||
|
WorldObject* ref = baseObject;
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_RANGE: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectVector units;
|
ObjectVector units;
|
||||||
GetWorldObjectsInDist(units, static_cast<float>(e.target.unitRange.maxDist));
|
GetWorldObjectsInDist(units, static_cast<float>(e.target.unitRange.maxDist));
|
||||||
|
|
||||||
@@ -2939,7 +2958,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((e.target.unitRange.creature && unit->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(unit, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
|
if (((e.target.unitRange.creature && unit->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && ref->IsInRange(unit, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist))
|
||||||
targets.push_back(unit);
|
targets.push_back(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2994,6 +3013,18 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
}
|
}
|
||||||
case SMART_TARGET_GAMEOBJECT_RANGE:
|
case SMART_TARGET_GAMEOBJECT_RANGE:
|
||||||
{
|
{
|
||||||
|
|
||||||
|
WorldObject* ref = baseObject;
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_RANGE: Entry: {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectVector units;
|
ObjectVector units;
|
||||||
GetWorldObjectsInDist(units, static_cast<float>(e.target.goRange.maxDist));
|
GetWorldObjectsInDist(units, static_cast<float>(e.target.goRange.maxDist));
|
||||||
|
|
||||||
@@ -3005,7 +3036,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
if (go && go->GetGUID() == unit->GetGUID())
|
if (go && go->GetGUID() == unit->GetGUID())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (((e.target.goRange.entry && IsGameObject(unit) && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((unit), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
|
if (((e.target.goRange.entry && IsGameObject(unit) && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && ref->IsInRange((unit), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist))
|
||||||
targets.push_back(unit);
|
targets.push_back(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3015,7 +3046,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
{
|
{
|
||||||
if (!scriptTrigger && !baseObject)
|
if (!scriptTrigger && !baseObject)
|
||||||
{
|
{
|
||||||
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID can not be used without invoker");
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CREATURE_GUID: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3028,7 +3060,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
{
|
{
|
||||||
if (!scriptTrigger && !GetBaseObject())
|
if (!scriptTrigger && !GetBaseObject())
|
||||||
{
|
{
|
||||||
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker");
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_GAMEOBJECT_GUID: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3060,32 +3093,75 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
|||||||
}
|
}
|
||||||
case SMART_TARGET_STORED:
|
case SMART_TARGET_STORED:
|
||||||
{
|
{
|
||||||
if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id))
|
WorldObject* ref = baseObject;
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_STORED: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id, *ref))
|
||||||
targets.assign(stored->begin(), stored->end());
|
targets.assign(stored->begin(), stored->end());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SMART_TARGET_CLOSEST_CREATURE:
|
case SMART_TARGET_CLOSEST_CREATURE:
|
||||||
{
|
{
|
||||||
Creature* target = GetClosestCreatureWithEntry(GetBaseObject(), e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead);
|
WorldObject* ref = baseObject;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_CREATURE: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Creature* target = GetClosestCreatureWithEntry(ref, e.target.unitClosest.entry, (float)(e.target.unitClosest.dist ? e.target.unitClosest.dist : 100), !e.target.unitClosest.dead);
|
||||||
if (target)
|
if (target)
|
||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SMART_TARGET_CLOSEST_GAMEOBJECT:
|
case SMART_TARGET_CLOSEST_GAMEOBJECT:
|
||||||
{
|
{
|
||||||
GameObject* target = GetClosestGameObjectWithEntry(GetBaseObject(), e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned);
|
WorldObject* ref = baseObject;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_GAMEOBJECT: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject* target = GetClosestGameObjectWithEntry(ref, e.target.goClosest.entry, (float)(e.target.goClosest.dist ? e.target.goClosest.dist : 100), e.target.goClosest.onlySpawned);
|
||||||
if (target)
|
if (target)
|
||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SMART_TARGET_CLOSEST_PLAYER:
|
case SMART_TARGET_CLOSEST_PLAYER:
|
||||||
{
|
{
|
||||||
if (WorldObject* obj = GetBaseObject())
|
WorldObject* ref = baseObject;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
ref = scriptTrigger;
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
{
|
{
|
||||||
Player* target = obj->SelectNearestPlayer((float)e.target.playerDistance.dist);
|
LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_PLAYER: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.",
|
||||||
if (target)
|
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
|
||||||
targets.push_back(target);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Player* target = ref->SelectNearestPlayer((float)e.target.playerDistance.dist))
|
||||||
|
targets.push_back(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SMART_TARGET_OWNER_OR_SUMMONER:
|
case SMART_TARGET_OWNER_OR_SUMMONER:
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public:
|
|||||||
{
|
{
|
||||||
// insert or replace
|
// insert or replace
|
||||||
_storedTargets.erase(id);
|
_storedTargets.erase(id);
|
||||||
_storedTargets.emplace(id, ObjectGuidVector(GetBaseObject(), targets));
|
_storedTargets.emplace(id, ObjectGuidVector(targets));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSmart(Creature* c = nullptr)
|
bool IsSmart(Creature* c = nullptr)
|
||||||
@@ -112,11 +112,11 @@ public:
|
|||||||
return smart;
|
return smart;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectVector const* GetStoredTargetVector(uint32 id) const
|
ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const
|
||||||
{
|
{
|
||||||
auto itr = _storedTargets.find(id);
|
auto itr = _storedTargets.find(id);
|
||||||
if (itr != _storedTargets.end())
|
if (itr != _storedTargets.end())
|
||||||
return itr->second.GetObjectVector();
|
return itr->second.GetObjectVector(ref);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1785,34 +1785,33 @@ typedef std::vector<WorldObject*> ObjectVector;
|
|||||||
class ObjectGuidVector
|
class ObjectGuidVector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObjectGuidVector(WorldObject* baseObject, ObjectVector const& objectVector) : _baseObject(baseObject), _objectVector(objectVector)
|
explicit ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector)
|
||||||
{
|
{
|
||||||
_guidVector.reserve(_objectVector.size());
|
_guidVector.reserve(_objectVector.size());
|
||||||
for (WorldObject* obj : _objectVector)
|
for (WorldObject* obj : _objectVector)
|
||||||
_guidVector.push_back(obj->GetGUID());
|
_guidVector.push_back(obj->GetGUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectVector const* GetObjectVector() const
|
ObjectVector const* GetObjectVector(WorldObject const& ref) const
|
||||||
{
|
{
|
||||||
UpdateObjects();
|
UpdateObjects(ref);
|
||||||
return &_objectVector;
|
return &_objectVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ObjectGuidVector() { }
|
~ObjectGuidVector() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorldObject* const _baseObject;
|
|
||||||
mutable ObjectVector _objectVector;
|
mutable ObjectVector _objectVector;
|
||||||
|
|
||||||
GuidVector _guidVector;
|
GuidVector _guidVector;
|
||||||
|
|
||||||
//sanitize vector using _guidVector
|
//sanitize vector using _guidVector
|
||||||
void UpdateObjects() const
|
void UpdateObjects(WorldObject const& ref) const
|
||||||
{
|
{
|
||||||
_objectVector.clear();
|
_objectVector.clear();
|
||||||
|
|
||||||
for (ObjectGuid const& guid : _guidVector)
|
for (ObjectGuid const& guid : _guidVector)
|
||||||
if (WorldObject* obj = ObjectAccessor::GetWorldObject(*_baseObject, guid))
|
if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid))
|
||||||
_objectVector.push_back(obj);
|
_objectVector.push_back(obj);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user