//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; }
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); } }
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); }
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)); }
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; }