Revert "Core/Entities: Reduce the probability of units dropping under the map (#21322)"

This reverts commit 9e0faace9a.
This commit is contained in:
Shauren
2018-04-07 00:25:00 +02:00
parent 5f897589f9
commit 2dadbda24a
11 changed files with 71 additions and 284 deletions
+43 -150
View File
@@ -3262,103 +3262,13 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
pos.SetOrientation(GetOrientation());
}
// Only call this function when you already checked for collision with vmap/gameobject.
// You should check for collision again after this one has been called.
// excludeCollisionHeight should only be true if you had collision, it wont add it to raycasts for dest position.
float WorldObject::SelectBestZForDestination(float x, float y, float z, bool excludeCollisionHeight) const
{
if (Unit const* unit = ToUnit())
{
float const ground = GetFloorZ();
bool const isInAir = (G3D::fuzzyGt(unit->GetPositionZ(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(unit->GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE));
if (isInAir)
{
// creatures never get MOVEMENTFLAG_FLYING, check it additionally for them
if (Creature const* creature = ToCreature())
if (creature->CanFly())
return z;
if (unit->IsFlying())
return z;
}
}
float myX, myY, myZ;
GetPosition(myX, myY, myZ);
float const myCollisionHeight = GetCollisionHeight();
float const destCollisionHeight = excludeCollisionHeight ? 0.0f : myCollisionHeight;
float const myGridHeight = GetMap()->GetGridMapHeight(myX, myY);
float const myVmapFloor = std::max(GetMap()->GetVMapFloor(myX, myY, myZ, 150.0f, myCollisionHeight),
GetMap()->GetGameObjectFloor(GetPhaseMask(), myX, myY, myZ, 150.0f, myCollisionHeight));
// which of these 3 do I want ?
float const destGridHeight = GetMap()->GetGridMapHeight(x, y);
float const destCeil = GetMap()->GetCeil(GetPhaseMask(), x, y, z, 150.0f, destCollisionHeight);
float const destVmapFloor = std::max(GetMap()->GetVMapFloor(x, y, z, 150.0f, destCollisionHeight),
GetMap()->GetGameObjectFloor(GetPhaseMask(), x, y, z, 150.0f, destCollisionHeight));
bool const hasVmapFloor = myVmapFloor > INVALID_HEIGHT;
bool const hasDestGridHeight = destGridHeight > INVALID_HEIGHT;
bool const hasDestVmapCeil = destCeil < VMAP_INVALID_CEIL && destCeil != destVmapFloor;
bool const hasDestVmapFloor = destVmapFloor > INVALID_HEIGHT;
bool const destBetweenVmaps = hasDestVmapCeil && hasDestVmapFloor;
bool const noVmap = !hasDestVmapFloor && !hasDestVmapCeil;
// It is possible that while moving, our feet are slightly moving under the ground. Jumping / reconnecting fixes this issue but we don't want to rely on that.
myZ += myCollisionHeight;
bool const isOnVmap = hasVmapFloor &&
((myZ < myGridHeight && std::fabs(myVmapFloor - myZ) < std::fabs(myGridHeight - myZ)) ||
(myZ > myGridHeight && myVmapFloor > myGridHeight));
bool const hasToFollowGridHeight = hasDestGridHeight && (noVmap ||
(z > destGridHeight && destGridHeight > destVmapFloor) ||
(z < destGridHeight && hasDestVmapFloor && !hasDestVmapCeil) ||
(z < destGridHeight && !hasDestVmapFloor) ||
(destBetweenVmaps && !isOnVmap && destGridHeight > destVmapFloor && destGridHeight < destCeil));
float result = INVALID_HEIGHT;
if (hasToFollowGridHeight)
{
result = destGridHeight;
if (hasDestVmapFloor)
if (std::fabs(destVmapFloor - destGridHeight) < myCollisionHeight)
result = std::max(destVmapFloor, destGridHeight);
if (hasDestVmapCeil)
if (std::fabs(destCeil - destGridHeight) < myCollisionHeight)
result = std::max(destCeil, destGridHeight);
}
else if (hasDestVmapFloor)
result = destVmapFloor;
else if (hasDestVmapCeil)
result = destCeil;
if (Unit const* unit = ToUnit())
if (!unit->CanSwim())
return result;
LiquidData liquidData;
ZLiquidStatus const liquidStatus = GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData, destCollisionHeight);
switch (liquidStatus)
{
case LIQUID_MAP_ABOVE_WATER:
return std::max<float>(liquidData.level, result);
case LIQUID_MAP_IN_WATER:
case LIQUID_MAP_UNDER_WATER:
return std::max<float>(z, result);
default:
return result;
}
}
void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle)
{
angle += GetOrientation();
float destx = pos.m_positionX + dist * std::cos(angle);
float desty = pos.m_positionY + dist * std::sin(angle);
float destz = pos.m_positionZ;
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))
@@ -3367,72 +3277,52 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
return;
}
bool const col = ComputeCollisionPosition(pos, { destx, desty, destz }, destx, desty, destz);
UpdateAllowedPositionZ(destx, desty, destz);
bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
// collision occured
if (col)
{
// move back a bit
destx -= CONTACT_DISTANCE * std::cos(angle);
desty -= CONTACT_DISTANCE * std::sin(angle);
dist = std::sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty));
destz = SelectBestZForDestination(destx, desty, destz, col);
float const step = dist / 10.0f;
// do not allow too big z changes
for (uint8 j = 0; j < 10 && std::fabs(pos.m_positionZ - destz) > 6.0f; ++j)
{
destx -= step * std::cos(angle);
desty -= step * std::sin(angle);
// There should not be any collision between our position and destx, desty, pos.m_positionZ at this point.
// Use pos.m_positionZ here because destz was not good.
destz = SelectBestZForDestination(destx, desty, pos.m_positionZ, col);
}
Trinity::NormalizeMapCoord(destx);
Trinity::NormalizeMapCoord(desty);
// We might want to loop until there is no more collision with a better z position. (And/or until a fixed #attemps have been made).
ComputeCollisionPosition(pos, { destx, desty, destz }, destx, desty, destz);
pos.Relocate(destx, desty, destz);
pos.SetOrientation(GetOrientation());
}
// check dynamic collision
col = GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
bool WorldObject::ComputeCollisionPosition(Position const& startPosition, Position const& endPosition, float& x, float& y, float& z) const
// Collided with a gameobject
if (col)
{
destx -= CONTACT_DISTANCE * std::cos(angle);
desty -= CONTACT_DISTANCE * std::sin(angle);
dist = std::sqrt((pos.m_positionX - destx)*(pos.m_positionX - destx) + (pos.m_positionY - desty)*(pos.m_positionY - desty));
}
float step = dist / 10.0f;
for (uint8 j = 0; j < 10; ++j)
{
Position vmapCollisionPos;
bool const vmapCollision = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), startPosition.m_positionX, startPosition.m_positionY, startPosition.m_positionZ + GetCollisionHeight(), endPosition.m_positionX, endPosition.m_positionY, endPosition.m_positionZ + GetCollisionHeight(), vmapCollisionPos.m_positionX, vmapCollisionPos.m_positionY, vmapCollisionPos.m_positionZ, -CONTACT_DISTANCE * 2.0f);
Position gameObjectCollisionPos;
bool const gameObjectCollision = GetMap()->getObjectHitPos(GetPhaseMask(), startPosition.m_positionX, startPosition.m_positionY, startPosition.m_positionZ + GetCollisionHeight(), endPosition.m_positionX, endPosition.m_positionY, endPosition.m_positionZ + GetCollisionHeight(), gameObjectCollisionPos.m_positionX, gameObjectCollisionPos.m_positionY, gameObjectCollisionPos.m_positionZ, -CONTACT_DISTANCE * 2.0f);
// Both collision occures, check which one is closest to start.
if (vmapCollision && gameObjectCollision)
// do not allow too big z changes
if (std::fabs(pos.m_positionZ - destz) > 6.0f)
{
if (startPosition.GetExactDist(vmapCollision) < startPosition.GetExactDist(gameObjectCollisionPos))
{
x = vmapCollisionPos.m_positionX;
y = vmapCollisionPos.m_positionY;
z = vmapCollisionPos.m_positionZ;
return true;
destx -= step * std::cos(angle);
desty -= step * std::sin(angle);
UpdateAllowedPositionZ(destx, desty, destz);
}
x = gameObjectCollisionPos.m_positionX;
y = gameObjectCollisionPos.m_positionY;
z = gameObjectCollisionPos.m_positionZ;
return true;
}
if (vmapCollision)
// we have correct destz now
else
{
x = vmapCollisionPos.m_positionX;
y = vmapCollisionPos.m_positionY;
z = vmapCollisionPos.m_positionZ;
return true;
pos.Relocate(destx, desty, destz);
break;
}
}
if (gameObjectCollision)
{
x = gameObjectCollisionPos.m_positionX;
y = gameObjectCollisionPos.m_positionY;
z = gameObjectCollisionPos.m_positionZ;
return true;
}
return false;
Trinity::NormalizeMapCoord(pos.m_positionX);
Trinity::NormalizeMapCoord(pos.m_positionY);
UpdateAllowedPositionZ(destx, desty, pos.m_positionZ);
pos.SetOrientation(GetOrientation());
}
void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
@@ -3625,7 +3515,10 @@ float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* gr
float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
{
return GetMap()->GetHeight(GetPhaseMask(), x, y, z, vmap, distanceToSearch, GetCollisionHeight());
if (z != MAX_HEIGHT)
z += GetCollisionHeight();
return GetMap()->GetHeight(GetPhaseMask(), x, y, z, vmap, distanceToSearch);
}
template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>&, uint32, float) const;