private GridCoordinates FindRandomGrid(IMapGrid mapGrid)
        {
            // TODO: Need to get valid tiles? (maybe just move right if the tile we chose is invalid?)

            var randomX = _robustRandom.Next((int)mapGrid.WorldBounds.Left, (int)mapGrid.WorldBounds.Right);
            var randomY = _robustRandom.Next((int)mapGrid.WorldBounds.Bottom, (int)mapGrid.WorldBounds.Top);

            return(mapGrid.GridTileToLocal(new MapIndices(randomX, randomY)));
        }
        private void PlaceNewTile(GridCoordinates coordinates, ushort tileType, IMap map, Vector2 position)
        {
            // tile can snap up to 0.75m away from grid
            var gridSearchBox = new Box2(-0.5f, -0.5f, 0.5f, 0.5f)
                                .Scale(1.5f)
                                .Translated(position);

            var gridsInArea = map.FindGridsIntersecting(gridSearchBox);

            IMapGrid closest   = null;
            float    distance  = float.PositiveInfinity;
            Box2     intersect = new Box2();

            foreach (var grid in gridsInArea)
            {
                // figure out closest intersect
                var gridIntersect = gridSearchBox.Intersect(grid.WorldBounds);
                var gridDist      = (gridIntersect.Center - position).LengthSquared;

                if (gridDist >= distance)
                {
                    continue;
                }

                distance  = gridDist;
                closest   = grid;
                intersect = gridIntersect;
            }

            if (closest != null) // stick to existing grid
            {
                // round to nearest cardinal dir
                var normal = new Angle(position - intersect.Center).GetCardinalDir().ToVec();

                // round coords to center of tile
                var tileIndices     = closest.WorldToTile(intersect.Center);
                var tileCenterLocal = closest.GridTileToLocal(tileIndices);
                var tileCenterWorld = tileCenterLocal.ToWorld(_mapManager).Position;

                // move mouse one tile out along normal
                var newTilePos = tileCenterWorld + normal * closest.TileSize;

                // you can always remove a tile
                if (Tile.Empty.TypeId != tileType)
                {
                    var tileBounds = Box2.UnitCentered.Scale(closest.TileSize).Translated(newTilePos);

                    var collideCount = map.FindGridsIntersecting(tileBounds).Count();

                    // prevent placing a tile if it overlaps more than one grid
                    if (collideCount > 1)
                    {
                        return;
                    }
                }

                var pos = closest.WorldToTile(position);
                closest.SetTile(pos, new Tile(tileType));
            }
            else // create a new grid
            {
                var newGrid = map.CreateGrid();
                newGrid.WorldPosition = position + (newGrid.TileSize / 2f); // assume bottom left tile origin
                var tilePos = newGrid.WorldToTile(position);
                newGrid.SetTile(tilePos, new Tile(tileType));
            }
        }
Exemple #3
0
        private bool IsRCDStillValid(AfterInteractEventArgs eventArgs, IMapGrid mapGrid, TileRef tile, MapIndices snapPos, RcdMode startingMode)
        {
            //Less expensive checks first. Failing those ones, we need to check that the tile isn't obstructed.
            if (_ammo <= 0)
            {
                _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"The RCD is out of ammo!");
                return(false);
            }

            if (_mode != startingMode)
            {
                return(false);
            }

            var coordinates = mapGrid.GridTileToLocal(tile.GridIndices);

            if (coordinates == GridCoordinates.InvalidGrid || !InteractionChecks.InRangeUnobstructed(eventArgs))
            {
                return(false);
            }

            switch (_mode)
            {
            //Floor mode just needs the tile to be a space tile (subFloor)
            case RcdMode.Floors:
                if (!tile.Tile.IsEmpty)
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can only build a floor on space!");
                    return(false);
                }

                return(true);

            //We don't want to place a space tile on something that's already a space tile. Let's do the inverse of the last check.
            case RcdMode.Deconstruct:
                if (tile.Tile.IsEmpty)
                {
                    return(false);
                }

                //They tried to decon a turf but the turf is blocked
                if (eventArgs.Target == null && tile.IsBlockedTurf(true))
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
                    return(false);
                }
                //They tried to decon a non-turf but it's not in the whitelist
                if (eventArgs.Target != null && !eventArgs.Target.TryGetComponent(out RCDDeconstructWhitelist rcd_decon))
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can't deconstruct that!");
                    return(false);
                }

                return(true);

            //Walls are a special behaviour, and require us to build a new object with a transform rather than setting a grid tile, thus we early return to avoid the tile set code.
            case RcdMode.Walls:
                if (tile.Tile.IsEmpty)
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build a wall on space!");
                    return(false);
                }

                if (tile.IsBlockedTurf(true))
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
                    return(false);
                }
                return(true);

            case RcdMode.Airlock:
                if (tile.Tile.IsEmpty)
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build an airlock on space!");
                    return(false);
                }
                if (tile.IsBlockedTurf(true))
                {
                    _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!");
                    return(false);
                }
                return(true);

            default:
                return(false);    //I don't know why this would happen, but sure I guess. Get out of here invalid state!
            }
        }
