Exemple #1
0
        public IEnumerable <Tile> GetNeighbors(Tile tile)
        {
            Block block;

            if (!_blockCache.TryGetValue(tile, out block))
            {
                block = _level.GetBlock(new BlockCoordinates((int)tile.X, _startY, (int)tile.Y));
                _blockCache.Add(tile, block);
            }

            HashSet <Tile> list = new HashSet <Tile>();

            for (int index = 0; index < Neighbors.GetLength(0); ++index)
            {
                var item = new Tile(tile.X + Neighbors[index, 0], tile.Y + Neighbors[index, 1]);

                // Check for too high steps
                BlockCoordinates coord = new BlockCoordinates((int)item.X, block.Coordinates.Y, (int)item.Y);
                if (_level.GetBlock(coord).IsSolid)
                {
                    if (_entity.CanClimb)
                    {
                        Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up);
                        bool  canMove = false;
                        for (int i = 0; i < 10; i++)
                        {
                            if (IsBlocked(blockUp.Coordinates))
                            {
                                blockUp = _level.GetBlock(blockUp.Coordinates + BlockCoordinates.Up);
                                continue;
                            }

                            canMove = true;
                            break;
                        }

                        if (!canMove)
                        {
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        _blockCache[item] = blockUp;
                    }
                    else
                    {
                        Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up);
                        if (blockUp.IsSolid)
                        {
                            // Can't jump
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        _blockCache[item] = blockUp;
                    }
                }
                else
                {
                    var blockDown = _level.GetBlock(coord + BlockCoordinates.Down);
                    if (!blockDown.IsSolid)
                    {
                        if (_entity.CanClimb)
                        {
                            bool canClimb = false;
                            blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Down);
                            for (int i = 0; i < 10; i++)
                            {
                                if (!blockDown.IsSolid)
                                {
                                    blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Down);
                                    continue;
                                }

                                canClimb = true;
                                break;
                            }

                            if (!canClimb)
                            {
                                continue;
                            }

                            blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Up);

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            _blockCache[item] = blockDown;
                        }
                        else
                        {
                            if (!_level.GetBlock(coord + BlockCoordinates.Down + BlockCoordinates.Down).IsSolid)
                            {
                                // Will fall
                                continue;
                            }

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            _blockCache[item] = blockDown;
                        }
                    }
                    else
                    {
                        if (IsObstructed(coord))
                        {
                            continue;
                        }

                        _blockCache[item] = _level.GetBlock(coord);
                    }
                }

                list.Add(item);
            }

            CheckDiagonals(block, list);

            return(list);
        }
Exemple #2
0
        public IEnumerable <ImprovedTile> GetNeighbors(ImprovedTile tile)
        {
            Block block;

            if (!_blockCache.TryGetValue(tile, out block))
            {
                block = _level.GetBlock(new BlockCoordinates(tile.X, _startY, tile.Y));
                _blockCache.Add(tile, block);
            }

            List <ImprovedTile> list = new List <ImprovedTile>();

            for (int index = 0; index < Neighbors.GetLength(0); ++index)
            {
                var item = new ImprovedTile(tile.X + Neighbors[index, 0], tile.Y + Neighbors[index, 1]);

                // Check for too high steps
                BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y);
                if (_level.GetBlock(coord).IsSolid)
                {
                    Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up);
                    if (blockUp.IsSolid)
                    {
                        // Can't jump
                        continue;
                    }

                    if (IsObstructed(blockUp.Coordinates))
                    {
                        continue;
                    }

                    _blockCache[item] = blockUp;
                }
                else
                {
                    var blockDown = _level.GetBlock(coord + BlockCoordinates.Down);
                    if (!blockDown.IsSolid)
                    {
                        if (!_level.GetBlock(coord + BlockCoordinates.Down + BlockCoordinates.Down).IsSolid)
                        {
                            // Will fall
                            continue;
                        }

                        if (IsObstructed(blockDown.Coordinates))
                        {
                            continue;
                        }

                        _blockCache[item] = blockDown;
                    }
                    else
                    {
                        if (IsObstructed(coord))
                        {
                            continue;
                        }

                        _blockCache[item] = _level.GetBlock(coord);
                    }
                }

                list.Add(item);
            }

            CheckDiagonals(block, list);

            return(list);
        }
