diff --git a/Source/Framework/Constants/MapConst.cs b/Source/Framework/Constants/MapConst.cs index cc2389d42..de0cad3e5 100644 --- a/Source/Framework/Constants/MapConst.cs +++ b/Source/Framework/Constants/MapConst.cs @@ -62,6 +62,8 @@ namespace Framework.Constants public const float InvalidHeight = -100000.0f; public const float MaxHeight = 100000.0f; public const float MaxFallDistance = 250000.0f; + public const float GroundHeightTolerance = 0.05f; + public const float DefaultCollesionHeight = 2.03128f; // Most common value in dbc public const uint MapMagic = 0x5350414D; //"MAPS"; public const uint MapVersionMagic = 0x392E3176; //"v1.9"; diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index 43e46bade..95853bb96 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -902,8 +902,8 @@ namespace Game.Chat Global.DB2Mgr.Map2ZoneCoordinates((int)zoneId, ref zoneX, ref zoneY); Map map = obj.GetMap(); - float groundZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight); - float floorZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ()); + float groundZ = obj.GetMapHeight(obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight); + float floorZ = obj.GetMapHeight(obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ()); GridCoord gridCoord = GridDefines.ComputeGridCoord(obj.GetPositionX(), obj.GetPositionY()); diff --git a/Source/Game/Collision/DynamicTree.cs b/Source/Game/Collision/DynamicTree.cs index 1dc3361df..3f9ad3d30 100644 --- a/Source/Game/Collision/DynamicTree.cs +++ b/Source/Game/Collision/DynamicTree.cs @@ -115,7 +115,7 @@ namespace Game.Collision public float GetHeight(float x, float y, float z, float maxSearchDist, PhaseShift phaseShift) { - Vector3 v = new(x, y, z + 0.5f); + Vector3 v = new(x, y, z); Ray r = new(v, new Vector3(0, 0, -1)); DynamicTreeIntersectionCallback callback = new(phaseShift); impl.IntersectZAllignedRay(r, callback, ref maxSearchDist); diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 4a9df32e2..b3e2aaf43 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -2717,7 +2717,7 @@ namespace Game.Entities // 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 = (MathFunctions.fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || MathFunctions.fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling + bool isInAir = (MathFunctions.fuzzyGt(GetPositionZMinusOffset(), ground + MapConst.GroundHeightTolerance) || MathFunctions.fuzzyLt(GetPositionZMinusOffset(), ground - MapConst.GroundHeightTolerance)); // Can be underground too, prevent the falling if (GetCreatureTemplate().InhabitType.HasAnyFlag(InhabitType.Air) && isInAir && !IsFalling()) { diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 76618018e..bf4938231 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1917,11 +1917,12 @@ namespace Game.Entities { if (IsInWorld) { + oz += GetCollisionHeight(); float x, y, z; if (IsTypeId(TypeId.Player)) { GetPosition(out x, out y, out z); - z += GetMidsectionHeight(); + z += GetCollisionHeight(); } else GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z); @@ -1937,21 +1938,30 @@ namespace Game.Entities if (!IsInMap(obj)) return false; - float x, y, z; + float ox, oy, oz; if (obj.IsTypeId(TypeId.Player)) { - obj.GetPosition(out x, out y, out z); - z += GetMidsectionHeight(); + obj.GetPosition(out ox, out oy, out oz); + oz += GetCollisionHeight(); } else - obj.GetHitSpherePointFor(new (GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight()), out x, out y, out z); + obj.GetHitSpherePointFor(new (GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight()), out ox, out oy, out oz); - return IsWithinLOS(x, y, z, checks, ignoreFlags); + float x, y, z; + if (IsPlayer()) + { + GetPosition(out x, out y, out z); + z += GetCollisionHeight(); + } + else + GetHitSpherePointFor(new (obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ() + obj.GetCollisionHeight()), out x, out y, out z); + + return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags); } Position GetHitSpherePointFor(Position dest) { - Vector3 vThis = new(GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight()); + Vector3 vThis = new(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight()); Vector3 vObj = new(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * Math.Min(dest.GetExactDist(GetPosition()), GetCombatReach()); @@ -2076,9 +2086,7 @@ namespace Game.Entities public void UpdateGroundPositionZ(float x, float y, ref float z) { - float new_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); - if (new_z > MapConst.InvalidHeight) - z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface + z = GetMapHeight(x, y, z); } public void UpdateAllowedPositionZ(float x, float y, ref float z) @@ -2098,8 +2106,8 @@ namespace Game.Entities bool canSwim = ToCreature().CanSwim(); float ground_z = z; float max_z = canSwim - ? GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk)) - : ((ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true))); + ? GetMapWaterOrGroundLevel(x, y, z, ref ground_z) + : (ground_z = GetMapHeight(x, y, z)); if (max_z > MapConst.InvalidHeight) { if (z > max_z) @@ -2110,7 +2118,7 @@ namespace Game.Entities } 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; } @@ -2122,7 +2130,7 @@ namespace Game.Entities if (!ToPlayer().CanFly()) { float ground_z = z; - float max_z = GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk)); + float max_z = GetMapWaterOrGroundLevel(x, y, z, ref ground_z); if (max_z > MapConst.InvalidHeight) { if (z > max_z) @@ -2133,7 +2141,7 @@ namespace Game.Entities } 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; } @@ -2141,7 +2149,7 @@ namespace Game.Entities } default: { - float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); + float ground_z = GetMapHeight(x, y, z); if (ground_z > MapConst.InvalidHeight) z = ground_z; break; @@ -2202,7 +2210,7 @@ namespace Game.Entities public Position GetNearPosition(float dist, float angle) { var pos = GetPosition(); - MovePosition(ref pos, dist, angle); + MovePosition(pos, dist, angle); return pos; } @@ -2216,7 +2224,7 @@ namespace Game.Entities public Position GetRandomNearPosition(float radius) { var pos = GetPosition(); - MovePosition(ref pos, radius * (float)RandomHelper.NextDouble(), (float)RandomHelper.NextDouble() * MathFunctions.PI * 2); + MovePosition(pos, radius * (float)RandomHelper.NextDouble(), (float)RandomHelper.NextDouble() * MathFunctions.PI * 2); return pos; } @@ -2226,7 +2234,7 @@ namespace Game.Entities GetNearPoint(obj, out x, out y, out z, obj.GetCombatReach(), distance2d, GetAngle(obj)); } - public void MovePosition(ref Position pos, float dist, float angle) + public void MovePosition(Position pos, float dist, float angle) { angle += GetOrientation(); float destx = pos.posX + dist * (float)Math.Cos(angle); @@ -2239,8 +2247,8 @@ namespace Game.Entities return; } - float ground = GetMap().GetHeight(GetPhaseShift(), destx, desty, MapConst.MaxHeight, true); - float floor = GetMap().GetHeight(GetPhaseShift(), destx, desty, pos.posZ, true); + float ground = GetMapHeight(destx, desty, MapConst.MaxHeight); + float floor = GetMapHeight(destx, desty, pos.posZ); float destz = Math.Abs(ground - pos.posZ) <= Math.Abs(floor - pos.posZ) ? ground : floor; float step = dist / 10.0f; @@ -2270,37 +2278,12 @@ namespace Game.Entities pos.SetOrientation(GetOrientation()); } - float NormalizeZforCollision(WorldObject obj, float x, float y, float z) - { - float ground = obj.GetMap().GetHeight(obj.GetPhaseShift(), x, y, MapConst.MaxHeight, true); - float floor = obj.GetMap().GetHeight(obj.GetPhaseShift(), x, y, z + 2.0f, true); - float helper = Math.Abs(ground - z) <= Math.Abs(floor - z) ? ground : floor; - if (z > helper) // must be above ground - { - Unit unit = obj.ToUnit(); - if (unit) - { - if (unit.CanFly()) - return z; - } - LiquidData liquid_status; - ZLiquidStatus res = obj.GetMap().GetLiquidStatus(obj.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquid_status); - if (res != 0 && liquid_status.level > helper) // water must be above ground - { - if (liquid_status.level > z) // z is underwater - return z; - else - return Math.Abs(liquid_status.level - z) <= Math.Abs(helper - z) ? liquid_status.level : helper; - } - } - return helper; - } - public void MovePositionToFirstCollision(ref Position pos, float dist, float angle) { angle += GetOrientation(); float destx = pos.posX + dist * (float)Math.Cos(angle); float desty = pos.posY + dist * (float)Math.Sin(angle); + float destz = pos.posZ; // Prevent invalid coordinates here, position is unchanged if (!GridDefines.IsValidMapCoord(destx, desty)) @@ -2309,8 +2292,8 @@ namespace Game.Entities return; } - float destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); - bool col = Global.VMapMgr.GetObjectHitPos(PhasingHandler.GetTerrainMapId(GetPhaseShift(), GetMap(), pos.posX, pos.posY), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f); + UpdateAllowedPositionZ(destx, desty, ref destz); + bool col = Global.VMapMgr.GetObjectHitPos(PhasingHandler.GetTerrainMapId(GetPhaseShift(), GetMap(), pos.posX, pos.posY), pos.posX, pos.posY, pos.posZ, destx, desty, destz, out destx, out desty, out destz, -0.5f); // collision occured if (col) @@ -2322,7 +2305,7 @@ namespace Game.Entities } // check dynamic collision - col = GetMap().GetObjectHitPos(GetPhaseShift(), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f); + col = GetMap().GetObjectHitPos(GetPhaseShift(), pos.posX, pos.posY, pos.posZ, destx, desty, destz, out destx, out desty, out destz, -0.5f); // Collided with a gameobject if (col) @@ -2341,7 +2324,7 @@ namespace Game.Entities { destx -= step * (float)Math.Cos(angle); desty -= step * (float)Math.Sin(angle); - destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); + UpdateAllowedPositionZ(destx, desty, ref destz); } // we have correct destz now else @@ -2353,7 +2336,7 @@ namespace Game.Entities GridDefines.NormalizeMapCoord(ref pos.posX); GridDefines.NormalizeMapCoord(ref pos.posY); - pos.posZ = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); + UpdateAllowedPositionZ(destx, desty, ref pos.posZ); pos.SetOrientation(GetOrientation()); } @@ -2361,7 +2344,24 @@ namespace Game.Entities { if (!IsInWorld) return m_staticFloorZ; - return Math.Max(m_staticFloorZ, GetMap().GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ())); + return Math.Max(m_staticFloorZ, GetMap().GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight())); + } + + float GetMapWaterOrGroundLevel(float x, float y, float z, ref float ground) + { + Unit unit = ToUnit(); + if (unit != null) + return GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground, !unit.HasAuraType(AuraType.WaterWalk), GetCollisionHeight()); + + return z; + } + + public float GetMapHeight(float x, float y, float z, bool vmap = true, float distanceToSearch = MapConst.DefaultHeightSearch) + { + if (z != MapConst.MaxHeight) + z += GetCollisionHeight(); + + return GetMap().GetHeight(GetPhaseShift(), x, y, z, vmap, distanceToSearch); } public void SetLocationInstanceId(uint _instanceId) { instanceId = _instanceId; } diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index d163cf19f..c770d1359 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -824,7 +824,8 @@ namespace Game.Entities { var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); var modelData = CliDB.CreatureModelDataStorage.LookupByKey(displayInfo.ModelID); - return scaleMod * (mountModelData.MountHeight + modelData.CollisionHeight * 0.5f); + float collisionHeight = scaleMod * (mountModelData.MountHeight + modelData.CollisionHeight * modelData.ModelScale * displayInfo.CreatureModelScale * 0.5f); + return collisionHeight == 0.0f ? MapConst.DefaultCollesionHeight : collisionHeight; } } } @@ -833,7 +834,8 @@ namespace Game.Entities var defaultDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); var defaultModelData = CliDB.CreatureModelDataStorage.LookupByKey(defaultDisplayInfo.ModelID); - return scaleMod * defaultModelData.CollisionHeight; + float collisionHeight1 = scaleMod * defaultModelData.CollisionHeight * defaultModelData.ModelScale * defaultDisplayInfo.CreatureModelScale; + return collisionHeight1 == 0.0f ? MapConst.DefaultCollesionHeight : collisionHeight1; } public Guardian GetGuardianPet() @@ -1005,12 +1007,12 @@ namespace Game.Entities if (player != null) player.SetFallInformation(0, GetPositionZ()); - float height = pos.GetPositionZ(); + float height = pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(); MoveSplineInit init = new(this); // Creatures without inhabit type air should begin falling after exiting the vehicle - if (IsTypeId(TypeId.Unit) && !ToCreature().CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), ref height) + 0.1f) + if (IsTypeId(TypeId.Unit) && !ToCreature().CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight(), ref height)) init.SetFall(); init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); diff --git a/Source/Game/Maps/GridMap.cs b/Source/Game/Maps/GridMap.cs index afb990c27..10d5477e8 100644 --- a/Source/Game/Maps/GridMap.cs +++ b/Source/Game/Maps/GridMap.cs @@ -501,7 +501,7 @@ namespace Game.Maps } // Get water state on map - public ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint ReqLiquidType, LiquidData data) + public ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint ReqLiquidType, LiquidData data, float collisionHeight) { // Check water type (if no water return) if (_liquidGlobalFlags == 0 && _liquidFlags == null) @@ -568,7 +568,7 @@ namespace Game.Maps 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 ZLiquidStatus.NoWater; // All ok in water . store data @@ -583,7 +583,7 @@ namespace Game.Maps // For speed check as int values float delta = liquid_level - z; - if (delta > 2.0f) // Under water + if (delta > collisionHeight) // Under water return ZLiquidStatus.UnderWater; if (delta > 0.0f) // In water return ZLiquidStatus.InWater; diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index daba742e7..1b5737770 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -1694,23 +1694,23 @@ namespace Game.Maps return childMap != null && childMap.i_gridFileExists[(int)(gx * MapConst.MaxGrids + gy)]; } - public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z) + public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z, float collisionHeight = MapConst.DefaultCollesionHeight) { float ground = 0f; return GetWaterOrGroundLevel(phaseShift, x, y, z, ref ground); } - public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z, ref float ground, bool swim = false) + public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z, ref float ground, bool swim = false, float collisionHeight = MapConst.DefaultCollesionHeight) { if (GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y) != null) { // 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); ground = ground_z; LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status); + ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status, collisionHeight); switch (res) { case ZLiquidStatus.AboveWater: @@ -1734,8 +1734,7 @@ namespace Game.Maps if (gmap != null) { 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; } @@ -1743,8 +1742,7 @@ namespace Game.Maps if (checkVMap) { if (Global.VMapMgr.IsHeightCalcEnabled()) - vmapHeight = Global.VMapMgr.GetHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist); - // look from a bit higher pos to find the floor + vmapHeight = Global.VMapMgr.GetHeight(terrainMapId, x, y, z, maxSearchDist); } // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT @@ -1887,8 +1885,7 @@ namespace Game.Maps if (gmap != null) { 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 > check_z) return false; } return true; @@ -1975,13 +1972,12 @@ namespace Game.Maps return 0; } - public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, uint ReqLiquidType) + public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, uint ReqLiquidType, float collisionHeight = MapConst.DefaultCollesionHeight) { - LiquidData throwaway; - return GetLiquidStatus(phaseShift, x, y, z, ReqLiquidType, out throwaway); + return GetLiquidStatus(phaseShift, x, y, z, ReqLiquidType, out _, collisionHeight); } - public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, uint ReqLiquidType, out LiquidData data) + public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, uint ReqLiquidType, out LiquidData data, float collisionHeight = MapConst.DefaultCollesionHeight) { data = new LiquidData(); var result = ZLiquidStatus.NoWater; @@ -2037,7 +2033,7 @@ namespace Game.Maps float delta = liquid_level - z; // Get position delta - if (delta > 2.0f) // Under water + if (delta > collisionHeight) // Under water return ZLiquidStatus.UnderWater; if (delta > 0.0f) // In water return ZLiquidStatus.InWater; @@ -2051,7 +2047,7 @@ namespace Game.Maps if (gmap != null) { var map_data = new LiquidData(); - 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 != ZLiquidStatus.NoWater && (map_data.level > ground_level)) { @@ -2067,7 +2063,7 @@ namespace Game.Maps return result; } - public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, float x, float y, float z, PositionFullTerrainStatus data, uint reqLiquidType = MapConst.MapAllLiquidTypes) + public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, float x, float y, float z, PositionFullTerrainStatus data, uint reqLiquidType = MapConst.MapAllLiquidTypes, float collisionHeight = MapConst.DefaultCollesionHeight) { uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y); AreaAndLiquidData vmapData = Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType); @@ -2081,7 +2077,7 @@ namespace Game.Maps // area lookup AreaTableRecord areaEntry = null; - if (vmapData.areaInfo.HasValue && (z + 2.0f <= mapHeight || mapHeight <= vmapData.floorZ)) + if (vmapData.areaInfo.HasValue && (z <= mapHeight || mapHeight <= vmapData.floorZ)) { WMOAreaTableRecord wmoEntry = Global.DB2Mgr.GetWMOAreaTable(vmapData.areaInfo.Value.RootId, vmapData.areaInfo.Value.AdtId, vmapData.areaInfo.Value.GroupId); if (wmoEntry != null) @@ -2110,7 +2106,7 @@ namespace Game.Maps // liquid processing data.LiquidStatus = ZLiquidStatus.NoWater; - if (vmapData.liquidInfo.HasValue && vmapData.liquidInfo.Value.Level > vmapData.floorZ && z + 2.0f > vmapData.floorZ) + if (vmapData.liquidInfo.HasValue && vmapData.liquidInfo.Value.Level > vmapData.floorZ && z > vmapData.floorZ) { uint liquidType = vmapData.liquidInfo.Value.LiquidType; if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks @@ -2147,7 +2143,7 @@ namespace Game.Maps data.LiquidInfo.Set(liquidInfo); float delta = vmapData.liquidInfo.Value.Level - z; - if (delta > 2.0f) + if (delta > collisionHeight) data.LiquidStatus = ZLiquidStatus.UnderWater; else if (delta > 0.0f) data.LiquidStatus = ZLiquidStatus.InWater; @@ -2160,7 +2156,7 @@ namespace Game.Maps if (gmap != null && (data.LiquidStatus == ZLiquidStatus.AboveWater || data.LiquidStatus == ZLiquidStatus.NoWater)) { LiquidData gridMapLiquid = new(); - ZLiquidStatus gridMapStatus = gmap.GetLiquidStatus(x, y, z, reqLiquidType, gridMapLiquid); + ZLiquidStatus gridMapStatus = gmap.GetLiquidStatus(x, y, z, reqLiquidType, gridMapLiquid, collisionHeight); if (gridMapStatus != ZLiquidStatus.NoWater && (gridMapLiquid.level > vmapData.floorZ)) { if (GetId() == 530 && gridMapLiquid.entry == 2) diff --git a/Source/Game/Movement/Generators/FleeingGenerator.cs b/Source/Game/Movement/Generators/FleeingGenerator.cs index 23b9b5968..133c9253b 100644 --- a/Source/Game/Movement/Generators/FleeingGenerator.cs +++ b/Source/Game/Movement/Generators/FleeingGenerator.cs @@ -103,9 +103,7 @@ namespace Game.Movement GetPoint(owner, ref destination); // Add LOS check for target point - Position currentPosition = owner.GetPosition(); - bool isInLOS = Global.VMapMgr.IsInLineOfSight(PhasingHandler.GetTerrainMapId(owner.GetPhaseShift(), owner.GetMap(), currentPosition.posX, currentPosition.posY), currentPosition.posX, currentPosition.posY, currentPosition.posZ + 2.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 2.0f, ModelIgnoreFlags.Nothing); - if (!isInLOS) + if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ())) { _timer.Reset(200); return; diff --git a/Source/Game/Movement/Generators/PathGenerator.cs b/Source/Game/Movement/Generators/PathGenerator.cs index abade3fc9..ce7dabcf0 100644 --- a/Source/Game/Movement/Generators/PathGenerator.cs +++ b/Source/Game/Movement/Generators/PathGenerator.cs @@ -174,7 +174,7 @@ namespace Game.Movement // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint i = 0; i < _pathPoints.Length; ++i) { - ZLiquidStatus status = _sourceUnit.GetMap().GetLiquidStatus(_sourceUnit.GetPhaseShift(), _pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, MapConst.MapAllLiquidTypes); + ZLiquidStatus status = _sourceUnit.GetMap().GetLiquidStatus(_sourceUnit.GetPhaseShift(), _pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, MapConst.MapAllLiquidTypes, _sourceUnit.GetCollisionHeight()); // One of the points is not in the water, cancel movement. if (status == ZLiquidStatus.NoWater) { @@ -839,7 +839,7 @@ namespace Game.Movement NavTerrainFlag GetNavTerrain(float x, float y, float z) { LiquidData data; - ZLiquidStatus liquidStatus = _sourceUnit.GetMap().GetLiquidStatus(_sourceUnit.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out data); + ZLiquidStatus liquidStatus = _sourceUnit.GetMap().GetLiquidStatus(_sourceUnit.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out data, _sourceUnit.GetCollisionHeight()); if (liquidStatus == ZLiquidStatus.NoWater) return NavTerrainFlag.Ground; diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 849b10bd5..12b1ed8d6 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -382,7 +382,7 @@ namespace Game.Movement float moveTimeHalf = (float)(speedZ / gravity); float dist = 2 * moveTimeHalf * speedXY; _owner.GetNearPoint2D(out float x, out float y, dist, _owner.GetOrientation() + angle); - float z = _owner.GetPositionZ() + _owner.GetMidsectionHeight(); + float z = _owner.GetPositionZ(); _owner.UpdateAllowedPositionZ(x, y, ref z); MoveJump(x, y, z, 0.0f, speedXY, speedZ); } @@ -440,7 +440,7 @@ namespace Game.Movement 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.args.path[i] = point; } @@ -518,7 +518,7 @@ namespace Game.Movement public void MoveFall(uint 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, MapConst.MaxFallDistance); + float tz = _owner.GetMapHeight(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ(), true, MapConst.MaxFallDistance); if (tz <= MapConst.InvalidHeight) return; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 49ad4f122..15e12a96e 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -858,10 +858,10 @@ namespace Game.Spells float angle = (float)RandomHelper.NextDouble() * (MathFunctions.PI * 35.0f / 180.0f) - (float)(Math.PI * 17.5f / 180.0f); m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultPlayerBoundingRadius, dis, 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 = MapConst.VMAPInvalidHeightValue; LiquidData liquidData; - if (m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquidData) != 0) + if (m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquidData, m_caster.GetCollisionHeight()) != 0) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map.GetWaterOrGroundLevel returns ground level