Exemple #4
0
        public override void AlignPlacementMode(ScreenCoordinates mouseScreen)
        {
            const float SearchBoxSize = 1.5f; // size of search box in meters

            MouseCoords = ScreenToCursorGrid(mouseScreen);

            var mapGrid = pManager.MapManager.GetGrid(MouseCoords.GridID);

            if (mapGrid.IsDefaultGrid)
            {
                // check if we are on an edge of a grid
                // create a box around the cursor
                DebugTools.Assert(mapGrid.WorldPosition == Vector2.Zero); // assert that LocalPos == WorldPos
                var gridSearchBox = Box2.UnitCentered.Scale(SearchBoxSize).Translated(MouseCoords.Position);

                // find grids in search box
                var gridsInArea = mapGrid.ParentMap.FindGridsIntersecting(gridSearchBox);

                // find closest grid intersecting our search box.
                IMapGrid closest   = null;
                var      distance  = float.PositiveInfinity;
                var      intersect = new Box2();
                foreach (var grid in gridsInArea)
                {
                    // figure out closest intersect
                    var gridIntersect = gridSearchBox.Intersect(grid.WorldBounds);
                    var gridDist      = (gridIntersect.Center - MouseCoords.Position).LengthSquared;

                    if (gridDist >= distance)
                    {
                        continue;
                    }

                    distance  = gridDist;
                    closest   = grid;
                    intersect = gridIntersect;
                }

                if (closest != null) // stick to existing grid
                {
                    // round to nearest cardinal dir
                    var normal = new Angle(MouseCoords.Position - intersect.Center).GetCardinalDir().ToVec();

                    // round coords to center of tile
                    var tileIndices     = closest.WorldToTile(intersect.Center);
                    var tileCenterLocal = closest.GridTileToLocal(tileIndices);
                    var tileCenterWorld = tileCenterLocal.ToWorld(pManager.MapManager).Position;

                    // move mouse one tile out along normal
                    var newTilePos = tileCenterWorld + normal * closest.TileSize;
                    MouseCoords = new GridCoordinates(closest.WorldToLocal(newTilePos), closest.Index);
                }
                //else free place
            }


            CurrentTile = mapGrid.GetTileRef(MouseCoords);
            float tileSize = mapGrid.TileSize; //convert from ushort to float

            GridDistancing = tileSize;

            if (pManager.CurrentPermission.IsTile)
            {
                if (!mapGrid.IsDefaultGrid)
                {
                    MouseCoords = new GridCoordinates(CurrentTile.X + tileSize / 2,
                                                      CurrentTile.Y + tileSize / 2,
                                                      MouseCoords.GridID);
                }
                // else we don't modify coords
            }
            else
            {
                MouseCoords = new GridCoordinates(CurrentTile.X + tileSize / 2 + pManager.PlacementOffset.X,
                                                  CurrentTile.Y + tileSize / 2 + pManager.PlacementOffset.Y,
                                                  MouseCoords.GridID);
            }
        }