Exemple #3
0
        public IEnumerable <Tile> GetNeighbors(Tile start)
        {
            if (!_blockCache.TryGetValue(start, out var block))
            {
                block = _level.GetBlock(new BlockCoordinates(start.X, _startY, start.Y));
                _blockCache.Add(start, block);
            }

            HashSet <Tile> neighbors = new HashSet <Tile>();

            for (int index = 0; index < Neighbors.GetLength(0); ++index)
            {
                var item = new Tile3d(start.X + Neighbors[index, 0], start.Y + Neighbors[index, 1], block.Coordinates.Y);

                bool isDiagonalMove = item.X != start.X && item.Y != start.Y;
                if (isDiagonalMove)
                {
                    // Don't allow cutting corners where there is a block
                    Tile undiagonal = new Tile(start.X, start.Y + Neighbors[index, 1]);
                    if (!_blockCache.TryGetValue(undiagonal, out var udblock))
                    {
                        continue;
                    }
                    if (udblock.Coordinates.Y != block.Coordinates.Y)
                    {
                        continue;
                    }
                }

                // Check for too high steps
                BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y);

                if (_level.GetBlock(coord).IsSolid)
                {
                    // Only allow diagonal movements if on same Y level
                    if (isDiagonalMove)
                    {
                        continue;
                    }

                    // Check if we hit head if we jump or climb up to next block
                    if (IsObstructed(block.Coordinates.BlockUp()))
                    {
                        continue;
                    }

                    if (_entity.CanClimb)
                    {
                        Block blockUp     = _level.GetBlock(coord.BlockUp());
                        Block currBlockUp = _level.GetBlock(block.Coordinates.BlockUp());                         // Check if we hit ceiling too
                        bool  canMove     = false;
                        for (int i = 0; i < 10; i++)
                        {
                            if (IsBlocked(blockUp) && !IsBlocked(currBlockUp))
                            {
                                blockUp     = _level.GetBlock(blockUp.Coordinates.BlockUp());
                                currBlockUp = _level.GetBlock(currBlockUp.Coordinates.BlockUp());
                                continue;
                            }

                            canMove = true;
                            break;
                        }

                        if (!canMove)
                        {
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = blockUp.Coordinates.Y;
                        _blockCache[item] = blockUp;
                    }
                    else
                    {
                        // Check block collision box, not hit box
                        if (_level.GetBlock(coord) is Fence)
                        {
                            continue;
                        }

                        Block blockUp = _level.GetBlock(coord.BlockUp());
                        if (blockUp.IsSolid)
                        {
                            // Can't jump. This is hardwired for 1 block jump height for all mobs.
                            continue;
                        }

                        if (IsObstructed(blockUp.Coordinates))
                        {
                            continue;
                        }

                        //TODO: There is a problem when there is a path both under and over a block. It chooses the last checked block.
                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = blockUp.Coordinates.Y;
                        _blockCache[item] = blockUp;
                    }
                }
                else
                {
                    if (IsObstructed(coord))
                    {
                        continue;
                    }

                    var blockDown = _level.GetBlock(coord.BlockDown());
                    if (blockDown.IsSolid)
                    {
                        // Continue on same Y level
                        if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != coord.Y)
                        {
                            //Log.Warn("Already had this coordinated but on different Y");
                            continue;
                        }
                        item.RealY        = coord.Y;
                        _blockCache[item] = _level.GetBlock(coord);
                    }
                    else
                    {
                        // Only allow diagonal movements if on same Y level
                        if (isDiagonalMove)
                        {
                            continue;
                        }

                        if (_entity.CanClimb)
                        {
                            bool canClimb = false;
                            blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown());
                            for (int i = 0; i < 10; i++)
                            {
                                if (!blockDown.IsSolid)
                                {
                                    blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown());
                                    continue;
                                }

                                canClimb = true;
                                break;
                            }

                            if (!canClimb)
                            {
                                continue;
                            }

                            blockDown = _level.GetBlock(blockDown.Coordinates.BlockUp());

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y)
                            {
                                //Log.Warn("Already had this coordinated but on different Y");
                                continue;
                            }
                            item.RealY        = blockDown.Coordinates.Y;
                            _blockCache[item] = blockDown;
                        }
                        else
                        {
                            if (!_level.GetBlock(coord.BlockDown().BlockDown()).IsSolid)
                            {
                                // Will fall
                                continue;
                            }

                            if (IsObstructed(blockDown.Coordinates))
                            {
                                continue;
                            }

                            if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y)
                            {
                                //Log.Warn("Already had this coordinated but on different Y");
                                continue;
                            }
                            item.RealY        = blockDown.Coordinates.Y;
                            _blockCache[item] = blockDown;
                        }
                    }
                }

                neighbors.Add(item);
            }

            CheckDiagonals(block, neighbors);

            return(neighbors);
        }