Core/Movement: merged Collision height handling from 335 branch to reduce the probability that creatures are falling under the map
This commit is contained in:
1 parent
3357ae7940
commit
50a91bd590
16 files changed
+134
-138
No files matched your search
@@ -1289,7 +1289,7 @@ void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32
|
||||
void WorldObject::UpdatePositionData()
|
||||
{
|
||||
PositionFullTerrainStatus data;
|
||||
GetMap()->GetFullTerrainStatusForPosition(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), data);
|
||||
GetMap()->GetFullTerrainStatusForPosition(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS);
|
||||
ProcessPositionDataChanged(data);
|
||||
}
|
||||
|
||||
@@ -1408,22 +1408,22 @@ bool WorldObject::IsInMap(const WorldObject* obj) const
|
||||
|
||||
bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const
|
||||
{
|
||||
return IsInDist(x, y, z, dist);
|
||||
return IsInDist(x, y, z, dist + GetCombatReach());
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinDist3d(const Position* pos, float dist) const
|
||||
bool WorldObject::IsWithinDist3d(Position const* pos, float dist) const
|
||||
{
|
||||
return IsInDist(pos, dist);
|
||||
return IsInDist(pos, dist + GetCombatReach());
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinDist2d(float x, float y, float dist) const
|
||||
{
|
||||
return IsInDist2d(x, y, dist);
|
||||
return IsInDist2d(x, y, dist + GetCombatReach());
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinDist2d(const Position* pos, float dist) const
|
||||
bool WorldObject::IsWithinDist2d(Position const* pos, float dist) const
|
||||
{
|
||||
return IsInDist2d(pos, dist);
|
||||
return IsInDist2d(pos, dist + GetCombatReach());
|
||||
}
|
||||
|
||||
bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const
|
||||
@@ -1438,7 +1438,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
|
||||
|
||||
Position WorldObject::GetHitSpherePointFor(Position const& dest) const
|
||||
{
|
||||
G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight());
|
||||
G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
|
||||
G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
|
||||
|
||||
@@ -1449,13 +1449,17 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch
|
||||
{
|
||||
if (IsInWorld())
|
||||
{
|
||||
oz += GetCollisionHeight();
|
||||
float x, y, z;
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
GetPosition(x, y, z);
|
||||
z += GetCollisionHeight();
|
||||
}
|
||||
else
|
||||
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
|
||||
|
||||
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, checks, ignoreFlags);
|
||||
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1466,13 +1470,25 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, LineOfSightChecks che
|
||||
if (!IsInMap(obj))
|
||||
return false;
|
||||
|
||||
float x, y, z;
|
||||
float ox, oy, oz;
|
||||
if (obj->GetTypeId() == TYPEID_PLAYER)
|
||||
obj->GetPosition(x, y, z);
|
||||
{
|
||||
obj->GetPosition(ox, oy, oz);
|
||||
oz += GetCollisionHeight();
|
||||
}
|
||||
else
|
||||
obj->GetHitSpherePointFor(GetPosition(), x, y, z);
|
||||
obj->GetHitSpherePointFor({ GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight() }, ox, oy, oz);
|
||||
|
||||
return IsWithinLOS(x, y, z, checks, ignoreFlags);
|
||||
float x, y, z;
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
GetPosition(x, y, z);
|
||||
z += GetCollisionHeight();
|
||||
}
|
||||
else
|
||||
GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
|
||||
|
||||
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags);
|
||||
}
|
||||
|
||||
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
|
||||
@@ -1630,9 +1646,7 @@ Position WorldObject::GetRandomPoint(const Position &srcPos, float distance) con
|
||||
|
||||
void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
|
||||
{
|
||||
float new_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z + 2.0f, true);
|
||||
if (new_z > INVALID_HEIGHT)
|
||||
z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
|
||||
z = GetMapHeight(x, y, z);
|
||||
}
|
||||
|
||||
void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
@@ -1652,8 +1666,8 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
bool canSwim = ToCreature()->CanSwim();
|
||||
float ground_z = z;
|
||||
float max_z = canSwim
|
||||
? GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
: ((ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true)));
|
||||
? GetMapWaterOrGroundLevel(x, y, z, &ground_z)
|
||||
: (ground_z = GetMapHeight(x, y, z));
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
@@ -1664,7 +1678,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
float ground_z = GetMapHeight(x, y, z);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
@@ -1676,7 +1690,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
if (!ToPlayer()->CanFly())
|
||||
{
|
||||
float ground_z = z;
|
||||
float max_z = GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
|
||||
float max_z = GetMapWaterOrGroundLevel(x, y, z, &ground_z);
|
||||
if (max_z > INVALID_HEIGHT)
|
||||
{
|
||||
if (z > max_z)
|
||||
@@ -1687,7 +1701,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
float ground_z = GetMapHeight(x, y, z);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
@@ -1695,7 +1709,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
|
||||
}
|
||||
default:
|
||||
{
|
||||
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
float ground_z = GetMapHeight(x, y, z);
|
||||
if (ground_z > INVALID_HEIGHT)
|
||||
z = ground_z;
|
||||
break;
|
||||
@@ -2476,8 +2490,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
|
||||
return;
|
||||
}
|
||||
|
||||
ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true);
|
||||
floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true);
|
||||
ground = GetMapHeight(destx, desty, MAX_HEIGHT);
|
||||
floor = GetMapHeight(destx, desty, pos.m_positionZ);
|
||||
destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
|
||||
|
||||
float step = dist/10.0f;
|
||||
@@ -2489,8 +2503,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
|
||||
{
|
||||
destx -= step * std::cos(angle);
|
||||
desty -= step * std::sin(angle);
|
||||
ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true);
|
||||
floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true);
|
||||
ground = GetMapHeight(destx, desty, MAX_HEIGHT);
|
||||
floor = GetMapHeight(destx, desty, pos.m_positionZ);
|
||||
destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
|
||||
}
|
||||
// we have correct destz now
|
||||
@@ -2507,38 +2521,13 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
|
||||
pos.SetOrientation(GetOrientation());
|
||||
}
|
||||
|
||||
// @todo: replace with WorldObject::UpdateAllowedPositionZ
|
||||
float NormalizeZforCollision(WorldObject* obj, float x, float y, float z)
|
||||
{
|
||||
float ground = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, MAX_HEIGHT, true);
|
||||
float floor = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, z + 2.0f, true);
|
||||
float helper = std::fabs(ground - z) <= std::fabs(floor - z) ? ground : floor;
|
||||
if (z > helper) // must be above ground
|
||||
{
|
||||
if (Unit* unit = obj->ToUnit())
|
||||
{
|
||||
if (unit->CanFly())
|
||||
return z;
|
||||
}
|
||||
LiquidData liquid_status;
|
||||
ZLiquidStatus res = obj->GetMap()->GetLiquidStatus(obj->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquid_status);
|
||||
if (res && liquid_status.level > helper) // water must be above ground
|
||||
{
|
||||
if (liquid_status.level > z) // z is underwater
|
||||
return z;
|
||||
else
|
||||
return std::fabs(liquid_status.level - z) <= std::fabs(helper - z) ? liquid_status.level : helper;
|
||||
}
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle)
|
||||
{
|
||||
angle += GetOrientation();
|
||||
float destx, desty, destz;
|
||||
destx = pos.m_positionX + dist * std::cos(angle);
|
||||
desty = pos.m_positionY + dist * std::sin(angle);
|
||||
destz = pos.m_positionZ;
|
||||
|
||||
// Prevent invalid coordinates here, position is unchanged
|
||||
if (!Trinity::IsValidMapCoord(destx, desty))
|
||||
@@ -2547,9 +2536,9 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
|
||||
return;
|
||||
}
|
||||
|
||||
destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ());
|
||||
UpdateAllowedPositionZ(destx, desty, destz);
|
||||
bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(PhasingHandler::GetTerrainMapId(GetPhaseShift(), GetMap(), pos.m_positionX, pos.m_positionY),
|
||||
pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
|
||||
pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
|
||||
|
||||
// collision occured
|
||||
if (col)
|
||||
@@ -2561,7 +2550,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
|
||||
}
|
||||
|
||||
// check dynamic collision
|
||||
col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
|
||||
col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
|
||||
|
||||
// Collided with a gameobject
|
||||
if (col)
|
||||
@@ -2580,7 +2569,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
|
||||
{
|
||||
destx -= step * std::cos(angle);
|
||||
desty -= step * std::sin(angle);
|
||||
destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ());
|
||||
UpdateAllowedPositionZ(destx, desty, destz);
|
||||
}
|
||||
// we have correct destz now
|
||||
else
|
||||
@@ -2592,7 +2581,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
|
||||
|
||||
Trinity::NormalizeMapCoord(pos.m_positionX);
|
||||
Trinity::NormalizeMapCoord(pos.m_positionY);
|
||||
pos.m_positionZ = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ());
|
||||
UpdateAllowedPositionZ(destx, desty, pos.m_positionZ);
|
||||
pos.SetOrientation(GetOrientation());
|
||||
}
|
||||
|
||||
@@ -2781,6 +2770,22 @@ float WorldObject::GetFloorZ() const
|
||||
return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()));
|
||||
}
|
||||
|
||||
float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* ground/* = nullptr*/) const
|
||||
{
|
||||
if (Unit const* unit = ToUnit())
|
||||
return GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ground, !unit->HasAuraType(SPELL_AURA_WATER_WALK), GetCollisionHeight());
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
|
||||
{
|
||||
if (z != MAX_HEIGHT)
|
||||
z += GetCollisionHeight();
|
||||
|
||||
return GetMap()->GetHeight(GetPhaseShift(), x, y, z, vmap, distanceToSearch);
|
||||
}
|
||||
|
||||
template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>&, uint32, float) const;
|
||||
template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::deque<GameObject*>&, uint32, float) const;
|
||||
template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::vector<GameObject*>&, uint32, float) const;
|
||||
|
||||
Reference in new issue
Block a user