public static void RingRandomizer(ref LevelFile level) { int ringsPerLevel = 10; int index = 0; int lw = level.header.width; int lh = level.header.height; Bounds bounds = GetCameraBounds(level); TumorRemover(ref level); // place new rings(s) for (int i = 0; i < ringsPerLevel; i++) { bool placed = false; do { int row = RNG.random.Next(bounds.Top, bounds.Bottom); int col = RNG.random.Next(bounds.Left, bounds.Right); index = row * lw + col; if (level.data.active[index] == TileID.Empty) { level.data.active[index] = TileID.Ring; placed = true; } } while (!placed); } }
public static void PlaceTile(ref LevelFile level, TileID toPlace, int numPerLevel, TileID toReplace = TileID.Empty, bool ignoreTags = false, int cushion = 3) { //int numPerLevel = 10; int index = 0; int lw = level.header.width; int lh = level.header.height; Bounds bounds = GetCameraBounds(level); //TumorRemover(ref level); // place new tumor(s) for (int i = 0; i < numPerLevel; i++) { bool placed = false; do { int row = RNG.random.Next(bounds.Top, bounds.Bottom); int col = RNG.random.Next(bounds.Left + cushion, bounds.Right - cushion); index = row * lw + col; if (level.data.active[index] == toReplace) { if (level.data.tag[index] == TileID.Empty || ignoreTags) { level.data.active[index] = toPlace; } placed = true; } } while (!placed); } }
public static void PrintLevelToConsole(LevelFile level) { var lh = level.header.height; var lw = level.header.width; Console.WriteLine("============================================"); for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { int index = i * lw + j; if (level.data.active[index] == TileID.Solid) { Console.Write("▓▓"); } else if (level.data.back1[index] == TileID.WholePiece) { Console.Write("▒▒"); } else if (level.data.back2[index] == TileID.WholePiece2) { Console.Write("░░"); } else { Console.Write(" "); } } Console.Write("\n"); } Console.WriteLine("============================================"); }
public static bool AppendPieceH(LevelPiece left, LevelPiece right, bool noExcept = false) { Pair L1ExitCoord = GetExitCoord(ref left.File); // Get entry and exit coords Pair L2EntryCoord = GetEntryCoord(ref right.File); // check for mismatch in level exit/entrance //if (left.CeilingEx != right.CeilingEn) FixCeiling(ref left, ref right); //if (left.FloorEx != right.FloorEn) FixFloor(ref left, ref right); // establish level boundaries and new level size Pair L1Origin = new Pair(), L2Origin = new Pair(); // initialize GetLevelOrigins(L1ExitCoord, L2EntryCoord, ref L1Origin, ref L2Origin); // set the values in this function // calculate dimensions for new level int width = L1ExitCoord.Second + right.File.header.width - L2EntryCoord.Second + 1; int height = Math.Max(L1Origin.First + left.File.header.height, L2Origin.First + right.File.header.height); // check for and correct ceiling and floor compatibility LevelPiece transition = new LevelPiece(new LevelFile(0, 0)); Pair TOrigin = new Pair(); if (left.CeilingEx != right.CeilingEn || left.FloorEx != right.FloorEn) { transition = CheckCeilingFloor(ref left, ref right); TOrigin.First = L1Origin.First + L1ExitCoord.First - transition.File.header.height + 2; TOrigin.Second = L2Origin.Second; width++; L2Origin.Second++; } // noExcept is used to make sure that the entrances and exits // can be added without triggering the size limitation if (!noExcept && (height > UsableHeight || width > UsableWidth)) { return(false); } TempLevel = GetNewLevelFile(width, height); // create new level CopyToCoords(ref left.File, ref TempLevel, L1Origin); // copy left level into new level if (transition.File.header.height != 0) { CopyToCoords(ref transition.File, ref TempLevel, TOrigin); } CopyToCoords(ref right.File, ref TempLevel, L2Origin); // copy right level into new level // get rid of old entrances int index = (L1Origin.First + L1ExitCoord.First) * TempLevel.header.width + (L1Origin.Second + L1ExitCoord.Second); TempLevel.data.tag[index] = TileID.Empty; index = (L2Origin.First + L2EntryCoord.First) * TempLevel.header.width + (L2Origin.Second + L2EntryCoord.Second); TempLevel.data.tag[index] = TileID.Empty; // set canvas piece info Canvas.File = TempLevel; Canvas.FloorEn = left.FloorEn; Canvas.FloorEx = right.FloorEx; Canvas.CeilingEn = left.CeilingEn; Canvas.CeilingEx = right.CeilingEx; return(true); }
public static void CopyToCoords(ref LevelFile copyLevel, ref LevelFile pasteLevel, Pair coords) // pass in the origin coords of the level to be copied from { int copyIndex = 0; int pasteIndex = 0; int copylw = copyLevel.header.width; int copylh = copyLevel.header.height; int pastelw = pasteLevel.header.width; int pastelh = pasteLevel.header.height; for (int i = 0; i < copylh; i++) { for (int j = 0; j < copylw; j++) { copyIndex = i * copylw + j; pasteIndex = (i + coords.First) * pastelw + (j + coords.Second); if (pasteLevel.data.tag[pasteIndex] != TileID.OOBMarker) { throw new LevelCollisionException(); } pasteLevel.data.active[pasteIndex] = copyLevel.data.active[copyIndex]; pasteLevel.data.back1[pasteIndex] = copyLevel.data.back1[copyIndex]; pasteLevel.data.back2[pasteIndex] = copyLevel.data.back2[copyIndex]; pasteLevel.data.tag[pasteIndex] = copyLevel.data.tag[copyIndex]; pasteLevel.data.overlay[pasteIndex] = copyLevel.data.overlay[copyIndex]; } } }
// This is the offset of the exit as compared to the entrance //public Pair Shift; public LevelPiece(LevelFile file) { File = file; Name = null; Folder = null; Margin.Left = 0; Margin.Right = 0; Margin.Top = 0; Margin.Bottom = 0; CeilingEn = false; CeilingEx = false; FloorEn = false; FloorEx = false; FullHeight = false; // Determines whether pieces can be placed above or below a certain piece. AllowBuildingAbove = true; AllowBuildingBelow = true; // The direction the entrance and exit tiles are facing. // Later on these should be replaced by a list of all entrances and exits to a piece. Entrance = Direction.None; Exit = Direction.None; }
public static LevelFile copyLevel(LevelFile level) { var levelNew = new LevelFile(); levelNew = level; return(levelNew); }
public static void FlipLevelH(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; FlipLayerH(ref level.data.back1, lw, lh); FlipLayerH(ref level.data.active, lw, lh); FlipLayerH(ref level.data.tag, lw, lh); FlipLayerH(ref level.data.overlay, lw, lh); FlipLayerH(ref level.data.back2, lw, lh); }
public static void OverlayStuff(ref LevelFile level) { for (int i = 0; i < 60; i++) { int index = RNG.random.Next(0, level.data.active.Length); //if (level.data.tag[index] == 0) //{ level.data.overlay[index] = (TileID)OverlayTiles[RNG.random.Next(0, OverlayTiles.Length)]; //} } }
public static void RandomCrumbles(ref LevelFile level) { for (int i = 0; i < 100; i++) { int index = RNG.random.Next(0, level.data.active.Length); if (level.data.active[index] == TileID.Solid) { level.data.active[index] = TileID.Crumble; } } }
public static void AddTiles(ref LevelFile level, int num) { for (int i = 0; i < num; i++) { int index = RNG.random.Next(0, level.data.active.Length); if (level.data.active[index] != TileID.Solid && level.data.tag[index] == TileID.Empty) { level.data.active[index] = (TileID)ActiveTiles[RNG.random.Next(0, ActiveTiles.Length)]; } } }
public static void WaterLevel(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; Bounds bounds = GetCameraBounds(level); for (int j = 0; j < lw; j++) { level.data.overlay[j] = TileID.WaterUB; } }
static int GetCeilingHeight(LevelFile level, Pair coord) { int ceilingHeight = 0; int lw = level.header.width; for (ceilingHeight = 1; ceilingHeight < coord.First; ceilingHeight++) { int index = (coord.First - ceilingHeight) * lw + coord.Second; if (level.data.active[index] == TileID.Solid) { break; } } return(ceilingHeight); }
public static LevelFile Load(string path) { LevelFile level = new LevelFile() { }; byte[] filedata = File.ReadAllBytes(path); // load level header byte[] tempBytes = new byte[4]; Buffer.BlockCopy(filedata, 0, tempBytes, 0, 4); Array.Reverse(tempBytes); level.header.version = BitConverter.ToInt32(tempBytes, 0); Buffer.BlockCopy(filedata, 4, tempBytes, 0, 4); Array.Reverse(tempBytes); level.header.width = BitConverter.ToInt32(tempBytes, 0); Buffer.BlockCopy(filedata, 8, tempBytes, 0, 4); Array.Reverse(tempBytes); level.header.height = BitConverter.ToInt32(tempBytes, 0); Buffer.BlockCopy(filedata, 12, tempBytes, 0, 4); Array.Reverse(tempBytes); level.header.layers = BitConverter.ToInt32(tempBytes, 0); // get data layer length int layerLength = level.header.width * level.header.height; //Console.WriteLine("file length (bytes): " + filedata.Length); //Console.WriteLine("layer length (bytes): " + layerLength); // initialize data layers level.data.back1 = new TileID[layerLength]; level.data.active = new TileID[layerLength]; level.data.tag = new TileID[layerLength]; level.data.overlay = new TileID[layerLength]; level.data.back2 = new TileID[layerLength]; // load data layers int offset = 16; LoadLayer(ref filedata, ref level.data.back1, ref offset); LoadLayer(ref filedata, ref level.data.active, ref offset); LoadLayer(ref filedata, ref level.data.tag, ref offset); LoadLayer(ref filedata, ref level.data.overlay, ref offset); LoadLayer(ref filedata, ref level.data.back2, ref offset); return(level); }
public static bool SmartCorruptActive(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; var options = new string[] { }; bool hasGas = false; int corruptLevel = 3; // loop over entire level for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { int index = i * lw + j; if (SmartTiles.TryGetValue((int)level.data.active[index], out int[] alts) && alts.Length > 0)
public static void SpikeStrips(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { int index = i * lw + j; if (level.data.active[index] == TileID.Solid && j % 5 == i % 5) { level.data.active[index] = TileID.SpikeU; } } } }
public static LevelFile GetNewLevelFile(int width = 54, int height = 32) { LevelFile level = new LevelFile(width, height); int index = 0; int lw = level.header.width; int lh = level.header.height; for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { index = i * lw + j; level.data.tag[index] = TileID.OOBMarker; } } return(level); }
public static bool AddEnemies(ref LevelFile level, int num) { bool hasGas = false; for (int i = 0; i < num; i++) { int index = RNG.random.Next(0, level.data.active.Length); if (level.data.active[index] == 0 && level.data.tag[index] == 0) { var tile = (TileID)EntityTiles[RNG.random.Next(0, EntityTiles.Length)]; level.data.active[index] = tile; if (tile == TileID.Gasper || tile == TileID.GasCloud) { hasGas = true; } } } return(hasGas); }
public static void TumorRemover(ref LevelFile level) { int index = 0; int lw = level.header.width; int lh = level.header.height; // delete original tumor for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { index = i * lw + j; if (level.data.active[index] == TileID.Tumor) { level.data.active[index] = TileID.Empty; } } } }
public static void Crushers(ref LevelFile level) { for (int i = 0; i < 30; i++) { int index = RNG.random.Next(0, level.data.active.Length); if (level.data.active[index] == TileID.Solid && level.data.tag[index] == TileID.Empty) { if (RNG.CoinFlip()) { level.data.active[index] = TileID.CrusherEye; } else { level.data.active[index] = TileID.CrusherGear; } level.data.tag[index] = TileID.Crusher; } } }
public static Pair GetEntryCoord(ref LevelFile level) { // Find new piece's entrance coordinates int index = 0; int lw = level.header.width; int lh = level.header.height; for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { index = i * lw + j; if (level.data.tag[index] == TileID.GreenTransitionL) { return(new Pair(i, j)); } } } return(new Pair()); }
public static Pair GetExitCoord(ref LevelFile level) { // Find Canvas exit coordinates int index = 0; int lw = level.header.width; int lh = level.header.height; for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { index = i * lw + j; if (level.data.tag[index] == TileID.YellowTransitionR) { return(new Pair(i, j)); } } } return(new Pair()); }
public static void Save(LevelFile level, string path) { // get data layer length int layerLength = level.header.width * level.header.height; int fileLength = layerLength * 5 * 4 + 16; //Console.WriteLine("file length (bytes): " + fileLength); //Console.WriteLine("layer length (bytes): " + layerLength); byte[] filedata = new byte[fileLength]; byte[] tempBytes = new byte[4]; tempBytes = BitConverter.GetBytes(level.header.version); Array.Reverse(tempBytes); Buffer.BlockCopy(tempBytes, 0, filedata, 0, 4); tempBytes = BitConverter.GetBytes(level.header.width); Array.Reverse(tempBytes); Buffer.BlockCopy(tempBytes, 0, filedata, 4, 4); tempBytes = BitConverter.GetBytes(level.header.height); Array.Reverse(tempBytes); Buffer.BlockCopy(tempBytes, 0, filedata, 8, 4); tempBytes = BitConverter.GetBytes(level.header.layers); Array.Reverse(tempBytes); Buffer.BlockCopy(tempBytes, 0, filedata, 12, 4); // save data layers int offset = 16; SaveLayer(ref filedata, ref level.data.back1, ref offset); SaveLayer(ref filedata, ref level.data.active, ref offset); SaveLayer(ref filedata, ref level.data.tag, ref offset); SaveLayer(ref filedata, ref level.data.overlay, ref offset); SaveLayer(ref filedata, ref level.data.back2, ref offset); string folder = Path.GetDirectoryName(path); if (!File.Exists(folder)) { Directory.CreateDirectory(folder); } File.WriteAllBytes(path, filedata); // output copied file }
public static LevelFile FixAspect(ref LevelFile levelIn) { int lh = levelIn.header.height; int lw = levelIn.header.width; if (lh * 16 > lw * 9) { lw = lh * 16 / 9; } else { lh = lw * 9 / 16; } LevelFile levelOut = LevelGenerator.GetNewLevelFile(lw, lh); int hOffset = lh - levelIn.header.width; LevelGenerator.CopyToCoords(ref levelIn, ref levelOut, new Pair(0, hOffset)); return(levelOut); }
public static LevelFile RotateLevel(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; LevelFile levelNew = new LevelFile(lh, lw); for (int row = 0; row < lh; row++) { for (int col = 0; col < lw; col++) { int copyIndex = row * lw + col; int pasteIndex = col * lh + (lh - row - 1); levelNew.data.active[pasteIndex] = GetRotation(level.data.active[copyIndex]); levelNew.data.back1[pasteIndex] = GetRotation(level.data.back1[copyIndex]); levelNew.data.back2[pasteIndex] = GetRotation(level.data.back2[copyIndex]); levelNew.data.tag[pasteIndex] = GetRotation(level.data.tag[copyIndex]); levelNew.data.overlay[pasteIndex] = GetRotation(level.data.overlay[copyIndex]); } } return(levelNew); }
public static Bounds GetCameraBounds(LevelFile level) { int lw = level.header.width; int lh = level.header.height; var bounds = new Bounds { Left = lw, Top = lh, Bottom = 0, Right = 0 }; bool CameraFound = false; int index = 0; for (int row = 0; row < lh; row++) { for (int col = 0; col < lw; col++) { index = row * lw + col; if (level.data.tag[index] == TileID.CameraBounds) { bounds.Top = Math.Min(row, bounds.Top); bounds.Bottom = Math.Max(row, bounds.Bottom); bounds.Left = Math.Min(col, bounds.Left); bounds.Right = Math.Max(col, bounds.Right); CameraFound = true; } } } // correct for aspect ratio double correctAspect = 16 / 9; double width = bounds.Right - bounds.Left; double height = bounds.Bottom - bounds.Top; double aspect = width / height; double hCenter = bounds.Left + (width / 2); double vCenter = bounds.Top + (height / 2); if (aspect < correctAspect) // aspect ratio too tall { width = height * 16 / 9; bounds.Right = (int)(hCenter - width / 2); bounds.Left = (int)(hCenter + width / 2); } if (aspect > correctAspect) // aspect ratio too wide { height = width * 9 / 16; bounds.Top = (int)(vCenter - height / 2); bounds.Bottom = (int)(vCenter + height / 2); } if (bounds.Top < 0) { bounds.Top = 0; } if (bounds.Left < 0) { bounds.Left = 0; } if (bounds.Right > lw) { bounds.Top = lw; } if (bounds.Bottom > lh) { bounds.Bottom = lh; } if (bounds.Top > bounds.Bottom || bounds.Left > bounds.Right || !CameraFound) { Console.WriteLine("Broken Bounds"); bounds.Top = 0; bounds.Left = 0; bounds.Bottom = lh; bounds.Right = lw; } return(bounds); }
public static string CorruptLevel(ref LevelFile level) { string TSAppend = ""; // smart corruptions done first if (Randomizer.settings.CRSmart) { if (SmartCorruptActive(ref level)) { TSAppend += "\n#added by level corruptor\nfx_shader_mid cloudripples\nmidfx_graphics None\nmidfx_layer 2\n"; } } if (Randomizer.settings.CROverlays) { SmartCorruptOverlay(ref level); } // tumor remover second if (Randomizer.settings.CRTumors) { if (Randomizer.settings.AreaType == "normal") { TumorRandomizer(ref level); } else if (Randomizer.settings.AreaType == "cart") { RingRandomizer(ref level); } else if (Randomizer.settings.AreaType == "dark") { TumorRemover(ref level); } else if (Randomizer.settings.AreaType == "glitch") { TumorRemover(ref level); } else if (Randomizer.settings.AreaType == "ironcart") { TumorRemover(ref level); } } // add enemies and add tiles is next AddTiles(ref level, Randomizer.settings.CRAddTiles); if (AddEnemies(ref level, Randomizer.settings.CRAddEnemies)) { TSAppend += "\nfx_shader_mid cloudripples\nmidfx_graphics None\nmidfx_layer 2\n"; } //PlaceTile(ref level, TileID.Feral, 5); // last priority is the various ones below //if (Randomizer.settings.CRChaos) TotalChaos(ref level); if (Randomizer.settings.CRCrumbles) { RandomCrumbles(ref level); } if (Randomizer.settings.CRSpikeStrips) { SpikeStrips(ref level); } if (Randomizer.settings.CRCrushers) { Crushers(ref level); } if (Randomizer.settings.CRWaterLevels && RNG.CoinFlip()) { WaterLevel(ref level); } return(TSAppend); }
public static void RandomizeMod(MainWindow mw) { //ShadersList = mw.ShadersList; saveDir = settings.GameDirectory; PrepModFolders(); // level corruptions string dir = $"{saveDir}tilemaps"; if (Directory.Exists(dir)) { string[] paths = Directory.GetFiles(dir); foreach (var file in paths) { LevelFile level = LevelManip.Load(file); //if(settings.MirrorMode) //{ // LevelManip.FlipLevelH(ref level); // FlipCSV(saveDir + "data/map.csv"); //} if (settings.DoCorruptions) { LevelCorruptors.CorruptLevel(ref level); } LevelManip.Save(level, file); } } // data folder dir = $"{saveDir}data"; if (Directory.Exists(dir)) { // tilesets.txt var file = $"{dir}/tilesets.txt"; if (File.Exists(file)) { string[] text = File.ReadAllLines(file); for (int i = 0; i < text.Length; i++) { if (text[i].Contains("palette")) { text[i] = TilesetManip.GetPalette(); } if (text[i].Contains("tile_graphics")) { text[i] = TilesetManip.GetTile(); } if (text[i].Contains("overlay_graphics")) { text[i] = TilesetManip.GetOverlay(); } if (text[i].Contains("global_particle")) { var split = text[i].Trim().Split(Convert.ToChar(" ")); text[i] = split[0] + " " + ParticleGenerator.GetParticle(settings); } } File.Delete(file); File.WriteAllLines(file, text); } } }
public static void DecorateMachine(ref LevelFile level) { int lw = level.header.width; int lh = level.header.height; //TileID[] brokenWindows = { TileID.DiagonalBL, TileID.DiagonalBR, TileID.SmallSideB, TileID.LargeSideB }; //TileID[] brokenWindows2 = { }; // loop over entire level for (int i = 0; i < lh; i++) { for (int j = 0; j < lw; j++) { int index = i * lw + j; int choice = 0; // BACKGROUND 1 TILES { TileID tile = level.data.back1[index]; // decorate windows if (tile == TileID.Back1Deco2 && (level.data.back1[index - lw] == TileID.WholePiece || level.data.back1[index - lw] == TileID.Back1Deco2)) // this if statement could cause a vector error if you place a window on the first row. So just don't do that! { choice = RNG.random.Next(0, 10); // make a random number selection to decide how to modify the window switch (choice) { case 0: level.data.back1[index] = TileID.Back1Deco4; break; case 1: level.data.back1[index] = (TileID)RNG.random.Next(50001, 50021); break; case 2: case 3: level.data.back2[index] = (TileID)RNG.random.Next(50034, 50054); break; } } // decorate remaining solid tiles if (tile == TileID.WholePiece) { choice = RNG.random.Next(0, 20); if (choice == 0) { level.data.back1[index] = TileID.Back1Deco1; } else if (choice < 4) { level.data.back1[index] = TileID.Back1Deco3; } } // decorate side pieces if (tile == TileID.LargeSideL) { choice = RNG.random.Next(0, 6); // make a random number selection to decide how to modify the window switch (choice) { case 0: break; case 1: case 2: level.data.back1[index] = TileID.SmallSideL; break; case 3: level.data.back1[index - 1] = (TileID)RNG.random.Next(50013, 50017); goto default; default: level.data.back1[index] = TileID.Empty; break; } } if (tile == TileID.LargeSideR) { choice = RNG.random.Next(0, 6); // make a random number selection to decide how to modify the window switch (choice) { case 0: break; case 1: case 2: level.data.back1[index] = TileID.SmallSideR; break; /*case 3: * level.data.back1[index + 1] = (TileID)RNG.random.Next(50013, 50017); * goto default;*/ default: level.data.back1[index] = TileID.Empty; break; } } if (tile == TileID.LargeSideB) { choice = RNG.random.Next(0, 6); // make a random number selection to decide how to modify the window switch (choice) { case 0: break; case 1: case 2: level.data.back1[index] = TileID.SmallSideB; break; /*case 3: * level.data.back1[index + lw] = (TileID)RNG.random.Next(50013, 50017); * goto default;*/ default: level.data.back1[index] = TileID.Empty; break; } } if (tile == TileID.LargeSideT) { choice = RNG.random.Next(0, 6); // make a random number selection to decide how to modify the window switch (choice) { case 0: break; case 1: case 2: level.data.back1[index] = TileID.SmallSideT; break; case 3: level.data.back1[index] = TileID.Back1Deco4; break; /*case 4: * level.data.back1[index - lw] = (TileID)RNG.random.Next(50013, 50017); * goto default;*/ default: level.data.back1[index] = TileID.Empty; break; } } } // BACKGROUND 2 TILES { TileID tile = level.data.back2[index]; // decorate windows if (tile == TileID.Back2Deco2 && (level.data.back2[index - lw] == TileID.WholePiece2 || level.data.back2[index - lw] == TileID.Back2Deco2)) // this if statement could cause a vector error if you place a window on the first row. So just don't do that! { choice = RNG.random.Next(0, 10); switch (choice) { case 0: level.data.back2[index] = TileID.Back2Deco4; break; case 1: level.data.back2[index] = (TileID)RNG.random.Next(50034, 50054); break; } } // decorate remaining solid tiles if (tile == TileID.WholePiece2) { choice = RNG.random.Next(0, 20); if (choice == 0) { level.data.back2[index] = TileID.Back2Deco1; } else if (choice < 4) { level.data.back2[index] = TileID.Back2Deco3; } } } } } }
private void CreatePiecePools(object sender, RoutedEventArgs e) { foreach (var folder in Directory.GetDirectories("data/levelpieces")) { string folderName = Path.GetFileNameWithoutExtension(folder); // get folder name if (folderName == "GEN") { continue; // ignore GEN folder } XDocument doc = new XDocument(); XElement pool = new XElement("pool"); pool.SetAttributeValue("enabled", "True"); pool.SetAttributeValue("source", folderName); pool.SetAttributeValue("author", "Uzerro"); pool.SetAttributeValue("order", "0"); foreach (var file in Directory.GetFiles(folder, "*.lvl", SearchOption.TopDirectoryOnly)) { string fileName = Path.GetFileNameWithoutExtension(file); // get file name XElement piece = new XElement("piece"); piece.SetAttributeValue("name", fileName); // create XElement for piece LevelFile level = LevelManip.Load(file); // load the associated level file Pair enCoord = LevelGenerator.GetEntryCoord(ref level); // get entry coord Pair exCoord = LevelGenerator.GetExitCoord(ref level); // get exit coord // check for ceilings and floors piece.SetAttributeValue("ceilingEn", "False"); piece.SetAttributeValue("ceilingEx", "False"); piece.SetAttributeValue("floorEn", "False"); piece.SetAttributeValue("floorEx", "False"); int index, lw = level.header.width, lh = level.header.height; if (level.data.active[0] == TileID.Solid) // checks top left tile for solid block { piece.SetAttributeValue("ceilingEn", "True"); } if (level.data.active[lw - 1] == TileID.Solid) // checks top right tile for solid block { piece.SetAttributeValue("ceilingEx", "True"); } index = (enCoord.First + 1) * lw + enCoord.Second; if (index < lh * lw) { if (level.data.active[index] == TileID.Solid) // checks tile underneath the entrance for solid block { piece.SetAttributeValue("floorEn", "True"); } } index = (exCoord.First + 1) * lw + exCoord.Second; if (index < lh * lw) { if (level.data.active[index] == TileID.Solid) // checks tile underneath the exit for solid block { piece.SetAttributeValue("floorEx", "True"); } } // FullHeight, AllowBuildingAbove/Below, Margin will need to be set manually. pool.Add(piece); } doc.Add(pool); doc.Save($"data/piecepools/{folderName}.xml"); } MessageBox.Show($"creating piece pools complete", "Info", MessageBoxButton.OK, MessageBoxImage.Information); }