public static void Main(string[] args) { bool showHelp = false; bool resourceMapping = true; bool generateBlobs = false; bool stripDumbBlobs = false; var options = new OptionSet() { { "no-resource-mapping", "don't do resource mapping for older level files", v => resourceMapping = v == null }, { "g|generate-blobs", "generate blobs for older level files when resource mapping fails", v => generateBlobs = v != null }, { "s|strip-lvb-blob-references", "strip references to .lvb.blo blob files", v => stripDumbBlobs = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List<string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_lvl [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string inputPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".map"); string lvbPath = Path.ChangeExtension(inputPath, ".lvb"); string lvbName = Path.GetFileName(lvbPath); var level = new LevelFile(); using (var input = File.OpenRead(inputPath)) { level.Deserialize(input); } if (stripDumbBlobs == true) { for (int i = 0; i < level.Floors.Count; i++) { var floor = level.Floors[i]; if (floor.FileName != null && floor.FileName.EndsWith(".lvb.blo") == true) { floor.FileName = null; level.Floors[i] = floor; } } for (int i = 0; i < level.Objects.Count; i++) { var obj = level.Objects[i]; if (obj.FileName != null && obj.FileName.EndsWith(".lvb.blo") == true) { obj.FileName = null; level.Objects[i] = obj; } } } var hasLevelBlob = level.Floors.Any(f => f.FileName == null) == true || level.Objects.Any(o => o.FileName == null) == true; var remap = new Dictionary<string, string>(); if (hasLevelBlob == true) { // TODO: decrap this block of code var resources = resourceMapping == true ? LoadBloTable() : new SortedDictionary<string, string>(); if (File.Exists(lvbPath) == false) { Console.WriteLine("Could not open '{0}'!", lvbPath); Console.WriteLine(); Console.WriteLine("Mapping of LVB resources to real locations isn't going to happen."); } else { using (var lvb = File.OpenRead(lvbPath)) { var levelBlob = new BlobFile(); levelBlob.Deserialize(lvb); var md5 = MD5.Create(); var unknownEntries = new List<BlobFile.Entry>(); foreach (var entry in levelBlob.Entries) { lvb.Seek(entry.Offset, SeekOrigin.Begin); var data = new byte[entry.Size]; if (lvb.Read(data, 0, data.Length) != data.Length) { throw new FormatException(); } var hash = md5.ComputeHash(data); var friendlyHash = BitConverter .ToString(hash) .Replace("-", "") .ToLowerInvariant(); if (resources.ContainsKey(friendlyHash) == true) { remap[entry.Name] = resources[friendlyHash]; } else { Console.WriteLine("Could not find real location for '{0},{1}'.", lvbName, entry.Name); unknownEntries.Add(entry); } } if (unknownEntries.Count > 0) { Console.WriteLine("Could not find all of the level blob resources."); if (generateBlobs == true) { // ReSharper disable JoinDeclarationAndInitializer string floorBlobName; // ReSharper restore JoinDeclarationAndInitializer floorBlobName = "f_!"; floorBlobName += Path.GetFileNameWithoutExtension(inputPath); floorBlobName = Path.ChangeExtension(floorBlobName, ".blo"); // ReSharper disable JoinDeclarationAndInitializer string floorBlobPath; // ReSharper restore JoinDeclarationAndInitializer floorBlobPath = Path.GetDirectoryName(inputPath); if (floorBlobPath == null) { throw new InvalidOperationException(); } floorBlobPath = Path.Combine(floorBlobPath, floorBlobName); Console.WriteLine("Creating '{0}'...", floorBlobPath); using (var output = File.Create(floorBlobPath)) { var floorBlob = new BlobFile { Version = 2, }; // generate fake entries var floors = unknownEntries .Where(f => f.Name.StartsWith("f")) .ToArray(); foreach (var floor in floors) { floorBlob.Entries.Add(new BlobFile.Entry() { Name = floor.Name, }); } floorBlob.Serialize(output); // generate real entries floorBlob.Entries.Clear(); foreach (var floor in floors) { Console.WriteLine(" adding '{0}'", floor.Name); lvb.Seek(floor.Offset, SeekOrigin.Begin); floorBlob.Entries.Add(new BlobFile.Entry() { Name = floor.Name, Offset = output.Position, Size = floor.Size, }); output.WriteFromStream(lvb, floor.Size); remap[floor.Name] = string.Format("{0},{1}", floorBlobName, floor.Name); } output.Seek(0, SeekOrigin.Begin); floorBlob.Serialize(output); } // ReSharper disable JoinDeclarationAndInitializer string objectBlobName; // ReSharper restore JoinDeclarationAndInitializer objectBlobName = "o_!"; objectBlobName += Path.GetFileNameWithoutExtension(inputPath); objectBlobName = Path.ChangeExtension(objectBlobName, ".blo"); // ReSharper disable JoinDeclarationAndInitializer string objectBlobPath; // ReSharper restore JoinDeclarationAndInitializer objectBlobPath = Path.GetDirectoryName(inputPath); if (objectBlobPath == null) { throw new InvalidOperationException(); } objectBlobPath = Path.Combine(objectBlobPath, objectBlobName); Console.WriteLine("Creating '{0}'...", objectBlobPath); using (var output = File.Create(objectBlobPath)) { var objectBlob = new BlobFile { Version = 2, }; // generate fake entries var objects = unknownEntries .Where(o => o.Name.StartsWith("o")) .ToArray(); foreach (var obj in objects) { objectBlob.Entries.Add(new BlobFile.Entry() { Name = obj.Name, }); } objectBlob.Serialize(output); // generate real entries objectBlob.Entries.Clear(); foreach (var obj in objects) { Console.WriteLine(" adding '{0}'", obj.Name); lvb.Seek(obj.Offset, SeekOrigin.Begin); objectBlob.Entries.Add(new BlobFile.Entry() { Name = obj.Name, Offset = output.Position, Size = obj.Size, }); output.WriteFromStream(lvb, obj.Size); remap[obj.Name] = string.Format("{0},{1}", objectBlobName, obj.Name); } output.Seek(0, SeekOrigin.Begin); objectBlob.Serialize(output); } } } } } } using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = level.Width, Height = level.Height, EntityCount = level.Entities.Count, PhysicsLow = new short[32], }; // not right? DERP //header.OffsetX = level.OffsetX; //header.OffsetY = level.OffsetY; Array.Copy(level.PhysicsLow, header.PhysicsLow, level.PhysicsLow.Length); header.PhysicsHigh = new short[32]; Array.Copy(level.PhysicsHigh, header.PhysicsHigh, level.PhysicsHigh.Length); header.LightColorWhite = level.LightColorWhite; header.LightColorRed = level.LightColorRed; header.LightColorGreen = level.LightColorGreen; header.LightColorBlue = level.LightColorBlue; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < level.TerrainIds.Length) { output.WriteValueU8((byte)level.TerrainIds[i]); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { var reference = new Map.BlobReference(); if (i < level.Floors.Count) { var floor = level.Floors[i]; if (floor.FileName == null) { if (remap.ContainsKey(floor.Id) == true) { reference.Path = remap[floor.Id]; } else { reference.Path = string.Format("{0},{1}", lvbName, floor.Id); } } else { reference.Path = string.Format("{0},{1}", floor.FileName, floor.Id); } } output.WriteStructure(reference); } var tiles = new byte[level.Width * level.Height * 4]; // ReSharper disable UnusedVariable int offset = 0; // ReSharper restore UnusedVariable for (int i = 0, j = 0; i < level.Tiles.Length; i++, j += 4) { tiles[j + 0] = level.Tiles[i].BitsA; tiles[j + 0] &= 0x7F; tiles[j + 1] = 0; tiles[j + 2] = level.Tiles[i].BitsC; tiles[j + 3] = level.Tiles[i].BitsB; } using (var rle = new MemoryStream()) { rle.WriteRLE(tiles, 4, level.Tiles.Length, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var t in level.Entities) { output.WriteStructure(t); var obj = level.Objects[t.ObjectId]; var reference = new Map.BlobReference(); if (obj.FileName == null) { if (remap.ContainsKey(obj.Id) == true) { reference.Path = remap[obj.Id]; } else { reference.Path = string.Format("{0},{1}", lvbName, obj.Id); } } else { reference.Path = string.Format("{0},{1}", obj.FileName, obj.Id); } output.WriteStructure(reference); } } }
public static void Main(string[] args) { bool showHelp = false; bool resourceMapping = true; bool generateBlobs = false; bool stripDumbBlobs = false; var options = new OptionSet() { { "no-resource-mapping", "don't do resource mapping for older level files", v => resourceMapping = v == null }, { "g|generate-blobs", "generate blobs for older level files when resource mapping fails", v => generateBlobs = v != null }, { "s|strip-lvb-blob-references", "strip references to .lvb.blo blob files", v => stripDumbBlobs = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_lvl [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string inputPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".map"); string lvbPath = Path.ChangeExtension(inputPath, ".lvb"); string lvbName = Path.GetFileName(lvbPath); var level = new LevelFile(); using (var input = File.OpenRead(inputPath)) { level.Deserialize(input); } if (stripDumbBlobs == true) { for (int i = 0; i < level.Floors.Count; i++) { var floor = level.Floors[i]; if (floor.FileName != null && floor.FileName.EndsWith(".lvb.blo") == true) { floor.FileName = null; level.Floors[i] = floor; } } for (int i = 0; i < level.Objects.Count; i++) { var obj = level.Objects[i]; if (obj.FileName != null && obj.FileName.EndsWith(".lvb.blo") == true) { obj.FileName = null; level.Objects[i] = obj; } } } var hasLevelBlob = level.Floors.Any(f => f.FileName == null) == true || level.Objects.Any(o => o.FileName == null) == true; var remap = new Dictionary <string, string>(); if (hasLevelBlob == true) { // TODO: decrap this block of code var resources = resourceMapping == true ? LoadBloTable() : new SortedDictionary <string, string>(); if (File.Exists(lvbPath) == false) { Console.WriteLine("Could not open '{0}'!", lvbPath); Console.WriteLine(); Console.WriteLine("Mapping of LVB resources to real locations isn't going to happen."); } else { using (var lvb = File.OpenRead(lvbPath)) { var levelBlob = new BlobFile(); levelBlob.Deserialize(lvb); var md5 = MD5.Create(); var unknownEntries = new List <BlobFile.Entry>(); foreach (var entry in levelBlob.Entries) { lvb.Seek(entry.Offset, SeekOrigin.Begin); var data = new byte[entry.Size]; if (lvb.Read(data, 0, data.Length) != data.Length) { throw new FormatException(); } var hash = md5.ComputeHash(data); var friendlyHash = BitConverter .ToString(hash) .Replace("-", "") .ToLowerInvariant(); if (resources.ContainsKey(friendlyHash) == true) { remap[entry.Name] = resources[friendlyHash]; } else { Console.WriteLine("Could not find real location for '{0},{1}'.", lvbName, entry.Name); unknownEntries.Add(entry); } } if (unknownEntries.Count > 0) { Console.WriteLine("Could not find all of the level blob resources."); if (generateBlobs == true) { // ReSharper disable JoinDeclarationAndInitializer string floorBlobName; // ReSharper restore JoinDeclarationAndInitializer floorBlobName = "f_!"; floorBlobName += Path.GetFileNameWithoutExtension(inputPath); floorBlobName = Path.ChangeExtension(floorBlobName, ".blo"); // ReSharper disable JoinDeclarationAndInitializer string floorBlobPath; // ReSharper restore JoinDeclarationAndInitializer floorBlobPath = Path.GetDirectoryName(inputPath); if (floorBlobPath == null) { throw new InvalidOperationException(); } floorBlobPath = Path.Combine(floorBlobPath, floorBlobName); Console.WriteLine("Creating '{0}'...", floorBlobPath); using (var output = File.Create(floorBlobPath)) { var floorBlob = new BlobFile { Version = 2, }; // generate fake entries var floors = unknownEntries .Where(f => f.Name.StartsWith("f")) .ToArray(); foreach (var floor in floors) { floorBlob.Entries.Add(new BlobFile.Entry() { Name = floor.Name, }); } floorBlob.Serialize(output); // generate real entries floorBlob.Entries.Clear(); foreach (var floor in floors) { Console.WriteLine(" adding '{0}'", floor.Name); lvb.Seek(floor.Offset, SeekOrigin.Begin); floorBlob.Entries.Add(new BlobFile.Entry() { Name = floor.Name, Offset = output.Position, Size = floor.Size, }); output.WriteFromStream(lvb, floor.Size); remap[floor.Name] = string.Format("{0},{1}", floorBlobName, floor.Name); } output.Seek(0, SeekOrigin.Begin); floorBlob.Serialize(output); } // ReSharper disable JoinDeclarationAndInitializer string objectBlobName; // ReSharper restore JoinDeclarationAndInitializer objectBlobName = "o_!"; objectBlobName += Path.GetFileNameWithoutExtension(inputPath); objectBlobName = Path.ChangeExtension(objectBlobName, ".blo"); // ReSharper disable JoinDeclarationAndInitializer string objectBlobPath; // ReSharper restore JoinDeclarationAndInitializer objectBlobPath = Path.GetDirectoryName(inputPath); if (objectBlobPath == null) { throw new InvalidOperationException(); } objectBlobPath = Path.Combine(objectBlobPath, objectBlobName); Console.WriteLine("Creating '{0}'...", objectBlobPath); using (var output = File.Create(objectBlobPath)) { var objectBlob = new BlobFile { Version = 2, }; // generate fake entries var objects = unknownEntries .Where(o => o.Name.StartsWith("o")) .ToArray(); foreach (var obj in objects) { objectBlob.Entries.Add(new BlobFile.Entry() { Name = obj.Name, }); } objectBlob.Serialize(output); // generate real entries objectBlob.Entries.Clear(); foreach (var obj in objects) { Console.WriteLine(" adding '{0}'", obj.Name); lvb.Seek(obj.Offset, SeekOrigin.Begin); objectBlob.Entries.Add(new BlobFile.Entry() { Name = obj.Name, Offset = output.Position, Size = obj.Size, }); output.WriteFromStream(lvb, obj.Size); remap[obj.Name] = string.Format("{0},{1}", objectBlobName, obj.Name); } output.Seek(0, SeekOrigin.Begin); objectBlob.Serialize(output); } } } } } } using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = level.Width, Height = level.Height, EntityCount = level.Entities.Count, PhysicsLow = new short[32], }; // not right? DERP //header.OffsetX = level.OffsetX; //header.OffsetY = level.OffsetY; Array.Copy(level.PhysicsLow, header.PhysicsLow, level.PhysicsLow.Length); header.PhysicsHigh = new short[32]; Array.Copy(level.PhysicsHigh, header.PhysicsHigh, level.PhysicsHigh.Length); header.LightColorWhite = level.LightColorWhite; header.LightColorRed = level.LightColorRed; header.LightColorGreen = level.LightColorGreen; header.LightColorBlue = level.LightColorBlue; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < level.TerrainIds.Length) { output.WriteValueU8((byte)level.TerrainIds[i]); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { var reference = new Map.BlobReference(); if (i < level.Floors.Count) { var floor = level.Floors[i]; if (floor.FileName == null) { if (remap.ContainsKey(floor.Id) == true) { reference.Path = remap[floor.Id]; } else { reference.Path = string.Format("{0},{1}", lvbName, floor.Id); } } else { reference.Path = string.Format("{0},{1}", floor.FileName, floor.Id); } } output.WriteStructure(reference); } var tiles = new byte[level.Width * level.Height * 4]; // ReSharper disable UnusedVariable int offset = 0; // ReSharper restore UnusedVariable for (int i = 0, j = 0; i < level.Tiles.Length; i++, j += 4) { tiles[j + 0] = level.Tiles[i].BitsA; tiles[j + 0] &= 0x7F; tiles[j + 1] = 0; tiles[j + 2] = level.Tiles[i].BitsC; tiles[j + 3] = level.Tiles[i].BitsB; } using (var rle = new MemoryStream()) { rle.WriteRLE(tiles, 4, level.Tiles.Length, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var t in level.Entities) { output.WriteStructure(t); var obj = level.Objects[t.ObjectId]; var reference = new Map.BlobReference(); if (obj.FileName == null) { if (remap.ContainsKey(obj.Id) == true) { reference.Path = remap[obj.Id]; } else { reference.Path = string.Format("{0},{1}", lvbName, obj.Id); } } else { reference.Path = string.Format("{0},{1}", obj.FileName, obj.Id); } output.WriteStructure(reference); } } }
public static void Main(string[] args) { bool showHelp = false; int width = 500; int height = 500; var options = new OptionSet() { { "?|help", "show this message and exit", v => showHelp = v != null }, { "w|width=", "set level width", v => width = v != null ? int.Parse(v) : width }, { "h|height=", "set level height", v => height = v != null ? int.Parse(v) : height }, }; List<string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 0 || extras.Count > 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var outputPath = extras.Count > 0 ? extras[0] : "space.map"; var templates = LoadEntities(); int cx = width / 2; int cy = height / 2; // ReSharper disable UnusedVariable var radius = (int)(Math.Min(width, height) / 2.0); // ReSharper restore UnusedVariable var range = Math.Min(width, height) / 2.5; var rng = new MersenneTwister(); var noise = PerlinNoise.Generate( width, height, 0.0325f, 1.0f, 0.5f, 16, rng); var physics = new bool[width,height]; var vision = new bool[width,height]; var entities = new List<Entity>(); for (int x = 8; x < width - 8; x++) { for (int y = 8; y < height - 8; y++) { var distance = GetDistance(cx, cy, x, y); if (distance > range && rng.Next(100) > 2) { continue; } var magic = noise[x, y]; if (magic >= 200) { } else if (magic >= 180) { if (rng.Next(100) >= 60 && (x % 2) == 0 && (y % 2) == 0) { var template = templates .Where(t => t.Category == "asteroid") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithPhysics(x, y, physics, width, height) == true) { var entity = new Entity(x, y, template); int speed = rng.Next(100); if (speed < 60) { entity.AnimationTime = 0; } else if (speed < 70) { entity.AnimationTime = 100; } else if (speed < 80) { entity.AnimationTime = 200; } else if (speed < 85) { entity.AnimationTime = 250; } else if (speed < 90) { entity.AnimationTime = 350; } else if (speed < 95) { entity.AnimationTime = 400; } else { entity.AnimationTime = 450; } template.BlockPhysics(x, y, physics); entities.Add(entity); } } } else if (magic >= 100) { } else if (magic >= 15) { } else { if (rng.Next(100) >= 80) { var template = templates .Where(t => t.Category == "nebula") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithVision(x, y, vision, width, height) == true) { var entity = new Entity(x, y, template) { AnimationTime = 50 }; template.BlockVision(x, y, vision); entities.Add(entity); } } } } } var tiles = new Level.Tile[width,height]; foreach (var entity in entities) { for (int rx = 0; rx < entity.Template.Width; rx++) { for (int ry = 0; ry < entity.Template.Height; ry++) { if (entity.Template.Physics[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Physics = entity.Template.Physics[rx, ry]; } if (entity.Template.Vision[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Vision = entity.Template.Vision[rx, ry]; } } } } var floors = new List<Map.BlobReference> { new Map.BlobReference() { Path = "f_default.blo,default.cfs" }, }; //floors.Add(new Map.BlobReference() { Path = "f_colors.blo,color3.cfs" }); using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = width, Height = height, EntityCount = entities.Count, LightColorWhite = 0xFFFFFF00u, LightColorRed = 0x0000FF00u, LightColorGreen = 0x00FF0000u, LightColorBlue = 0xFF000000u, PhysicsLow = new short[32], PhysicsHigh = new short[32], }; header.PhysicsHigh[0] = 0; header.PhysicsHigh[1] = 1024; header.PhysicsHigh[2] = 1024; header.PhysicsHigh[3] = 1024; header.PhysicsHigh[4] = 1024; header.PhysicsHigh[5] = 1024; header.PhysicsHigh[6] = 16; header.PhysicsHigh[7] = 16; header.PhysicsHigh[8] = 16; header.PhysicsHigh[9] = 16; header.PhysicsHigh[10] = 16; header.PhysicsHigh[11] = 32; header.PhysicsHigh[12] = 32; header.PhysicsHigh[13] = 32; header.PhysicsHigh[14] = 32; header.PhysicsHigh[15] = 32; header.PhysicsHigh[16] = 64; header.PhysicsHigh[17] = 64; header.PhysicsHigh[18] = 64; header.PhysicsHigh[19] = 64; header.PhysicsHigh[20] = 64; header.PhysicsHigh[21] = 128; header.PhysicsHigh[22] = 128; header.PhysicsHigh[23] = 128; header.PhysicsHigh[24] = 128; header.PhysicsHigh[25] = 128; header.PhysicsHigh[26] = 1024; header.PhysicsHigh[27] = 1024; header.PhysicsHigh[29] = 1024; header.PhysicsHigh[28] = 1024; header.PhysicsHigh[30] = 1024; header.PhysicsHigh[31] = 1024; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < 16) { output.WriteValueU8((byte)i); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { if (i < floors.Count) { output.WriteStructure(floors[i]); } else { output.Seek(64, SeekOrigin.Current); } } var buffer = new byte[width * height * 4]; for (int y = 0, offset = 0; y < height; y++) { for (int x = 0; x < width; x++, offset += 4) { buffer[offset + 0] = tiles[x, y].BitsA; buffer[offset + 1] = 0; buffer[offset + 2] = tiles[x, y].BitsC; buffer[offset + 3] = tiles[x, y].BitsB; } } using (var rle = new MemoryStream()) { rle.WriteRLE(buffer, 4, width * height, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var source in entities) { var entity = new Level.Entity { X = (short)((source.X - source.Template.OffsetX) * 16), Y = (short)((source.Y - source.Template.OffsetY) * 16), AnimationTime = source.AnimationTime, }; output.WriteStructure(entity); var reference = new Map.BlobReference { Path = string.Format("{0},{1}", source.Template.BloName, source.Template.CfsName), }; output.WriteStructure(reference); } } }
public static void Main(string[] args) { bool showHelp = false; int width = 500; int height = 500; var options = new OptionSet() { { "?|help", "show this message and exit", v => showHelp = v != null }, { "w|width=", "set level width", v => width = v != null?int.Parse(v) : width }, { "h|height=", "set level height", v => height = v != null?int.Parse(v) : height }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 0 || extras.Count > 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var outputPath = extras.Count > 0 ? extras[0] : "space.map"; var templates = LoadEntities(); int cx = width / 2; int cy = height / 2; // ReSharper disable UnusedVariable var radius = (int)(Math.Min(width, height) / 2.0); // ReSharper restore UnusedVariable var range = Math.Min(width, height) / 2.5; var rng = new MersenneTwister(); var noise = PerlinNoise.Generate( width, height, 0.0325f, 1.0f, 0.5f, 16, rng); var physics = new bool[width, height]; var vision = new bool[width, height]; var entities = new List <Entity>(); for (int x = 8; x < width - 8; x++) { for (int y = 8; y < height - 8; y++) { var distance = GetDistance(cx, cy, x, y); if (distance > range && rng.Next(100) > 2) { continue; } var magic = noise[x, y]; if (magic >= 200) { } else if (magic >= 180) { if (rng.Next(100) >= 60 && (x % 2) == 0 && (y % 2) == 0) { var template = templates .Where(t => t.Category == "asteroid") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithPhysics(x, y, physics, width, height) == true) { var entity = new Entity(x, y, template); int speed = rng.Next(100); if (speed < 60) { entity.AnimationTime = 0; } else if (speed < 70) { entity.AnimationTime = 100; } else if (speed < 80) { entity.AnimationTime = 200; } else if (speed < 85) { entity.AnimationTime = 250; } else if (speed < 90) { entity.AnimationTime = 350; } else if (speed < 95) { entity.AnimationTime = 400; } else { entity.AnimationTime = 450; } template.BlockPhysics(x, y, physics); entities.Add(entity); } } } else if (magic >= 100) { } else if (magic >= 15) { } else { if (rng.Next(100) >= 80) { var template = templates .Where(t => t.Category == "nebula") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithVision(x, y, vision, width, height) == true) { var entity = new Entity(x, y, template) { AnimationTime = 50 }; template.BlockVision(x, y, vision); entities.Add(entity); } } } } } var tiles = new Level.Tile[width, height]; foreach (var entity in entities) { for (int rx = 0; rx < entity.Template.Width; rx++) { for (int ry = 0; ry < entity.Template.Height; ry++) { if (entity.Template.Physics[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Physics = entity.Template.Physics[rx, ry]; } if (entity.Template.Vision[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Vision = entity.Template.Vision[rx, ry]; } } } } var floors = new List <Map.BlobReference> { new Map.BlobReference() { Path = "f_default.blo,default.cfs" }, }; //floors.Add(new Map.BlobReference() { Path = "f_colors.blo,color3.cfs" }); using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = width, Height = height, EntityCount = entities.Count, LightColorWhite = 0xFFFFFF00u, LightColorRed = 0x0000FF00u, LightColorGreen = 0x00FF0000u, LightColorBlue = 0xFF000000u, PhysicsLow = new short[32], PhysicsHigh = new short[32], }; header.PhysicsHigh[0] = 0; header.PhysicsHigh[1] = 1024; header.PhysicsHigh[2] = 1024; header.PhysicsHigh[3] = 1024; header.PhysicsHigh[4] = 1024; header.PhysicsHigh[5] = 1024; header.PhysicsHigh[6] = 16; header.PhysicsHigh[7] = 16; header.PhysicsHigh[8] = 16; header.PhysicsHigh[9] = 16; header.PhysicsHigh[10] = 16; header.PhysicsHigh[11] = 32; header.PhysicsHigh[12] = 32; header.PhysicsHigh[13] = 32; header.PhysicsHigh[14] = 32; header.PhysicsHigh[15] = 32; header.PhysicsHigh[16] = 64; header.PhysicsHigh[17] = 64; header.PhysicsHigh[18] = 64; header.PhysicsHigh[19] = 64; header.PhysicsHigh[20] = 64; header.PhysicsHigh[21] = 128; header.PhysicsHigh[22] = 128; header.PhysicsHigh[23] = 128; header.PhysicsHigh[24] = 128; header.PhysicsHigh[25] = 128; header.PhysicsHigh[26] = 1024; header.PhysicsHigh[27] = 1024; header.PhysicsHigh[29] = 1024; header.PhysicsHigh[28] = 1024; header.PhysicsHigh[30] = 1024; header.PhysicsHigh[31] = 1024; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < 16) { output.WriteValueU8((byte)i); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { if (i < floors.Count) { output.WriteStructure(floors[i]); } else { output.Seek(64, SeekOrigin.Current); } } var buffer = new byte[width * height * 4]; for (int y = 0, offset = 0; y < height; y++) { for (int x = 0; x < width; x++, offset += 4) { buffer[offset + 0] = tiles[x, y].BitsA; buffer[offset + 1] = 0; buffer[offset + 2] = tiles[x, y].BitsC; buffer[offset + 3] = tiles[x, y].BitsB; } } using (var rle = new MemoryStream()) { rle.WriteRLE(buffer, 4, width * height, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var source in entities) { var entity = new Level.Entity { X = (short)((source.X - source.Template.OffsetX) * 16), Y = (short)((source.Y - source.Template.OffsetY) * 16), AnimationTime = source.AnimationTime, }; output.WriteStructure(entity); var reference = new Map.BlobReference { Path = string.Format("{0},{1}", source.Template.BloName, source.Template.CfsName), }; output.WriteStructure(reference); } } }