aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Object
diff options
context:
space:
mode:
authorJeremy <Golrag@users.noreply.github.com>2017-12-29 22:32:07 +0100
committerfunjoker <funjoker109@gmail.com>2021-04-15 05:53:27 +0200
commit446fc391f02d3ca8e1332b58f910a5b7d1c8e226 (patch)
tree5d01bfbbcde6b263d330c0647092ca48bf98f62b /src/server/game/Entities/Object
parent61585de8aee2f2168e54c713d5bfb7c61444d4b3 (diff)
Core/Entities: Fix some weird movement due to los issues (#21125)
* Core/Entities: Fix some weird movement due to los issues - Made LoS check use collisionHeight instead of midsection. Value was too low. - Gnomes will now have a breath bar more quickly than for example a tauren. - Changes have been made to checking for ground z as well, some tweeking might be needed but removed most of the scattered +2.0f/+0.5f/we * Add 0.05f to isInAir check in Creature::UpdateMovementFlags (cherry picked from commit e42903ec16f4849b71bc8736e3151a1e11d3cd25)
Diffstat (limited to 'src/server/game/Entities/Object')
-rw-r--r--src/server/game/Entities/Object/Object.cpp101
-rw-r--r--src/server/game/Entities/Object/Object.h6
2 files changed, 55 insertions, 52 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 55be0ac8e52..cde6da3c0d4 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -930,7 +930,7 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
void WorldObject::UpdatePositionData()
{
PositionFullTerrainStatus data;
- GetMap()->GetFullTerrainStatusForPosition(_phaseShift, GetPositionX(), GetPositionY(), GetPositionZ(), data);
+ GetMap()->GetFullTerrainStatusForPosition(_phaseShift, GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS);
ProcessPositionDataChanged(data);
}
@@ -1086,7 +1086,7 @@ bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare,
Position WorldObject::GetHitSpherePointFor(Position const& dest) const
{
- G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight());
+ 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());
@@ -1097,11 +1097,12 @@ 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 += GetMidsectionHeight();
+ z += GetCollisionHeight();
}
else
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
@@ -1117,16 +1118,25 @@ bool WorldObject::IsWithinLOSInMap(WorldObject const* 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);
- z += GetMidsectionHeight();
+ obj->GetPosition(ox, oy, oz);
+ oz += GetCollisionHeight();
+ }
+ else
+ obj->GetHitSpherePointFor({ GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight() }, ox, oy, oz);
+
+ float x, y, z;
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ GetPosition(x, y, z);
+ z += GetCollisionHeight();
}
else
- obj->GetHitSpherePointFor({ GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight() }, x, y, z);
+ GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
- return IsWithinLOS(x, y, z, checks, ignoreFlags);
+ 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
@@ -1284,9 +1294,7 @@ Position WorldObject::GetRandomPoint(Position const& 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
@@ -1306,8 +1314,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)
@@ -1318,7 +1326,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;
}
@@ -1330,7 +1338,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)
@@ -1341,7 +1349,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;
}
@@ -1349,7 +1357,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;
@@ -2104,8 +2112,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;
@@ -2135,38 +2143,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))
@@ -2175,9 +2158,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)
@@ -2189,7 +2172,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)
@@ -2208,7 +2191,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
@@ -2220,7 +2203,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());
}
@@ -2382,7 +2365,23 @@ float WorldObject::GetFloorZ() const
{
if (!IsInWorld())
return m_staticFloorZ;
- return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()));
+ return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight()));
+}
+
+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;
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index b877d8c6670..530b3aae43f 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -125,6 +125,8 @@ namespace UF
}
}
+float const DEFAULT_COLLISION_HEIGHT = 2.03128f; // Most common value in dbc
+
class TC_GAME_API Object
{
public:
@@ -589,7 +591,9 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
float GetFloorZ() const;
virtual float GetCollisionHeight() const { return 0.0f; }
- float GetMidsectionHeight() const { return GetCollisionHeight() / 2.0f; }
+
+ float GetMapWaterOrGroundLevel(float x, float y, float z, float* ground = nullptr) const;
+ float GetMapHeight(float x, float y, float z, bool vmap = true, float distanceToSearch = 50.0f) const; // DEFAULT_HEIGHT_SEARCH in map.h
virtual uint16 GetAIAnimKitId() const { return 0; }
virtual uint16 GetMovementAnimKitId() const { return 0; }