示例#1
0
        private static Vector2D?FindClosestPosition(Vector2D position)
        {
            var physicsSpace   = ServerWorldService.GetPhysicsSpace();
            var collisionGroup = CollisionGroup.Default;

            if (IsValidPosition(
                    // round position
                    position.ToVector2Ushort().ToVector2D()))
            {
                // can teleport right there
                return(position);
            }

            // check nearby tiles
            var tile = ServerWorldService.GetTile(position.ToVector2Ushort());

            foreach (var neighborTile in tile.EightNeighborTiles)
            {
                if (!neighborTile.IsValidTile)
                {
                    continue;
                }

                var neighborTilePosition = neighborTile.Position.ToVector2D();
                if (IsValidPosition(neighborTilePosition))
                {
                    return(neighborTilePosition);
                }
            }

            return(null);

            // Local function for checking if the position is valid.
            bool IsValidPosition(Vector2D pos)
            {
                using var objectsNearby = physicsSpace.TestRectangle(
                          // include some padding, otherwise the check will include border-objects
                          position: pos + (0.01, 0.01),
                          size: (0.98, 0.98),
                          collisionGroup: collisionGroup,
                          sendDebugEvent: false);
                if (objectsNearby.Count > 0)
                {
                    return(false);
                }

                var posTile = Server.World.GetTile(pos.ToVector2Ushort());

                return(ServerCharacterSpawnHelper.IsValidSpawnTile(posTile,
                                                                   checkNeighborTiles: false));
            }
        }
示例#2
0
        protected virtual bool ServerIsValidSpawnPosition(Vector2D worldPosition)
        {
            const double noObstaclesCheckRadius = 1.5;
            var          physicsSpace           = Server.World.GetPhysicsSpace();

            foreach (var _ in physicsSpace.TestCircle(worldPosition,
                                                      radius: noObstaclesCheckRadius,
                                                      CollisionGroups.Default,
                                                      sendDebugEvent: false).EnumerateAndDispose())
            {
                // position is not valid for spawning
                return(false);
            }

            return(ServerCharacterSpawnHelper.IsValidSpawnTile(
                       Api.Server.World.GetTile(worldPosition.ToVector2Ushort()),
                       checkNeighborTiles: true));
        }
        public static void ServerTrySpawnMobsCustom(
            IProtoCharacter protoMob,
            ICollection <ICharacter> spawnedCollection,
            int countToSpawn,
            RectangleInt excludeBounds,
            int maxSpawnDistanceFromExcludeBounds,
            double noObstaclesCheckRadius,
            int maxAttempts)
        {
            if (countToSpawn <= 0)
            {
                return;
            }

            var spawnBounds = excludeBounds.Inflate(maxSpawnDistanceFromExcludeBounds,
                                                    maxSpawnDistanceFromExcludeBounds);
            var physicsSpace = Api.Server.World.GetPhysicsSpace();

            while (maxAttempts-- > 0)
            {
                var position = new Vector2D(spawnBounds.Left + RandomHelper.NextDouble() * spawnBounds.Width,
                                            spawnBounds.Bottom + RandomHelper.NextDouble() * spawnBounds.Height);
                if (IsTooClose(position))
                {
                    continue;
                }

                var character = ServerTrySpawnMob(position);
                if (character is null)
                {
                    // cannot spawn there
                    continue;
                }

                spawnedCollection.Add(character);

                countToSpawn--;
                if (countToSpawn == 0)
                {
                    return;
                }
            }

            bool IsTooClose(in Vector2D position)
            => position.X >= excludeBounds.X &&
            position.Y >= excludeBounds.Y &&
            position.X < excludeBounds.X + excludeBounds.Width &&
            position.Y < excludeBounds.Y + excludeBounds.Height;

            ICharacter ServerTrySpawnMob(Vector2D worldPosition)
            {
                foreach (var _ in physicsSpace.TestCircle(worldPosition,
                                                          radius: noObstaclesCheckRadius,
                                                          CollisionGroups.Default,
                                                          sendDebugEvent: false).EnumerateAndDispose())
                {
                    // position is not valid for spawning
                    return(null);
                }

                if (!ServerCharacterSpawnHelper.IsValidSpawnTile(
                        Api.Server.World.GetTile(worldPosition.ToVector2Ushort()),
                        checkNeighborTiles: true))
                {
                    return(null);
                }

                return(Api.Server.Characters.SpawnCharacter(protoMob,
                                                            worldPosition));
            }
        }