Compare commits

..

No commits in common. "d2960720bdd7420ba6bd795068b599db75df79fa" and "d1593f38c5e1adaf466cd23a5d592b06d96f4235" have entirely different histories.

24 changed files with 414 additions and 410 deletions

View File

@ -32,19 +32,20 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="src\Program.cs" /> <Compile Include="src\Program.cs" />
<Compile Include="src\BaseCommand.cs" />
<Compile Include="src\ExtractCommand.cs" /> <Compile Include="src\ExtractCommand.cs" />
<Compile Include="src\ToJsonCommand.cs" /> <Compile Include="src\ToJsonCommand.cs" />
<Compile Include="src\FromJsonCommand.cs" /> <Compile Include="src\FromJsonCommand.cs" />
<Compile Include="src\CompressCommand.cs" /> <Compile Include="src\CompressCommand.cs" />
<Compile Include="src\DecompressCommand.cs" /> <Compile Include="src\DecompressCommand.cs" />
<Compile Include="src\DumpunitsCommand.cs" /> <Compile Include="src\DumpunitsCommand.cs" />
<Compile Include="src\CopymapConverter.cs" />
<Compile Include="src\ConvertCommand.cs" /> <Compile Include="src\ConvertCommand.cs" />
<Compile Include="src\AddBitmapCommand.cs" /> <Compile Include="src\AddBitmapCommand.cs" />
<Compile Include="src\DelBitmapCommand.cs" /> <Compile Include="src\DelBitmapCommand.cs" />
<Compile Include="src\PackCommand.cs" /> <Compile Include="src\PackCommand.cs" />
<Compile Include="src\Bmp2MapCommand.cs" /> <Compile Include="src\Bmp2MapCommand.cs" />
<Compile Include="src\BitmapHelpers.cs" /> <Compile Include="src\BitmapHelpers.cs" />
<Compile Include="src\ConvertCommandHelper.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
@ -65,11 +66,12 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" />
<Reference Include="System.Web.Extensions" />
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@ -1,12 +1,13 @@
using System.IO; using System.IO;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging;
using AdrianKousz.Util; using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class AddBitmapCommand : CmdApp.Command public class AddBitmapCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var output = File.OpenWrite(args[1])) using (var output = File.OpenWrite(args[1]))
@ -22,11 +23,20 @@ namespace AdrianKousz.GenieEngine
GenieFile.Serialize(scn, output); GenieFile.Serialize(scn, output);
} }
} }
public AddBitmapCommand()
override public int GetArgumentCount()
{ {
MinArgumentCount = 3; return 3;
Description = "Add a pregame bitmap"; }
Help = "Add a pregame bitmap to a scenario."
override public string GetDescription()
{
return "Add a pregame bitmap";
}
override public string GetHelp()
{
return "Add a pregame bitmap to a scenario."
+ "\nThe bitmap has to be indexed, otherwise, the game will probably crash." + "\nThe bitmap has to be indexed, otherwise, the game will probably crash."
+ "\nAdditionally, a game-specific palette will be used to display the image." + "\nAdditionally, a game-specific palette will be used to display the image."
+ "\n" + "\n"

View File

@ -0,0 +1,36 @@
using System;
using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine
{
public class BaseCommand : ICommand<string[]>
{
protected string[] args;
virtual public string GetDescription()
{
return "(Empty description)";
}
virtual public string GetHelp()
{
return "(Empty help text)";
}
virtual public int GetArgumentCount()
{
return 1;
}
virtual public void SetArguments(string[] args)
{
this.args = args;
}
virtual public void Run()
{
foreach (var str in args)
Console.WriteLine(str);
}
}
}

View File

@ -9,24 +9,25 @@ namespace AdrianKousz.GenieEngine
{ {
public static class BitmapHelpers public static class BitmapHelpers
{ {
public static unsafe void FillMap(Scenario scn, Bitmap bmp1, Bitmap bmp2) public static unsafe void FillMap(Scenario scn, Bitmap bmp, Bitmap bmp2)
{ {
using (var ubmp1 = new UnsafeBitmap(bmp1)) using (var ubmp = new UnsafeBitmap(bmp))
using (var ubmp2 = new UnsafeBitmap(bmp2)) using (var ubmp2 = new UnsafeBitmap(bmp2))
{ {
var factory = new ScnDefaultFactory(); var factory = new ScnDefaultFactory();
EnsureValid(ubmp1, ubmp2); Check(ubmp);
Check(ubmp2);
var ptr1 = ubmp1.Scan0; var ptr = ubmp.Scan0;
var last1 = ptr1 + ubmp1.Stride * ubmp1.Height; var last = ptr + ubmp.Stride * ubmp.Height;
var ptr2 = ubmp2.Scan0; var ptr2 = ubmp2.Scan0;
var last2 = ptr2 + ubmp2.Stride * ubmp2.Height; var last2 = ptr2 + ubmp2.Stride * ubmp2.Height;
var map = factory.MakeMap(); var map = factory.MakeMap();
map.SizeX = ubmp1.Width; map.SizeX = ubmp.Width;
map.SizeY = ubmp1.Height; map.SizeY = ubmp.Height;
map.LinearTiles = new Scenario.ScnMap.Tile[map.SizeX * map.SizeY]; map.LinearTiles = new Scenario.ScnMap.Tile[map.SizeX * map.SizeY];
var gaiaunits = new List<Scenario.ScnUnit>(); var gaiaunits = new List<Scenario.ScnUnit>();
@ -40,37 +41,26 @@ namespace AdrianKousz.GenieEngine
treemapping[20] = 349; treemapping[20] = 349;
var i = 0; var i = 0;
var id = 0; while (ptr < last && ptr2 < last2) {
while (ptr1 < last1 && ptr2 < last2) { var treeid = treemapping[*ptr];
var treeid = treemapping[*ptr1];
if (treeid != 0) { if (treeid != 0) {
var unit = factory.MakeUnit(); var unit = factory.MakeUnit();
var posy = i / map.SizeX; var posy = i / map.SizeX;
var posx = i - (posy * map.SizeX); var posx = i - (posy * map.SizeX);
unit.Id = id++;
unit.UnitId = treeid; unit.UnitId = treeid;
unit.PosX = posx + 0.5f; unit.PosX = posx + 0.5f;
unit.PosY = posy + 0.5f; unit.PosY = posy + 0.5f;
unit.Rotation = unit.InitialFrame = (short)Util.Math.Rand(0, 14); unit.Rotation = (short)Util.Math.Rand(0, 13);
gaiaunits.Add(unit); gaiaunits.Add(unit);
} }
map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr1++, (byte)(*ptr2++ / 40), 0); map.LinearTiles[i++] = new Scenario.ScnMap.Tile(*ptr++, (byte)(*ptr2++ / 37), 0);
} }
scn.NextId = id;
scn.Map = map; scn.Map = map;
scn.Units[0] = gaiaunits; scn.Units[0] = gaiaunits;
} }
} }
private static void EnsureValid(UnsafeBitmap ubmp1, UnsafeBitmap ubmp2)
{
if (ubmp1.Width != ubmp2.Width || ubmp1.Height != ubmp2.Height)
throw new ArgumentException("Bitmaps have unequal dimensions");
Check(ubmp1);
Check(ubmp2);
}
private static void Check(UnsafeBitmap ubmp) private static void Check(UnsafeBitmap ubmp)
{ {
if (ubmp.PixelFormat != PixelFormat.Format8bppIndexed) if (ubmp.PixelFormat != PixelFormat.Format8bppIndexed)

View File

@ -1,12 +1,13 @@
using System.IO; using System;
using System.IO;
using System.Drawing; using System.Drawing;
using AdrianKousz.Util; using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class Bmp2MapCommand : CmdApp.Command public class Bmp2MapCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var srcstream = File.OpenRead(args[0])) using (var srcstream = File.OpenRead(args[0]))
using (var outstream = File.OpenWrite(args[1])) using (var outstream = File.OpenWrite(args[1]))
@ -22,16 +23,24 @@ namespace AdrianKousz.GenieEngine
} }
} }
public Bmp2MapCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 4; return 4;
Description = "Generate a scenario map based on bitmaps"; }
Help = "Generate a scenario map based on bitmaps with automatic forest generation."
override public string GetDescription()
{
return "Generate a scenario map based on bitmaps";
}
override public string GetHelp()
{
return "Generate a scenario map based on bitmaps with automatic forest generation."
+ "\n" + "\n"
+ "\nTwo bitmaps need to be specified: One terrain map and one elevation map." + "\nTwo bitmaps need to be specified: One terrain map and one elevation map."
+ "\nBoth bitmaps need to be indexed or grayscale." + "\nBoth bitmaps need to be indexed or grayscale."
+ "\nThe index/gray values of the first bitmap are translated directly to a terrain ID." + "\nThe index/gray values of the first bitmap are translated directly to a terrain ID."
+ "\nThe index/gray values of the second bitmap are divided by 40 to generate elevations 0-6." + "\nThe index/gray values of the second bitmap are divided by 37 to generate elevations 0-6."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input scenario> <output scenario> <terrain bitmap> <elevation bitmap>" + "\n<input scenario> <output scenario> <terrain bitmap> <elevation bitmap>"

View File

@ -1,28 +1,35 @@
using System.IO; using System.IO;
using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class CompressCommand : CmdApp.Command public class CompressCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var output = File.OpenWrite(args[1])) using (var output = File.OpenWrite(args[1]))
{ {
GenieFile.ScenarioCompress(input, output); GenieFile.ScenarioCompression(input, output, false);
} }
} }
public CompressCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 2; return 2;
Description = "Recompress a decompressed scenario file"; }
Help = "Recompress a previously decompressed scenario file."
override public string GetDescription()
{
return "Recompress a decompressed scenario file";
}
override public string GetHelp()
{
return "Recompress a previously decompressed scenario file."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input binary file> <output scenario>" + "\n<input binary file> <output scenario>"
; ;
} }
} }
} }

