Core/Entities: Fix some weird movement due to los issues

Port From (https://github.com/TrinityCore/TrinityCore/commit/446fc391f02d3ca8e1332b58f910a5b7d1c8e226)
This commit is contained in:
hondacrx
2021-04-16 16:14:43 -04:00
parent 76b09c2731
commit 17132dd6b6
12 changed files with 93 additions and 95 deletions
+2
View File
@@ -62,6 +62,8 @@ namespace Framework.Constants
public const float InvalidHeight = -100000.0f; public const float InvalidHeight = -100000.0f;
public const float MaxHeight = 100000.0f; public const float MaxHeight = 100000.0f;
public const float MaxFallDistance = 250000.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 MapMagic = 0x5350414D; //"MAPS";
public const uint MapVersionMagic = 0x392E3176; //"v1.9"; public const uint MapVersionMagic = 0x392E3176; //"v1.9";
+2 -2
View File
@@ -902,8 +902,8 @@ namespace Game.Chat
Global.DB2Mgr.Map2ZoneCoordinates((int)zoneId, ref zoneX, ref zoneY); Global.DB2Mgr.Map2ZoneCoordinates((int)zoneId, ref zoneX, ref zoneY);
Map map = obj.GetMap(); Map map = obj.GetMap();
float groundZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight); float groundZ = obj.GetMapHeight(obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight);
float floorZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ()); float floorZ = obj.GetMapHeight(obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ());
GridCoord gridCoord = GridDefines.ComputeGridCoord(obj.GetPositionX(), obj.GetPositionY()); GridCoord gridCoord = GridDefines.ComputeGridCoord(obj.GetPositionX(), obj.GetPositionY());
+1 -1
View File
@@ -115,7 +115,7 @@ namespace Game.Collision
public float GetHeight(float x, float y, float z, float maxSearchDist, PhaseShift phaseShift) 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)); Ray r = new(v, new Vector3(0, 0, -1));
DynamicTreeIntersectionCallback callback = new(phaseShift); DynamicTreeIntersectionCallback callback = new(phaseShift);
impl.IntersectZAllignedRay(r, callback, ref maxSearchDist); impl.IntersectZAllignedRay(r, callback, ref maxSearchDist);
+1 -1
View File
@@ -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) // 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(); 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()) if (GetCreatureTemplate().InhabitType.HasAnyFlag(InhabitType.Air) && isInAir && !IsFalling())
{ {
+53 -53
View File
@@ -1917,11 +1917,12 @@ namespace Game.Entities
{ {
if (IsInWorld) if (IsInWorld)
{ {
oz += GetCollisionHeight();
float x, y, z; float x, y, z;
if (IsTypeId(TypeId.Player)) if (IsTypeId(TypeId.Player))
{ {
GetPosition(out x, out y, out z); GetPosition(out x, out y, out z);
z += GetMidsectionHeight(); z += GetCollisionHeight();
} }
else else
GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z); GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z);
@@ -1937,21 +1938,30 @@ namespace Game.Entities
if (!IsInMap(obj)) if (!IsInMap(obj))
return false; return false;
float x, y, z; float ox, oy, oz;
if (obj.IsTypeId(TypeId.Player)) if (obj.IsTypeId(TypeId.Player))
{ {
obj.GetPosition(out x, out y, out z); obj.GetPosition(out ox, out oy, out oz);
z += GetMidsectionHeight(); oz += GetCollisionHeight();
} }
else 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) 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 vObj = new(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * Math.Min(dest.GetExactDist(GetPosition()), GetCombatReach()); 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) public void UpdateGroundPositionZ(float x, float y, ref float z)
{ {
float new_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); z = GetMapHeight(x, y, z);
if (new_z > MapConst.InvalidHeight)
z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
} }
public void UpdateAllowedPositionZ(float x, float y, ref float z) public void UpdateAllowedPositionZ(float x, float y, ref float z)
@@ -2098,8 +2106,8 @@ namespace Game.Entities
bool canSwim = ToCreature().CanSwim(); bool canSwim = ToCreature().CanSwim();
float ground_z = z; float ground_z = z;
float max_z = canSwim float max_z = canSwim
? GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk)) ? GetMapWaterOrGroundLevel(x, y, z, ref ground_z)
: ((ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true))); : (ground_z = GetMapHeight(x, y, z));
if (max_z > MapConst.InvalidHeight) if (max_z > MapConst.InvalidHeight)
{ {
if (z > max_z) if (z > max_z)
@@ -2110,7 +2118,7 @@ namespace Game.Entities
} }
else else
{ {
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); float ground_z = GetMapHeight(x, y, z);
if (z < ground_z) if (z < ground_z)
z = ground_z; z = ground_z;
} }
@@ -2122,7 +2130,7 @@ namespace Game.Entities
if (!ToPlayer().CanFly()) if (!ToPlayer().CanFly())
{ {
float ground_z = z; 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 (max_z > MapConst.InvalidHeight)
{ {
if (z > max_z) if (z > max_z)
@@ -2133,7 +2141,7 @@ namespace Game.Entities
} }
else else
{ {
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); float ground_z = GetMapHeight(x, y, z);
if (z < ground_z) if (z < ground_z)
z = ground_z; z = ground_z;
} }
@@ -2141,7 +2149,7 @@ namespace Game.Entities
} }
default: default:
{ {
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true); float ground_z = GetMapHeight(x, y, z);
if (ground_z > MapConst.InvalidHeight) if (ground_z > MapConst.InvalidHeight)
z = ground_z; z = ground_z;
break; break;
@@ -2202,7 +2210,7 @@ namespace Game.Entities
public Position GetNearPosition(float dist, float angle) public Position GetNearPosition(float dist, float angle)
{ {
var pos = GetPosition(); var pos = GetPosition();
MovePosition(ref pos, dist, angle); MovePosition(pos, dist, angle);
return pos; return pos;
} }
@@ -2216,7 +2224,7 @@ namespace Game.Entities
public Position GetRandomNearPosition(float radius) public Position GetRandomNearPosition(float radius)
{ {
var pos = GetPosition(); 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; return pos;
} }
@@ -2226,7 +2234,7 @@ namespace Game.Entities
GetNearPoint(obj, out x, out y, out z, obj.GetCombatReach(), distance2d, GetAngle(obj)); 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(); angle += GetOrientation();
float destx = pos.posX + dist * (float)Math.Cos(angle); float destx = pos.posX + dist * (float)Math.Cos(angle);
@@ -2239,8 +2247,8 @@ namespace Game.Entities
return; return;
} }
float ground = GetMap().GetHeight(GetPhaseShift(), destx, desty, MapConst.MaxHeight, true); float ground = GetMapHeight(destx, desty, MapConst.MaxHeight);
float floor = GetMap().GetHeight(GetPhaseShift(), destx, desty, pos.posZ, true); float floor = GetMapHeight(destx, desty, pos.posZ);
float destz = Math.Abs(ground - pos.posZ) <= Math.Abs(floor - pos.posZ) ? ground : floor; float destz = Math.Abs(ground - pos.posZ) <= Math.Abs(floor - pos.posZ) ? ground : floor;
float step = dist / 10.0f; float step = dist / 10.0f;
@@ -2270,37 +2278,12 @@ namespace Game.Entities
pos.SetOrientation(GetOrientation()); 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) public void MovePositionToFirstCollision(ref Position pos, float dist, float angle)
{ {
angle += GetOrientation(); angle += GetOrientation();
float destx = pos.posX + dist * (float)Math.Cos(angle); float destx = pos.posX + dist * (float)Math.Cos(angle);
float desty = pos.posY + dist * (float)Math.Sin(angle); float desty = pos.posY + dist * (float)Math.Sin(angle);
float destz = pos.posZ;
// Prevent invalid coordinates here, position is unchanged // Prevent invalid coordinates here, position is unchanged
if (!GridDefines.IsValidMapCoord(destx, desty)) if (!GridDefines.IsValidMapCoord(destx, desty))
@@ -2309,8 +2292,8 @@ namespace Game.Entities
return; return;
} }
float destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); UpdateAllowedPositionZ(destx, desty, ref destz);
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); 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 // collision occured
if (col) if (col)
@@ -2322,7 +2305,7 @@ namespace Game.Entities
} }
// check dynamic collision // 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 // Collided with a gameobject
if (col) if (col)
@@ -2341,7 +2324,7 @@ namespace Game.Entities
{ {
destx -= step * (float)Math.Cos(angle); destx -= step * (float)Math.Cos(angle);
desty -= step * (float)Math.Sin(angle); desty -= step * (float)Math.Sin(angle);
destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); UpdateAllowedPositionZ(destx, desty, ref destz);
} }
// we have correct destz now // we have correct destz now
else else
@@ -2353,7 +2336,7 @@ namespace Game.Entities
GridDefines.NormalizeMapCoord(ref pos.posX); GridDefines.NormalizeMapCoord(ref pos.posX);
GridDefines.NormalizeMapCoord(ref pos.posY); GridDefines.NormalizeMapCoord(ref pos.posY);
pos.posZ = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); UpdateAllowedPositionZ(destx, desty, ref pos.posZ);
pos.SetOrientation(GetOrientation()); pos.SetOrientation(GetOrientation());
} }
@@ -2361,7 +2344,24 @@ namespace Game.Entities
{ {
if (!IsInWorld) if (!IsInWorld)
return m_staticFloorZ; 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; } public void SetLocationInstanceId(uint _instanceId) { instanceId = _instanceId; }
+6 -4
View File
@@ -824,7 +824,8 @@ namespace Game.Entities
{ {
var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId());
var modelData = CliDB.CreatureModelDataStorage.LookupByKey(displayInfo.ModelID); 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 defaultDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId());
var defaultModelData = CliDB.CreatureModelDataStorage.LookupByKey(defaultDisplayInfo.ModelID); 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() public Guardian GetGuardianPet()
@@ -1005,12 +1007,12 @@ namespace Game.Entities
if (player != null) if (player != null)
player.SetFallInformation(0, GetPositionZ()); player.SetFallInformation(0, GetPositionZ());
float height = pos.GetPositionZ(); float height = pos.GetPositionZ() + vehicle.GetBase().GetCollisionHeight();
MoveSplineInit init = new(this); MoveSplineInit init = new(this);
// Creatures without inhabit type air should begin falling after exiting the vehicle // 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.SetFall();
init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false);
+3 -3
View File
@@ -501,7 +501,7 @@ namespace Game.Maps
} }
// Get water state on map // 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) // Check water type (if no water return)
if (_liquidGlobalFlags == 0 && _liquidFlags == null) if (_liquidGlobalFlags == 0 && _liquidFlags == null)
@@ -568,7 +568,7 @@ namespace Game.Maps
float ground_level = GetHeight(x, y); float ground_level = GetHeight(x, y);
// Check water level and ground level // 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; return ZLiquidStatus.NoWater;
// All ok in water . store data // All ok in water . store data
@@ -583,7 +583,7 @@ namespace Game.Maps
// For speed check as int values // For speed check as int values
float delta = liquid_level - z; float delta = liquid_level - z;
if (delta > 2.0f) // Under water if (delta > collisionHeight) // Under water
return ZLiquidStatus.UnderWater; return ZLiquidStatus.UnderWater;
if (delta > 0.0f) // In water if (delta > 0.0f) // In water
return ZLiquidStatus.InWater; return ZLiquidStatus.InWater;
+17 -21
View File
@@ -1694,23 +1694,23 @@ namespace Game.Maps
return childMap != null && childMap.i_gridFileExists[(int)(gx * MapConst.MaxGrids + gy)]; 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; float ground = 0f;
return GetWaterOrGroundLevel(phaseShift, x, y, z, ref ground); 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) 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 // 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; ground = ground_z;
LiquidData liquid_status; 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) switch (res)
{ {
case ZLiquidStatus.AboveWater: case ZLiquidStatus.AboveWater:
@@ -1734,8 +1734,7 @@ namespace Game.Maps
if (gmap != null) if (gmap != null)
{ {
float gridHeight = gmap.GetHeight(x, y); float gridHeight = gmap.GetHeight(x, y);
// look from a bit higher pos to find the floor, ignore under surface case if (z > gridHeight)
if (z + 2.0f > gridHeight)
mapHeight = gridHeight; mapHeight = gridHeight;
} }
@@ -1743,8 +1742,7 @@ namespace Game.Maps
if (checkVMap) if (checkVMap)
{ {
if (Global.VMapMgr.IsHeightCalcEnabled()) if (Global.VMapMgr.IsHeightCalcEnabled())
vmapHeight = Global.VMapMgr.GetHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist); vmapHeight = Global.VMapMgr.GetHeight(terrainMapId, x, y, z, maxSearchDist);
// look from a bit higher pos to find the floor
} }
// mapHeight set for any above raw ground Z or <= INVALID_HEIGHT // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
@@ -1887,8 +1885,7 @@ namespace Game.Maps
if (gmap != null) if (gmap != null)
{ {
float mapHeight = gmap.GetHeight(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 > mapHeight && mapHeight > check_z)
if (z + 2.0f > mapHeight && mapHeight > check_z)
return false; return false;
} }
return true; return true;
@@ -1975,13 +1972,12 @@ namespace Game.Maps
return 0; 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 _, collisionHeight);
return GetLiquidStatus(phaseShift, x, y, z, ReqLiquidType, out throwaway);
} }
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(); data = new LiquidData();
var result = ZLiquidStatus.NoWater; var result = ZLiquidStatus.NoWater;
@@ -2037,7 +2033,7 @@ namespace Game.Maps
float delta = liquid_level - z; float delta = liquid_level - z;
// Get position delta // Get position delta
if (delta > 2.0f) // Under water if (delta > collisionHeight) // Under water
return ZLiquidStatus.UnderWater; return ZLiquidStatus.UnderWater;
if (delta > 0.0f) // In water if (delta > 0.0f) // In water
return ZLiquidStatus.InWater; return ZLiquidStatus.InWater;
@@ -2051,7 +2047,7 @@ namespace Game.Maps
if (gmap != null) if (gmap != null)
{ {
var map_data = new LiquidData(); 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: // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
if (map_result != ZLiquidStatus.NoWater && (map_data.level > ground_level)) if (map_result != ZLiquidStatus.NoWater && (map_data.level > ground_level))
{ {
@@ -2067,7 +2063,7 @@ namespace Game.Maps
return result; 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); uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
AreaAndLiquidData vmapData = Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType); AreaAndLiquidData vmapData = Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType);
@@ -2081,7 +2077,7 @@ namespace Game.Maps
// area lookup // area lookup
AreaTableRecord areaEntry = null; 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); WMOAreaTableRecord wmoEntry = Global.DB2Mgr.GetWMOAreaTable(vmapData.areaInfo.Value.RootId, vmapData.areaInfo.Value.AdtId, vmapData.areaInfo.Value.GroupId);
if (wmoEntry != null) if (wmoEntry != null)
@@ -2110,7 +2106,7 @@ namespace Game.Maps
// liquid processing // liquid processing
data.LiquidStatus = ZLiquidStatus.NoWater; 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; uint liquidType = vmapData.liquidInfo.Value.LiquidType;
if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks
@@ -2147,7 +2143,7 @@ namespace Game.Maps
data.LiquidInfo.Set(liquidInfo); data.LiquidInfo.Set(liquidInfo);
float delta = vmapData.liquidInfo.Value.Level - z; float delta = vmapData.liquidInfo.Value.Level - z;
if (delta > 2.0f) if (delta > collisionHeight)
data.LiquidStatus = ZLiquidStatus.UnderWater; data.LiquidStatus = ZLiquidStatus.UnderWater;
else if (delta > 0.0f) else if (delta > 0.0f)
data.LiquidStatus = ZLiquidStatus.InWater; data.LiquidStatus = ZLiquidStatus.InWater;
@@ -2160,7 +2156,7 @@ namespace Game.Maps
if (gmap != null && (data.LiquidStatus == ZLiquidStatus.AboveWater || data.LiquidStatus == ZLiquidStatus.NoWater)) if (gmap != null && (data.LiquidStatus == ZLiquidStatus.AboveWater || data.LiquidStatus == ZLiquidStatus.NoWater))
{ {
LiquidData gridMapLiquid = new(); 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 (gridMapStatus != ZLiquidStatus.NoWater && (gridMapLiquid.level > vmapData.floorZ))
{ {
if (GetId() == 530 && gridMapLiquid.entry == 2) if (GetId() == 530 && gridMapLiquid.entry == 2)
@@ -103,9 +103,7 @@ namespace Game.Movement
GetPoint(owner, ref destination); GetPoint(owner, ref destination);
// Add LOS check for target point // Add LOS check for target point
Position currentPosition = owner.GetPosition(); if (!owner.IsWithinLOS(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()))
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)
{ {
_timer.Reset(200); _timer.Reset(200);
return; return;
@@ -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 // 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) 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. // One of the points is not in the water, cancel movement.
if (status == ZLiquidStatus.NoWater) if (status == ZLiquidStatus.NoWater)
{ {
@@ -839,7 +839,7 @@ namespace Game.Movement
NavTerrainFlag GetNavTerrain(float x, float y, float z) NavTerrainFlag GetNavTerrain(float x, float y, float z)
{ {
LiquidData data; 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) if (liquidStatus == ZLiquidStatus.NoWater)
return NavTerrainFlag.Ground; return NavTerrainFlag.Ground;
+3 -3
View File
@@ -382,7 +382,7 @@ namespace Game.Movement
float moveTimeHalf = (float)(speedZ / gravity); float moveTimeHalf = (float)(speedZ / gravity);
float dist = 2 * moveTimeHalf * speedXY; float dist = 2 * moveTimeHalf * speedXY;
_owner.GetNearPoint2D(out float x, out float y, dist, _owner.GetOrientation() + angle); _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); _owner.UpdateAllowedPositionZ(x, y, ref z);
MoveJump(x, y, z, 0.0f, speedXY, speedZ); MoveJump(x, y, z, 0.0f, speedXY, speedZ);
} }
@@ -440,7 +440,7 @@ namespace Game.Movement
if (_owner.IsFlying()) if (_owner.IsFlying())
point.Z = z; point.Z = z;
else 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; init.args.path[i] = point;
} }
@@ -518,7 +518,7 @@ namespace Game.Movement
public void MoveFall(uint id = 0) public void MoveFall(uint id = 0)
{ {
// use larger distance for vmap height search than in most other cases // 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) if (tz <= MapConst.InvalidHeight)
return; return;
+2 -2
View File
@@ -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); 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); 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; float liquidLevel = MapConst.VMAPInvalidHeightValue;
LiquidData liquidData; 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; liquidLevel = liquidData.level;
if (liquidLevel <= ground) // When there is no liquid Map.GetWaterOrGroundLevel returns ground level if (liquidLevel <= ground) // When there is no liquid Map.GetWaterOrGroundLevel returns ground level