Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fixes door monster LOS exploit & AOS House Gump NPE #2091

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 64 additions & 62 deletions Projects/Server/Maps/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -961,31 +961,28 @@ private Sector InternalGetSector(int x, int y)
return _invalidSector;
}

public bool LineOfSight(Point3D org, Point3D dest)
public bool LineOfSight(Point3D origin, Point3D destination)
{
if (this == Internal)
{
return false;
}

if (!Utility.InRange(org, dest, MaxLOSDistance))
if (!Utility.InRange(origin, destination, MaxLOSDistance))
{
return false;
}

var end = dest;

if (org.X > dest.X || org.X == dest.X && org.Y > dest.Y || org.X == dest.X && org.Y == dest.Y && org.Z > dest.Z)
if (origin.X > destination.X || origin.X == destination.X && origin.Y > destination.Y || origin.X == destination.X && origin.Y == destination.Y && origin.Z > destination.Z)
{
(org, dest) = (dest, org);
(origin, destination) = (destination, origin);
}

int height;
Point3D p;
var path = new Point3DList();
TileFlag flags;

if (org == dest)
if (origin == destination)
{
return true;
}
Expand All @@ -995,21 +992,21 @@ public bool LineOfSight(Point3D org, Point3D dest)
path.Clear();
}

var xd = dest.m_X - org.m_X;
var yd = dest.m_Y - org.m_Y;
var zd = dest.m_Z - org.m_Z;
var xd = destination.X - origin.X;
var yd = destination.Y - origin.Y;
var zd = destination.Z - origin.Z;
var zslp = Math.Sqrt(xd * xd + yd * yd);
var sq3d = zd != 0 ? Math.Sqrt(zslp * zslp + zd * zd) : zslp;

var rise = yd / sq3d;
var run = xd / sq3d;
zslp = zd / sq3d;