View File

@ -1,11 +1,12 @@
using System.IO; using System;
using System.IO;
using AdrianKousz.Util; using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class ConvertCommand : CmdApp.Command public class ConvertCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var srcstream = File.OpenRead(args[0])) using (var srcstream = File.OpenRead(args[0]))
using (var outstream = File.OpenWrite(args[1])) using (var outstream = File.OpenWrite(args[1]))
@ -14,46 +15,37 @@ namespace AdrianKousz.GenieEngine
var refscn = GenieFile.Deserialize<Scenario>(refstream); var refscn = GenieFile.Deserialize<Scenario>(refstream);
var srcscn = GenieFile.Deserialize<Scenario>(srcstream); var srcscn = GenieFile.Deserialize<Scenario>(srcstream);
refscn.Filename = srcscn.Filename; srcscn.VersionString = refscn.VersionString;
refscn.InstructionsUncompressed = srcscn.InstructionsUncompressed; srcscn.VersionNumber = refscn.VersionNumber;
refscn.NextId = srcscn.NextId; srcscn.RawIndividualVictory = refscn.RawIndividualVictory;
refscn.PlayerCount = srcscn.PlayerCount; srcscn.RawDisables = refscn.RawDisables;
srcscn.RawRemaining = refscn.RawRemaining;
refscn.PlayerSettings = srcscn.PlayerSettings; srcscn.PlayerSettings.ForEach(x => {
refscn.Resources2 = srcscn.Resources2; x.FilenameAI = x.FilenameCTY = x.FilenamePER = "RandomGame";
refscn.Messages = srcscn.Messages; x.ScriptAI = x.ScriptCTY = x.ScriptPER = "";
refscn.Cinematics = srcscn.Cinematics;
refscn.GlobalVictory = srcscn.GlobalVictory;
refscn.Map = srcscn.Map;
refscn.Units = srcscn.Units;
refscn.PlayerSettings.ForEach(x => {
x.NameStringID = -1;
x.FilenameAI = "RandomGame"; x.FilenameCTY = ""; x.FilenamePER = "";
x.ScriptAI = ""; x.ScriptCTY = ""; x.ScriptPER = "";
}); });
Enumerables.ForBoth(refscn.PlayerSettings2, srcscn.PlayerSettings2, (r, s) => { var converter = new CopymapConverter();
r.Name = s.Name; converter.Convert(srcscn);
r.CameraX = s.CameraX;
r.CameraY = s.CameraY;
r.AlliedVictory = s.AlliedVictory;
r.Stances = s.Stances;
});
var converter = new ConvertCommandHelper(); GenieFile.Serialize(srcscn, outstream);
converter.Convert(refscn);
GenieFile.Serialize(refscn, outstream);
} }
} }
public ConvertCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 3; return 3;
Description = "Convert AOE1 scenario"; }
Help = "Convert AOE1 scenario to AOE2"
override public string GetDescription()
{
return "Convert AOE1 scenario";
}
override public string GetHelp()
{
return "Convert AOE1 scenario to AOE2"
+ "\n" + "\n"
+ "\nThe converter needs an existing AOE2 scenario to start with." + "\nThe converter needs an existing AOE2 scenario to start with."
+ "\n" + "\n"

View File

@ -4,20 +4,44 @@ using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class ConvertCommandHelper public class CopymapConverter
{ {
public void Convert(Scenario scn) public void Convert(Scenario scn)
{ {
ChangeUnits_AOE1_AOE2(scn); scn.Units = ChangeUnits_AOE1_AOE2(scn.Units);
MoveUnits_AOE1_AOE2(scn); MoveUnits_AOE1_AOE2(scn.Units);
ChangeTiles_AOE1_AOE2(scn); ChangeTiles_AOE1_AOE2(scn.Units, scn.Map);
RandomizeTrees_AOE2(scn); RandomizeTrees_AOE2(scn.Units);
}
/**
* Some buildings are not the same size.
* They need to be moved by half a unit.
*/
private void MoveUnits_AOE1_AOE2(IList<Scenario.ScnUnit>[] units)
{
var mapping = new int[] {
// Towers
79, 199, 69, 278,
// Other Buildings
109, 68, 103,
};
units.ForEach(list => {
list.ForEach(unit => {
mapping.ForEach(buildingid => {
if (unit.UnitId == buildingid) {
unit.PosX -= 0.5f;
unit.PosY -= 0.5f;
}
});
});
});
} }
/** /**
* Simple mapping of unit IDs * Simple mapping of unit IDs
*/ */
private void ChangeUnits_AOE1_AOE2(Scenario scn) private List<Scenario.ScnUnit>[] ChangeUnits_AOE1_AOE2(IList<Scenario.ScnUnit>[] units)
{ {
var mapping = new short[] { var mapping = new short[] {
// Resources // Resources
@ -117,43 +141,26 @@ namespace AdrianKousz.GenieEngine
129, 129, 129, 129,
}.ToDictionary(); }.ToDictionary();
scn.Units = scn.Units.Map(list => { var result = units.Map(list => {
return (IList<Scenario.ScnUnit>)list return list
.Filter(unit => mapping.ContainsKey(unit.UnitId)) .Filter(unit => mapping.ContainsKey(unit.UnitId))
.Map(unit => { .ForEach(unit => {
unit.UnitId = mapping[unit.UnitId]; unit.UnitId = mapping[unit.UnitId];
return unit; }).ToList();
}) }).ToArray();
.ToList();
}).ToList();
}
/** return result;
* Some buildings are not the same size.
* They need to be moved by half a unit.
*/
private void MoveUnits_AOE1_AOE2(Scenario scn)
{
var minus = new int[] { 79, 68, 562, };
var plus = new int[] { 109, };
scn.Units.ForEach(list => {
list.ForEach(unit => {
minus.ForEach(buildingid => { if (unit.UnitId != buildingid) return; unit.PosX -= 0.5f; unit.PosY -= 0.5f; });
plus.ForEach(buildingid => { if (unit.UnitId != buildingid) return; unit.PosX += 0.5f; unit.PosY += 0.5f; });
});
});
} }
/** /**
* Farms need to be converted including the underlying terrain. * Farms need to be converted including the underlying terrain.
*/ */
private void ChangeTiles_AOE1_AOE2(Scenario scn) private void ChangeTiles_AOE1_AOE2(IList<Scenario.ScnUnit>[] units, Scenario.ScnMap map)
{ {
var map = scn.Map; units.ForEach(list => {
scn.Units.ForEach(list => {
list.ForEach(unit => { list.ForEach(unit => {
var posx = (int)unit.PosX; var posx = (int)(unit.PosX - 0.5);
var posy = (int)unit.PosY; var posy = (int)(unit.PosY - 0.5);
var linearpos = posy * map.SizeX + posx; var linearpos = posy * map.SizeX + posx;
if (false) { if (false) {
// switch // switch
@ -184,16 +191,16 @@ namespace AdrianKousz.GenieEngine
* Forests would contain the same tree graphic * Forests would contain the same tree graphic
* without this function * without this function
*/ */
private void RandomizeTrees_AOE2(Scenario scn) private void RandomizeTrees_AOE2(IList<Scenario.ScnUnit>[] units)
{ {
var treeids = new int[] { var treeids = new int[] {
411, 351, 414, 350, 348, 349, 411, 351, 414, 350, 348, 349,
}; };
scn.Units.ForEach(list => { units.ForEach(list => {
list.ForEach(unit => { list.ForEach(unit => {
treeids.ForEach(treeid => { treeids.ForEach(treeid => {
if (unit.UnitId == treeid) { if (unit.UnitId == treeid) {
unit.Rotation = unit.InitialFrame = (short)Util.Math.Rand(0, 14); unit.Rotation = (short)Util.Math.Rand(0, 13); // Whats the maximum?
} }
}); });
}); });

View File

@ -1,24 +1,31 @@
using System.IO; using System.IO;
using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class DecompressCommand : CmdApp.Command public class DecompressCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var output = File.OpenWrite(args[1])) using (var output = File.OpenWrite(args[1]))
{ {
GenieFile.ScenarioDecompress(input, output); GenieFile.ScenarioCompression(input, output, true);
} }
} }
public DecompressCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 2; return 2;
Description = "Decompress a scenario file"; }
Help = "Decompress a scenario file for hex editing."
override public string GetDescription()
{
return "Decompress a scenario file";
}
override public string GetHelp()
{
return "Decompress a scenario file for hex editing."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input scenario> <output binary file>" + "\n<input scenario> <output binary file>"

View File

@ -1,11 +1,12 @@
using System.IO; using System.IO;
using System.Drawing;
using AdrianKousz.Util; using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class DelBitmapCommand : CmdApp.Command public class DelBitmapCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var output = File.OpenWrite(args[1])) using (var output = File.OpenWrite(args[1]))
@ -20,11 +21,19 @@ namespace AdrianKousz.GenieEngine
} }
} }
public DelBitmapCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 2; return 2;
Description = "Remove the pregame bitmap"; }
Help = "Remove the pregame bitmap from a scenario."
override public string GetDescription()
{
return "Remove the pregame bitmap";
}
override public string GetHelp()
{
return "Remove the pregame bitmap from a scenario."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input scenario> <output scenario>" + "\n<input scenario> <output scenario>"

View File

@ -1,12 +1,13 @@
using System; using System;
using System.IO; using System.IO;
using System.Collections.Generic;
using AdrianKousz.Util; using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class DumpunitsCommand : CmdApp.Command public class DumpunitsCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
Scenario scn; Scenario scn;
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
@ -14,24 +15,29 @@ namespace AdrianKousz.GenieEngine
scn = GenieFile.Deserialize<Scenario>(input); scn = GenieFile.Deserialize<Scenario>(input);
} }
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3,-8} {4}", "Player", "ID", "UnitID", "TileID", "Position"); Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position");
Console.WriteLine(); Console.WriteLine();
var i = 0; var i = 0;
scn.Units.ForEach(list => { scn.Units.ForEach(list => {
Console.WriteLine("Units of player {0}:", i++);
list.ForEach(unit => { list.ForEach(unit => {
var tilex = (int)unit.PosX; var tilex = (int)(unit.PosX - 0.5);
var tiley = (int)unit.PosY; var tiley = (int)(unit.PosY - 0.5);
var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex]; var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex];
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3,-8} ({4,6:0.##},{5,6:0.##})", i, unit.Id, unit.UnitId, tile.Id, unit.PosX, unit.PosY); Console.WriteLine("{0,-8} {1,-8} {2,-8} ({3,6:0.##},{4,6:0.##})", unit.Id, unit.UnitId, tile.Id, unit.PosX, unit.PosY);
}); });
i++; Console.WriteLine();
}); });
} }
public DumpunitsCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 1; return 1;
Description = "Dump units and underlying map tiles"; }
override public string GetDescription()
{
return "Dump units and map tiles below";
} }
} }
} }

