Core/AreaTriggers: Optimize target searching

* Don't visit grid objects for serverside areatriggers (search world container only for player)
* Move existing target list to "exitUnits" instead of copying it
This commit is contained in:
Shauren
2021-01-30 17:12:42 +01:00
parent 7851cd3a96
commit 23144d0665
2 changed files with 38 additions and 31 deletions

View File

@@ -329,7 +329,7 @@ float AreaTrigger::GetProgress() const
void AreaTrigger::UpdateTargetList()
{
std::list<Unit*> targetList;
std::vector<Unit*> targetList;
switch (GetTemplate()->Type)
{
@@ -352,7 +352,22 @@ void AreaTrigger::UpdateTargetList()
HandleUnitEnterExit(targetList);
}
void AreaTrigger::SearchUnitInSphere(std::list<Unit*>& targetList)
void AreaTrigger::SearchUnits(std::vector<Unit*>& targetList, float radius, bool check3D)
{
Trinity::AnyUnitInObjectRangeCheck check(this, radius, check3D);
if (IsServerSide())
{
Trinity::PlayerListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitWorldObjects(this, searcher, GetTemplate()->MaxSearchRadius);
}
else
{
Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitAllObjects(this, searcher, GetTemplate()->MaxSearchRadius);
}
}
void AreaTrigger::SearchUnitInSphere(std::vector<Unit*>& targetList)
{
float radius = GetTemplate()->SphereDatas.Radius;
if (GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_DYNAMIC_SHAPE))
@@ -365,20 +380,16 @@ void AreaTrigger::SearchUnitInSphere(std::list<Unit*>& targetList)
}
}
Trinity::AnyUnitInObjectRangeCheck check(this, radius);
Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitAllObjects(this, searcher, GetTemplate()->MaxSearchRadius);
SearchUnits(targetList, radius, true);
}
void AreaTrigger::SearchUnitInBox(std::list<Unit*>& targetList)
void AreaTrigger::SearchUnitInBox(std::vector<Unit*>& targetList)
{
float extentsX = GetTemplate()->BoxDatas.Extents[0];
float extentsY = GetTemplate()->BoxDatas.Extents[1];
float extentsZ = GetTemplate()->BoxDatas.Extents[2];
Trinity::AnyUnitInObjectRangeCheck check(this, GetTemplate()->MaxSearchRadius, false);
Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitAllObjects(this, searcher, GetTemplate()->MaxSearchRadius);
SearchUnits(targetList, GetTemplate()->MaxSearchRadius, false);
float halfExtentsX = extentsX / 2.0f;
float halfExtentsY = extentsY / 2.0f;
@@ -395,51 +406,46 @@ void AreaTrigger::SearchUnitInBox(std::list<Unit*>& targetList)
G3D::AABox const box({ minX, minY, minZ }, { maxX, maxY, maxZ });
targetList.remove_if([&box](Unit* unit) -> bool
targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [&box](Unit* unit) -> bool
{
return !box.contains({ unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ() });
});
}), targetList.end());
}
void AreaTrigger::SearchUnitInPolygon(std::list<Unit*>& targetList)
void AreaTrigger::SearchUnitInPolygon(std::vector<Unit*>& targetList)
{
Trinity::AnyUnitInObjectRangeCheck check(this, GetTemplate()->MaxSearchRadius, false);
Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitAllObjects(this, searcher, GetTemplate()->MaxSearchRadius);
SearchUnits(targetList, GetTemplate()->MaxSearchRadius, false);
float height = GetTemplate()->PolygonDatas.Height;
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
targetList.remove_if([this, minZ, maxZ](Unit* unit) -> bool
targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [this, minZ, maxZ](Unit* unit) -> bool
{
return !CheckIsInPolygon2D(unit)
|| unit->GetPositionZ() < minZ
|| unit->GetPositionZ() > maxZ;
});
}), targetList.end());
}
void AreaTrigger::SearchUnitInCylinder(std::list<Unit*>& targetList)
void AreaTrigger::SearchUnitInCylinder(std::vector<Unit*>& targetList)
{
Trinity::AnyUnitInObjectRangeCheck check(this, GetTemplate()->MaxSearchRadius, false);
Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targetList, check);
Cell::VisitAllObjects(this, searcher, GetTemplate()->MaxSearchRadius);
SearchUnits(targetList, GetTemplate()->MaxSearchRadius, false);
float height = GetTemplate()->CylinderDatas.Height;
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
targetList.remove_if([minZ, maxZ](Unit* unit) -> bool
targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [minZ, maxZ](Unit* unit) -> bool
{
return unit->GetPositionZ() < minZ
|| unit->GetPositionZ() > maxZ;
});
}), targetList.end());
}
void AreaTrigger::HandleUnitEnterExit(std::list<Unit*> const& newTargetList)
void AreaTrigger::HandleUnitEnterExit(std::vector<Unit*> const& newTargetList)
{
GuidUnorderedSet exitUnits = _insideUnits;
_insideUnits.clear();
GuidUnorderedSet exitUnits(std::move(_insideUnits));
std::vector<Unit*> enteringUnits;

View File

@@ -118,12 +118,13 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
float GetProgress() const;
void UpdateTargetList();
void SearchUnitInSphere(std::list<Unit*>& targetList);
void SearchUnitInBox(std::list<Unit*>& targetList);
void SearchUnitInPolygon(std::list<Unit*>& targetList);
void SearchUnitInCylinder(std::list<Unit*>& targetList);
void SearchUnits(std::vector<Unit*>& targetList, float radius, bool check3D);
void SearchUnitInSphere(std::vector<Unit*>& targetList);
void SearchUnitInBox(std::vector<Unit*>& targetList);
void SearchUnitInPolygon(std::vector<Unit*>& targetList);
void SearchUnitInCylinder(std::vector<Unit*>& targetList);
bool CheckIsInPolygon2D(Position const* pos) const;
void HandleUnitEnterExit(std::list<Unit*> const& targetList);
void HandleUnitEnterExit(std::vector<Unit*> const& targetList);
void DoActions(Unit* unit);
void UndoActions(Unit* unit);