double y = org.m_Y;
double z = org.m_Z;
double x = org.m_X;
while (Utility.NumberBetween(x, dest.m_X, org.m_X, 0.5) && Utility.NumberBetween(y, dest.m_Y, org.m_Y, 0.5) &&
Utility.NumberBetween(z, dest.m_Z, org.m_Z, 0.5))
double y = origin.Y;
double z = origin.Z;
double x = origin.X;
while (Utility.NumberBetween(x, destination.X, origin.X, 0.5) && Utility.NumberBetween(y, destination.Y, origin.Y, 0.5) &&
Utility.NumberBetween(z, destination.Z, origin.Z, 0.5))
{
var ix = (int)Math.Round(x);
var iy = (int)Math.Round(y);
Expand All @@ -1018,7 +1015,7 @@ public bool LineOfSight(Point3D org, Point3D dest)
{
p = path.Last;

if (p.m_X != ix || p.m_Y != iy || p.m_Z != iz)
if (p.X != ix || p.Y != iy || p.Z != iz)
{
path.Add(ix, iy, iz);
}
Expand All @@ -1040,27 +1037,27 @@ public bool LineOfSight(Point3D org, Point3D dest)

p = path.Last;

if (p != dest)
if (p != destination)
{
path.Add(dest);
path.Add(destination);
}

Point3D pTop = org, pBottom = dest;
Point3D pTop = origin, pBottom = destination;
Utility.FixPoints(ref pTop, ref pBottom);

var pathCount = path.Count;
var endTop = end.m_Z + 1;
var endTop = destination.Z + 1;

for (var i = 0; i < pathCount; ++i)
{
var point = path[i];
var pointTop = point.m_Z + 1;
var pointTop = point.Z + 1;

var landTile = Tiles.GetLandTile(point.X, point.Y);
GetAverageZ(point.m_X, point.m_Y, out var landZ, out _, out var landTop);
GetAverageZ(point.X, point.Y, out var landZ, out _, out var landTop);

if (landZ <= pointTop && landTop >= point.m_Z &&
(point.m_X != end.m_X || point.m_Y != end.m_Y || landZ > endTop || landTop < end.m_Z) &&
(point.X != destination.X || point.Y != destination.Y || landZ > endTop || landTop < destination.Z) &&
!landTile.Ignored)
{
return false;
Expand All @@ -1082,22 +1079,22 @@ public bool LineOfSight(Point3D org, Point3D dest)

bool foundStatic = false;

foreach (var t in Tiles.GetStaticAndMultiTiles(point.m_X, point.m_Y))
foreach (var t in Tiles.GetStaticAndMultiTiles(point.X, point.Y))
{
foundStatic = true;

var id = TileData.ItemTable[t.ID & TileData.MaxItemValue];

flags = id.Flags;
height = id.CalcHeight;

if (t.Z <= pointTop && t.Z + height >= point.Z && (flags & (TileFlag.Window | TileFlag.NoShoot)) != 0)
if (
t.Z <= pointTop && t.Z + id.CalcHeight >= point.Z &&
(flags & (TileFlag.Window | TileFlag.NoShoot)) != 0 &&
(point.X != destination.X ||
point.Y != destination.Y ||
t.Z > endTop || t.Z + id.CalcHeight < destination.Z)
)
{
if (point.m_X == end.m_X && point.m_Y == end.m_Y && t.Z <= endTop && t.Z + height >= end.m_Z)
{
continue;
}

return false;
}
}
Expand All @@ -1120,57 +1117,62 @@ public bool LineOfSight(Point3D org, Point3D dest)
}
}

var rect = new Rectangle2D(pTop.m_X, pTop.m_Y, pBottom.m_X - pTop.m_X + 1, pBottom.m_Y - pTop.m_Y + 1);
var rect = new Rectangle2D(pTop.X, pTop.Y, pBottom.X - pTop.X + 1, pBottom.Y - pTop.Y + 1);

foreach (var i in GetItemsInBounds(rect))
foreach (var item in GetItemsInBounds(rect))
{
if (!i.Visible)
if (!item.Visible)
{
continue;
}

if (i is BaseMulti || i.ItemID > TileData.MaxItemValue)
if (item is BaseMulti || item.ItemID > TileData.MaxItemValue)
{
continue;
}

var id = i.ItemData;
var id = item.ItemData;
flags = id.Flags;

if ((flags & (TileFlag.Window | TileFlag.NoShoot)) == 0)
{
continue;
}

height = id.CalcHeight;

var found = false;

var count = path.Count;

for (var j = 0; j < count; ++j)
for (var i = 0; i < path.Count; ++i)
{
var point = path[j];
var pointTop = point.m_Z + 1;
var loc = i.Location;

// if (t.Z <= point.Z && t.Z+height >= point.Z && ( height != 0 || ( t.Z == dest.Z && zd != 0 ) ))
if (loc.m_X == point.m_X && loc.m_Y == point.m_Y && loc.m_Z <= pointTop && loc.m_Z + height >= point.m_Z)
var pathPoint = path[i];
var pointTop = pathPoint.Z + 1;
var itemLocation = item.Location;

if (
// Item is on same tile as this point along the LOS path
itemLocation.X == pathPoint.X &&
itemLocation.Y == pathPoint.Y &&
itemLocation.Z <= pointTop &&

// Item rests on the same level as the path
itemLocation.Z + id.CalcHeight >= pathPoint.Z &&

// Fix door bugging monsters when door is at the START or END of the LOS path by allowing LOS
!(flags.HasFlag(TileFlag.Door) &&
itemLocation.X == origin.X && itemLocation.Y == origin.Y ||
itemLocation.X == destination.X && itemLocation.Y == destination.Y) &&

// Item is at some point along the path BEFORE the target
(itemLocation.X != destination.X ||
itemLocation.Y != destination.Y ||

// Item is diagonally looking DOWN at the target
itemLocation.Z > endTop ||

// Item is diagonally looking UP at the target
itemLocation.Z + id.CalcHeight < destination.Z)
)
{
if (loc.m_X != end.m_X || loc.m_Y != end.m_Y || loc.m_Z > endTop || loc.m_Z + height < end.m_Z)
{
found = true;
break;
}
return false;
}
}

if (!found)
{
continue;
}

return false;
}

return true;
Expand Down
6 changes: 3 additions & 3 deletions Projects/UOContent/Gumps/Houses/HouseGumpAOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ public HouseGumpAOS(HouseGumpPageAOS page, Mobile from, BaseHouse house) : base(

AddImage(10, 10, 100);

if (m_House.Sign != null)
{
var lines = m_House.Sign.GetName().Wrap(10, 6);
var lines = m_House.Sign?.GetName().Wrap(10, 6);

if (lines != null)
{
for (int i = 0, y = (114 - lines.Count * 14) / 2; i < lines.Count; ++i, y += 14)
{
var s = lines[i];
Expand Down
Loading