View File

@ -4,9 +4,9 @@ using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class ExtractCommand : CmdApp.Command public class ExtractCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var file = File.OpenRead(args[0])) using (var file = File.OpenRead(args[0]))
{ {
@ -22,10 +22,14 @@ namespace AdrianKousz.GenieEngine
} }
} }
public ExtractCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 1; return 1;
Description = "Extract files from campaign file"; }
override public string GetDescription()
{
return "Extract files from campaign file";
} }
} }
} }

View File

@ -4,9 +4,9 @@ using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class FromJsonCommand : CmdApp.Command public class FromJsonCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var reader = input.GetReader()) using (var reader = input.GetReader())
@ -18,11 +18,19 @@ namespace AdrianKousz.GenieEngine
} }
} }
public FromJsonCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 2; return 2;
Description = "Convert a JSON file to a scenario"; }
Help = "Read a Scenario structure formatted as JSON and save it as a Scenario."
override public string GetDescription()
{
return "Convert a JSON file to a scenario";
}
override public string GetHelp()
{
return "Read a Scenario structure formatted as JSON and save it as a Scenario."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input json> <output scenario>" + "\n<input json> <output scenario>"

View File

@ -4,9 +4,9 @@ using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class PackCommand : CmdApp.Command public class PackCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
var files = new List<Campaign.CpnFile>(); var files = new List<Campaign.CpnFile>();
for (var i = 2; i < args.Length; i++) { for (var i = 2; i < args.Length; i++) {
@ -33,10 +33,14 @@ namespace AdrianKousz.GenieEngine
} }
} }
public PackCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 3; return 3;
Description = "Pack files into a campaign file"; }
override public string GetDescription()
{
return "Pack files into a campaign file";
} }
} }
} }

