/// <summary> /// Cuts the specified rectangle. Returns true if a *potentially noticable change* occurred as a result. (changed a cut to true on a tile where there is a wall) /// </summary> /// <param name="target"></param> /// <param name="cuts"></param> /// <param name="rect"></param> /// <returns></returns> public static bool ApplyCutRectangle(VMArchitecture target, sbyte floor, bool[] cuts, Rectangle rect) { var walls = target.Walls[floor - 1]; var width = target.Width; bool change = false; for (int x = rect.Left; x < rect.Right; x++) { for (int y = rect.Top; y < rect.Bottom; y++) { if (x < 0 || x >= target.Width || y < 0 || y >= target.Height) { continue; } var offset = (y * target.Width + x); if (walls[offset].Segments == 0 && (offset + width < walls.Length && walls[offset + width].Segments == 0) && (offset + 1 < walls.Length && walls[offset + 1].Segments == 0) && (offset - width > 0 && walls[offset - width].Segments == 0) && (offset - 1 > 0 && walls[offset - 1].Segments == 0) ) { continue; } if (!cuts[offset]) { cuts[offset] = true; change = true; } } } return(change); }
public static int GetPatternDirection(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) { return(-1); } var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & WallSegments.HorizontalDiag) > 0) { return(direction); } else if ((wall.Segments & WallSegments.VerticalDiag) > 0) { return(direction); } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) { direction = altDir; } else { return(-1); } return(direction); }
public static void StampTerrainmap(VMArchitecture arch, byte[] tilemap, short x, short y, Vector2 xInc, Vector2 yInc) { var width = tilemap[0]; var height = tilemap[1]; for (int i = 2; i < tilemap.Length; i++) { if (tilemap[i] == 0) { continue; } var src = new Vector2((i - 2) % width, (i - 2) / width); var dst = src.X * xInc + src.Y * yInc; var xo = (int)(dst.X); var yo = (int)(dst.Y); if (x + xo >= arch.Width - 1 || y + yo >= arch.Height - 1) { continue; } var mult = tilemap[i] / 255f; var archOff = (y + yo) * arch.Width + (x + xo); arch.Terrain.GrassState[archOff] = (byte)(((1 - mult) * arch.Terrain.GrassState[archOff] + mult * 255)); } }
public static bool VerifyDrawWall(VMArchitecture target, Point pos, int length, int direction, sbyte level) { pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { if (target.OutsideClip((short)pos.X, (short)pos.Y, level)) { return(false); } var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & AnyDiag) == 0 && (!diagCheck || (wall.Segments == 0))) { wall.Segments |= WLMainSeg[direction]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, level), wall)) { return(false); } if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; //get the other side of the wall if (target.OutsideClip((short)tPos.X, (short)tPos.Y, level)) { return(false); //both sides of wall must be in bounds } wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); if (!(level == 1 || target.Supported[level - 2][pos.Y * target.Width + pos.X] || target.Supported[level - 2][tPos.Y * target.Width + tPos.X])) { return(false); } if ((wall.Segments & AnyDiag) == 0) { wall.Segments |= WLSubSeg[direction / 2]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)tPos.X, (short)tPos.Y, level), wall)) { return(false); } } else { return(false); } } else { if (!(level == 1 || target.Supported[level - 2][pos.Y * target.Width + pos.X])) { return(false); } } } else { return(false); } pos += WLStep[direction]; } return(true); }
public static bool VerifyEraseWall(VMArchitecture target, Point pos, int length, int direction, sbyte level) { pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { if (pos.X <= 0 || pos.X >= target.Width || pos.Y <= 0 || pos.Y >= target.Height) { return(false); } var wall = target.GetWall((short)pos.X, (short)pos.Y, level); wall.Segments &= ~WLMainSeg[direction]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, level), wall)) { return(false); } if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments &= ~WLSubSeg[direction / 2]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)tPos.X, (short)tPos.Y, level), wall)) { return(false); } } pos += WLStep[direction]; } return(true); }
public static int EraseWall(VMArchitecture target, Point pos, int length, int direction, ushort pattern, ushort style, sbyte level) { if (!VerifyEraseWall(target, pos, length, direction, level)) { return(0); } int totalWalls = 0; pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & WLMainSeg[direction]) > 0) { totalWalls++; } wall.Segments &= ~WLMainSeg[direction]; target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments &= ~WLSubSeg[direction / 2]; target.SetWall((short)tPos.X, (short)tPos.Y, level, wall); } pos += WLStep[direction]; } return(totalWalls); }
public static void RepeatTilemap(VMArchitecture arch, short[] tilemap, short x, short y, sbyte level, int xtimes, int ytimes) { for (int xo = 0; xo < xtimes; xo++) { for (int yo = 0; yo < ytimes; yo++) { StampTilemap(arch, tilemap, (short)(x + xo * tilemap[0]), (short)(y + yo * tilemap[1]), level); } } }
public static void ApplyTerrainBlend(VMArchitecture arch, int flags, Rectangle area, int startVal, int xChange, int yChange, Point[] coneCtr, float[] pivots, float[] ranges) { //neighbourhood of 5 flags. 1=ccw edge, 2 = ccw corner, 4 = my edge, 8 = cw corner, 16 = cw edge bool flipCone = (flags & 4) == 0; if (flipCone) { return; //flipCone mode was experimental and actually doesn't work with the corner drawing method I was using. } bool corner1 = ((flags & 4) == 0) ? (((flags & 1) == 0 && ((flags & 2) > 0)) ? true : false) //inverted mode. draw part corner if no edge to make up for it : ((flags & 2) == 0); // corner fade if no corner present bool corner2 = ((flags & 4) == 0) ? (((flags & 16) == 0 && ((flags & 8) > 0)) ? true : false) //inverted mode. draw part corner if no edge to make up for it : ((flags & 8) == 0); // corner fade if no corner present for (int x = 0; x < area.Width; x++) { var ox = x + area.X; for (int y = 0; y < area.Height; y++) { var oy = y + area.Y; var val = startVal + xChange * x + yChange * y; int closest = -1; int closestDist = int.MaxValue; for (int i = 0; i < coneCtr.Length; i++) { var dx = coneCtr[i].X - ox; var dy = coneCtr[i].Y - oy; var dist = dx * dx + dy * dy; if (dist < closestDist) { closestDist = dist; closest = i; } } if (closest != -1) { if ((closest == 0 && corner1) || (closest == 1 && corner2)) { val = (int)(val * ((flipCone?1:0) + ConeMult(coneCtr[closest], new Point(ox, oy), pivots[closest], ranges[closest] * (flipCone ? -1 : 1)))); } else if (flipCone) { val = 0; } } val += arch.Terrain.GrassState[oy * arch.Width + ox]; arch.Terrain.GrassState[oy * arch.Width + ox] = (byte)(Math.Max(0, Math.Min(255, val))); } } }
public static bool[] GenerateRoomCut(VMArchitecture target, sbyte floor, WorldRotation dir, HashSet <uint> cutRooms) { var result = new bool[target.Width * target.Height]; var offset = 0; var roommap = target.Rooms[floor - 1].Map; var cutDir = CutCheckDir[(int)dir]; var walls = target.Walls[floor - 1]; var width = target.Width; for (int y1 = 0; y1 < target.Height; y1++) { for (int x1 = 0; x1 < target.Width; x1++) { if (walls[offset].Segments == 0 && (offset + width < walls.Length && walls[offset + width].Segments == 0) && (offset + 1 < walls.Length && walls[offset + 1].Segments == 0) && (offset - width > 0 && walls[offset - width].Segments == 0) && (offset - 1 > 0 && walls[offset - 1].Segments == 0) ) { offset++; continue; //ignore empty tiles as an optimisation } bool cut = false; for (int i = 0; i < 3; i++) { var x = x1 + ((i == 1) ? cutDir[0] : 0); var y = y1 + ((i == 2) ? cutDir[1] : 0); for (int j = 0; j < ((i > 0)?4:5); j++) { if (x < 0 || x >= target.Width || y < 0 || y >= target.Height) { break; } if (cutRooms.Contains(roommap[y * target.Width + x] & 65535)) { cut = true; break; } x += cutDir[0]; y += cutDir[1]; } if (cut) { break; } } result[offset++] = cut; } } return(result); }
public static void FillTerrainRect(VMArchitecture arch, Rectangle area, byte value) { for (int x = 0; x < area.Width; x++) { var ox = x + area.X; for (int y = 0; y < area.Height; y++) { var oy = y + area.Y; arch.Terrain.GrassState[oy * arch.Width + ox] = value; } } }
//things 2 note //default style is 1 //default pattern is 0 //mid drawing pattern/style is 255 public static int DrawWall(VMArchitecture target, Point pos, int length, int direction, ushort pattern, ushort style, sbyte level, bool force) { if (!force && !VerifyDrawWall(target, pos, length, direction, level)) return 0; int totalWalls = 0; pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i=0; i<length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & (WLMainSeg[direction] | AnyDiag)) == 0 && (!diagCheck || (wall.Segments == 0))) { //no wall here already, apply it. wall.Segments |= WLMainSeg[direction]; if (diagCheck) { wall.TopRightStyle = style; wall.BottomLeftPattern = pattern; wall.BottomRightPattern = pattern; } else if (WLMainSeg[direction] == WallSegments.TopRight) { wall.TopRightStyle = style; wall.TopRightPattern = pattern; } else { wall.TopLeftStyle = style; wall.TopLeftPattern = pattern; } totalWalls++; target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments |= WLSubSeg[direction / 2]; if (WLSubSeg[direction / 2] == WallSegments.BottomRight) wall.BottomRightPattern = pattern; else wall.BottomLeftPattern = pattern; target.SetWall((short)tPos.X, (short)tPos.Y, level, wall); } } pos += WLStep[direction]; } return totalWalls; }
//==== TERRAIN ==== public static int DotTerrain(VMArchitecture target, Point pos, short mod) { var bounds = target.DisableClip ? new Rectangle(0, 0, target.Width, target.Height) : target.BuildableArea; bounds.X--; bounds.Y--; bounds.Width++; bounds.Height++; if (!bounds.Contains(pos)) { return(0); } var current = target.GetTerrainGrass((short)pos.X, (short)pos.Y); var n = (byte)Math.Max(0, Math.Min(255, current + mod)); target.SetTerrainGrass((short)pos.X, (short)pos.Y, n); return((Math.Abs(current - n) + 31) / 32); }
public static void FillTileLine(VMArchitecture arch, short tile, short x, short y, sbyte level, short[] line, bool horiz) { for (int i = 0; i < line.Length; i += 2) { var segLen = line[i]; var thickness = line[i + 1]; if (horiz) { FillTiles(arch, tile, x, (short)(y - thickness), level, segLen, thickness * 2 + 1); x += segLen; } else { FillTiles(arch, tile, (short)(x - thickness), y, level, thickness * 2 + 1, segLen); y += segLen; } } }
public static int DrawWallRect(VMArchitecture target, Rectangle rect, ushort pattern, ushort style, sbyte level) { if (!( VerifyDrawWall(target, new Point(rect.X, rect.Y), rect.Width, 0, level) && VerifyDrawWall(target, new Point(rect.X, rect.Y), rect.Height, 2, level) && VerifyDrawWall(target, new Point(rect.X, rect.Y + rect.Height), rect.Width, 0, level) && VerifyDrawWall(target, new Point(rect.X + rect.Width, rect.Y), rect.Height, 2, level) )) { return(0); } int totalWalls = 0; totalWalls += DrawWall(target, new Point(rect.X, rect.Y), rect.Width, 0, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X, rect.Y), rect.Height, 2, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X, rect.Y + rect.Height), rect.Width, 0, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X + rect.Width, rect.Y), rect.Height, 2, pattern, style, level, true); return(totalWalls); }
public static void FillTiles(VMArchitecture arch, short tile, short x, short y, sbyte level, int xtimes, int ytimes) { for (int xo = 0; xo < xtimes; xo++) { var x2 = (short)(x + xo); if (x2 < 1 || x2 >= arch.Width - 1) { continue; } for (int yo = 0; yo < ytimes; yo++) { var y2 = (short)(y + yo); if (y2 < 1 || y2 >= arch.Height - 1) { continue; } arch.SetFloor(x2, y2, level, new FloorTile() { Pattern = (ushort)tile }, true); } } }
public static void StampTilemap(VMArchitecture arch, short[] tilemap, short x, short y, sbyte level, bool skipZero) { var width = tilemap[0]; var height = tilemap[1]; for (int i = 2; i < tilemap.Length; i++) { if (skipZero && tilemap[i] == 0) { continue; } var xo = (i - 2) % width; var yo = (i - 2) / width; if (x + xo >= arch.Width - 1 || y + yo >= arch.Height - 1) { continue; } arch.SetFloor((short)(x + xo), (short)(y + yo), level, new LotView.Model.FloorTile() { Pattern = (ushort)tilemap[i] }, true); } }
//returns floors covered public static int FloorPatternRect(VMArchitecture target, Rectangle rect, ushort dir, ushort pattern, sbyte level) { int floorsCovered = 0; if (rect.Width == 0 && rect.Height == 0) { //dot mode, just fill a tile. can be a diagonal. if (rect.X < 0 || rect.X >= target.Width || rect.Y < 0 || rect.Y >= target.Width) return 0; var wall = target.GetWall((short)rect.X, (short)rect.Y, level); if ((wall.Segments & AnyDiag) > 0) { bool side = ((wall.Segments & WallSegments.HorizontalDiag) > 0) ? (dir < 2) : (dir < 1 || dir > 2); if (side) { if (wall.TopLeftStyle != pattern) { floorsCovered++; wall.TopLeftStyle = pattern; } } else { if (wall.TopLeftPattern != pattern) { floorsCovered++; wall.TopLeftPattern = pattern; } } target.SetWall((short)rect.X, (short)rect.Y, level, wall); } else { var floor = target.GetFloor((short)rect.X, (short)rect.Y, level); if (floor.Pattern != pattern) { floor.Pattern = pattern; if (target.SetFloor((short)rect.X, (short)rect.Y, level, floor, false)) floorsCovered += 2; } } return floorsCovered; } var xEnd = Math.Min(target.Width, rect.X + rect.Width+1); var yEnd = Math.Min(target.Height, rect.Y + rect.Height+1); for (int y = Math.Max(0, rect.Y); y < yEnd; y++) { for (int x = Math.Max(0, rect.X); x < xEnd; x++) { var wall = target.GetWall((short)x, (short)y, level); if ((wall.Segments & AnyDiag) > 0) //diagonal floors are stored in walls { if (wall.TopLeftStyle != pattern) { wall.TopLeftStyle = pattern; floorsCovered++; } if (wall.TopLeftPattern != pattern) { wall.TopLeftPattern = pattern; floorsCovered++; } target.SetWall((short)x, (short)y, level, wall); } else { var floor = target.GetFloor((short)x, (short)y, level); if (floor.Pattern != pattern) { floor.Pattern = pattern; if (target.SetFloor((short)x, (short)y, level, floor, false)) floorsCovered += 2; } } } } return floorsCovered; }
public static int WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height) { return(-1); } var wall = target.GetWall((short)pos.X, (short)pos.Y, level); //direction starts lefttop, righttop if ((wall.Segments & WallSegments.HorizontalDiag) > 0) { if (direction < 2) { //bottom (bottom right pattern) wall.BottomRightPattern = pattern; } else { //top (bottom left pattern) wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); return(direction); } else if ((wall.Segments & WallSegments.VerticalDiag) > 0) { if (direction > 0 && direction < 3) { //left wall.BottomLeftPattern = pattern; } else { //right wall.BottomRightPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); return(direction); } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) { direction = altDir; } else { return(-1); } if (direction == 0) { wall.TopLeftPattern = pattern; } else if (direction == 1) { wall.TopRightPattern = pattern; } else if (direction == 2) { wall.BottomRightPattern = pattern; } else if (direction == 3) { wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); return(direction); }
public static int RaiseTerrain(VMArchitecture target, Rectangle pos, short height, bool smoothMode) { //does a sort of flood fill from the start point to ensure the raise is valid //when any point height is changed its neighbours are checked for the height difference constraint int constrain = 5 * 10; if (smoothMode) { constrain = 1 * 10; } var bounds = target.DisableClip ? new Rectangle(0, 0, target.Width, target.Height) : target.BuildableArea; var tl = target.TerrainLimit; bounds = Rectangle.Intersect(bounds, tl); bounds.Width--; bounds.Height--; if (!pos.Intersects(bounds)) { return(0); } else { pos = Rectangle.Intersect(pos, bounds); } var considered = new Dictionary <Point, short>(); var stack = new Stack <Point>(); for (int x = 0; x <= pos.Width; x++) { for (int y = 0; y <= pos.Height; y++) { var p = pos.Location + new Point(x, y); stack.Push(p); considered.Add(p, height); if (!(target.DisableClip || target.Context.SlopeVertexCheck(p.X, p.Y))) { return(0); } } } var tr = target.Terrain; var firstDiff = tr.Heights[pos.Y * tr.Width + pos.X] - height; while (stack.Count > 0) { var p = stack.Pop(); //check adjacent points var adj = new Point[] { p + new Point(-1, 0), p + new Point(1, 0), p + new Point(0, -1), p + new Point(0, 1), }; //if any of these are OOB exit early. TODO var myHeight = considered[p]; // check each adjacent height. if it has to be changed, first check if it can be: // - if a wall, floor (on any level) or object is preventing this from happening, fail. // - else queue its height to be changed and check its adjacent. foreach (var a in adj) { if (a.X < 0 || a.Y < 0 || a.X >= tr.Width || a.Y >= tr.Height) { return(0); } short ht; if (!considered.TryGetValue(a, out ht)) { ht = tr.Heights[a.Y * tr.Width + a.X]; } var diff = myHeight - ht; var first = height - ht; if (!target.TerrainLimit.Contains(a)) { if (!target.DisableClip && Math.Abs(diff) > 100 * 10) { return(0); } else { continue; } } if (diff * first <= 0) { continue; } if (smoothMode) { constrain = Math.Min(5, Math.Max(1, (int)Math.Round(DistanceToRect(a, pos)))) * 10; } if (diff > constrain) { //lower the terrain ht = (short)(myHeight - constrain); } else if (diff < -constrain) { //raise the terrain ht = (short)(myHeight + constrain); } else { continue; } if (!(target.DisableClip || target.Context.SlopeVertexCheck(a.X, a.Y))) { return(0); } //we needed to change the height. verify that that is a legal move. (walls, floors, objects demand no slope change) //todo considered[a] = ht; //this can overwrite previous expectations stack.Push(a); } } //actually change the terrain int cost = 0; foreach (var change in considered) { var changedBy = Math.Abs(target.GetTerrainHeight((short)change.Key.X, (short)change.Key.Y) - change.Value); cost += (changedBy + 9) / 10; target.SetTerrainHeight((short)change.Key.X, (short)change.Key.Y, change.Value); if (change.Key.X > 0 && change.Key.Y > 0) { target.SetTerrainGrass((short)(change.Key.X - 1), (short)(change.Key.Y - 1), (byte)Math.Min(255, target.GetTerrainGrass((short)(change.Key.X - 1), (short)(change.Key.Y - 1)) + changedBy * 6)); } } return(cost); }
/// <summary> /// Cuts the specified rectangle. Returns true if a *potentially noticable change* occurred as a result. (changed a cut to true on a tile where there is a wall) /// </summary> /// <param name="target"></param> /// <param name="cuts"></param> /// <param name="rect"></param> /// <returns></returns> public static bool ApplyCutRectangle(VMArchitecture target, sbyte floor, bool[] cuts, Rectangle rect) { var walls = target.Walls[floor - 1]; var width = target.Width; bool change = false; for (int x = rect.Left; x < rect.Right; x++) { for (int y=rect.Top; y < rect.Bottom; y++) { if (x < 0 || x >= target.Width || y < 0 || y >= target.Height) continue; var offset = (y * target.Width + x); if (walls[offset].Segments == 0 && (offset + width < walls.Length && walls[offset + width].Segments == 0) && (offset + 1 < walls.Length && walls[offset + 1].Segments == 0) && (offset - width > 0 && walls[offset - width].Segments == 0) && (offset - 1 > 0 && walls[offset - 1].Segments == 0) ) continue; if (!cuts[offset]) { cuts[offset] = true; change = true; } } } return change; }
public static bool[] GenerateRoomCut(VMArchitecture target, sbyte floor, WorldRotation dir, HashSet<uint> cutRooms) { var result = new bool[target.Width*target.Height]; var offset = 0; var roommap = target.Rooms[floor-1].Map; var cutDir = CutCheckDir[(int)dir]; var walls = target.Walls[floor - 1]; var width = target.Width; for (int y1=0;y1<target.Height; y1++) { for (int x1=0; x1<target.Width; x1++) { if (walls[offset].Segments == 0 && (offset + width < walls.Length && walls[offset + width].Segments == 0) && (offset + 1 < walls.Length && walls[offset + 1].Segments == 0) && (offset - width > 0 && walls[offset - width].Segments == 0) && (offset - 1 > 0 && walls[offset - 1].Segments == 0) ) { offset++; continue; //ignore empty tiles as an optimisation } bool cut = false; for (int i=0; i<3; i++) { var x = x1 + ((i == 1) ? cutDir[0] : 0); var y = y1 + ((i == 2) ? cutDir[1] : 0); for (int j=0; j<((i>0)?4:5); j++) { if (x < 0 || x >= target.Width || y < 0 || y >= target.Height) break; if (cutRooms.Contains(roommap[y * target.Width + x] & 65535)) { cut = true; break; } x += cutDir[0]; y += cutDir[1]; } if (cut) break; } result[offset++] = cut; } } return result; }
public static PatternReplaceCount WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height) return new PatternReplaceCount { Total = -1 }; //pattern replace count used a little differently here. cost still stores replaced cost, but total stores replaced direction. PatternReplaceCount replaceCost = new PatternReplaceCount(false); ushort replaced = 0; var wall = target.GetWall((short)pos.X, (short)pos.Y, level); //direction starts lefttop, righttop if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && wall.TopRightStyle == 1) { if (direction < 2) { //bottom (bottom right pattern) replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } else { //top (bottom left pattern) replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) return new PatternReplaceCount { Total = -1 }; replaceCost.Add(replaced); replaceCost.Total = direction; return replaceCost; } else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && wall.TopRightStyle == 1) { if (direction > 0 && direction < 3) { //left replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } else { //right replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) return new PatternReplaceCount { Total = -1 }; replaceCost.Add(replaced); replaceCost.Total = direction; return replaceCost; } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) direction = altDir; else { return new PatternReplaceCount { Total = -1 }; } if (direction == 0 && wall.TopLeftThick) { replaced = wall.TopLeftPattern; wall.TopLeftPattern = pattern; } else if (direction == 1 && wall.TopRightThick) { replaced = wall.TopRightPattern; wall.TopRightPattern = pattern; } else if (direction == 2 && pos.X < target.Width && target.GetWall((short)(pos.X + 1), (short)pos.Y, level).TopLeftThick) { replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } else if (direction == 3 && pos.Y < target.Height && target.GetWall((short)pos.X, (short)(pos.Y + 1), level).TopRightThick) { replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) return new PatternReplaceCount { Total = -1 }; replaceCost.Add(replaced); replaceCost.Total = direction; return replaceCost; }
public static int GetArchValue(VMArchitecture arch) { Floors = GameContent.Get.WorldFloors; Walls = GameContent.Get.WorldWalls; int value = 0; for (int level = 0; level < arch.Stories; level++) { var walls = arch.Walls[level]; var floors = arch.Floors[level]; int index = 0; for (int y = 0; y < arch.Height; y++) { for (int x = 0; x < arch.Width; x++) { if (arch.FineBuildableArea[index]) { var floor = floors[index]; var wall = walls[index]; if (floor.Pattern > 0) { value += GetFloorPrice(floor.Pattern); } if (wall.Segments > 0) { if ((wall.Segments & WallSegments.AnyDiag) > 0) { value += GetWallPrice(wall.TopRightStyle); if (wall.TopLeftPattern != 0) { value += GetFloorPrice(wall.TopLeftPattern) / 2; } if (wall.TopLeftStyle != 0) { value += GetFloorPrice(wall.TopLeftStyle) / 2; } if (wall.BottomLeftPattern != 0) { value += GetPatternPrice(wall.BottomLeftPattern); } if (wall.BottomRightPattern != 0) { value += GetPatternPrice(wall.BottomRightPattern); } } else { if ((wall.Segments & WallSegments.TopLeft) > 0) { value += GetWallPrice(wall.TopLeftStyle); value += GetPatternPrice(wall.TopLeftPattern); var wall2 = walls[index - 1]; value += GetPatternPrice(wall2.BottomRightPattern); } if ((wall.Segments & WallSegments.TopRight) > 0) { value += GetWallPrice(wall.TopRightStyle); value += GetPatternPrice(wall.TopRightPattern); var wall2 = walls[index - arch.Width]; value += GetPatternPrice(wall2.BottomLeftPattern); } } } } index++; } } } return(value); }
public static int DrawWallRect(VMArchitecture target, Rectangle rect, ushort pattern, ushort style, sbyte level) { if (!( VerifyDrawWall(target, new Point(rect.X, rect.Y), rect.Width, 0, level) && VerifyDrawWall(target, new Point(rect.X, rect.Y), rect.Height, 2, level) && VerifyDrawWall(target, new Point(rect.X, rect.Y + rect.Height), rect.Width, 0, level) && VerifyDrawWall(target, new Point(rect.X + rect.Width, rect.Y), rect.Height, 2, level) )) return 0; int totalWalls = 0; totalWalls += DrawWall(target, new Point(rect.X, rect.Y), rect.Width, 0, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X, rect.Y), rect.Height, 2, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X, rect.Y + rect.Height), rect.Width, 0, pattern, style, level, true); totalWalls += DrawWall(target, new Point(rect.X + rect.Width, rect.Y), rect.Height, 2, pattern, style, level, true); return totalWalls; }
//for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result /// <summary> /// Fills a room with a certain wall pattern. Returns walls covered /// </summary> public static int WallPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) return 0; pos.X = Math.Max(Math.Min(pos.X, target.Width-1), 0); pos.Y = Math.Max(Math.Min(pos.Y, target.Height-1), 0); var walls = target.Walls[level-1]; var width = target.Width; var height = target.Height; int wallsCovered = 0; byte[] Map = new byte[target.Width * target.Height]; //flood fill recursively. Each time choose find and choose the first "0" as the base. //The first recursion (outside) cannot fill into diagonals. var spread = new Stack<Point>(); spread.Push(pos); 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] < 3 && ((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1)) SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, false); else { if (mainWalls.BottomRightPattern != pattern) wallsCovered++; mainWalls.BottomRightPattern = pattern; } if (Map[minX + item.Y * width]<3 && ((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1)) SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, false); else { if (mainWalls.TopLeftPattern != pattern) wallsCovered++; mainWalls.TopLeftPattern = pattern; } if (Map[item.X + plusY * width]<3 && ((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1)) SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, false); else { if (mainWalls.BottomLeftPattern != pattern) wallsCovered++; mainWalls.BottomLeftPattern = pattern; } if (Map[item.X + minY * width]<3 && ((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1)) SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, false); else { if (mainWalls.TopRightPattern != pattern) wallsCovered++; mainWalls.TopRightPattern = pattern; } walls[item.X + item.Y * width] = mainWalls; } return wallsCovered; }
public static PatternReplaceCount FloorPatternRect(VMArchitecture target, Rectangle rect, ushort dir, ushort pattern, sbyte level) //returns floors covered { PatternReplaceCount floorsCovered = new PatternReplaceCount(true); if (rect.Width == 0 && rect.Height == 0) { //dot mode, just fill a tile. can be a diagonal. if (rect.X < 0 || rect.X >= target.Width || rect.Y < 0 || rect.Y >= target.Width) { return(floorsCovered); } var wall = target.GetWall((short)rect.X, (short)rect.Y, level); if ((wall.Segments & AnyDiag) > 0 && pattern < 65534) { bool side = ((wall.Segments & WallSegments.HorizontalDiag) > 0) ? (dir < 2) : (dir < 1 || dir > 2); if (side) { if (wall.TopLeftStyle != pattern) { floorsCovered.Add(wall.TopLeftStyle); wall.TopLeftStyle = pattern; } } else { if (wall.TopLeftPattern != pattern) { floorsCovered.Add(wall.TopLeftPattern); wall.TopLeftPattern = pattern; } } target.SetWall((short)rect.X, (short)rect.Y, level, wall); } else if ((wall.Segments & AnyDiag) == 0) { var floor = target.GetFloor((short)rect.X, (short)rect.Y, level); if (floor.Pattern != pattern) { var old = floor.Pattern; floor.Pattern = pattern; if (target.SetFloor((short)rect.X, (short)rect.Y, level, floor, false)) { floorsCovered.DAdd(old); } } } return(floorsCovered); } var xEnd = Math.Min(target.Width, rect.X + rect.Width + 1); var yEnd = Math.Min(target.Height, rect.Y + rect.Height + 1); for (int y = Math.Max(0, rect.Y); y < yEnd; y++) { for (int x = Math.Max(0, rect.X); x < xEnd; x++) { var wall = target.GetWall((short)x, (short)y, level); if ((wall.Segments & AnyDiag) > 0) //diagonal floors are stored in walls { if (pattern < 65534) { continue; } if (wall.TopLeftStyle != pattern) { wall.TopLeftStyle = pattern; floorsCovered.Add(wall.TopLeftStyle); } if (wall.TopLeftPattern != pattern) { wall.TopLeftPattern = pattern; floorsCovered.Add(wall.TopLeftPattern); } target.SetWall((short)x, (short)y, level, wall); } else { var floor = target.GetFloor((short)x, (short)y, level); if (floor.Pattern != pattern) { var old = floor.Pattern; floor.Pattern = pattern; if (target.SetFloor((short)x, (short)y, level, floor, false)) { floorsCovered.DAdd(old); } } } } } return(floorsCovered); }
/// <summary> /// Fills a room with a certain wall pattern. Returns walls covered /// </summary> public static PatternReplaceCount WallPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) { return(new PatternReplaceCount()); } pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0); pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0); var walls = target.Walls[level - 1]; var width = target.Width; var height = target.Height; PatternReplaceCount wallsCovered = new PatternReplaceCount(false); byte[] Map = new byte[target.Width * target.Height]; //flood fill recursively. Each time choose find and choose the first "0" as the base. //The first recursion (outside) cannot fill into diagonals. var spread = new Stack <Point>(); spread.Push(pos); 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] < 3 && ((PXWalls.Segments & WallSegments.TopLeft) == 0 || PXWalls.TopLeftStyle != 1)) { wallsCovered += SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, false); } else { if (mainWalls.BottomRightPattern != pattern && PXWalls.TopLeftThick) { wallsCovered.Add(mainWalls.BottomRightPattern); mainWalls.BottomRightPattern = pattern; } } if (Map[minX + item.Y * width] < 3 && ((mainWalls.Segments & WallSegments.TopLeft) == 0 || mainWalls.TopLeftStyle != 1)) { wallsCovered += SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, false); } else { if (mainWalls.TopLeftPattern != pattern && mainWalls.TopLeftThick) { wallsCovered.Add(mainWalls.TopLeftPattern);; mainWalls.TopLeftPattern = pattern; } } if (Map[item.X + plusY * width] < 3 && ((PYWalls.Segments & WallSegments.TopRight) == 0 || PYWalls.TopRightStyle != 1)) { wallsCovered += SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, false); } else { if (mainWalls.BottomLeftPattern != pattern && PYWalls.TopRightThick) { wallsCovered.Add(mainWalls.BottomLeftPattern); mainWalls.BottomLeftPattern = pattern; } } if (Map[item.X + minY * width] < 3 && ((mainWalls.Segments & WallSegments.TopRight) == 0 || mainWalls.TopRightStyle != 1)) { wallsCovered += SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, false); } else { if (mainWalls.TopRightPattern != pattern && mainWalls.TopRightThick) { wallsCovered.Add(mainWalls.TopRightPattern); mainWalls.TopRightPattern = pattern; } } walls[item.X + item.Y * width] = mainWalls; } return(wallsCovered); }
public static int EraseWall(VMArchitecture target, Point pos, int length, int direction, ushort pattern, ushort style, sbyte level) { if (!VerifyEraseWall(target, pos, length, direction, level)) return 0; int totalWalls = 0; pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & WLMainSeg[direction]) > 0) totalWalls++; wall.Segments &= ~WLMainSeg[direction]; target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments &= ~WLSubSeg[direction / 2]; target.SetWall((short)tPos.X, (short)tPos.Y, level, wall); pos += WLStep[direction]; } } return totalWalls; }
//for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result /// <summary> /// Fills a room with a certain Floor pattern. Returns floors covered /// </summary> public static int FloorPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) return 0; pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0); pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0); var walls = target.Walls[level-1]; var width = target.Width; var height = target.Height; int floorsCovered = 0; byte[] Map = new byte[target.Width * target.Height]; //flood fill recursively. Each time choose find and choose the first "0" as the base. //The first recursion (outside) cannot fill into diagonals. var spread = new Stack<Point>(); spread.Push(pos); 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]; var floor = target.GetFloor((short)item.X, (short)item.Y, level); if ((byte)mainWalls.Segments > 15) { //draw floor onto a diagonal; var wall = walls[item.X + item.Y * width]; byte flags = Map[item.X + item.Y * width]; if (flags == 3) continue; if ((mainWalls.Segments & WallSegments.HorizontalDiag) > 0) flags = (byte)(3 - flags); if ((flags & 1) == 1 && wall.TopLeftPattern != pattern) { floorsCovered++; wall.TopLeftPattern = pattern; } else if ((flags & 2) == 2 && wall.TopLeftStyle != pattern) { floorsCovered++; wall.TopLeftStyle = pattern; } walls[item.X + item.Y * width] = wall; continue; //don't spread on diagonals for now } else { //normal tile, draw a floor here. if (floor.Pattern != pattern) { floor.Pattern = pattern; if (target.SetFloor((short)item.X, (short)item.Y, level, floor, false)) floorsCovered++; } } if (Map[plusX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.BottomRight) == 0) SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, true); if (Map[minX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.TopLeft) == 0) SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, true); if (Map[item.X + plusY * width] < 3 && (mainWalls.Segments & WallSegments.BottomLeft) == 0) SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, true); if (Map[item.X + minY * width] < 3 && (mainWalls.Segments & WallSegments.TopRight) == 0) SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, true); walls[item.X + item.Y * width] = mainWalls; } return floorsCovered; }
public static int GetPatternDirection(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) return -1; var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & WallSegments.HorizontalDiag) > 0) { return direction; } else if ((wall.Segments & WallSegments.VerticalDiag) > 0) { return direction; } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) direction = altDir; else { return -1; } return direction; }
public static bool VerifyDrawWall(VMArchitecture target, Point pos, int length, int direction, sbyte level) { pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & AnyDiag) == 0 && (!diagCheck || (wall.Segments == 0))) { wall.Segments &= ~WLMainSeg[direction]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, level), wall)) return false; if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); if (!(level == 1 || target.Supported[level - 2][pos.Y * target.Width + pos.X] || target.Supported[level - 2][tPos.Y * target.Width + tPos.X])) return false; if ((wall.Segments & AnyDiag) == 0) { wall.Segments |= WLSubSeg[direction / 2]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)tPos.X, (short)tPos.Y, level), wall)) return false; } else return false; } else { if (!(level == 1 || target.Supported[level - 2][pos.Y * target.Width + pos.X])) return false; } } else return false; pos += WLStep[direction]; } return true; }
public static PatternReplaceCount WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height) { return new PatternReplaceCount { Total = -1 } } ; //pattern replace count used a little differently here. cost still stores replaced cost, but total stores replaced direction. PatternReplaceCount replaceCost = new PatternReplaceCount(false); ushort replaced = 0; var wall = target.GetWall((short)pos.X, (short)pos.Y, level); //direction starts lefttop, righttop if ((wall.Segments & WallSegments.HorizontalDiag) > 0 && wall.TopRightStyle == 1) { if (direction < 2) { //bottom (bottom right pattern) replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } else { //top (bottom left pattern) replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) { return new PatternReplaceCount { Total = -1 } } ; replaceCost.Add(replaced); replaceCost.Total = direction; return(replaceCost); } else if ((wall.Segments & WallSegments.VerticalDiag) > 0 && wall.TopRightStyle == 1) { if (direction > 0 && direction < 3) { //left replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } else { //right replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) { return new PatternReplaceCount { Total = -1 } } ; replaceCost.Add(replaced); replaceCost.Total = direction; return(replaceCost); } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) { direction = altDir; } else { return(new PatternReplaceCount { Total = -1 }); } if (direction == 0 && wall.TopLeftThick) { replaced = wall.TopLeftPattern; wall.TopLeftPattern = pattern; } else if (direction == 1 && wall.TopRightThick) { replaced = wall.TopRightPattern; wall.TopRightPattern = pattern; } else if (direction == 2 && pos.X < target.Width && target.GetWall((short)(pos.X + 1), (short)pos.Y, level).TopLeftThick) { replaced = wall.BottomRightPattern; wall.BottomRightPattern = pattern; } else if (direction == 3 && pos.Y < target.Height && target.GetWall((short)pos.X, (short)(pos.Y + 1), level).TopRightThick) { replaced = wall.BottomLeftPattern; wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (replaced == pattern) { return new PatternReplaceCount { Total = -1 } } ; replaceCost.Add(replaced); replaceCost.Total = direction; return(replaceCost); }
public static bool VerifyEraseWall(VMArchitecture target, Point pos, int length, int direction, sbyte level) { pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); wall.Segments &= ~WLMainSeg[direction]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, level), wall)) return false; if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments &= ~WLSubSeg[direction / 2]; if (!target.Context.CheckWallValid(LotTilePos.FromBigTile((short)tPos.X, (short)tPos.Y, level), wall)) return false; pos += WLStep[direction]; } } return true; }
/// <summary> /// Fills a room with a certain Floor pattern. Returns floors covered /// </summary> public static PatternReplaceCount FloorPatternFill(VMArchitecture target, Point pos, ushort pattern, sbyte level) //for first floor gen, curRoom should be 1. For floors above, it should be the last genmap result { if (pattern > 65533 || pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y >= target.Height) { return(new PatternReplaceCount()); } pos.X = Math.Max(Math.Min(pos.X, target.Width - 1), 0); pos.Y = Math.Max(Math.Min(pos.Y, target.Height - 1), 0); var walls = target.Walls[level - 1]; var width = target.Width; var height = target.Height; PatternReplaceCount floorsCovered = new PatternReplaceCount(true); byte[] Map = new byte[target.Width * target.Height]; //flood fill recursively. Each time choose find and choose the first "0" as the base. //The first recursion (outside) cannot fill into diagonals. var spread = new Stack <Point>(); spread.Push(pos); 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]; var floor = target.GetFloor((short)item.X, (short)item.Y, level); if ((byte)mainWalls.Segments > 15) { //draw floor onto a diagonal; var wall = walls[item.X + item.Y * width]; byte flags = Map[item.X + item.Y * width]; if (flags == 3) { continue; } if ((mainWalls.Segments & WallSegments.HorizontalDiag) > 0) { flags = (byte)(3 - flags); } if ((flags & 1) == 1 && wall.TopLeftPattern != pattern) { floorsCovered.Add(wall.TopLeftPattern); wall.TopLeftPattern = pattern; } else if ((flags & 2) == 2 && wall.TopLeftStyle != pattern) { floorsCovered.Add(wall.TopLeftStyle); wall.TopLeftStyle = pattern; } walls[item.X + item.Y * width] = wall; continue; //don't spread on diagonals for now } else { //normal tile, draw a floor here. if (floor.Pattern != pattern) { var old = floor.Pattern; floor.Pattern = pattern; if (target.SetFloor((short)item.X, (short)item.Y, level, floor, false)) { floorsCovered.DAdd(old); } } } if (Map[plusX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.BottomRight) == 0) { SpreadOnto(walls, plusX, item.Y, 0, Map, width, height, spread, pattern, true); } if (Map[minX + item.Y * width] < 3 && (mainWalls.Segments & WallSegments.TopLeft) == 0) { SpreadOnto(walls, minX, item.Y, 2, Map, width, height, spread, pattern, true); } if (Map[item.X + plusY * width] < 3 && (mainWalls.Segments & WallSegments.BottomLeft) == 0) { SpreadOnto(walls, item.X, plusY, 1, Map, width, height, spread, pattern, true); } if (Map[item.X + minY * width] < 3 && (mainWalls.Segments & WallSegments.TopRight) == 0) { SpreadOnto(walls, item.X, minY, 3, Map, width, height, spread, pattern, true); } walls[item.X + item.Y * width] = mainWalls; } return(floorsCovered); }
public static int WallPatternDot(VMArchitecture target, Point pos, ushort pattern, int direction, int altDir, sbyte level) { if (pos.X < 0 || pos.X >= target.Width || pos.Y < 0 || pos.Y > target.Height) return -1; var wall = target.GetWall((short)pos.X, (short)pos.Y, level); //direction starts lefttop, righttop if ((wall.Segments & WallSegments.HorizontalDiag) > 0) { if (direction < 2) { //bottom (bottom right pattern) wall.BottomRightPattern = pattern; } else { //top (bottom left pattern) wall.BottomLeftPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); return direction; } else if ((wall.Segments & WallSegments.VerticalDiag) > 0) { if (direction > 0 && direction < 3) { //left wall.BottomLeftPattern = pattern; } else { //right wall.BottomRightPattern = pattern; } target.SetWall((short)pos.X, (short)pos.Y, level, wall); return direction; } if ((wall.Segments & (WallSegments)(1 << direction)) > 0) { } else if ((wall.Segments & (WallSegments)(1 << altDir)) > 0) direction = altDir; else { return -1; } if (direction == 0) wall.TopLeftPattern = pattern; else if (direction == 1) wall.TopRightPattern = pattern; else if (direction == 2) wall.BottomRightPattern = pattern; else if (direction == 3) wall.BottomLeftPattern = pattern; target.SetWall((short)pos.X, (short)pos.Y, level, wall); return direction; }
//things 2 note //default style is 1 //default pattern is 0 //mid drawing pattern/style is 255 public static int DrawWall(VMArchitecture target, Point pos, int length, int direction, ushort pattern, ushort style, sbyte level, bool force) { if (!force && !VerifyDrawWall(target, pos, length, direction, level)) { return(0); } int totalWalls = 0; pos += WLStartOff[direction]; bool diagCheck = (direction % 2 == 1); for (int i = 0; i < length; i++) { var wall = target.GetWall((short)pos.X, (short)pos.Y, level); if ((wall.Segments & (WLMainSeg[direction] | AnyDiag)) == 0 && (!diagCheck || (wall.Segments == 0))) { //no wall here already, apply it. wall.Segments |= WLMainSeg[direction]; if (diagCheck) { wall.TopRightStyle = style; wall.BottomLeftPattern = pattern; wall.BottomRightPattern = pattern; } else if (WLMainSeg[direction] == WallSegments.TopRight) { wall.TopRightStyle = style; wall.TopRightPattern = pattern; } else { wall.TopLeftStyle = style; wall.TopLeftPattern = pattern; } totalWalls++; target.SetWall((short)pos.X, (short)pos.Y, level, wall); if (!diagCheck) { var tPos = pos + WLSubOff[direction / 2]; wall = target.GetWall((short)tPos.X, (short)tPos.Y, level); wall.Segments |= WLSubSeg[direction / 2]; if (WLSubSeg[direction / 2] == WallSegments.BottomRight) { wall.BottomRightPattern = pattern; } else { wall.BottomLeftPattern = pattern; } target.SetWall((short)tPos.X, (short)tPos.Y, level, wall); } } pos += WLStep[direction]; } return(totalWalls); }
public static void StampTilemap(VMArchitecture arch, short[] tilemap, short x, short y, sbyte level) { StampTilemap(arch, tilemap, x, y, level, false); }