diff options
| author | Jeremy <Golrag@users.noreply.github.com> | 2017-12-29 22:32:07 +0100 |
|---|---|---|
| committer | funjoker <funjoker109@gmail.com> | 2021-04-15 05:53:27 +0200 |
| commit | 446fc391f02d3ca8e1332b58f910a5b7d1c8e226 (patch) | |
| tree | 5d01bfbbcde6b263d330c0647092ca48bf98f62b /src/server/game/Entities/Object | |
| parent | 61585de8aee2f2168e54c713d5bfb7c61444d4b3 (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.cpp | 101 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 6 |
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; } |