View File

@ -1,39 +1,51 @@
using System.Collections.Generic; using AdrianKousz.Util;
using System.Windows.Forms; using System.Collections.Generic;
using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class Program public class Program : IApp<string, string[]>
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
System.Threading.Thread.CurrentThread.Name = "main"; System.Threading.Thread.CurrentThread.Name = "main";
Log.SetUncaughtExceptionHandler(); Log.SetUncaughtExceptionHandler();
new CmdApp.Builder() if (System.Diagnostics.Debugger.IsAttached) {
.Header("Scenario Editor") debug();
.NoArg(new MessageBoxCommand()) return;
.Add("convert", new ConvertCommand()) }
.Add("bmp2map", new Bmp2MapCommand())
.Add("addbmp", new AddBitmapCommand()) new CmdApp(new Program(), args).Run();
.Add("delbmp", new DelBitmapCommand())
.Add("compress", new CompressCommand())
.Add("decompress", new DecompressCommand())
.Add("tojson", new ToJsonCommand())
.Add("fromjson", new FromJsonCommand())
.Add("dumpunits", new DumpunitsCommand())
.Add("extract", new ExtractCommand())
.Add("pack", new PackCommand())
.Build()
.Run(args);
} }
private class MessageBoxCommand : CmdApp.Command public string GetHeader()
{ {
public override void Run(string[] args) return "Scenario Editor";
{ }
MessageBox.Show("Start the program on the command line like \n> GenieEdit.exe help");
public IDictionary<string, ICommand<string[]>> GetCommands()
{
var result = new Dictionary<string, ICommand<string[]>>();
result.Add("convert", new ConvertCommand());
result.Add("bmp2map", new Bmp2MapCommand());
result.Add("addbmp", new AddBitmapCommand());
result.Add("delbmp", new DelBitmapCommand());
result.Add("compress", new CompressCommand());
result.Add("decompress", new DecompressCommand());
result.Add("tojson", new ToJsonCommand());
result.Add("fromjson", new FromJsonCommand());
result.Add("dumpunits", new DumpunitsCommand());
result.Add("extract", new ExtractCommand());
result.Add("pack", new PackCommand());
return result;
}
private static void debug()
{
var fn = "";
using (var istream = System.IO.File.OpenRead(fn)) {
var scn = GenieFile.Deserialize<Scenario>(istream);
System.Diagnostics.Debugger.Break(); // Great to inspect scn
} }
} }
} }

View File

