mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 01:37:00 +00:00
[11659] Rewrite object pos selector.
* Instead coordinates use angle projections to expected pos distance circle. This let do mostly only angle comparison and then speedup checks. * Fixed some long existed bugs in algo and simplify code. Possible more work need.
This commit is contained in:
parent
e776dbbfc8
commit
15bb164d72
4 changed files with 292 additions and 294 deletions
|
|
@ -1703,8 +1703,8 @@ namespace MaNGOS
|
|||
class NearUsedPosDo
|
||||
{
|
||||
public:
|
||||
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
|
||||
: i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
|
||||
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float absAngle, ObjectPosSelector& selector)
|
||||
: i_object(obj), i_searcher(searcher), i_absAngle(absAngle), i_selector(selector) {}
|
||||
|
||||
void operator()(Corpse*) const {}
|
||||
void operator()(DynamicObject*) const {}
|
||||
|
|
@ -1712,13 +1712,12 @@ namespace MaNGOS
|
|||
void operator()(Creature* c) const
|
||||
{
|
||||
// skip self or target
|
||||
if(c==i_searcher || c==&i_object)
|
||||
if (c == i_searcher || c == &i_object)
|
||||
return;
|
||||
|
||||
float x,y,z;
|
||||
float x, y, z;
|
||||
|
||||
if( !c->isAlive() || c->hasUnitState(UNIT_STAT_NOT_MOVE) ||
|
||||
!c->GetMotionMaster()->GetDestination(x,y,z) )
|
||||
if (c->IsStopped() || !c->GetMotionMaster()->GetDestination(x, y, z))
|
||||
{
|
||||
x = c->GetPositionX();
|
||||
y = c->GetPositionY();
|
||||
|
|
@ -1728,10 +1727,10 @@ namespace MaNGOS
|
|||
}
|
||||
|
||||
template<class T>
|
||||
void operator()(T* u) const
|
||||
void operator()(T* u) const
|
||||
{
|
||||
// skip self or target
|
||||
if(u==i_searcher || u==&i_object)
|
||||
if (u == i_searcher || u == &i_object)
|
||||
return;
|
||||
|
||||
float x,y;
|
||||
|
|
@ -1745,26 +1744,32 @@ namespace MaNGOS
|
|||
// we must add used pos that can fill places around center
|
||||
void add(WorldObject* u, float x, float y) const
|
||||
{
|
||||
// dist include size of u and i_object
|
||||
float dx = i_object.GetPositionX() - x;
|
||||
float dy = i_object.GetPositionY() - y;
|
||||
float dist2d = sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
float delta = i_selector.m_searcherSize + u->GetObjectBoundingRadius();
|
||||
|
||||
// u is too nearest/far away to i_object
|
||||
if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
|
||||
if (dist2d < i_selector.m_searcherDist - delta ||
|
||||
dist2d >= i_selector.m_searcherDist + delta)
|
||||
return;
|
||||
|
||||
float angle = i_object.GetAngle(u)-i_angle;
|
||||
float angle = i_object.GetAngle(u) - i_absAngle;
|
||||
|
||||
// move angle to range -pi ... +pi
|
||||
while( angle > M_PI_F)
|
||||
while (angle > M_PI_F)
|
||||
angle -= 2.0f * M_PI_F;
|
||||
while(angle < -M_PI_F)
|
||||
while (angle < -M_PI_F)
|
||||
angle += 2.0f * M_PI_F;
|
||||
|
||||
// dist include size of u
|
||||
float dist2d = i_object.GetDistance2d(x,y);
|
||||
i_selector.AddUsedPos(u->GetObjectBoundingRadius(), angle, dist2d + i_object.GetObjectBoundingRadius());
|
||||
i_selector.AddUsedArea(u->GetObjectBoundingRadius(), angle, dist2d);
|
||||
}
|
||||
private:
|
||||
WorldObject const& i_object;
|
||||
WorldObject const* i_searcher;
|
||||
float i_angle;
|
||||
float i_absAngle;
|
||||
ObjectPosSelector& i_selector;
|
||||
};
|
||||
} // namespace MaNGOS
|
||||
|
|
@ -1782,16 +1787,16 @@ void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float abs
|
|||
|
||||
void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_bounding_radius, float distance2d, float absAngle) const
|
||||
{
|
||||
GetNearPoint2D(x, y, distance2d+searcher_bounding_radius, absAngle);
|
||||
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle);
|
||||
z = GetPositionZ();
|
||||
|
||||
// if detection disabled, return first point
|
||||
if(!sWorld.getConfig(CONFIG_BOOL_DETECT_POS_COLLISION))
|
||||
{
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1801,113 +1806,79 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
|
|||
bool first_los_conflict = false; // first point LOS problems
|
||||
|
||||
// prepare selector for work
|
||||
ObjectPosSelector selector(GetPositionX(), GetPositionY(), GetObjectBoundingRadius(), distance2d+searcher_bounding_radius);
|
||||
ObjectPosSelector selector(GetPositionX(), GetPositionY(), distance2d + searcher_bounding_radius + GetObjectBoundingRadius(), searcher_bounding_radius);
|
||||
|
||||
// adding used positions around object
|
||||
{
|
||||
MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
|
||||
MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this,u_do);
|
||||
MaNGOS::NearUsedPosDo u_do(*this, searcher, absAngle, selector);
|
||||
MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this, u_do);
|
||||
|
||||
Cell::VisitAllObjects(this, worker, distance2d);
|
||||
Cell::VisitAllObjects(this, worker, distance2d + searcher_bounding_radius);
|
||||
}
|
||||
|
||||
// maybe can just place in primary position
|
||||
if( selector.CheckOriginal() )
|
||||
if (selector.CheckOriginalAngle())
|
||||
{
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if(IsWithinLOS(x,y,z))
|
||||
if (IsWithinLOS(x, y, z))
|
||||
return;
|
||||
|
||||
first_los_conflict = true; // first point have LOS problems
|
||||
}
|
||||
|
||||
float angle; // candidate of angle for free pos
|
||||
|
||||
// special case when one from list empty and then empty side preferred
|
||||
if(selector.FirstAngle(angle))
|
||||
{
|
||||
GetNearPoint2D(x,y,distance2d,absAngle+angle);
|
||||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
|
||||
if(IsWithinLOS(x,y,z))
|
||||
return;
|
||||
}
|
||||
|
||||
// set first used pos in lists
|
||||
selector.InitializeAngle();
|
||||
|
||||
float angle; // candidate of angle for free pos
|
||||
|
||||
// select in positions after current nodes (selection one by one)
|
||||
while(selector.NextAngle(angle)) // angle for free pos
|
||||
while (selector.NextAngle(angle)) // angle for free pos
|
||||
{
|
||||
GetNearPoint2D(x,y,distance2d,absAngle+angle);
|
||||
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle + angle);
|
||||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if(IsWithinLOS(x,y,z))
|
||||
if (IsWithinLOS(x, y, z))
|
||||
return;
|
||||
}
|
||||
|
||||
// BAD NEWS: not free pos (or used or have LOS problems)
|
||||
// Attempt find _used_ pos without LOS problem
|
||||
|
||||
if(!first_los_conflict)
|
||||
if (!first_los_conflict)
|
||||
{
|
||||
x = first_x;
|
||||
y = first_y;
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
// special case when one from list empty and then empty side preferred
|
||||
if( selector.IsNonBalanced() )
|
||||
{
|
||||
if(!selector.FirstAngle(angle)) // _used_ pos
|
||||
{
|
||||
GetNearPoint2D(x,y,distance2d,absAngle+angle);
|
||||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
|
||||
if(IsWithinLOS(x,y,z))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set first used pos in lists
|
||||
selector.InitializeAngle();
|
||||
|
||||
// select in positions after current nodes (selection one by one)
|
||||
while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
|
||||
while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
|
||||
{
|
||||
GetNearPoint2D(x,y,distance2d,absAngle+angle);
|
||||
GetNearPoint2D(x, y, distance2d + searcher_bounding_radius, absAngle + angle);
|
||||
z = GetPositionZ();
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
|
||||
if(IsWithinLOS(x,y,z))
|
||||
if (IsWithinLOS(x, y, z))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1916,9 +1887,9 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
|
|||
y = first_y;
|
||||
|
||||
if (searcher)
|
||||
searcher->UpdateAllowedPositionZ(x,y,z); // update to LOS height if available
|
||||
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
|
||||
else
|
||||
UpdateGroundPositionZ(x,y,z);
|
||||
UpdateGroundPositionZ(x, y, z);
|
||||
}
|
||||
|
||||
void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue