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; }
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; }
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; }
//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<BlueprintRoom> rooms) { 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. 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) { remaining = true; Map[i] = (ushort)rooms.Count; 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] = (ushort)rooms.Count; 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] = (ushort)rooms.Count; 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] = (ushort)rooms.Count; 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] = (ushort)rooms.Count; spread.Push(new Point(item.X, minY)); } } rooms.Add(new BlueprintRoom { IsOutside = outside }); outside = false; } } }