Ejemplo n.º 1
0
        public void Deserialize(BinaryReader reader)
        {
            Width = reader.ReadInt32();
            Height = reader.ReadInt32();
            Stories = reader.ReadInt32();

            var size = Width * Height;

            Walls = new WallTile[Stories][];
            for (int l=0;l<Stories;l++)
            {
                Walls[l] = new WallTile[size];
                for (int i = 0; i < size; i++) Walls[l][i] = WallTileSerializer.Deserialize(reader);
            }

            Floors = new FloorTile[Stories][];
            for (int l = 0; l < Stories; l++)
            {
                Floors[l] = new FloorTile[size];
                for (int i = 0; i < size; i++) Floors[l][i] = new FloorTile { Pattern = reader.ReadUInt16() };
            }

            WallsDirty = reader.ReadBoolean();
            FloorsDirty = reader.ReadBoolean();
        }
Ejemplo n.º 2
0
        //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result
        /// <summary>
        /// Generates the room map for the specified walls array.
        /// </summary>
        public void GenerateMap(WallTile[] Walls, FloorTile[] Floors, int width, int height, List<VMRoom> rooms)
        {
            Map = new uint[width*height]; //although 0 is the base of the array, room 1 is known to simantics as room 0.
            //values of 0 indicate the room has not been chosen in that location yet.

            bool noFloorBad = (rooms.Count > 1);

            this.Width = width;
            this.Height = height;

            //flood fill recursively. Each time choose find and choose the first "0" as the base.
            //The first recursion (outside) cannot fill into diagonals.
            bool remaining = true;
            bool outside = true;
            while (remaining)
            {
                var spread = new Stack<Point>();
                remaining = false;
                for (int i = 0; i < Map.Length; i++)
                {
                    if (Map[i] == 0)
                    {
                        ExpectedTile = Floors[i].Pattern;
                        //if (ExpectedTile == 0 && noFloorBad) continue;
                        if (ExpectedTile < 65534) ExpectedTile = 0;
                        remaining = true;
                        Map[i] = (ushort)rooms.Count;
                        spread.Push(new Point(i % width, i / width));
                        break;
                    }
                }

                if (remaining)
                {
                    int rminX = spread.Peek().X;
                    int rmaxX = rminX;
                    int rminY = spread.Peek().Y;
                    int rmaxY = rminY;
                    var wallObs = new List<VMObstacle>();
                    ushort area = 0;
                    while (spread.Count > 0)
                    {
                        area++;
                        var item = spread.Pop();

                        if (item.X > rmaxX) rmaxX = item.X;
                        if (item.X < rminX) rminX = item.X;
                        if (item.Y > rmaxY) rmaxY = item.Y;
                        if (item.Y < rminY) rminY = item.Y;

                        var plusX = (item.X+1)%width;
                        var minX = (item.X + width - 1) % width;
                        var plusY = (item.Y+1)%height;
                        var minY = (item.Y + height - 1) % height;

                        var mainWalls = Walls[item.X + item.Y * width];

                        int obsX = item.X << 4;
                        int obsY = item.Y << 4;

                        if ((mainWalls.Segments & WallSegments.HorizontalDiag) > 0)
                        {
                            wallObs.Add(new VMObstacle(obsX + 9, obsY - 1, obsX + 17, obsY + 7));
                            wallObs.Add(new VMObstacle(obsX + 4, obsY + 4, obsX + 12, obsY + 12));
                            wallObs.Add(new VMObstacle(obsX - 1, obsY + 9, obsX + 7, obsY + 17));
                        }

                        if ((mainWalls.Segments & WallSegments.VerticalDiag) > 0)
                        {
                            wallObs.Add(new VMObstacle(obsX - 1, obsY - 1, obsX + 7, obsY + 7));
                            wallObs.Add(new VMObstacle(obsX + 4, obsY + 4, obsX + 12, obsY + 12));
                            wallObs.Add(new VMObstacle(obsX + 9, obsY + 9, obsX + 17, obsY + 17));
                        }

                        if ((byte)mainWalls.Segments > 15) continue; //don't spread on diagonals for now

                        var PXWalls = Walls[plusX + item.Y * width];
                        var PYWalls = Walls[item.X + plusY * width];

                        if ((mainWalls.Segments & WallSegments.TopLeft) > 0 && !mainWalls.TopLeftDoor) wallObs.Add(new VMObstacle(obsX - 3, obsY - 3, obsX + 6, obsY + 19));
                        if ((mainWalls.Segments & WallSegments.TopRight) > 0 && !mainWalls.TopRightDoor) wallObs.Add(new VMObstacle(obsX - 3, obsY - 3, obsX + 19, obsY + 6));
                        if ((mainWalls.Segments & WallSegments.BottomLeft) > 0 && !PYWalls.TopRightDoor) wallObs.Add(new VMObstacle(obsX - 3, obsY + 13, obsX + 19, obsY + 19));
                        if ((mainWalls.Segments & WallSegments.BottomRight) > 0 && !PXWalls.TopLeftDoor) wallObs.Add(new VMObstacle(obsX + 13, obsY - 3, obsX + 19, obsY + 19));

                        //

                        if (((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1))
                            SpreadOnto(Walls, Floors, plusX, item.Y, 0, Map, width, height, spread, (ushort)rooms.Count, ExpectedTile, noFloorBad);

                        if (((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1))
                            SpreadOnto(Walls, Floors, minX, item.Y, 2, Map, width, height, spread, (ushort)rooms.Count, ExpectedTile, noFloorBad);

                        if (((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1))
                            SpreadOnto(Walls, Floors, item.X, plusY, 1, Map, width, height, spread, (ushort)rooms.Count, ExpectedTile, noFloorBad);

                        if (((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1))
                            SpreadOnto(Walls, Floors, item.X, minY, 3, Map, width, height, spread, (ushort)rooms.Count, ExpectedTile, noFloorBad);
                    }

                    var bounds = new Rectangle(rminX, rminY, (rmaxX - rminX) + 1, (rmaxY - rminY) + 1);
                    var roomObs = GenerateRoomObs((ushort)rooms.Count, bounds);
                    OptimizeObstacles(wallObs);
                    OptimizeObstacles(roomObs);
                    rooms.Add(new VMRoom
                    {
                        IsOutside = outside || ExpectedTile > 65533,
                        IsPool = ExpectedTile > 65533,
                        Bounds = bounds,
                        WallObs = wallObs,
                        RoomObs = roomObs,
                        Area = area
                    });
                    outside = false;
                }
            }
        }
Ejemplo n.º 3
0
        private static void SpreadOnto(WallTile[] walls, FloorTile[] floors, int x, int y, int inDir, uint[] map, int width, int height, Stack<Point> spread, ushort room, ushort expectedTile, bool noAir)
        {
            var wall = walls[x + y * width];
            var floor = floors[x + y * width].Pattern;

            if ((expectedTile > 0 && expectedTile != floor) || (expectedTile == 0 && floor > 65533))
            {
                return;
            }

            if ((wall.Segments & WallSegments.HorizontalDiag) > 0)
            {
                if (inDir < 2)
                {
                    //bottom (bottom right pattern)
                    if ((map[x + y * width] & (uint)0x0000FFFF)>0) return; //don't spread onto
                    map[x + y * width] |= room;

                }
                else
                {
                    //top (bottom left pattern)
                    if ((map[x + y * width] & (uint)0xFFFF0000) > 0) return; //don't spread onto
                    map[x + y * width] |= (uint)room<<16;
                }
                //if (!floorMode) walls[x + y * width] = wall;
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0)
            {
                if (inDir > 0 && inDir < 3)
                {
                    //left
                    if ((map[x + y * width] & (uint)0x0000FFFF) > 0) return; //don't spread onto
                    map[x + y * width] |= room;
                }
                else
                {
                    //right
                    if ((map[x + y * width] & (uint)0xFFFF0000) > 0) return; //don't spread onto
                    map[x + y * width] |= (uint)room << 16;
                }
                //if (!floorMode) walls[x + y * width] = wall;
            }
            else
            {
                if (map[x + y * width] > 0) return;
                map[x + y * width] = (uint)(room | (room<<16));
            }

            spread.Push(new Point(x, y));
        }
Ejemplo n.º 4
0
        public bool SetFloor(short tileX, short tileY, sbyte level, FloorTile floor, bool force)
        {
            //returns false on failure
            var offset = GetOffset(tileX, tileY);

            if (!force)
            {
                //first check if we're supported
                if (level > 1 && !Supported[level - 2][offset]) return false;
                //check if objects need/don't need floors
                if (!Context.CheckFloorValid(LotTilePos.FromBigTile((short)tileX, (short)tileY, level), floor)) return false;
            }

            Floors[level-1][offset] = floor;

            if (RealMode) FloorsDirty = true;
            Redraw = true;
            return true;
        }
Ejemplo n.º 5
0
 public bool CheckFloorValid(LotTilePos pos, FloorTile floor)
 {
     if (pos.Level < 1 || pos.Level > ObjectsAt.Count || !ObjectsAt[pos.Level - 1].ContainsKey(pos.TileID)) return true;
     var objs = ObjectsAt[pos.Level - 1][pos.TileID];
     foreach (var id in objs)
     {
         var obj = VM.GetObjectById(id);
         if (obj.FloorChangeValid(floor, pos.Level) != VMPlacementError.Success) return false;
     }
     return true;
 }
Ejemplo n.º 6
0
 public bool CheckFloorValid(LotTilePos pos, FloorTile floor)
 {
     var objs = SetToNextCache.GetObjectsAt(pos);
     if (objs == null) return true;
     foreach (var obj in objs)
     {
         if (obj.FloorChangeValid(floor, pos.Level) != VMPlacementError.Success) return false;
     }
     return true;
 }
Ejemplo n.º 7
0
        public VMPlacementError FloorChangeValid(FloorTile floor, sbyte level)
        {
            var placeFlags = (VMPlacementFlags)ObjectData[(int)VMStackObjectVariable.PlacementFlags];

            if (floor.Pattern == 65535)
            {
                if ((placeFlags & (VMPlacementFlags.AllowOnPool | VMPlacementFlags.RequirePool)) == 0) return VMPlacementError.CantPlaceOnWater;
            }
            else
            {
                if ((placeFlags & VMPlacementFlags.RequirePool) > 0) return VMPlacementError.MustPlaceOnPool;
                if (floor.Pattern == 63354)
                {
                    if ((placeFlags & (VMPlacementFlags.OnWater | VMPlacementFlags.RequireWater)) == 0) return VMPlacementError.CantPlaceOnWater;
                } else
                {
                    if ((placeFlags & VMPlacementFlags.RequireWater) > 0) return VMPlacementError.MustPlaceOnWater;
                    if (floor.Pattern == 0)
                    {
                        if (level == 1)
                        {
                            if ((placeFlags & VMPlacementFlags.OnTerrain) == 0) return VMPlacementError.NotAllowedOnTerrain;
                        }
                        else
                        {
                            if ((placeFlags & VMPlacementFlags.InAir) == 0 && Object.OBJ.LevelOffset == 0) return VMPlacementError.CantPlaceInAir;
                            //TODO: special hack check that determines if we need can add/remove a tile to fulfil this if LevelOffset > 0
                        }
                    }
                    else
                    {
                        if ((placeFlags & VMPlacementFlags.OnFloor) == 0 &&
                            ((Object.OBJ.LevelOffset == 0) || (placeFlags & VMPlacementFlags.InAir) == 0)) return VMPlacementError.NotAllowedOnFloor;
                    }
                }
            }
            return VMPlacementError.Success;
        }