@ -4,9 +4,9 @@ using AdrianKousz.Util;
namespace AdrianKousz.GenieEngine namespace AdrianKousz.GenieEngine
{ {
public class ToJsonCommand : CmdApp.Command public class ToJsonCommand : BaseCommand
{ {
override public void Run(string[] args) override public void Run()
{ {
using (var input = File.OpenRead(args[0])) using (var input = File.OpenRead(args[0]))
using (var output = File.OpenWrite(args[1])) using (var output = File.OpenWrite(args[1]))
@ -18,11 +18,19 @@ namespace AdrianKousz.GenieEngine
} }
} }
public ToJsonCommand() override public int GetArgumentCount()
{ {
MinArgumentCount = 2; return 2;
Description = "Convert a scenario to a JSON file"; }
Help = "Save a Scenario structure formatted as JSON."
override public string GetDescription()
{
return "Convert a scenario to a JSON file";
}
override public string GetHelp()
{
return "Save a Scenario structure formatted as JSON."
+ "\n" + "\n"
+ "\nParameters:" + "\nParameters:"
+ "\n<input scenario> <output json>" + "\n<input scenario> <output json>"

View File

@ -31,12 +31,14 @@ namespace AdrianKousz.GenieEngine
number = reader.ReadInt32(); number = reader.ReadInt32();
result.Files = new PositionInfo() result.Files = new PositionInfo()
.CreateArray(number) .CreateList()
.Fill(() => new PositionInfo { .Fill(number, () => {
Size = reader.ReadInt32(), return new PositionInfo {
Offset = reader.ReadInt32(), Size = reader.ReadInt32(),
Name = reader.ReadZString(255), Offset = reader.ReadInt32(),
Filename = reader.ReadZString(257), Name = reader.ReadZString(255),
Filename = reader.ReadZString(257),
};
}) })
.Map(x => { .Map(x => {
var file = new Campaign.CpnFile(); var file = new Campaign.CpnFile();
@ -46,7 +48,7 @@ namespace AdrianKousz.GenieEngine
file.Filename = x.Filename; file.Filename = x.Filename;
return file; return file;
}) })
.ToList(); .ToArray();
return result; return result;
} }

View File

@ -101,29 +101,13 @@ namespace AdrianKousz.GenieEngine
return new ExtendedBinaryWriter(new NonDisposingStreamWrapper(stream), Scenario.Encoding); return new ExtendedBinaryWriter(new NonDisposingStreamWrapper(stream), Scenario.Encoding);
} }
public static void ScenarioDecompress(Stream input, Stream output) public static void ScenarioCompression(Stream input, Stream output, bool decompress)
{ {
CopyHeader(input, output); var mode = decompress ? CompressionMode.Decompress : CompressionMode.Compress;
using (var comp = new DeflateStream(input, CompressionMode.Decompress)) byte[] buffer;
{
comp.CopyTo(output);
}
}
public static void ScenarioCompress(Stream input, Stream output) buffer = input.ReadBytes(8);
{
CopyHeader(input, output);
using (var comp = new DeflateStream(output, CompressionMode.Compress))
{
input.CopyTo(comp);
}
}
private static void CopyHeader(Stream input, Stream output)
{
var buffer = input.ReadBytes(8);
output.Write(buffer); output.Write(buffer);
var headerLength = buffer[4] var headerLength = buffer[4]
@ -134,6 +118,11 @@ namespace AdrianKousz.GenieEngine
buffer = input.ReadBytes(headerLength); buffer = input.ReadBytes(headerLength);
output.Write(buffer); output.Write(buffer);
using (var comp = new DeflateStream(input, mode))
{
comp.CopyTo(output);
}
} }
#endregion #endregion

View File

@ -4,11 +4,10 @@
{ {
Scenario MakeScenario(); Scenario MakeScenario();
Scenario.ScnPlayerSettings MakePlayerSettings(); Scenario.ScnPlayerSettings MakePlayerSettings();
Scenario.ScnResource2 MakeResources2();
Scenario.ScnPlayerSettings2 MakePlayerSettings2();
Scenario.ScnMessages MakeMessages(); Scenario.ScnMessages MakeMessages();
Scenario.ScnCinematics MakeCinematics(); Scenario.ScnCinematics MakeCinematics();
Scenario.ScnGlobalVictory MakeGlobalVictory(); Scenario.ScnGlobalVictory MakeGlobalVictory();
Scenario.ScnResourceCopy MakeResourceCopy();
Scenario.ScnMap MakeMap(); Scenario.ScnMap MakeMap();
Scenario.ScnUnit MakeUnit(); Scenario.ScnUnit MakeUnit();
} }

View File

@ -22,30 +22,30 @@ namespace AdrianKousz.GenieEngine
public String Filename; public String Filename;
public DateTime Timestamp; public DateTime Timestamp;
public String InstructionsUncompressed; public String InstructionsUncompressed;
public Int32 NextId; public Int32 NextId;
public Int32 PlayerCount; public Int32 PlayerCount;
public IList<ScnPlayerSettings> PlayerSettings;
public IList<ScnResource2> Resources2;
public IList<ScnPlayerSettings2> PlayerSettings2;
public ScnMessages Messages; public ScnMessages Messages;
public ScnCinematics Cinematics; public ScnCinematics Cinematics;
public ScnGlobalVictory GlobalVictory; public ScnGlobalVictory GlobalVictory;
public ScnMap Map; public ScnMap Map;
public IList<IList<ScnUnit>> Units;
public ScnPlayerSettings[] PlayerSettings;
public ScnResourceCopy[] ResourceCopies;
public IList<ScnUnit>[] Units;
// NOTE: Raw byte arrays that do not have a parser (yet?)
public Byte[] RawIndividualVictory;
public Byte[] RawDisables;
public Byte[] RawRemaining;
// NOTE: Unknown values
public Int32 Unknown1; public Int32 Unknown1;
public Int32 Unknown2; public Int32 Unknown2;
public Int32 Unknown3; public Int32 Unknown3;
public Byte Unknown4; public Byte Unknown4;
public Single Unknown5; public Single Unknown5;
public Byte[] RawIndividualVictory;
public Byte[] RawDisables;
public Byte[] RawRemaining;
public class ScnPlayerSettings public class ScnPlayerSettings
{ {
public const Int32 ExpectedUnknownInfo = 4; public const Int32 ExpectedUnknownInfo = 4;
@ -55,11 +55,17 @@ namespace AdrianKousz.GenieEngine
public Int32 NameStringID; public Int32 NameStringID;
public Boolean Active; public Boolean Active;
public Boolean Human; public Boolean Human;
public Byte AIType;
public Int32 Civ; public Int32 Civ;
public Int32 StartingAge;
public Int32 UnknownInfo; public Int32 UnknownInfo;
public String FilenameAI;
public String FilenameCTY;
public String FilenamePER;
public String ScriptAI;
public String ScriptCTY;
public String ScriptPER;
public Byte AIType;
public Int32 ResourceWood; public Int32 ResourceWood;
public Int32 ResourceFood; public Int32 ResourceFood;
public Int32 ResourceGold; public Int32 ResourceGold;
@ -67,51 +73,9 @@ namespace AdrianKousz.GenieEngine
public Int32 ResourceOre; public Int32 ResourceOre;
public Int32 UnknownResource; public Int32 UnknownResource;
public Boolean AlliedVictory;
public Int32[] Diplomacy; public Int32[] Diplomacy;
public Boolean AlliedVictory;
public String FilenameAI; public Int32 StartingAge;
public String FilenameCTY;
public String FilenamePER;
public String ScriptAI;
public String ScriptCTY;
public String ScriptPER;
}
public class ScnResource2
{
public const Single ExpectedUnknown = 0;
public Single Wood;
public Single Food;
public Single Gold;
public Single Stone;
public Single Ore;
public Single Unknown;
public Single PopulationLimit;
}
public class ScnPlayerSettings2
{
public String Name;
public Single CameraX;
public Single CameraY;
public Int16 UnknownX;
public Int16 UnknownY;
public Int32 Color;
public Byte AlliedVictory;
public Stance[] Stances;
public Single Unknown1;
public Int32 Unknown2;
public Byte[] Unknown;
public class Stance
{
public Byte Stance1;
public Int32 Stance2;
}
} }
public class ScnMessages public class ScnMessages
@ -163,6 +127,19 @@ namespace AdrianKousz.GenieEngine
public Int32 Unknown; public Int32 Unknown;
} }
public class ScnResourceCopy
{
public const Single ExpectedUnknownResource = 0;
public Single ResourceGold;
public Single ResourceWood;
public Single ResourceFood;
public Single ResourceStone;
public Single ResourceOre;
public Single UnknownResource;
public Single PopulationLimit;
}
public class ScnMap public class ScnMap
{ {
public Int32 CameraX; public Int32 CameraX;

View File

@ -32,10 +32,13 @@ namespace AdrianKousz.GenieEngine
result.Cinematics = MakeCinematics(); result.Cinematics = MakeCinematics();
result.GlobalVictory = MakeGlobalVictory(); result.GlobalVictory = MakeGlobalVictory();
result.Map = MakeMap(); result.Map = MakeMap();
result.PlayerSettings = result.PlayerSettings.NewList().Fill(Scenario.NumPlayers, MakePlayerSettings); result.ResourceCopies = new Scenario.ScnResourceCopy[Scenario.NumPlayerSections - 1]
result.Resources2 = result.Resources2.NewList().Fill(Scenario.NumPlayerSections - 1, MakeResources2); .Fill(MakeResourceCopy);
result.PlayerSettings2 = result.PlayerSettings2.NewList().Fill(Scenario.NumPlayerSections - 1, MakePlayerSettings2); result.PlayerSettings = new Scenario.ScnPlayerSettings[Scenario.NumPlayers]
result.Units = MakeUnitList(Scenario.NumPlayerSections); .Fill(MakePlayerSettings);
result.Units = new List<Scenario.ScnUnit>[Scenario.NumPlayerSections]
.Fill();
} }
return result; return result;
@ -60,25 +63,6 @@ namespace AdrianKousz.GenieEngine
return result; return result;
} }
public Scenario.ScnResource2 MakeResources2()
{
// AOE2 standard
var result = new Scenario.ScnResource2();
result.Unknown = Scenario.ScnResource2.ExpectedUnknown;
result.Food = 200;
result.Wood = 200;
result.Gold = 100;
result.Stone = 200;
result.PopulationLimit = 75;
return result;
}
public Scenario.ScnPlayerSettings2 MakePlayerSettings2()
{
var result = new Scenario.ScnPlayerSettings2();
return result;
}
public Scenario.ScnMessages MakeMessages() public Scenario.ScnMessages MakeMessages()
{ {
var result = new Scenario.ScnMessages(); var result = new Scenario.ScnMessages();
@ -117,6 +101,19 @@ namespace AdrianKousz.GenieEngine
return result; return result;
} }
public Scenario.ScnResourceCopy MakeResourceCopy()
{
// AOE2 standard
var result = new Scenario.ScnResourceCopy();
result.UnknownResource = Scenario.ScnResourceCopy.ExpectedUnknownResource;
result.ResourceFood = 200;
result.ResourceWood = 200;
result.ResourceGold = 100;
result.ResourceStone = 200;
result.PopulationLimit = 75;
return result;
}
public Scenario.ScnMap MakeMap() public Scenario.ScnMap MakeMap()
{ {
var result = new Scenario.ScnMap(); var result = new Scenario.ScnMap();
@ -138,13 +135,6 @@ namespace AdrianKousz.GenieEngine
result.GarrisonnedInId = -1; result.GarrisonnedInId = -1;
return result; return result;
} }
public static IList<IList<Scenario.ScnUnit>> MakeUnitList(int count = Scenario.NumPlayerSections)
{
IList<IList<Scenario.ScnUnit>> result = new List<IList<Scenario.ScnUnit>>()
.Fill(count, () => (IList<Scenario.ScnUnit>)new List<Scenario.ScnUnit>());
return result;
}
} }
} }

