public static void ImportExpansionPdb(string strFile) { PdbPacker pdbp = new PdbPacker(strFile); ArrayList alsTileSets = new ArrayList(); for (int i = 0; i < pdbp.Count; i++) { PdbPacker.File file = pdbp[i]; if (!file.str.EndsWith(".lvl")) { continue; } // Load up the pieces Ini ini = Ini.LoadBinary(new MemoryStream(file.ab)); string strTileMapFilename = ini["General"]["TileMap"].Value; TileMap tmap = TileMap.Load(new MemoryStream(pdbp[strTileMapFilename].ab)); // First, tell the active LevelDoc not to switch its templates based on the following // template load LevelDoc lvldActive = (LevelDoc)DocManager.GetActiveDocument(typeof(LevelDoc)); if (lvldActive != null) { lvldActive.SwitchTemplatesEnabled = false; } // If the TileSet for this level is not yet available, load it now TemplateDoc tmpd = (TemplateDoc)DocManager.OpenDocument(tmap.Filename.Replace(".tset", ".tc")); TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.FileName == tmap.Filename) { tset = tsetT; break; } } if (tset == null) { tset = new TileSet(tmpd, tmap.Filename); alsTileSets.Add(tset); } // Re-enable template switching if (lvldActive != null) { lvldActive.SwitchTemplatesEnabled = true; } // Create a new level description, and deduce which templates are in it, with what visibility LevelDoc lvld = (LevelDoc)DocManager.NewDocument(typeof(LevelDoc), null); lvld.OutputFilename = file.str; ImportTileMap(tmap, tset, tmpd, lvld); // Walls are stored in the terrain map. Load them. string strTrmapFilename = ini["General"]["TerrainMap"].Value; TerrainMap trmap = TerrainMap.Load(new MemoryStream(pdbp[strTrmapFilename].ab)); ImportWalls(trmap, lvld); // Load everything else lvld.LoadIni(ini); } }
public static void SaveExpansionPdb(string strFile, Document[] adoc, string strVersion) { // First save all level docs //annoying //DocManager.SaveAllModified(typeof(LevelDoc)); // Remember active document LevelDoc lvldActive = (LevelDoc)DocManager.GetActiveDocument(typeof(LevelDoc)); // Save documents adoc in an expansion .pdb. Expansion .pdbs need: // - .lvl, .tmap, .trmap, but not .tsets since these come from game .pdbs // - need a version.txt // - need an if demo trigger check "inserted" at save time // - .pdb needs WARI creator, ADD1 type // - data should be compressed for obfuscation purposes PdbPacker pdbp = new PdbPacker(); // Add version.txt byte[] abT = new byte[strVersion.Length + 1]; for (int n = 0; n < strVersion.Length; n++) { abT[n] = (byte)strVersion[n]; } abT[abT.Length - 1] = 0; pdbp.Add(new PdbPacker.File("version.txt", abT)); // Load res.h from embedded resource in prep for pre-process System.Reflection.Assembly ass = typeof(GobImage).Module.Assembly; Stream stmResDotH = ass.GetManifestResourceStream("m.EmbeddedResources." + "res.h"); if (stmResDotH == null) { throw new Exception("Cannot load res.h"); } // Compile levels Random rand = new Random(); ArrayList alsTileSets = new ArrayList(); foreach (LevelDoc lvld in adoc) { // Need to do this unfortunately; some of the "saving" code relies on what the "active" document // is!! DocManager.SetActiveDocument(typeof(LevelDoc), lvld); TemplateDoc tmpd = lvld.GetTemplateDoc(); // Get appropriate TileSet, or make one if this map // uses a new tile collection TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.TemplateDoc == tmpd) { tset = tsetT; break; } } // Create new tile set if none found if (tset == null) { tset = new TileSet(tmpd, tmpd.GetName() + ".tset"); alsTileSets.Add(tset); } #if false // Generate base file name for this level (this is never user-visible, but it should be // as unique as possible char[] achBase = new char[16]; for (int n = 0; n < achBase.Length; n++) { int nT = rand.Next() % (26 + 10); if (nT < 26) { achBase[n] = (char)(nT + 97); } else { achBase[n] = (char)(nT + 48 - 26); } } if (lvld.MaxPlayers > 1) { achBase[0] = 'm'; achBase[1] = '_'; } string strBase = new String(achBase); #else // This isn't unique which can cause problems due to how packfiles work. // Could change packfile api to accept .pdb parameter. // Note1: set next mission action requires predictable filename // Note2: mission sorting is based on filename, not title // Could put lots of "support" in to fix these problems, or just ship // it like this. // // Hack: filename length 29 // Maximum extension on filename: 7 string strBase = lvld.Title; if (strBase.Length > 29 - 7) { strBase = strBase.Substring(0, 29 - 7); } // If multiplayer, add "m_" to the name by losing the last two characters // so sort order is preserved if (lvld.MaxPlayers > 1) { strBase = "m_" + strBase.Substring(0, strBase.Length - 2); } #endif // Get tile map file for this level MemoryStream stmTmap = new MemoryStream(); TileMap tmap = TileMap.CreateFromImage(tset, lvld.GetMapBitmap(tmpd.TileSize, tmpd, true), tmpd.TileSize); tmap.Save(stmTmap); string strTmap = strBase + ".tmap"; pdbp.Add(new PdbPacker.File(strTmap, stmTmap.ToArray())); stmTmap.Close(); // Get the terrain map file for this level MemoryStream stmTRmap = new MemoryStream(); TerrainMap trmap = new TerrainMap(lvld.GetTerrainMap(tmpd.TileSize, tmpd, false)); trmap.Save(stmTRmap); string strTRmap = strBase + ".trmap"; pdbp.Add(new PdbPacker.File(strTRmap, stmTRmap.ToArray())); stmTRmap.Close(); // Save .ini file for this level doc MemoryStream stmLvld = new MemoryStream(); lvld.SaveIni(stmLvld, -1, strTmap, strTRmap, tmpd.GetName() + ".palbin", true); // Pre-process stmLvld.Seek(0, SeekOrigin.Begin); MemoryStream stmPreprocessed = Misc.PreprocessStream(stmLvld, stmResDotH); stmPreprocessed.Seek(0, SeekOrigin.Begin); Ini iniPreProcessed = new Ini(stmPreprocessed); MemoryStream stmLvldPreProcessedBinary = new MemoryStream(); iniPreProcessed.SaveBinary(stmLvldPreProcessedBinary); stmLvldPreProcessedBinary.Close(); string strLvlName = lvld.OutputFilename; if (strLvlName == null) { strLvlName = strBase + ".lvl"; } pdbp.Add(new PdbPacker.File(strLvlName, stmLvldPreProcessedBinary.ToArray())); stmLvldPreProcessedBinary.Close(); } stmResDotH.Close(); // Restore active document if (lvldActive != null) { DocManager.SetActiveDocument(typeof(LevelDoc), lvldActive); } // Now save out pdb pdbp.Save(strFile, "WARI", "ADD2"); }
public static void ExportLevels(string[] astr, int nVersion) { // Get tile size Size sizTile = new Size(0, 0); sizTile.Width = int.Parse(astr[1]); sizTile.Height = sizTile.Width; // Get depth int nDepth = Int32.Parse(astr[2]); // Get background threshold double nAreaBackgroundThreshold = double.Parse(astr[3]); // Background luminance multiplier double nLuminanceMultBackground = double.Parse(astr[4]); // Background saturation multiplier double nSaturationMultBackground = double.Parse(astr[5]); // Foreground luminance multiplier double nLuminanceMultForeground = double.Parse(astr[6]); // Foreground saturation multiplier double nSaturationMultForeground = double.Parse(astr[7]); // Palette directory string strPalDir = astr[8]; // Get output directory string strDir = Path.GetFullPath(astr[9]); // Expand filespecs ArrayList alsFiles = new ArrayList(); for (int n = 9; n < astr.Length; n++) { string strFileT = Path.GetFileName(astr[n]); string strDirT = Path.GetDirectoryName(astr[n]); if (strDirT == "") { strDirT = "."; } string[] astrFiles = Directory.GetFiles(strDirT, strFileT); alsFiles.AddRange(astrFiles); } // Attempt to process these level doc ArrayList alsTileSets = new ArrayList(); foreach (string strFile in alsFiles) { Console.Write("Loading " + strFile + "..."); LevelDoc lvld = (LevelDoc)DocManager.OpenDocument(strFile); if (lvld == null) { throw new Exception("Could not load level doc " + strFile); } Console.Write(" Done.\n"); // Size this template collection if necessary TemplateDoc tmpd = lvld.GetTemplateDoc(); if (sizTile.Width != tmpd.TileSize.Width || sizTile.Height != tmpd.TileSize.Height) { TemplateTools.ScaleTemplates(tmpd, sizTile); } // Get appropriate TileSet, or make one if this map // uses a new tile collection TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.TileCollectionFileName == Path.GetFileName(lvld.GetTemplateDoc().GetPath())) { tset = tsetT; break; } } // Create new tile set if none found if (tset == null) { string strTcPath = lvld.GetTemplateDoc().GetPath(); string strTcName = Path.GetFileNameWithoutExtension(strTcPath); string strTcDir = Path.GetDirectoryName(strTcPath); string strT3 = strTcDir + Path.DirectorySeparatorChar + strPalDir + Path.DirectorySeparatorChar + strTcName; tset = new TileSet(lvld.GetTemplateDoc(), Path.GetFileName(strTcPath), strT3, nDepth, sizTile); alsTileSets.Add(tset); } // Get and save a tile map for this level string strTmap = Path.GetFileName(lvld.GetPath().Replace(".ld", ".tmap")); string strFileTmap = strDir + Path.DirectorySeparatorChar + strTmap; Console.Write("Creating & writing " + strFileTmap + "..."); TileMap tmap = TileMap.CreateFromImage(tset, lvld.GetMapBitmap(tmpd.TileSize, tmpd, true), tmpd.TileSize); tmap.Save(strFileTmap); Console.Write(" Done.\n"); // Get and save terrain map for this level string strTrmap = Path.GetFileName(lvld.GetPath().Replace(".ld", ".trmap")); string strFileTrmap = strDir + Path.DirectorySeparatorChar + strTrmap; Console.Write("Creating & writing " + strFileTrmap + "..."); TerrainMap trmap = new TerrainMap(lvld.GetTerrainMap(tmpd.TileSize, tmpd, false)); trmap.Save(strFileTrmap); Console.Write(" Done.\n"); // Save .ini for this level doc string strFileIni = strDir + Path.DirectorySeparatorChar + Path.GetFileName(strFile).Replace(".ld", ".lvl"); Console.Write("Writing " + strFileIni + "..."); lvld.SaveIni(strFileIni, nVersion, strTmap, strTrmap, tset.PalBinFileName); Console.Write(" Done.\n"); lvld.Dispose(); } // Now write out tilesets foreach (TileSet tset in alsTileSets) { // Save tile set string strFileTset = strDir + Path.DirectorySeparatorChar + tset.FileName; Console.Write("Creating & writing " + strFileTset + ", " + tset.Count.ToString() + " tiles..."); tset.Save(strFileTset); tset.SaveMini(strFileTset, nAreaBackgroundThreshold, nLuminanceMultBackground, nSaturationMultBackground, nLuminanceMultForeground, nSaturationMultForeground); Console.Write(" Done.\n"); } }
public void InitFromImage(TileSet tset, Bitmap bm) { Color[] aclrTile = new Color[m_sizTile.Width * m_sizTile.Height]; for (int ty = 0; ty < m_cty; ty++) { for (int tx = 0; tx < m_ctx; tx++) { TileSet.ExtractTilePixels(bm, tx, ty, m_sizTile, ref aclrTile); int index = tset.FindTileIndex(aclrTile); if (index == -1) throw new Exception("Couldn't find tile index!"); m_aiTile[ty, tx] = index; } } }
static void ImportTileMap(TileMap tmap, TileSet tset, TemplateDoc tmpd, LevelDoc lvld) { // The TileMap is a list of indexes into a tile set. A Tileset is a list of tiles compiled // from Templates. Reverse the tilemap into Templates, and set into lvld. bool[,] afCellTaken = new bool[64, 64]; ArrayList alsTemplPos = new ArrayList(); Template[] atmpl = tmpd.GetTemplates(); for (int ty = 0; ty < tmap.Height; ty++) { for (int tx = 0; tx < tmap.Width; tx++) { // Cell mapped already? if (afCellTaken[ty, tx]) { continue; } // Cell not mapped. Create TemplatePos. int iTile = tmap.GetTileIndex(tx, ty); TileData tdata = tset.GetTileData(iTile); Template tmpl = atmpl[tdata.iTemplate]; // Don't bother with background tiles if (tmpl == tmpd.GetBackgroundTemplate()) { continue; } int txOrigin = tx - tdata.txTemplate; int tyOrigin = ty - tdata.tyTemplate; bool[,] afMapped = new bool[tmpl.Cty, tmpl.Ctx]; for (int tyTmpl = 0; tyTmpl < tmpl.Cty; tyTmpl++) { for (int txTmpl = 0; txTmpl < tmpl.Ctx; txTmpl++) { int txT = txOrigin + txTmpl; int tyT = tyOrigin + tyTmpl; if (txT < 0 || txT >= 64 || tyT < 0 || tyT >= 64) { continue; } if (afCellTaken[tyT, txT]) { continue; } int iTileT = tmap.GetTileIndex(txT, tyT); if (iTileT != -1) { TileData tdataT = tset.GetTileData(iTileT); if (tdataT.iTemplate != tdata.iTemplate) { continue; } if (tdataT.txTemplate != txTmpl || tdataT.tyTemplate != tyTmpl) { continue; } } afMapped[tyTmpl, txTmpl] = true; afCellTaken[tyT, txT] = true; } } alsTemplPos.Add(new TemplatePos(tmpl, txOrigin, tyOrigin, afMapped)); } } // Figure out the bounds. Rectangle rcBounds = new Rectangle((64 - tmap.Width) / 2, (64 - tmap.Height) / 2, tmap.Width, tmap.Height); lvld.Bounds = rcBounds; // The list of TemplatePos's has been created. Add to LevelDoc. ArrayList alsTiles = new ArrayList(); foreach (TemplatePos tpos in alsTemplPos) { Tile tile = new Tile(tpos.tmpl.Name, tpos.txOrigin + rcBounds.Left, tpos.tyOrigin + rcBounds.Top, tpos.afMapped, tpos.tmpl.OccupancyMap); alsTiles.Add(tile); } lvld.AddMapItems((IMapItem[])alsTiles.ToArray(typeof(IMapItem))); }
public static TileMap CreateFromImage(TileSet tset, Bitmap bm, Size sizTile) { int ctx = bm.Width / sizTile.Width; int cty = bm.Height / sizTile.Height; TileMap tmap = new TileMap(tset.FileName, ctx, cty, sizTile); tmap.InitFromImage(tset, bm); return tmap; }
public static void ExportLevels(string[] astr, int nVersion) { // Get tile size Size sizTile = new Size(0, 0); sizTile.Width = int.Parse(astr[1]); sizTile.Height = sizTile.Width; // Get depth int nDepth = Int32.Parse(astr[2]); // Get background threshold double nAreaBackgroundThreshold = double.Parse(astr[3]); // Background luminance multiplier double nLuminanceMultBackground = double.Parse(astr[4]); // Background saturation multiplier double nSaturationMultBackground = double.Parse(astr[5]); // Foreground luminance multiplier double nLuminanceMultForeground = double.Parse(astr[6]); // Foreground saturation multiplier double nSaturationMultForeground = double.Parse(astr[7]); // Palette directory string strPalDir = astr[8]; // Get output directory string strDir = Path.GetFullPath(astr[9]); // Expand filespecs ArrayList alsFiles = new ArrayList(); for (int n = 9; n < astr.Length; n++) { string strFileT = Path.GetFileName(astr[n]); string strDirT = Path.GetDirectoryName(astr[n]); if (strDirT == "") strDirT = "."; string[] astrFiles = Directory.GetFiles(strDirT, strFileT); alsFiles.AddRange(astrFiles); } // Attempt to process these level doc ArrayList alsTileSets = new ArrayList(); foreach (string strFile in alsFiles) { Console.Write("Loading " + strFile + "..."); LevelDoc lvld = (LevelDoc)DocManager.OpenDocument(strFile); if (lvld == null) throw new Exception("Could not load level doc " + strFile); Console.Write(" Done.\n"); // Size this template collection if necessary TemplateDoc tmpd = lvld.GetTemplateDoc(); if (sizTile.Width != tmpd.TileSize.Width || sizTile.Height != tmpd.TileSize.Height) TemplateTools.ScaleTemplates(tmpd, sizTile); // Get appropriate TileSet, or make one if this map // uses a new tile collection TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.TileCollectionFileName == Path.GetFileName(lvld.GetTemplateDoc().GetPath())) { tset = tsetT; break; } } // Create new tile set if none found if (tset == null) { string strTcPath = lvld.GetTemplateDoc().GetPath(); string strTcName = Path.GetFileNameWithoutExtension(strTcPath); string strTcDir = Path.GetDirectoryName(strTcPath); string strT3 = strTcDir + Path.DirectorySeparatorChar + strPalDir + Path.DirectorySeparatorChar + strTcName; tset = new TileSet(lvld.GetTemplateDoc(), Path.GetFileName(strTcPath), strT3, nDepth, sizTile); alsTileSets.Add(tset); } // Get and save a tile map for this level string strTmap = Path.GetFileName(lvld.GetPath().Replace(".ld", ".tmap")); string strFileTmap = strDir + Path.DirectorySeparatorChar + strTmap; Console.Write("Creating & writing " + strFileTmap + "..."); TileMap tmap = TileMap.CreateFromImage(tset, lvld.GetMapBitmap(tmpd.TileSize, tmpd, true), tmpd.TileSize); tmap.Save(strFileTmap); Console.Write(" Done.\n"); // Get and save terrain map for this level string strTrmap = Path.GetFileName(lvld.GetPath().Replace(".ld", ".trmap")); string strFileTrmap = strDir + Path.DirectorySeparatorChar + strTrmap; Console.Write("Creating & writing " + strFileTrmap + "..."); TerrainMap trmap = new TerrainMap(lvld.GetTerrainMap(tmpd.TileSize, tmpd, false)); trmap.Save(strFileTrmap); Console.Write(" Done.\n"); // Save .ini for this level doc string strFileIni = strDir + Path.DirectorySeparatorChar + Path.GetFileName(strFile).Replace(".ld", ".lvl"); Console.Write("Writing " + strFileIni + "..."); lvld.SaveIni(strFileIni, nVersion, strTmap, strTrmap, tset.PalBinFileName); Console.Write(" Done.\n"); lvld.Dispose(); } // Now write out tilesets foreach (TileSet tset in alsTileSets) { // Save tile set string strFileTset = strDir + Path.DirectorySeparatorChar + tset.FileName; Console.Write("Creating & writing " + strFileTset + ", " + tset.Count.ToString() + " tiles..."); tset.Save(strFileTset); tset.SaveMini(strFileTset, nAreaBackgroundThreshold, nLuminanceMultBackground, nSaturationMultBackground, nLuminanceMultForeground, nSaturationMultForeground); Console.Write(" Done.\n"); } }
public static void SaveExpansionPdb(string strFile, Document[] adoc, string strVersion) { // First save all level docs //annoying //DocManager.SaveAllModified(typeof(LevelDoc)); // Remember active document LevelDoc lvldActive = (LevelDoc)DocManager.GetActiveDocument(typeof(LevelDoc)); // Save documents adoc in an expansion .pdb. Expansion .pdbs need: // - .lvl, .tmap, .trmap, but not .tsets since these come from game .pdbs // - need a version.txt // - need an if demo trigger check "inserted" at save time // - .pdb needs WARI creator, ADD1 type // - data should be compressed for obfuscation purposes PdbPacker pdbp = new PdbPacker(); // Add version.txt byte[] abT = new byte[strVersion.Length + 1]; for (int n = 0; n < strVersion.Length; n++) abT[n] = (byte)strVersion[n]; abT[abT.Length - 1] = 0; pdbp.Add(new PdbPacker.File("version.txt", abT)); // Load res.h from embedded resource in prep for pre-process System.Reflection.Assembly ass = typeof(GobImage).Module.Assembly; Stream stmResDotH = ass.GetManifestResourceStream("m.EmbeddedResources." + "res.h"); if (stmResDotH == null) throw new Exception("Cannot load res.h"); // Compile levels Random rand = new Random(); ArrayList alsTileSets = new ArrayList(); foreach (LevelDoc lvld in adoc) { // Need to do this unfortunately; some of the "saving" code relies on what the "active" document // is!! DocManager.SetActiveDocument(typeof(LevelDoc), lvld); TemplateDoc tmpd = lvld.GetTemplateDoc(); // Get appropriate TileSet, or make one if this map // uses a new tile collection TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.TemplateDoc == tmpd) { tset = tsetT; break; } } // Create new tile set if none found if (tset == null) { tset = new TileSet(tmpd, tmpd.GetName() + ".tset"); alsTileSets.Add(tset); } #if false // Generate base file name for this level (this is never user-visible, but it should be // as unique as possible char[] achBase = new char[16]; for (int n = 0; n < achBase.Length; n++) { int nT = rand.Next() % (26 + 10); if (nT < 26) { achBase[n] = (char)(nT + 97); } else { achBase[n] = (char)(nT + 48 - 26); } } if (lvld.MaxPlayers > 1) { achBase[0] = 'm'; achBase[1] = '_'; } string strBase = new String(achBase); #else // This isn't unique which can cause problems due to how packfiles work. // Could change packfile api to accept .pdb parameter. // Note1: set next mission action requires predictable filename // Note2: mission sorting is based on filename, not title // Could put lots of "support" in to fix these problems, or just ship // it like this. // // Hack: filename length 29 // Maximum extension on filename: 7 string strBase = lvld.Title; if (strBase.Length > 29 - 7) strBase = strBase.Substring(0, 29 - 7); // If multiplayer, add "m_" to the name by losing the last two characters // so sort order is preserved if (lvld.MaxPlayers > 1) strBase = "m_" + strBase.Substring(0, strBase.Length - 2); #endif // Get tile map file for this level MemoryStream stmTmap = new MemoryStream(); TileMap tmap = TileMap.CreateFromImage(tset, lvld.GetMapBitmap(tmpd.TileSize, tmpd, true), tmpd.TileSize); tmap.Save(stmTmap); string strTmap = strBase + ".tmap"; pdbp.Add(new PdbPacker.File(strTmap, stmTmap.ToArray())); stmTmap.Close(); // Get the terrain map file for this level MemoryStream stmTRmap = new MemoryStream(); TerrainMap trmap = new TerrainMap(lvld.GetTerrainMap(tmpd.TileSize, tmpd, false)); trmap.Save(stmTRmap); string strTRmap = strBase + ".trmap"; pdbp.Add(new PdbPacker.File(strTRmap, stmTRmap.ToArray())); stmTRmap.Close(); // Save .ini file for this level doc MemoryStream stmLvld = new MemoryStream(); lvld.SaveIni(stmLvld, -1, strTmap, strTRmap, tmpd.GetName() + ".palbin", true); // Pre-process stmLvld.Seek(0, SeekOrigin.Begin); MemoryStream stmPreprocessed = Misc.PreprocessStream(stmLvld, stmResDotH); stmPreprocessed.Seek(0, SeekOrigin.Begin); Ini iniPreProcessed = new Ini(stmPreprocessed); MemoryStream stmLvldPreProcessedBinary = new MemoryStream(); iniPreProcessed.SaveBinary(stmLvldPreProcessedBinary); stmLvldPreProcessedBinary.Close(); string strLvlName = lvld.OutputFilename; if (strLvlName == null) { strLvlName = strBase + ".lvl"; } pdbp.Add(new PdbPacker.File(strLvlName, stmLvldPreProcessedBinary.ToArray())); stmLvldPreProcessedBinary.Close(); } stmResDotH.Close(); // Restore active document if (lvldActive != null) DocManager.SetActiveDocument(typeof(LevelDoc), lvldActive); // Now save out pdb pdbp.Save(strFile, "WARI", "ADD2"); }