aboutsummaryrefslogtreecommitdiff
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
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)
-rw-r--r--src/common/Collision/DynamicTree.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Object/Object.cpp101
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp11
-rw-r--r--src/server/game/Maps/Map.cpp36
-rw-r--r--src/server/game/Maps/Map.h10
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp8
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp3
-rw-r--r--src/server/game/Movement/PathGenerator.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp4
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp5
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp2
14 files changed, 100 insertions, 96 deletions
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp
index 5111ba7afa0..3d8ca49a4fe 100644
--- a/src/common/Collision/DynamicTree.cpp
+++ b/src/common/Collision/DynamicTree.cpp
@@ -255,7 +255,7 @@ bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3
float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const& phaseShift) const
{
- G3D::Vector3 v(x, y, z + 0.5f);
+ G3D::Vector3 v(x, y, z);
G3D::Ray r(v, G3D::Vector3(0, 0, -1));
DynamicTreeIntersectionCallback callback(phaseShift);
impl->intersectZAllignedRay(r, callback, maxSearchDist);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index c7fe527aade..a8fb84f7f47 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -3046,7 +3046,7 @@ void Creature::UpdateMovementFlags()
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
float ground = GetFloorZ();
- bool isInAir = (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling
+ bool isInAir = (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
if (GetCreatureTemplate()->InhabitType & INHABIT_AIR && isInAir && !IsFalling())
{
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; }
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e3c088700af..d69a54935e9 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -13164,12 +13164,12 @@ void Unit::_ExitVehicle(Position const* exitPosition)
if (player)
player->SetFallInformation(0, GetPositionZ());
- float height = pos.GetPositionZ();
+ float height = pos.GetPositionZ() + vehicle->GetBase()->GetCollisionHeight();
Movement::MoveSplineInit init(this);
// Creatures without inhabit type air should begin falling after exiting the vehicle
- if (GetTypeId() == TYPEID_UNIT && !CanFly() && height > GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), &height) + 0.1f)
+ if (GetTypeId() == TYPEID_UNIT && !CanFly() && height > GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + vehicle->GetBase()->GetCollisionHeight(), &height))
init.SetFall();
init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false);
@@ -14597,6 +14597,7 @@ bool Unit::VisibleAuraSlotCompare::operator()(AuraApplication* left, AuraApplica
return left->GetSlot() < right->GetSlot();
}
+// Returns collisionheight of the unit. If it is 0, it returns DEFAULT_COLLISION_HEIGHT.
float Unit::GetCollisionHeight() const
{
float scaleMod = GetObjectScale(); // 99% sure about this
@@ -14609,7 +14610,8 @@ float Unit::GetCollisionHeight() const
{
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.AssertEntry(GetNativeDisplayId());
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.AssertEntry(displayInfo->ModelID);
- return scaleMod * (mountModelData->MountHeight + modelData->CollisionHeight * 0.5f);
+ float const collisionHeight = scaleMod * (mountModelData->MountHeight + modelData->CollisionHeight * modelData->ModelScale * displayInfo->CreatureModelScale * 0.5f);
+ return collisionHeight == 0.0f ? DEFAULT_COLLISION_HEIGHT : collisionHeight;
}
}
}
@@ -14618,5 +14620,6 @@ float Unit::GetCollisionHeight() const
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.AssertEntry(GetNativeDisplayId());
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.AssertEntry(displayInfo->ModelID);
- return scaleMod * modelData->CollisionHeight;
+ float const collisionHeight = scaleMod * modelData->CollisionHeight * modelData->ModelScale * displayInfo->CreatureModelScale;
+ return collisionHeight == 0.0f ? DEFAULT_COLLISION_HEIGHT : collisionHeight;
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 3f5b679afb9..91138fc043e 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2373,7 +2373,7 @@ uint8 GridMap::getTerrainType(float x, float y) const
}
// Get water state on map
-inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
+inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight)
{
// Check water type (if no water return)
if (!_liquidGlobalFlags && !_liquidFlags)
@@ -2439,7 +2439,7 @@ inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 R
float ground_level = getHeight(x, y);
// Check water level and ground level
- if (liquid_level < ground_level || z < ground_level - 2)
+ if (liquid_level < ground_level || z < ground_level)
return LIQUID_MAP_NO_WATER;
// All ok in water -> store data
@@ -2454,7 +2454,7 @@ inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 R
// For speed check as int values
float delta = liquid_level - z;
- if (delta > 2.0f) // Under water
+ if (delta > collisionHeight) // Under water
return LIQUID_MAP_UNDER_WATER;
if (delta > 0.0f) // In water
return LIQUID_MAP_IN_WATER;
@@ -2487,18 +2487,18 @@ bool Map::HasChildMapGridFile(uint32 mapId, int32 gx, int32 gy) const
return childMapItr != m_childTerrainMaps->end() && (*childMapItr)->i_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy];
}
-float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/)
+float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/, float collisionHeight /*= DEFAULT_COLLISION_HEIGHT*/)
{
if (GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
{
// we need ground level (including grid height version) for proper return water level in point
- float ground_z = GetHeight(phaseShift, x, y, z, true, 50.0f);
+ float ground_z = GetHeight(phaseShift, x, y, z + collisionHeight, true, 50.0f);
if (ground)
*ground = ground_z;
LiquidData liquid_status;
- ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
+ ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight);
switch (res)
{
case LIQUID_MAP_ABOVE_WATER:
@@ -2521,8 +2521,7 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
{
float gridHeight = gmap->getHeight(x, y);
- // look from a bit higher pos to find the floor, ignore under surface case
- if (z + 2.0f > gridHeight)
+ if (z > gridHeight)
mapHeight = gridHeight;
}
@@ -2531,7 +2530,7 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float
{
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
if (vmgr->isHeightCalcEnabled())
- vmapHeight = vmgr->getHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor
+ vmapHeight = vmgr->getHeight(terrainMapId, x, y, z, maxSearchDist);
}
// mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
@@ -2646,8 +2645,7 @@ bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, u
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
{
float mapHeight = gmap->getHeight(x, y);
- // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
- if (z + 2.0f > mapHeight && mapHeight > check_z)
+ if (z > mapHeight && mapHeight > vmap_z)
return false;
}
return true;
@@ -2721,7 +2719,7 @@ uint8 Map::GetTerrainType(PhaseShift const& phaseShift, float x, float y)
return 0;
}
-ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
+ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight)
{
ZLiquidStatus result = LIQUID_MAP_NO_WATER;
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
@@ -2776,7 +2774,7 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float
float delta = liquid_level - z;
// Get position delta
- if (delta > 2.0f) // Under water
+ if (delta > collisionHeight) // Under water
return LIQUID_MAP_UNDER_WATER;
if (delta > 0.0f) // In water
return LIQUID_MAP_IN_WATER;
@@ -2789,7 +2787,7 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
{
LiquidData map_data;
- ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data);
+ ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight);
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
{
@@ -2807,7 +2805,7 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float
return result;
}
-void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType)
+void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight)
{
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
VMAP::AreaAndLiquidData vmapData;
@@ -2823,7 +2821,7 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
// area lookup
AreaTableEntry const* areaEntry = nullptr;
- if (vmapData.areaInfo && (z + 2.0f <= mapHeight || mapHeight <= vmapData.floorZ))
+ if (vmapData.areaInfo && (z <= mapHeight || mapHeight <= vmapData.floorZ))
if (WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId))
areaEntry = sAreaTableStore.LookupEntry(wmoEntry->AreaTableID);
@@ -2849,7 +2847,7 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
// liquid processing
data.liquidStatus = LIQUID_MAP_NO_WATER;
- if (vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ && z + 2.0f > vmapData.floorZ)
+ if (vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ && z > vmapData.floorZ)
{
uint32 liquidType = vmapData.liquidInfo->type;
if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks
@@ -2883,7 +2881,7 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
data.liquidInfo->type_flags = 1 << liquidFlagType;
float delta = vmapData.liquidInfo->level - z;
- if (delta > 2.0f)
+ if (delta > collisionHeight)
data.liquidStatus = LIQUID_MAP_UNDER_WATER;
else if (delta > 0.0f)
data.liquidStatus = LIQUID_MAP_IN_WATER;
@@ -2896,7 +2894,7 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
if (gmap && (data.liquidStatus == LIQUID_MAP_ABOVE_WATER || data.liquidStatus == LIQUID_MAP_NO_WATER))
{
LiquidData gridMapLiquid;
- ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid);
+ ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid, collisionHeight);
if (gridMapStatus != LIQUID_MAP_NO_WATER && (gridMapLiquid.level > vmapData.floorZ))
{
if (GetId() == 530 && gridMapLiquid.entry == 2)
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 9721ff6dc2a..54ee5f50b38 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -256,7 +256,7 @@ public:
float getMinHeight(float x, float y) const;
float getLiquidLevel(float x, float y) const;
uint8 getTerrainType(float x, float y) const;
- ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr);
+ ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
};
#pragma pack(push, 1)
@@ -402,9 +402,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
void AddChildTerrainMap(Map* map) { m_childTerrainMaps->push_back(map); map->m_parentTerrainMap = this; }
void UnlinkAllChildTerrainMaps() { m_childTerrainMaps->clear(); }
- void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS) const;
- void GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS);
- ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr);
+ void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h
+ void GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
+ ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
bool GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId);
uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors = nullptr);
@@ -564,7 +564,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
BattlegroundMap* ToBattlegroundMap() { if (IsBattlegroundOrArena()) return reinterpret_cast<BattlegroundMap*>(this); else return nullptr; }
BattlegroundMap const* ToBattlegroundMap() const { if (IsBattlegroundOrArena()) return reinterpret_cast<BattlegroundMap const*>(this); return nullptr; }
- float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false);
+ float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
float GetMinHeight(PhaseShift const& phaseShift, float x, float y);
float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH);
float GetStaticHeight(PhaseShift const& phaseShift, Position const& pos, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return GetStaticHeight(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), checkVMap, maxSearchDist); }
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index ace37edc11f..1874b9ab921 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -21,6 +21,8 @@
#include "Define.h"
#include "DetourNavMesh.h"
+float const GROUND_HEIGHT_TOLERANCE = 0.05f; // Extra tolerance to z position to check if it is in air or on ground.
+
enum SpellEffIndex : uint8
{
EFFECT_0 = 0,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 210658b9210..7df25b72817 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -457,7 +457,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
float moveTimeHalf = speedZ / Movement::gravity;
float dist = 2 * moveTimeHalf * speedXY;
_owner->GetNearPoint2D(x, y, dist, _owner->GetOrientation() + angle);
- z = _owner->GetPositionZ() + _owner->GetMidsectionHeight();
+ z = _owner->GetPositionZ();
_owner->UpdateAllowedPositionZ(x, y, z);
MoveJump(x, y, z, 0.0f, speedXY, speedZ);
}
@@ -510,7 +510,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool
if (_owner->IsFlying())
point.z = z;
else
- point.z = _owner->GetMap()->GetHeight(_owner->GetPhaseShift(), point.x, point.y, z);
+ point.z = _owner->GetMapHeight(point.x, point.y, z);
init.Path().push_back(point);
}
@@ -593,11 +593,11 @@ void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info)
void MotionMaster::MoveFall(uint32 id /*=0*/)
{
// use larger distance for vmap height search than in most other cases
- float tz = _owner->GetMap()->GetHeight(_owner->GetPhaseShift(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE);
+ float tz = _owner->GetMapHeight(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE);
if (tz <= INVALID_HEIGHT)
{
TC_LOG_DEBUG("misc", "MotionMaster::MoveFall: unable to retrieve a proper height at map %u (x: %f, y: %f, z: %f).",
- _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ());
+ _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ() + _owner->GetPositionZ());
return;
}
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index 3978907847a..d4bc99da9ec 100644
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -115,8 +115,7 @@ void FleeingMovementGenerator<T>::SetTargetLocation(T* owner)
GetPoint(owner, destination);
// Add LOS check for target point
- Position currentPosition = owner->GetPosition();
- if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), currentPosition.m_positionX, currentPosition.m_positionY), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 2.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 2.0f, VMAP::ModelIgnoreFlags::Nothing))
+ if (!owner->IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()))
{
_timer.Reset(200);
return;
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index 25ea5638f08..5124c5c4bea 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -184,7 +184,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
// Check both start and end points, if they're both in water, then we can *safely* let the creature move
for (uint32 i = 0; i < _pathPoints.size(); ++i)
{
- ZLiquidStatus status = _sourceUnit->GetMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, nullptr);
+ ZLiquidStatus status = _sourceUnit->GetMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, nullptr, _sourceUnit->GetCollisionHeight());
// One of the points is not in the water, cancel movement.
if (status == LIQUID_MAP_NO_WATER)
{
@@ -647,7 +647,7 @@ void PathGenerator::UpdateFilter()
NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z)
{
LiquidData data;
- ZLiquidStatus liquidStatus = _sourceUnit->GetMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data);
+ ZLiquidStatus liquidStatus = _sourceUnit->GetMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data, _sourceUnit->GetCollisionHeight());
if (liquidStatus == LIQUID_MAP_NO_WATER)
return NAV_GROUND;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index a9a5c34f38a..0e897c3b109 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1351,10 +1351,10 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS, dist, angle);
- float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseShift(), x, y, z, true, 50.0f);
+ float ground = m_caster->GetMapHeight(x, y, z);
float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
LiquidData liquidData;
- if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquidData))
+ if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquidData, m_caster->GetCollisionHeight()))
liquidLevel = liquidData.level;
if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 991de3f28b9..e3d62a42dd1 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -260,8 +260,8 @@ public:
sDB2Manager.Map2ZoneCoordinates(zoneId, zoneX, zoneY);
Map* map = object->GetMap();
- float groundZ = map->GetHeight(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT);
- float floorZ = map->GetHeight(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ());
+ float groundZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT);
+ float floorZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ());
GridCoord gridCoord = Trinity::ComputeGridCoord(object->GetPositionX(), object->GetPositionY());
@@ -299,7 +299,6 @@ public:
LiquidData liquidStatus;
ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus);
-
if (status)
handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status);
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index 8e5f63ef364..77ea3de389b 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -734,7 +734,7 @@ struct boss_jormungarAI : public boss_northrend_beastsAI
events.ScheduleEvent(EVENT_EMERGE, 6s, 0, PHASE_SUBMERGED);
me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
}
- me->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionY() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionZ() + me->GetMidsectionHeight());
+ me->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionY() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionZ() + me->GetCollisionHeight());
}
void Emerge()