diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 0b4541985..00d1fbb9f 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -297,7 +297,7 @@ void SmartAI::EndPath(bool fail) mEscortNPCFlags = 0; } - ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS); + ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS, *me); if (targets && mEscortQuestID) { if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) @@ -535,7 +535,7 @@ void SmartAI::UpdateAI(uint32 diff) 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; if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 5c304cfab..6e0b8b1ef 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2051,7 +2051,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } 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) break; @@ -2919,6 +2927,17 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, break; 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; GetWorldObjectsInDist(units, static_cast(e.target.unitRange.maxDist)); @@ -2939,7 +2958,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, 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); } @@ -2994,6 +3013,18 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } 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; GetWorldObjectsInDist(units, static_cast(e.target.goRange.maxDist)); @@ -3005,7 +3036,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, if (go && go->GetGUID() == unit->GetGUID()) 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); } @@ -3015,7 +3046,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { 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; } @@ -3028,7 +3060,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { 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; } @@ -3060,32 +3093,75 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } 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()); break; } 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) targets.push_back(target); break; } 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) targets.push_back(target); break; } 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); - if (target) - targets.push_back(target); + LOG_ERROR("scripts.ai.sai", "SMART_TARGET_CLOSEST_PLAYER: Entry {} SourceType {} Event {} Action {} Target {} is missing base object or invoker.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); + break; } + + if (Player* target = ref->SelectNearestPlayer((float)e.target.playerDistance.dist)) + targets.push_back(target); break; } case SMART_TARGET_OWNER_OR_SUMMONER: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 4cf33a56e..92142ec35 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -80,7 +80,7 @@ public: { // insert or replace _storedTargets.erase(id); - _storedTargets.emplace(id, ObjectGuidVector(GetBaseObject(), targets)); + _storedTargets.emplace(id, ObjectGuidVector(targets)); } bool IsSmart(Creature* c = nullptr) @@ -112,11 +112,11 @@ public: return smart; } - ObjectVector const* GetStoredTargetVector(uint32 id) const + ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const { auto itr = _storedTargets.find(id); if (itr != _storedTargets.end()) - return itr->second.GetObjectVector(); + return itr->second.GetObjectVector(ref); return nullptr; } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 1c3f500ec..5bb07ec3e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1785,34 +1785,33 @@ typedef std::vector ObjectVector; class ObjectGuidVector { public: - ObjectGuidVector(WorldObject* baseObject, ObjectVector const& objectVector) : _baseObject(baseObject), _objectVector(objectVector) + explicit ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector) { _guidVector.reserve(_objectVector.size()); for (WorldObject* obj : _objectVector) _guidVector.push_back(obj->GetGUID()); } - ObjectVector const* GetObjectVector() const + ObjectVector const* GetObjectVector(WorldObject const& ref) const { - UpdateObjects(); + UpdateObjects(ref); return &_objectVector; } ~ObjectGuidVector() { } private: - WorldObject* const _baseObject; mutable ObjectVector _objectVector; GuidVector _guidVector; //sanitize vector using _guidVector - void UpdateObjects() const + void UpdateObjects(WorldObject const& ref) const { _objectVector.clear(); for (ObjectGuid const& guid : _guidVector) - if (WorldObject* obj = ObjectAccessor::GetWorldObject(*_baseObject, guid)) + if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid)) _objectVector.push_back(obj); } };