private unsafe LandTile[] ReadLandBlock(int x, int y) { try { int offset = ((x * m_BlockHeight) + y) * 196 + 4; if (m_MapIndex != null) { offset = m_MapIndex.Lookup(offset); } m_Map.Seek(offset, SeekOrigin.Begin); LandTile[] tiles = new LandTile[64]; fixed(LandTile *pTiles = tiles) { NativeReader.Read(m_Map.SafeFileHandle.DangerousGetHandle(), pTiles, 192); } return(tiles); } catch { if (DateTime.UtcNow >= m_NextLandWarning) { Console.WriteLine("Warning: Land EOS for {0} ({1}, {2})", m_Owner, x, y); m_NextLandWarning = DateTime.UtcNow + TimeSpan.FromMinutes(1.0); } return(m_InvalidLandBlock); } }
private static bool GetFloorZ(Map map, int x, int y, out int z) { LandTile lt = map.Tiles.GetLandTile(x, y); if (IsFloor(lt.ID) && map.CanFit(x, y, lt.Z, 16, false, false)) { z = lt.Z; return(true); } StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y); for (int i = 0; i < tiles.Length; ++i) { StaticTile t = tiles[i]; ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; if (IsStaticFloor(t.ID) && map.CanFit(x, y, t.Z + (id.Surface ? id.CalcHeight : 0), 16, false, false)) { z = t.Z + (id.Surface ? id.CalcHeight : 0); return(true); } } z = 0; return(false); }
private unsafe LandTile[] ReadLandBlock(int x, int y) { try { m_Map.Seek(((x * m_BlockHeight) + y) * 196 + 4, SeekOrigin.Begin); LandTile[] tiles = new LandTile[64]; fixed(LandTile *pTiles = tiles) { #if !MONO NativeReader.Read(m_Map.SafeFileHandle.DangerousGetHandle(), pTiles, 192); #else NativeReader.Read(m_Map.Handle, pTiles, 192); #endif } return(tiles); } catch { if (DateTime.Now >= m_NextLandWarning) { Console.WriteLine("Warning: Land EOS for {0} ({1}, {2})", m_Owner, x, y); m_NextLandWarning = DateTime.Now + TimeSpan.FromMinutes(1.0); } return(m_InvalidLandBlock); } }
private unsafe int PatchLand(TileMatrix matrix, string dataPath, string indexPath) { using (FileStream fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (FileStream fsIndex = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { BinaryReader indexReader = new BinaryReader(fsIndex); int count = (int)(indexReader.BaseStream.Length / 4); for (int i = 0; i < count; ++i) { int blockID = indexReader.ReadInt32(); int x = blockID / matrix.BlockHeight; int y = blockID % matrix.BlockHeight; fsData.Seek(4, SeekOrigin.Current); var tiles = new LandTile[64]; fixed(LandTile *pTiles = tiles) { NativeReader.Read(fsData.SafeFileHandle.DangerousGetHandle(), pTiles, 192); } matrix.SetLandBlock(x, y, tiles); } indexReader.Close(); return(count); } } }
public LandTile[] GetLandBlock(int x, int y) { if (x < 0 || y < 0 || x >= m_BlockWidth || y >= m_BlockHeight || m_Map == null) { return(m_InvalidLandBlock); } if (m_LandTiles[x] == null) { m_LandTiles[x] = new LandTile[m_BlockHeight][]; } var tiles = m_LandTiles[x][y]; if (tiles == null) { lock (m_FileShare) { for (int i = 0; tiles == null && i < m_FileShare.Count; ++i) { TileMatrix shared = m_FileShare[i]; lock (shared) { if (x >= 0 && x < shared.m_BlockWidth && y >= 0 && y < shared.m_BlockHeight) { var theirTiles = shared.m_LandTiles[x]; if (theirTiles != null) { tiles = theirTiles[y]; } if (tiles != null) { var theirBits = shared.m_LandPatches[x]; if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0) { tiles = null; } } } } } } if (tiles == null) { tiles = ReadLandBlock(x, y); } m_LandTiles[x][y] = tiles; } return(tiles); }
public void SetLandBlock(int x, int y, LandTile[] value) { if (x < 0 || y < 0 || x >= m_BlockWidth || y >= m_BlockHeight) { return; } if (m_LandTiles[x] == null) { m_LandTiles[x] = new LandTile[m_BlockHeight][]; } m_LandTiles[x][y] = value; if (m_LandPatches[x] == null) { m_LandPatches[x] = new int[(m_BlockHeight + 31) >> 5]; } m_LandPatches[x][y >> 5] |= 1 << (y & 0x1F); }
private unsafe int PatchLand(TileMatrix matrix, string dataPath, string indexPath) { using (FileStream fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (FileStream fsIndex = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { BinaryReader indexReader = new BinaryReader(fsIndex); int count = (int)(indexReader.BaseStream.Length / 4); for (int i = 0; i < count; ++i) { int blockID = indexReader.ReadInt32(); int x = blockID / matrix.BlockHeight; int y = blockID % matrix.BlockHeight; fsData.Seek(4, SeekOrigin.Current); var tiles = new LandTile[64]; fixed (LandTile* pTiles = tiles) { #if !MONO NativeReader.Read(fsData.SafeFileHandle.DangerousGetHandle(), pTiles, 192); #else NativeReader.Read( fsData.Handle, pTiles, 192 ); #endif } matrix.SetLandBlock(x, y, tiles); } indexReader.Close(); return count; } } }
private unsafe int PatchLand(TileMatrix matrix, string dataPath, string indexPath) { using var fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read); using var fsIndex = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read); var indexReader = new BinaryReader(fsIndex); var count = (int)(indexReader.BaseStream.Length / 4); for (var i = 0; i < count; ++i) { var blockID = indexReader.ReadInt32(); var x = blockID / matrix.BlockHeight; var y = blockID % matrix.BlockHeight; fsData.Seek(4, SeekOrigin.Current); var tiles = new LandTile[64]; fixed(LandTile *pTiles = tiles) { var ptr = fsData.SafeFileHandle?.DangerousGetHandle(); if (ptr == null) { throw new Exception($"Cannot open {fsData.Name}"); } NativeReader.Read(ptr.Value, pTiles, 192); } matrix.SetLandBlock(x, y, tiles); } indexReader.Close(); return(count); }
private static bool IsFloor(Map map, int x, int y, bool canFit) { LandTile lt = map.Tiles.GetLandTile(x, y); if (IsFloor(lt.ID) && (canFit || CanFit(map, x, y, lt.Z))) { return(true); } StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y); for (int i = 0; i < tiles.Length; ++i) { StaticTile t = tiles[i]; ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; if (IsStaticFloor(t.ID) && (canFit || CanFit(map, x, y, t.Z + (id.Surface ? id.CalcHeight : 0)))) { return(true); } } return(false); }
public void SetLandBlock( int x, int y, LandTile[] value ) { if ( x < 0 || y < 0 || x >= m_BlockWidth || y >= m_BlockHeight ) return; if ( m_LandTiles[x] == null ) m_LandTiles[x] = new LandTile[m_BlockHeight][]; m_LandTiles[x][y] = value; if ( m_LandPatches[x] == null ) m_LandPatches[x] = new int[(m_BlockHeight + 31) >> 5]; m_LandPatches[x][y >> 5] |= 1 << (y & 0x1F); }
private static bool CanFit(Map map, int x, int y, int z) { bool hasSurface = false; LandTile lt = map.Tiles.GetLandTile(x, y); int lowZ = 0, avgZ = 0, topZ = 0; map.GetAverageZ(x, y, ref lowZ, ref avgZ, ref topZ); TileFlag landFlags = TileData.LandTable[lt.ID & TileData.MaxLandValue].Flags; if ((landFlags & TileFlag.Impassable) != 0 && topZ > z && (z + 16) > lowZ) { return(false); } else if ((landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored) { hasSurface = true; } StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y); bool surface, impassable; for (int i = 0; i < staticTiles.Length; ++i) { if (IsDisplayCase(staticTiles[i].ID)) { continue; } ItemData id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue]; surface = id.Surface; impassable = id.Impassable; if ((surface || impassable) && (staticTiles[i].Z + id.CalcHeight) > z && (z + 16) > staticTiles[i].Z) { return(false); } else if (surface && !impassable && z == (staticTiles[i].Z + id.CalcHeight)) { hasSurface = true; } } Sector sector = map.GetSector(x, y); List <Item> items = sector.Items; for (int i = 0; i < items.Count; ++i) { Item item = items[i]; if (item.AtWorldPoint(x, y)) { ItemData id = item.ItemData; surface = id.Surface; impassable = id.Impassable; if ((surface || impassable) && (item.Z + id.CalcHeight) > z && (z + 16) > item.Z) { return(false); } else if (surface && !impassable && z == (item.Z + id.CalcHeight)) { hasSurface = true; } } } return(hasSurface); }
private IEnumerable <Point3D> Compute(Rectangle3D area) { // Check all corners to skip large bodies of water. for (var index = 0; index < Filters.Length; index++) { var filter = Filters[index]; if (Equals(filter, TileFlag.Wet)) { LandTile land1 = Facet.Tiles.GetLandTile(area.Start.X, area.Start.Y); // TL LandTile land2 = Facet.Tiles.GetLandTile(area.End.X, area.Start.Y); // TR LandTile land3 = Facet.Tiles.GetLandTile(area.Start.X, area.End.Y); // BL LandTile land4 = Facet.Tiles.GetLandTile(area.End.X, area.End.Y); // BR bool ignore1 = land1.Ignored || TileData.LandTable[land1.ID].Flags.HasFlag(TileFlag.Wet); bool ignore2 = land2.Ignored || TileData.LandTable[land2.ID].Flags.HasFlag(TileFlag.Wet); bool ignore3 = land3.Ignored || TileData.LandTable[land3.ID].Flags.HasFlag(TileFlag.Wet); bool ignore4 = land4.Ignored || TileData.LandTable[land4.ID].Flags.HasFlag(TileFlag.Wet); if (ignore1 && ignore2 && ignore3 && ignore4) { yield break; } break; } } Point3D p = Point3D.Zero; for (p.X = area.Start.X; p.X <= area.End.X; p.X++) { for (p.Y = area.Start.Y; p.Y <= area.End.Y; p.Y++) { LandTile land = Facet.Tiles.GetLandTile(p.X, p.Y); p.Z = land.Z; if (Contains(p)) { continue; } if (!CanSpawn(p.X, p.Y, p.Z)) { continue; } if (Filters.Length > 0) { if (land.Ignored) { continue; } TileFlag flags = TileData.LandTable[land.ID].Flags; bool any1 = false; for (var index = 0; index < Filters.Length; index++) { var f = Filters[index]; if (flags.HasFlag(f)) { any1 = true; break; } } if (any1) { continue; } bool valid = true; var tiles = Facet.Tiles.GetStaticTiles(p.X, p.Y); for (var index = 0; index < tiles.Length; index++) { StaticTile tile = tiles[index]; flags = TileData.ItemTable[tile.ID].Flags; bool any2 = false; for (var i = 0; i < Filters.Length; i++) { var f = Filters[i]; if (flags.HasFlag(f)) { any2 = true; break; } } if (any2) { valid = false; break; } } if (!valid) { continue; } } if (Validator != null && !Validator(Facet, p.X, p.Y, p.Z)) { continue; } yield return(p); } } }
//-------------------------------------------------------------------------- // Determine whether or not a tile is an 'invalid' one. These are the black // tiles that sepearate the spaces between dungeons--they are intrinsically // impassable, block everything. //-------------------------------------------------------------------------- private bool IsInvalidLandTile( LandTile tile ) { int id = tile.ID; int[] invalidLandTiles = Map.InvalidLandTiles; for ( int i = 0; i < invalidLandTiles.Length; i++ ) if( id == invalidLandTiles[i] ) return true; return false; }
//-------------------------------------------------------------------------- // Does the land block my vision? //-------------------------------------------------------------------------- public bool LandBlocksVis( LandTile landTile, int x, int y, int eyelevel, Point3D beholder ) { if( !Config.GetInstance().Mountain( landTile.ID ) ) { return false; } //ItemData data = TileData.ItemTable[landTile.ID]; int minZ = 0, avgZ = 0, maxZ = 0; m_map.GetAverageZ( x, y, ref minZ, ref avgZ, ref maxZ ); if ( minZ <= eyelevel // for caves && maxZ >= eyelevel && !landTile.Ignored ) { return true; } return false; }
//-------------------------------------------------------------------------- // Is this an invalid tile which also blocks vix? //-------------------------------------------------------------------------- public bool IsVizBlockingInvalidLand( LandTile landTile, StaticTile[] staticTiles, int x, int y ) { if( IsInvalidLandTile( landTile ) ) { if( staticTiles.Length == 0 ) { if( !ContainsVisibleItem( x, y ) ) { return true; } } } return false; }
public bool IsSeaTile(LandTile t) { return t.Z == -5 && ((t.ID >= 0xA8 && t.ID <= 0xAB) || (t.ID >= 0x136 && t.ID <= 0x137)); }
private void Compute(Rectangle3D area) { // Check all corners to skip large bodies of water. if (Filters.Contains(TileFlag.Wet)) { LandTile land1 = Facet.Tiles.GetLandTile(area.Start.X, area.Start.Y); // TL LandTile land2 = Facet.Tiles.GetLandTile(area.End.X, area.Start.Y); // TR LandTile land3 = Facet.Tiles.GetLandTile(area.Start.X, area.End.Y); // BL LandTile land4 = Facet.Tiles.GetLandTile(area.End.X, area.End.Y); // BR if ((land1.Ignored || TileData.LandTable[land1.ID].Flags.HasFlag(TileFlag.Wet)) && (land2.Ignored || TileData.LandTable[land2.ID].Flags.HasFlag(TileFlag.Wet)) && (land3.Ignored || TileData.LandTable[land3.ID].Flags.HasFlag(TileFlag.Wet)) && (land4.Ignored || TileData.LandTable[land4.ID].Flags.HasFlag(TileFlag.Wet))) { return; } } int x, y, z, h; for (x = area.Start.X; x < area.End.X; x++) { for (y = area.Start.Y; y < area.End.Y; y++) { h = GetHashCode(x, y); if (_Points.ContainsKey(h)) { continue; } z = Facet.Tiles.GetLandTile(x, y).Z;//.GetAverageZ(x, y); if (!CanSpawn(x, y, z)) { continue; } if (Filters.Length > 0) { LandTile land = Facet.Tiles.GetLandTile(x, y); if (land.Ignored) { continue; } TileFlag flags = TileData.LandTable[land.ID].Flags; if (Filters.Any(f => flags.HasFlag(f))) { continue; } bool valid = true; foreach (StaticTile tile in Facet.Tiles.GetStaticTiles(x, y)) { flags = TileData.ItemTable[tile.ID].Flags; if (Filters.Any(f => flags.HasFlag(f))) { valid = false; break; } } if (!valid) { continue; } } if (Validator != null && !Validator(Facet, x, y, z)) { continue; } lock (_Points) { _Points[h] = new Point3D(x, y, z); } } } }
private unsafe LandTile[] ReadLandBlock( int x, int y ) { try { m_Map.Seek( ((x * m_BlockHeight) + y) * 196 + 4, SeekOrigin.Begin ); LandTile[] tiles = new LandTile[64]; fixed ( LandTile *pTiles = tiles ) { #if !MONO NativeReader.Read( m_Map.SafeFileHandle.DangerousGetHandle(), pTiles, 192 ); #else NativeReader.Read( m_Map.Handle, pTiles, 192 ); #endif } return tiles; } catch { if ( DateTime.Now >= m_NextLandWarning ) { Console.WriteLine( "Warning: Land EOS for {0} ({1}, {2})", m_Owner, x, y ); m_NextLandWarning = DateTime.Now + TimeSpan.FromMinutes( 1.0 ); } return m_InvalidLandBlock; } }
public static bool IsWater(this LandTile tile) { return(LandWaterTiles.Contains(tile.ID) || TileData.LandTable[tile.ID].Flags.HasFlag(TileFlag.Wet) || Insensitive.Contains(TileData.LandTable[tile.ID].Name, "water")); }
/* This could be probably be re-implemented if necessary (perhaps via an ITile interface?). public List<Tile> GetTilesAt( Point2D p, bool items, bool land, bool statics ) { List<Tile> list = new List<Tile>(); if ( this == Map.Internal ) return list; if ( land ) list.Add( Tiles.GetLandTile( p.m_X, p.m_Y ) ); if ( statics ) list.AddRange( Tiles.GetStaticTiles( p.m_X, p.m_Y, true ) ); if ( items ) { Sector sector = GetSector( p ); foreach ( Item item in sector.Items ) if ( item.AtWorldPoint( p.m_X, p.m_Y ) ) list.Add( new StaticTile( (ushort)item.ItemID, (sbyte) item.Z ) ); } return list; } */ /// <summary> /// Gets the highest surface that is lower than <paramref name="p"/>. /// </summary> /// <param name="p">The reference point.</param> /// <returns>A surface <typeparamref name="Tile"/> or <typeparamref name="Item"/>.</returns> public object GetTopSurface( Point3D p ) { if ( this == Map.Internal ) return null; object surface = null; int surfaceZ = int.MinValue; LandTile lt = Tiles.GetLandTile( p.X, p.Y ); if ( !lt.Ignored ) { int avgZ = GetAverageZ( p.X, p.Y ); if ( avgZ <= p.Z ) { surface = lt; surfaceZ = avgZ; if ( surfaceZ == p.Z ) return surface; } } StaticTile[] staticTiles = Tiles.GetStaticTiles( p.X, p.Y, true ); for ( int i = 0; i < staticTiles.Length; i++ ) { StaticTile tile = staticTiles[i]; ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; if ( id.Surface || ( id.Flags & TileFlag.Wet ) != 0 ) { int tileZ = tile.Z + id.CalcHeight; if ( tileZ > surfaceZ && tileZ <= p.Z ) { surface = tile; surfaceZ = tileZ; if ( surfaceZ == p.Z ) return surface; } } } Sector sector = GetSector( p.X, p.Y ); for ( int i = 0; i < sector.Items.Count; i++ ) { Item item = sector.Items[i]; if ( !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue && item.AtWorldPoint( p.X, p.Y ) && !item.Movable ) { ItemData id = item.ItemData; if ( id.Surface || ( id.Flags & TileFlag.Wet ) != 0 ) { int itemZ = item.Z + id.CalcHeight; if ( itemZ > surfaceZ && itemZ <= p.Z ) { surface = item; surfaceZ = itemZ; if ( surfaceZ == p.Z ) return surface; } } } } return surface; }
public void FixColumn( int x, int y ) { LandTile landTile = Tiles.GetLandTile( x, y ); int landZ = 0, landAvg = 0, landTop = 0; GetAverageZ( x, y, ref landZ, ref landAvg, ref landTop ); StaticTile[] tiles = Tiles.GetStaticTiles( x, y, true ); List<Item> items = new List<Item>(); IPooledEnumerable eable = GetItemsInRange( new Point3D( x, y, 0 ), 0 ); foreach ( Item item in eable ) { if ( !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue ) { items.Add( item ); if ( items.Count > 100 ) break; } } eable.Free(); if ( items.Count > 100 ) return; items.Sort( ZComparer.Default ); for ( int i = 0; i < items.Count; ++i ) { Item toFix = items[i]; if ( !toFix.Movable ) continue; int z = int.MinValue; int currentZ = toFix.Z; if ( !landTile.Ignored && landAvg <= currentZ ) z = landAvg; for ( int j = 0; j < tiles.Length; ++j ) { StaticTile tile = tiles[j]; ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; int checkZ = tile.Z; int checkTop = checkZ + id.CalcHeight; if ( checkTop == checkZ && !id.Surface ) ++checkTop; if ( checkTop > z && checkTop <= currentZ ) z = checkTop; } for ( int j = 0; j < items.Count; ++j ) { if ( j == i ) continue; Item item = items[j]; ItemData id = item.ItemData; int checkZ = item.Z; int checkTop = checkZ + id.CalcHeight; if ( checkTop == checkZ && !id.Surface ) ++checkTop; if ( checkTop > z && checkTop <= currentZ ) z = checkTop; } if ( z != int.MinValue ) toFix.Location = new Point3D( toFix.X, toFix.Y, z ); } }
public bool CanFit( int x, int y, int z, int height, bool checkBlocksFit, bool checkMobiles, bool requireSurface ) { if ( this == Map.Internal ) return false; if ( x < 0 || y < 0 || x >= m_Width || y >= m_Height ) return false; bool hasSurface = false; LandTile lt = Tiles.GetLandTile( x, y ); int lowZ = 0, avgZ = 0, topZ = 0; GetAverageZ( x, y, ref lowZ, ref avgZ, ref topZ ); TileFlag landFlags = TileData.LandTable[lt.ID & TileData.MaxLandValue].Flags; if ( ( landFlags & TileFlag.Impassable ) != 0 && avgZ > z && ( z + height ) > lowZ ) return false; else if ( ( landFlags & TileFlag.Impassable ) == 0 && z == avgZ && !lt.Ignored ) hasSurface = true; StaticTile[] staticTiles = Tiles.GetStaticTiles( x, y, true ); bool surface, impassable; for ( int i = 0; i < staticTiles.Length; ++i ) { ItemData id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue]; surface = id.Surface; impassable = id.Impassable; if ( ( surface || impassable ) && ( staticTiles[i].Z + id.CalcHeight ) > z && ( z + height ) > staticTiles[i].Z ) return false; else if ( surface && !impassable && z == ( staticTiles[i].Z + id.CalcHeight ) ) hasSurface = true; } Sector sector = GetSector( x, y ); List<Item> items = sector.Items; List<Mobile> mobs = sector.Mobiles; for ( int i = 0; i < items.Count; ++i ) { Item item = items[i]; if ( !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue && item.AtWorldPoint( x, y ) ) { ItemData id = item.ItemData; surface = id.Surface; impassable = id.Impassable; if ( ( surface || impassable || ( checkBlocksFit && item.BlocksFit ) ) && ( item.Z + id.CalcHeight ) > z && ( z + height ) > item.Z ) return false; else if ( surface && !impassable && !item.Movable && z == ( item.Z + id.CalcHeight ) ) hasSurface = true; } } if ( checkMobiles ) { for ( int i = 0; i < mobs.Count; ++i ) { Mobile m = mobs[i]; if ( m.Location.m_X == x && m.Location.m_Y == y && ( m.AccessLevel == AccessLevel.Player || !m.Hidden ) ) if ( ( m.Z + 16 ) > z && ( z + height ) > m.Z ) return false; } } return !requireSurface || hasSurface; }
public bool LineOfSight( Point3D org, Point3D dest ) { if( this == Map.Internal ) return false; if( !Utility.InRange( org, dest, m_MaxLOSDistance ) ) return false; Point3D start = org; Point3D 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) ) { Point3D swap = org; org = dest; dest = swap; } double rise, run, zslp; double sq3d; double x, y, z; int xd, yd, zd; int ix, iy, iz; int height; bool found; Point3D p; Point3DList path = m_PathList; TileFlag flags; if( org == dest ) return true; if( path.Count > 0 ) path.Clear(); xd = dest.m_X - org.m_X; yd = dest.m_Y - org.m_Y; zd = dest.m_Z - org.m_Z; zslp = Math.Sqrt( xd * xd + yd * yd ); if( zd != 0 ) sq3d = Math.Sqrt( zslp * zslp + zd * zd ); else sq3d = zslp; rise = ((float)yd) / sq3d; run = ((float)xd) / sq3d; zslp = ((float)zd) / sq3d; y = org.m_Y; z = org.m_Z; 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 ) ) { ix = (int)Math.Round( x ); iy = (int)Math.Round( y ); iz = (int)Math.Round( z ); if( path.Count > 0 ) { p = path.Last; if( p.m_X != ix || p.m_Y != iy || p.m_Z != iz ) path.Add( ix, iy, iz ); } else { path.Add( ix, iy, iz ); } x += run; y += rise; z += zslp; } if( path.Count == 0 ) return true;//<--should never happen, but to be safe. p = path.Last; if( p != dest ) path.Add( dest ); Point3D pTop = org, pBottom = dest; Utility.FixPoints( ref pTop, ref pBottom ); int pathCount = path.Count; for( int i = 0; i < pathCount; ++i ) { Point3D point = path[i]; LandTile landTile = Tiles.GetLandTile( point.X, point.Y ); int landZ = 0, landAvg = 0, landTop = 0; GetAverageZ( point.m_X, point.m_Y, ref landZ, ref landAvg, ref landTop ); if( landZ <= point.m_Z && landTop >= point.m_Z && (point.m_X != end.m_X || point.m_Y != end.m_Y || landZ > end.m_Z || landTop < end.m_Z) && !landTile.Ignored ) return false; /* --Do land tiles need to be checked? There is never land between two people, always statics.-- LandTile landTile = Tiles.GetLandTile( point.X, point.Y ); if ( landTile.Z-1 >= point.Z && landTile.Z+1 <= point.Z && (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Impassable) != 0 ) return false; */ StaticTile[] statics = Tiles.GetStaticTiles( point.m_X, point.m_Y, true ); bool contains = false; int ltID = landTile.ID; for( int j = 0; !contains && j < m_InvalidLandTiles.Length; ++j ) contains = (ltID == m_InvalidLandTiles[j]); if( contains && statics.Length == 0 ) { IPooledEnumerable eable = GetItemsInRange( point, 0 ); foreach( Item item in eable ) { if( item.Visible ) contains = false; if( !contains ) break; } eable.Free(); if( contains ) return false; } for( int j = 0; j < statics.Length; ++j ) { StaticTile t = statics[j]; ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; flags = id.Flags; height = id.CalcHeight; if( t.Z <= point.Z && t.Z + height >= point.Z && (flags & (TileFlag.Window | TileFlag.NoShoot)) != 0 ) { if( point.m_X == end.m_X && point.m_Y == end.m_Y && t.Z <= end.m_Z && t.Z + height >= end.m_Z ) continue; return false; } /*if ( t.Z <= point.Z && t.Z+height >= point.Z && (flags&TileFlag.Window)==0 && (flags&TileFlag.NoShoot)!=0 && ( (flags&TileFlag.Wall)!=0 || (flags&TileFlag.Roof)!=0 || (((flags&TileFlag.Surface)!=0 && zd != 0)) ) )*/ /*{ //Console.WriteLine( "LoS: Blocked by Static \"{0}\" Z:{1} T:{3} P:{2} F:x{4:X}", TileData.ItemTable[t.ID&TileData.MaxItemValue].Name, t.Z, point, t.Z+height, flags ); //Console.WriteLine( "if ( {0} && {1} && {2} && ( {3} || {4} || {5} || ({6} && {7} && {8}) ) )", t.Z <= point.Z, t.Z+height >= point.Z, (flags&TileFlag.Window)==0, (flags&TileFlag.Impassable)!=0, (flags&TileFlag.Wall)!=0, (flags&TileFlag.Roof)!=0, (flags&TileFlag.Surface)!=0, t.Z != dest.Z, zd != 0 ) ; return false; }*/ } } Rectangle2D rect = new Rectangle2D( pTop.m_X, pTop.m_Y, (pBottom.m_X - pTop.m_X) + 1, (pBottom.m_Y - pTop.m_Y) + 1 ); IPooledEnumerable area = GetItemsInBounds( rect ); foreach( Item i in area ) { if( !i.Visible ) continue; if( i is BaseMulti || i.ItemID > TileData.MaxItemValue ) continue; ItemData id = i.ItemData; flags = id.Flags; if( (flags & (TileFlag.Window | TileFlag.NoShoot)) == 0 ) continue; height = id.CalcHeight; found = false; int count = path.Count; for( int j = 0; j < count; ++j ) { Point3D point = path[j]; Point3D 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 <= point.m_Z && loc.m_Z + height >= point.m_Z ) { if( loc.m_X == end.m_X && loc.m_Y == end.m_Y && loc.m_Z <= end.m_Z && loc.m_Z + height >= end.m_Z ) continue; found = true; break; } } if( !found ) continue; area.Free(); return false; /*if ( (flags & (TileFlag.Impassable | TileFlag.Surface | TileFlag.Roof)) != 0 ) //flags = TileData.ItemTable[i.ItemID&TileData.MaxItemValue].Flags; //if ( (flags&TileFlag.Window)==0 && (flags&TileFlag.NoShoot)!=0 && ( (flags&TileFlag.Wall)!=0 || (flags&TileFlag.Roof)!=0 || (((flags&TileFlag.Surface)!=0 && zd != 0)) ) ) { //height = TileData.ItemTable[i.ItemID&TileData.MaxItemValue].Height; //Console.WriteLine( "LoS: Blocked by ITEM \"{0}\" P:{1} T:{2} F:x{3:X}", TileData.ItemTable[i.ItemID&TileData.MaxItemValue].Name, i.Location, i.Location.Z+height, flags ); area.Free(); return false; }*/ } area.Free(); return true; }
public static bool IsCoastline(this LandTile tile) { return(LandCoastlineTiles.Contains(tile.ID) || (TileData.LandTable[tile.ID].Flags == TileFlag.Impassable && Insensitive.Contains(TileData.LandTable[tile.ID].Name, "sand"))); }
public LandTile[] GetLandBlock( int x, int y ) { if ( x < 0 || y < 0 || x >= m_BlockWidth || y >= m_BlockHeight || m_Map == null ) return m_InvalidLandBlock; if ( m_LandTiles[x] == null ) m_LandTiles[x] = new LandTile[m_BlockHeight][]; LandTile[] tiles = m_LandTiles[x][y]; if ( tiles == null ) { for ( int i = 0; tiles == null && i < m_FileShare.Count; ++i ) { TileMatrix shared = m_FileShare[i]; if ( x >= 0 && x < shared.m_BlockWidth && y >= 0 && y < shared.m_BlockHeight ) { LandTile[][] theirTiles = shared.m_LandTiles[x]; if ( theirTiles != null ) tiles = theirTiles[y]; if ( tiles != null ) { int[] theirBits = shared.m_LandPatches[x]; if ( theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0 ) tiles = null; } } } if ( tiles == null ) tiles = ReadLandBlock( x, y ); m_LandTiles[x][y] = tiles; } return tiles; }