View File

@ -33,7 +33,7 @@ namespace AdrianKousz.GenieEngine
result.VersionString = reader.ReadString(4); result.VersionString = reader.ReadString(4);
reader.ReadInt32(); // Header Length reader.ReadInt32(); // Header Length
result.Unknown1 = reader.ReadInt32(); result.Unknown1 = reader.ReadInt32();
result.Timestamp = reader.ReadInt32().ToDateTime(); result.Timestamp = DateTimes.FromUnixTime(reader.ReadInt32());
result.InstructionsUncompressed = reader.ReadZStringInt32(); result.InstructionsUncompressed = reader.ReadZStringInt32();
result.Unknown2 = reader.ReadInt32(); result.Unknown2 = reader.ReadInt32();
result.PlayerCount = reader.ReadInt32(); result.PlayerCount = reader.ReadInt32();
@ -49,7 +49,8 @@ namespace AdrianKousz.GenieEngine
result.VersionNumber = reader.ReadSingle(); result.VersionNumber = reader.ReadSingle();
Version = result.VersionNumber; Version = result.VersionNumber;
result.PlayerSettings = result.PlayerSettings.NewList().Fill(Scenario.NumPlayers, factory.MakePlayerSettings); result.PlayerSettings = new Scenario.ScnPlayerSettings[Scenario.NumPlayers]
.Fill(factory.MakePlayerSettings);
// PlayerSettings 1 // PlayerSettings 1
@ -64,8 +65,8 @@ namespace AdrianKousz.GenieEngine
} }
result.PlayerSettings.ForEach(x => { result.PlayerSettings.ForEach(x => {
x.Active = reader.ReadBooleanInt32(); x.Active = reader.ReadBoolean();
x.Human = reader.ReadBooleanInt32(); x.Human = reader.ReadBoolean();
x.Civ = reader.ReadInt32(); x.Civ = reader.ReadInt32();
x.UnknownInfo = reader.ReadInt32(); x.UnknownInfo = reader.ReadInt32();
}); });
@ -109,7 +110,7 @@ namespace AdrianKousz.GenieEngine
result.Cinematics.FilenameLoss = reader.ReadStringInt16(); result.Cinematics.FilenameLoss = reader.ReadStringInt16();
result.Cinematics.FilenameBitmap = reader.ReadStringInt16(); result.Cinematics.FilenameBitmap = reader.ReadStringInt16();
var hasBitmap = reader.ReadBooleanInt32(); var hasBitmap = reader.ReadBoolean();
result.Cinematics.BitmapWidth = reader.ReadInt32(); result.Cinematics.BitmapWidth = reader.ReadInt32();
result.Cinematics.BitmapHeight = reader.ReadInt32(); result.Cinematics.BitmapHeight = reader.ReadInt32();
@ -165,13 +166,13 @@ namespace AdrianKousz.GenieEngine
result.GlobalVictory = factory.MakeGlobalVictory(); result.GlobalVictory = factory.MakeGlobalVictory();
result.GlobalVictory.RequireConquest = reader.ReadBooleanInt32(); result.GlobalVictory.RequireConquest = reader.ReadBoolean();
result.GlobalVictory.Ruins = reader.ReadInt32(); result.GlobalVictory.Ruins = reader.ReadInt32();
result.GlobalVictory.Artifacts = reader.ReadInt32(); result.GlobalVictory.Artifacts = reader.ReadInt32();
result.GlobalVictory.Discovery = reader.ReadInt32(); result.GlobalVictory.Discovery = reader.ReadInt32();
result.GlobalVictory.PercentExplored = reader.ReadInt32(); result.GlobalVictory.PercentExplored = reader.ReadInt32();
result.GlobalVictory.Unknown = reader.ReadInt32(); result.GlobalVictory.Unknown = reader.ReadInt32();
result.GlobalVictory.RequireAllCustom = reader.ReadBooleanInt32(); result.GlobalVictory.RequireAllCustom = reader.ReadBoolean();
result.GlobalVictory.Mode = reader.ReadInt32(); result.GlobalVictory.Mode = reader.ReadInt32();
result.GlobalVictory.Score = reader.ReadInt32(); result.GlobalVictory.Score = reader.ReadInt32();
result.GlobalVictory.Time = reader.ReadInt32(); result.GlobalVictory.Time = reader.ReadInt32();
@ -187,7 +188,7 @@ namespace AdrianKousz.GenieEngine
ReadSeparator(reader, "Player Environment"); ReadSeparator(reader, "Player Environment");
result.PlayerSettings.ForEach(x => { result.PlayerSettings.ForEach(x => {
x.AlliedVictory = reader.ReadBooleanInt32(); x.AlliedVictory = reader.ReadBoolean();
}); });
if (Version >= 1.15f) number = (Scenario.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/; if (Version >= 1.15f) number = (Scenario.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
@ -222,17 +223,18 @@ namespace AdrianKousz.GenieEngine
number = reader.ReadInt32(); number = reader.ReadInt32();
result.Resources2 = result.Resources2.NewList().Fill(number - 1, factory.MakeResources2); result.ResourceCopies = new Scenario.ScnResourceCopy[number - 1]
.Fill(factory.MakeResourceCopy);
result.Resources2.ForEach(x => { result.ResourceCopies.ForEach(x => {
x.Food = reader.ReadSingle(); x.ResourceFood = reader.ReadSingle();
x.Wood = reader.ReadSingle(); x.ResourceWood = reader.ReadSingle();
x.Gold = reader.ReadSingle(); x.ResourceGold = reader.ReadSingle();
x.Stone = reader.ReadSingle(); x.ResourceStone = reader.ReadSingle();
if (Version >= 1.18f) { if (Version >= 1.18f) {
x.Ore = reader.ReadSingle(); x.ResourceOre = reader.ReadInt32();
if (Version < 1.3f) { if (Version < 1.3f) {
x.Unknown = reader.ReadSingle(); x.UnknownResource = reader.ReadInt32();
} }
} }
if (Version >= 1.22f) { if (Version >= 1.22f) {
@ -242,7 +244,7 @@ namespace AdrianKousz.GenieEngine
// Units // Units
result.Units = ScnDefaultFactory.MakeUnitList(number); result.Units = new List<Scenario.ScnUnit>[number].Fill();
result.Units.ForEach(x => { result.Units.ForEach(x => {
var count = reader.ReadInt32(); var count = reader.ReadInt32();
@ -263,39 +265,7 @@ namespace AdrianKousz.GenieEngine
}); });
}); });
// PlayerSettings2 // More Player Settings and Triggers
number = reader.ReadInt32();
result.PlayerSettings2 = result.PlayerSettings2.NewList().Fill(number - 1, factory.MakePlayerSettings2);
result.PlayerSettings2.ForEach(x => {
x.Name = reader.ReadZStringInt16();
x.CameraX = reader.ReadSingle();
x.CameraY = reader.ReadSingle();
x.UnknownX = reader.ReadInt16();
x.UnknownY = reader.ReadInt16();
x.AlliedVictory = reader.ReadByte();
number = reader.ReadInt16();
x.Stances = new Scenario.ScnPlayerSettings2.Stance[number].Fill();
x.Stances.ForEach(y => { y.Stance1 = reader.ReadByte(); });
x.Stances.ForEach(y => { y.Stance2 = reader.ReadInt32(); });
if (Version >= 1.18f) {
x.Color = reader.ReadInt32();
}
x.Unknown1 = reader.ReadSingle();
x.Unknown2 = reader.ReadInt32();
if (x.Unknown1 == 1.0f || x.Unknown1 == 2.0f) {
x.Unknown = reader.ReadBytes(1 + (int)x.Unknown1 * 8 + x.Unknown2 * 44);
} else {
var msg = string.Format("Numbers {0}/{1} for {2}", x.Unknown1, x.Unknown2, x.Name);
throw new System.NotImplementedException(msg);
}
});
// Triggers
var bytestream = new MemoryStream(); var bytestream = new MemoryStream();
reader.BaseStream.CopyTo(bytestream); reader.BaseStream.CopyTo(bytestream);

View File

@ -17,15 +17,13 @@ namespace AdrianKousz.GenieEngine
public void Write(ExtendedBinaryWriter writer, Scenario value) public void Write(ExtendedBinaryWriter writer, Scenario value)
{ {
EnsureValid(value);
var Version = value.VersionNumber; var Version = value.VersionNumber;
var UncompressedHeaderLength = 20 + writer.GetZByteCount(value.InstructionsUncompressed); var UncompressedHeaderLength = 20 + writer.GetZByteCount(value.InstructionsUncompressed);
// Uncompressed header // Uncompressed header
writer.WriteStringRaw(value.VersionString); writer.WriteStringRaw(value.VersionString);
writer.Write((System.Int32)UncompressedHeaderLength); writer.Write((int)UncompressedHeaderLength);
writer.Write(value.Unknown1); writer.Write(value.Unknown1);
writer.Write((System.Int32)DateTimes.ToUnixTime(value.Timestamp)); writer.Write((System.Int32)DateTimes.ToUnixTime(value.Timestamp));
writer.WriteZStringInt32(value.InstructionsUncompressed); writer.WriteZStringInt32(value.InstructionsUncompressed);
@ -55,8 +53,8 @@ namespace AdrianKousz.GenieEngine
} }
value.PlayerSettings.ForEach(x => { value.PlayerSettings.ForEach(x => {
writer.WriteBooleanInt32(x.Active); writer.Write(x.Active);
writer.WriteBooleanInt32(x.Human); writer.Write(x.Human);
writer.Write(x.Civ); writer.Write(x.Civ);
writer.Write(x.UnknownInfo); writer.Write(x.UnknownInfo);
}); });
@ -98,7 +96,7 @@ namespace AdrianKousz.GenieEngine
var hasBitmap = value.Cinematics.RawBitmap.Length > 0; var hasBitmap = value.Cinematics.RawBitmap.Length > 0;
writer.WriteBooleanInt32(hasBitmap); writer.Write(hasBitmap);
writer.Write(value.Cinematics.BitmapWidth); writer.Write(value.Cinematics.BitmapWidth);
writer.Write(value.Cinematics.BitmapHeight); writer.Write(value.Cinematics.BitmapHeight);
writer.Write(value.Cinematics.BitmapUnknown); writer.Write(value.Cinematics.BitmapUnknown);
@ -115,9 +113,9 @@ namespace AdrianKousz.GenieEngine
}); });
value.PlayerSettings.ForEach(x => { value.PlayerSettings.ForEach(x => {
writer.Write((System.Int32)writer.GetByteCount(x.ScriptAI)); writer.Write((int)writer.GetByteCount(x.ScriptAI));
writer.Write((System.Int32)writer.GetByteCount(x.ScriptCTY)); writer.Write((int)writer.GetByteCount(x.ScriptCTY));
writer.Write((System.Int32)writer.GetByteCount(x.ScriptPER)); writer.Write((int)writer.GetByteCount(x.ScriptPER));
writer.WriteStringRaw(x.ScriptAI); writer.WriteStringRaw(x.ScriptAI);
writer.WriteStringRaw(x.ScriptCTY); writer.WriteStringRaw(x.ScriptCTY);
writer.WriteStringRaw(x.ScriptPER); writer.WriteStringRaw(x.ScriptPER);
@ -150,13 +148,13 @@ namespace AdrianKousz.GenieEngine
// Diplomacy // Diplomacy
writer.WriteBooleanInt32(value.GlobalVictory.RequireConquest); writer.Write(value.GlobalVictory.RequireConquest);
writer.Write(value.GlobalVictory.Ruins); writer.Write(value.GlobalVictory.Ruins);
writer.Write(value.GlobalVictory.Artifacts); writer.Write(value.GlobalVictory.Artifacts);
writer.Write(value.GlobalVictory.Discovery); writer.Write(value.GlobalVictory.Discovery);
writer.Write(value.GlobalVictory.PercentExplored); writer.Write(value.GlobalVictory.PercentExplored);
writer.Write(value.GlobalVictory.Unknown); writer.Write(value.GlobalVictory.Unknown);
writer.WriteBooleanInt32(value.GlobalVictory.RequireAllCustom); writer.Write(value.GlobalVictory.RequireAllCustom);
writer.Write(value.GlobalVictory.Mode); writer.Write(value.GlobalVictory.Mode);
writer.Write(value.GlobalVictory.Score); writer.Write(value.GlobalVictory.Score);
writer.Write(value.GlobalVictory.Time); writer.Write(value.GlobalVictory.Time);
@ -174,7 +172,7 @@ namespace AdrianKousz.GenieEngine
WriteSeparator(writer, "Player Environment"); WriteSeparator(writer, "Player Environment");
value.PlayerSettings.ForEach(x => { value.PlayerSettings.ForEach(x => {
writer.WriteBooleanInt32(x.AlliedVictory); writer.Write(x.AlliedVictory);
}); });
writer.Write(value.RawDisables); writer.Write(value.RawDisables);
@ -205,17 +203,17 @@ namespace AdrianKousz.GenieEngine
// ResourceCopies // ResourceCopies
writer.Write((System.Int32)value.Units.Count); writer.Write((int)value.Units.Length);
value.Resources2.ForEach(x => { value.ResourceCopies.ForEach(x => {
writer.Write(x.Food); writer.Write(x.ResourceFood);
writer.Write(x.Wood); writer.Write(x.ResourceWood);
writer.Write(x.Gold); writer.Write(x.ResourceGold);
writer.Write(x.Stone); writer.Write(x.ResourceStone);
if (Version >= 1.18f) { if (Version >= 1.18f) {
writer.Write(x.Ore); writer.Write(x.ResourceOre);
if (Version < 1.3f) { if (Version < 1.3f) {
writer.Write(x.Unknown); writer.Write(x.UnknownResource);
} }
} }
if (Version >= 1.22f) { if (Version >= 1.22f) {
@ -226,7 +224,7 @@ namespace AdrianKousz.GenieEngine
// Units // Units
value.Units.ForEach(x => { value.Units.ForEach(x => {
writer.Write((System.Int32)x.Count); writer.Write((int)x.Count);
x.ForEach(y => { x.ForEach(y => {
writer.Write(y.PosX); writer.Write(y.PosX);
writer.Write(y.PosY); writer.Write(y.PosY);
@ -242,31 +240,7 @@ namespace AdrianKousz.GenieEngine
}); });
}); });
// PlayerSettings2 // More Player Settings and Triggers
writer.Write((System.Int32)(value.PlayerSettings2.Count + 1));
value.PlayerSettings2.ForEach(x => {
writer.WriteZStringInt16(x.Name);
writer.Write(x.CameraX);
writer.Write(x.CameraY);
writer.Write(x.UnknownX);
writer.Write(x.UnknownY);
writer.Write(x.AlliedVictory);
writer.Write((System.Int16)x.Stances.Length);
x.Stances.ForEach(y => { writer.Write(y.Stance1); });
x.Stances.ForEach(y => { writer.Write(y.Stance2); });
if (Version >= 1.18f) {
writer.Write(x.Color);
}
writer.Write(x.Unknown1);
writer.Write(x.Unknown2);
writer.Write(x.Unknown);
});
// Triggers
writer.Write(value.RawRemaining); writer.Write(value.RawRemaining);
@ -282,14 +256,6 @@ namespace AdrianKousz.GenieEngine
{ {
writer.Write(Scenario.Separator); writer.Write(Scenario.Separator);
} }
private void EnsureValid(Scenario value)
{
if (value.PlayerSettings.Count != Scenario.NumPlayers)
throw new System.InvalidOperationException("PlayerSettings.Count != 16");
if (value.Units.Count - 1 != value.Resources2.Count)
throw new System.InvalidOperationException("Conflicting unit and resource copy count");
}
} }
} }

View File

@ -2,4 +2,4 @@
[assembly: AssemblyTitle("ScenLib")] [assembly: AssemblyTitle("ScenLib")]
[assembly: AssemblyDescription("Read and write scenario data from Genie Engine games")] [assembly: AssemblyDescription("Read and write scenario data from Genie Engine games")]
[assembly: AssemblyVersion("0.6")] [assembly: AssemblyVersion("0.5")]