예제 #1
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. Returns the next free room to be assigned.
        /// </summary>
        public ushort GenerateMap(WallTile[] Walls, int width, int height, ushort curRoom)
        {
            Map = new ushort[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.

            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;
            while (remaining)
            {
                var spread = new Stack<Point>();
                remaining = false;
                for (int i = 0; i < Map.Length; i++)
                {
                    if (Map[i] == 0)
                    {
                        remaining = true;
                        Map[i] = curRoom;
                        spread.Push(new Point(i % width, i / width));
                        break;
                    }
                }

                if (remaining)
                {
                    while (spread.Count > 0)
                    {
                        var item = spread.Pop();

                        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];
                        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 (Map[plusX + item.Y * width] == 0 && ((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1))
                            { Map[plusX + item.Y * width] = curRoom; spread.Push(new Point(plusX, item.Y)); }
                        if (Map[minX + item.Y * width] == 0 && ((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1))
                            { Map[minX + item.Y * width] = curRoom; spread.Push(new Point(minX, item.Y)); }
                        if (Map[item.X + plusY * width] == 0 && ((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1))
                            { Map[item.X + plusY * width] = curRoom; spread.Push(new Point(item.X, plusY)); }
                        if (Map[item.X + minY * width] == 0 && ((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1))
                            { Map[item.X + minY * width] = curRoom; spread.Push(new Point(item.X, minY)); }
                    }
                    curRoom++;
                }
            }
            return curRoom;
        }
예제 #2
0
        public void SetWall(short tileX, short tileY, WallTile wall)
        {
            var off = GetOffset(tileX, tileY);

            Walls[off] = wall;
            WallsAt.Remove(off);
            if (wall.TopLeftStyle != 0 || wall.TopRightStyle != 0)
            {
                WallsAt.Add(off);
            }
        }
예제 #3
0
 public void SetWall(short tileX, short tileY, WallTile wall)
 {
     var off = GetOffset(tileX, tileY);
     Walls[off] = wall;
     WallsAt.Remove(off);
     if (wall.TopLeftStyle != 0 || wall.TopRightStyle != 0) WallsAt.Add(off);
 }
예제 #4
0
 public bool CheckWallValid(LotTilePos pos, WallTile wall)
 {
     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.WallChangeValid(wall, obj.Direction, false) != VMPlacementError.Success) return false;
     }
     return true;
 }
        public void SetWall(short tileX, short tileY, sbyte level, WallTile wall)
        {
            var off = GetOffset(tileX, tileY);

            WallsAt[level-1].Remove(off);
            if (wall.Segments > 0) {
                Walls[level - 1][off] = wall;
                WallsAt[level - 1].Add(off);
            }
            else
            {
                Walls[level - 1][off] = new WallTile();
            }

            if (RealMode) WallsDirty = true;
            Redraw = true;
        }
        private void GenerateWallData(WallTile[] walls, List<int> wallsAt, bool notTop)
        {
            var width = blueprint.Width;
            var height = blueprint.Height;
            Cuts = new WallCuts[width * height];
            DownJunctions = new JunctionFlags[width * height];
            UpJunctions = new JunctionFlags[width * height];

            foreach (var off in wallsAt)
            {
                var wall = walls[off];
                var x = off % width;
                var y = off / width;
                var result = new WallCuts();
                if (notTop && WallsDownAt(x, y))
                {
                    var cuts = GetCutEdges(off % width, off / width);

                    if (wall.TopLeftThick && wall.TopLeftStyle != 255)
                    {
                        if (cuts != 0)
                        {
                            if ((cuts & CutawayEdges.NegativeX) == CutawayEdges.NegativeX) result.TLCut = WallCut.Up; //if we are on the very edge of the cut we're up
                            else if ((cuts & CutawayEdges.PositiveY) == CutawayEdges.PositiveY) {
                                if ((cuts & CutawayEdges.NegativeY) == CutawayEdges.NegativeY)
                                {
                                    result.TLCut = WallCut.Down; //special case, cuts at both sides... just put wall down
                                }
                                else
                                {
                                    result.TLCut = WallCut.DownRightUpLeft;
                                }
                            }
                            else if ((cuts & CutawayEdges.NegativeY) == CutawayEdges.NegativeY)
                            {
                                result.TLCut = WallCut.DownLeftUpRight;
                            }
                            else result.TLCut = WallCut.Down;
                        }
                        else
                        {
                            result.TLCut = WallCut.Down;
                        }

                    }

                    if (wall.TopRightStyle == 1) //NOTE: top right style also includes diagonals!
                    {
                        if (wall.Segments == WallSegments.HorizontalDiag) {
                            if (cuts != 0)
                            {
                                var cutOnLeft = (cuts & (CutawayEdges.PositiveY | CutawayEdges.NegativeX)) > 0;
                                var cutOnRight = (cuts & (CutawayEdges.NegativeY | CutawayEdges.PositiveX)) > 0;
                                if (cutOnLeft && cutOnRight) result.TRCut = WallCut.Down;
                                else if (cutOnLeft) result.TRCut = WallCut.DownRightUpLeft;
                                else if (cutOnRight) result.TRCut = WallCut.DownLeftUpRight;
                                else result.TRCut = WallCut.Down;
                            }
                            else
                            {
                                result.TRCut = WallCut.Down;
                            }
                        }
                        else if (wall.Segments == WallSegments.VerticalDiag)
                        {
                            if (cuts != 0) //this info is not useful for front rotation, but is useful for sides.
                            {
                                var cutOnLeft = (cuts & (CutawayEdges.PositiveY | CutawayEdges.PositiveX)) > 0;
                                var cutOnRight = (cuts & (CutawayEdges.NegativeY | CutawayEdges.NegativeX)) > 0;
                                if (cutOnLeft && cutOnRight) result.TRCut = WallCut.Down;
                                else if (cutOnLeft) result.TRCut = WallCut.DownRightUpLeft;
                                else if (cutOnRight) result.TRCut = WallCut.DownLeftUpRight;
                                else result.TRCut = WallCut.Down;
                            }
                            else
                            {
                                result.TRCut = WallCut.Down;
                            }
                        }
                        else
                        {
                            if (cuts != 0)
                            {
                                if ((cuts & CutawayEdges.NegativeY) == CutawayEdges.NegativeY) result.TRCut = WallCut.Up; //if we are on the very edge of the cut we're up
                                else if ((cuts & CutawayEdges.PositiveX) == CutawayEdges.PositiveX)
                                {
                                    if ((cuts & CutawayEdges.NegativeX) == CutawayEdges.NegativeX)
                                    { //special case, cuts at both sides... just put wall down
                                        result.TRCut = WallCut.Down;
                                    }
                                    else
                                    {
                                        result.TRCut = WallCut.DownLeftUpRight;
                                    }
                                }
                                else if ((cuts & CutawayEdges.NegativeX) == CutawayEdges.NegativeX)
                                {
                                    result.TRCut = WallCut.DownRightUpLeft;
                                }
                                else result.TRCut = WallCut.Down;
                            }
                            else
                            {
                                result.TRCut = WallCut.Down;
                            }
                        }
                    }
                }
                //add to relevant junctions
                if ((wall.Segments & WallSegments.TopLeft) > 0 && !(wall.TopLeftDoor && result.TLCut > 0) && wall.TopLeftThick)
                {
                    if (result.TLCut > 0)
                    {
                        DownJunctions[off] |= JunctionFlags.BottomLeft;
                        if (y < height) DownJunctions[off + width] |= JunctionFlags.TopRight;
                    }
                    else
                    {
                        UpJunctions[off] |= JunctionFlags.BottomLeft;
                        if (y < height) UpJunctions[off + width] |= JunctionFlags.TopRight;
                    }
                }

                if ((wall.Segments & WallSegments.TopRight) > 0 && !(wall.TopRightDoor && result.TRCut > 0) && wall.TopRightThick)
                {
                    if (result.TRCut > 0)
                    {
                        DownJunctions[off] |= JunctionFlags.BottomRight;
                        if (x < width) DownJunctions[off + 1] |= JunctionFlags.TopLeft;
                    }
                    else
                    {
                        UpJunctions[off] |= JunctionFlags.BottomRight;
                        if (x < width) UpJunctions[off + 1] |= JunctionFlags.TopLeft;
                    }
                }

                if (wall.Segments == WallSegments.VerticalDiag && (wall.TopRightStyle == 1 || wall.TopRightStyle == 255))
                {
                    if (result.TRCut > 0)
                    {
                        DownJunctions[off] |= JunctionFlags.DiagBottom;
                        if (x < width && y < height) DownJunctions[off + 1 + width] |= JunctionFlags.DiagTop;
                    }
                    else
                    {
                        UpJunctions[off] |= JunctionFlags.DiagBottom;
                        if (x < width && y < height) UpJunctions[off + 1 + width] |= JunctionFlags.DiagTop;
                    }
                }
                else if (wall.Segments == WallSegments.HorizontalDiag && (wall.TopRightStyle == 1 || wall.TopRightStyle == 255))
                {
                    if (result.TRCut > 0)
                    {
                        if (x < width) DownJunctions[off + 1] |= JunctionFlags.DiagLeft;
                        if (y < height) DownJunctions[off + width] |= JunctionFlags.DiagRight;
                    }
                    else
                    {
                        if (x < width) UpJunctions[off + 1] |= JunctionFlags.DiagLeft;
                        if (y < height) UpJunctions[off + width] |= JunctionFlags.DiagRight;
                    }
                }
                Cuts[off] = result;
            }
        }
        private WallTile RotateWall(WorldRotation rot, WallTile input, short x, short y, sbyte level)
        {
            int rotN = (int)rot;
            var output = new WallTile();
            if (rot != 0)
            {
                if (input.Segments == WallSegments.HorizontalDiag)
                {
                    output.Segments = ((rotN % 2) == 0) ? WallSegments.HorizontalDiag : WallSegments.VerticalDiag;
                    output.TopRightStyle = input.TopRightStyle;
                    switch (rotN)
                    {
                        case 1:
                            output.BottomRightPattern = input.BottomLeftPattern;
                            output.BottomLeftPattern = input.BottomRightPattern;
                            output.TopLeftStyle = input.TopLeftPattern;
                            output.TopLeftPattern = input.TopLeftStyle;
                            break;
                        case 2:
                            output.BottomRightPattern = input.BottomLeftPattern; //flip sides
                            output.BottomLeftPattern = input.BottomRightPattern;
                            output.TopLeftStyle = input.TopLeftPattern;
                            output.TopLeftPattern = input.TopLeftStyle;
                            break;
                        case 3:
                            output.BottomRightPattern = input.BottomRightPattern;
                            output.BottomLeftPattern = input.BottomLeftPattern;
                            output.TopLeftStyle = input.TopLeftStyle;
                            output.TopLeftPattern = input.TopLeftPattern;
                            break;
                    }

                }
                else if (input.Segments == WallSegments.VerticalDiag)
                {
                    output.Segments = ((rotN % 2) == 0) ? WallSegments.VerticalDiag : WallSegments.HorizontalDiag;
                    output.TopRightStyle = input.TopRightStyle;
                    switch (rotN)
                    {
                        case 1:
                            output.BottomRightPattern = input.BottomRightPattern;
                            output.BottomLeftPattern = input.BottomLeftPattern;
                            output.TopLeftStyle = input.TopLeftStyle;
                            output.TopLeftPattern = input.TopLeftPattern;
                            break;
                        case 2:
                            output.BottomRightPattern = input.BottomLeftPattern; //flip sides
                            output.BottomLeftPattern = input.BottomRightPattern;
                            output.TopLeftStyle = input.TopLeftPattern;
                            output.TopLeftPattern = input.TopLeftStyle;
                            break;
                        case 3:
                            output.BottomRightPattern = input.BottomLeftPattern;
                            output.BottomLeftPattern = input.BottomRightPattern;
                            output.TopLeftStyle = input.TopLeftPattern;
                            output.TopLeftPattern = input.TopLeftStyle;
                            break;
                    }
                }
                else
                {
                    switch (rotN)
                    {
                        case 1:
                            if ((input.Segments & WallSegments.TopLeft) > 0) output.Segments |= WallSegments.TopRight;
                            if ((input.Segments & WallSegments.TopRight) > 0) output.Segments |= WallSegments.BottomRight;
                            if ((input.Segments & WallSegments.BottomRight) > 0) output.Segments |= WallSegments.BottomLeft;
                            if ((input.Segments & WallSegments.BottomLeft) > 0) output.Segments |= WallSegments.TopLeft;
                            output.TopLeftPattern = input.BottomLeftPattern;
                            output.TopRightPattern = input.TopLeftPattern;
                            output.BottomRightPattern = input.TopRightPattern;
                            output.BottomLeftPattern = input.BottomRightPattern;

                            if (y + 1 < blueprint.Height)
                            {
                                var newLeft = blueprint.GetWall(x, (short)(y + 1), level);
                                output.TopLeftStyle = newLeft.TopRightStyle;
                                output.ObjSetTLStyle = newLeft.ObjSetTRStyle;
                                output.TopLeftDoor = newLeft.TopRightDoor;
                            }

                            output.TopRightStyle = input.TopLeftStyle;
                            output.ObjSetTRStyle = input.ObjSetTLStyle;
                            output.TopRightDoor = input.TopLeftDoor;
                            break;
                        case 2:
                            if ((input.Segments & WallSegments.TopLeft) > 0) output.Segments |= WallSegments.BottomRight;
                            if ((input.Segments & WallSegments.TopRight) > 0) output.Segments |= WallSegments.BottomLeft;
                            if ((input.Segments & WallSegments.BottomRight) > 0) output.Segments |= WallSegments.TopLeft;
                            if ((input.Segments & WallSegments.BottomLeft) > 0) output.Segments |= WallSegments.TopRight;
                            output.TopLeftPattern = input.BottomRightPattern;
                            output.TopRightPattern = input.BottomLeftPattern;
                            output.BottomRightPattern = input.TopLeftPattern;
                            output.BottomLeftPattern = input.TopRightPattern;

                            if (y + 1 < blueprint.Height)
                            {
                                var newRight = blueprint.GetWall(x, (short)(y + 1), level);
                                output.TopRightStyle = newRight.TopRightStyle;
                                output.ObjSetTRStyle = newRight.ObjSetTRStyle;
                                output.TopRightDoor = newRight.TopRightDoor;
                            }

                            if (x + 1 < blueprint.Width)
                            {
                                var newLeft = blueprint.GetWall((short)(x + 1), y, level);
                                output.TopLeftStyle = newLeft.TopLeftStyle;
                                output.ObjSetTLStyle = newLeft.ObjSetTLStyle;
                                output.TopLeftDoor = newLeft.TopLeftDoor;
                            }

                            break;
                        case 3:
                            if ((input.Segments & WallSegments.TopLeft) > 0) output.Segments |= WallSegments.BottomLeft;
                            if ((input.Segments & WallSegments.TopRight) > 0) output.Segments |= WallSegments.TopLeft;
                            if ((input.Segments & WallSegments.BottomRight) > 0) output.Segments |= WallSegments.TopRight;
                            if ((input.Segments & WallSegments.BottomLeft) > 0) output.Segments |= WallSegments.BottomRight;
                            output.TopLeftPattern = input.TopRightPattern;
                            output.TopRightPattern = input.BottomRightPattern;
                            output.BottomRightPattern = input.BottomLeftPattern;
                            output.BottomLeftPattern = input.TopLeftPattern;

                            output.TopLeftStyle = input.TopRightStyle;
                            output.TopLeftDoor = input.TopRightDoor;
                            output.ObjSetTLStyle = input.ObjSetTRStyle;

                            if (x + 1 < blueprint.Width)
                            {
                                var newRight = blueprint.GetWall((short)(x + 1), y, level);
                                output.TopRightStyle = newRight.TopLeftStyle;
                                output.ObjSetTRStyle = newRight.ObjSetTLStyle;
                                output.TopRightDoor = newRight.TopLeftDoor;
                            }
                            break;
                    }
                }
            }
            else
            {
                output = input;
            }

            return output;
        }
        private static void SpreadOnto(WallTile[] walls, int x, int y, int inDir, byte[] map, int width, int height, Stack<Point> spread, ushort pattern, bool floorMode)
        {
            var wall = walls[x + y * width];
            if ((wall.Segments & WallSegments.HorizontalDiag) > 0)
            {
                if (inDir < 2)
                {
                    //bottom (bottom right pattern)
                    if (!floorMode) wall.BottomLeftPattern = pattern;
                    map[x + y * width] |= 1;
                } else
                {
                    //top (bottom left pattern)
                    if (!floorMode) wall.BottomRightPattern = pattern;
                    map[x + y * width] |= 2;
                }
                if (!floorMode) walls[x + y * width] = wall;
            }
            else if ((wall.Segments & WallSegments.VerticalDiag) > 0)
            {
                if (inDir > 0 && inDir < 3)
                {
                    //left
                    if (!floorMode) wall.BottomRightPattern = pattern;
                    map[x + y * width] |= 1;
                }
                else
                {
                    //right
                    if (!floorMode) wall.BottomLeftPattern = pattern;
                    map[x + y * width] |= 2;
                }
                if (!floorMode) walls[x + y * width] = wall;
            }
            else
            {
                map[x + y * width] = 3;
            }

            spread.Push(new Point(x, y));
        }
예제 #9
0
        public VMPlacementError WallChangeValid(WallTile wall, Direction direction, bool checkUnused)
        {
            var placeFlags = (WallPlacementFlags)ObjectData[(int)VMStackObjectVariable.WallPlacementFlags];

            bool diag = ((wall.Segments & (WallSegments.HorizontalDiag | WallSegments.VerticalDiag)) > 0);
            if (diag && (placeFlags & WallPlacementFlags.DiagonalAllowed) == 0) return VMPlacementError.CantBeThroughWall; //does not allow diagonal and one is present
            else if (!diag && ((placeFlags & WallPlacementFlags.DiagonalRequired) > 0)) return VMPlacementError.MustBeOnDiagonal; //needs diagonal and one is not present

            int rotate = (DirectionToWallOff(direction) + 1) % 4;
            int rotPart = RotateWallSegs(wall.Segments, rotate);
            int useRotPart = RotateWallSegs(wall.OccupiedWalls, rotate);

            if (((int)placeFlags & rotPart) != ((int)placeFlags & 15)) return VMPlacementError.MustBeAgainstWall; //walls required are not there in this configuration

            //walls that we are attaching to must not be in use!
            if (checkUnused && ((int)placeFlags & useRotPart) > 0) return VMPlacementError.MustBeAgainstUnusedWall;

            if (((int)placeFlags & (rotPart << 8)) > 0) return VMPlacementError.CantBeThroughWall; //walls not allowed are there in this configuration

            return VMPlacementError.Success;
        }