Compare commits
5 Commits
233d0c9c89
...
82d8551ab1
Author | SHA1 | Date |
---|---|---|
Adrian | 82d8551ab1 | |
Adrian | 41cb3e798b | |
Adrian | bb5ac298a4 | |
Adrian | b65cbcd980 | |
Adrian | 4f98f03cfa |
54
README.md
54
README.md
|
@ -4,7 +4,61 @@ Command line application and library to edit scenario and campaign files.
|
|||
|
||||
**Alpha version**
|
||||
|
||||
## Usage
|
||||
|
||||
Available commands are:
|
||||
copymap Copy parts of scenarios
|
||||
compress Recompress a decompressed scenario file
|
||||
decompress Decompress a scenario file for hex editing
|
||||
extract Extract scenarios from campaign file
|
||||
dump Dump a scenario file to JSON
|
||||
dumpunits Dump units and map tiles below
|
||||
|
||||
The command `copymap` is able convert an AOE1 to an AOE2 scenario.
|
||||
There seem to be some issues with cliffs.
|
||||
|
||||
[OpeningMoves-AOE2.scx](files/OpeningMoves-AOE2.scx)
|
||||
is a fully automated conversion of a scenario from the AOE1 demo version:
|
||||
|
||||
$ GenieEdit.exe copymap files/examples/aoe2x-Empty.scx "files/examples/aoe1demo-Reigno_1-Opening Moves.scn" files/OpeningMoves-AOE2.scx
|
||||
|
||||
(Stone are set to 100 to be able to build a town center from the beginning.)
|
||||
|
||||
It can also be used to dump units from any version of a scenario:
|
||||
|
||||
$ GenieEdit.exe dumpunits Debug2.scx
|
||||
Scenario Editor
|
||||
|
||||
ID UnitID TileID Position
|
||||
|
||||
Units of player 0:
|
||||
0 69 23 ( 1,5, 11,5)
|
||||
1 69 23 ( 2,5, 11,5)
|
||||
...
|
||||
|
||||
### Code
|
||||
|
||||
Have a look at the command implementations. They are very short.
|
||||
|
||||
## Build
|
||||
|
||||
Clone my projects MainUtil.cs ExUtil.cs and this repository
|
||||
and build `src/GenieEdit.sln`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are very welcome. ☺
|
||||
Keep in mind that the API is still very unstable.
|
||||
|
||||
Suggestions:
|
||||
|
||||
1. Gather UnitIDs of AOE1
|
||||
2. Much help is appreciated to figure out ID mappings
|
||||
for the conversion process.
|
||||
3. Ideas how to configure the converter (mapping tables).
|
||||
There are some notes in German:
|
||||
[AOE1](files/units-aoe1.txt),
|
||||
[AOE2](files/units-aoe2.txt)
|
||||
3. The application should be able to generate maps from images
|
||||
in the future. How should units be placed using the image?
|
||||
4. Feedback about the API.
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,59 @@
|
|||
Gold 66
|
||||
Bush 59
|
||||
Stone 102
|
||||
Klippe 3x3 264
|
||||
Dorfbewohner 83
|
||||
|
||||
Kleiner Wall 72
|
||||
Mittelgrosser Wall 117
|
||||
Befestigungsanlage 155
|
||||
|
||||
Beobachtungsturm 2x2 79
|
||||
Abwehrturm 2x2 199
|
||||
Wachturm 2x2 69
|
||||
Geschützturm 2x2 278
|
||||
|
||||
Haus 2x2 70
|
||||
Artefakt 159
|
||||
Bauernhof=>Feld 3x3 50
|
||||
Dorfzentrum 3x3 109
|
||||
Kaserne 3x3 12
|
||||
Kornspeicher 3x3 68
|
||||
Lagergrube 3x3 103
|
||||
Stall 101
|
||||
|
||||
Baum 134
|
||||
Buche 140
|
||||
Eiche 141 144 145 146
|
||||
Esche, Fichte 148 136
|
||||
Kiefer 197 194 193 192 135 137 138 139 391 392
|
||||
Palme 150-153
|
||||
|
||||
Wald Gelaende TileID=10:
|
||||
142 143 147 195 365 366 367 393
|
||||
|
||||
Palmenhain Gelaende TileID=13:
|
||||
113 114 121 129
|
||||
|
||||
Dschungel TileID=20:
|
||||
113 114 121 129
|
||||
|
||||
Kiefernwald TileID=19:
|
||||
161 198 203 226 391 392
|
||||
|
||||
Fisch Kueste 260
|
||||
Fisch Kueste 263
|
||||
Fisch Lachs 53
|
||||
Fisch Thun 52
|
||||
Fisch Wal 370
|
||||
|
||||
Aligator 1
|
||||
Aligator Koenig 362
|
||||
Elefant 48
|
||||
Elefant Koenig 90
|
||||
Gazelle 65
|
||||
Gazelle Koenig 384
|
||||
Loewe 126
|
||||
Loewe Koenig 89
|
||||
Vogel Adler 96
|
||||
Vogel Habicht 95
|
|
@ -0,0 +1,74 @@
|
|||
Gold 66
|
||||
Bush 59
|
||||
Stone 102
|
||||
Klippe 3x3 264
|
||||
Dorfbewohner 83
|
||||
|
||||
Palisadenwall 72
|
||||
Steinwallall 117
|
||||
Befestigter Wall 155
|
||||
|
||||
Aussenposten 1x1 598
|
||||
Beobachtungsturm 1x1 79
|
||||
Wachturm 1x1 79
|
||||
Hauptturm 1x1 79
|
||||
|
||||
Haus 2x2 70
|
||||
Reliquie 285
|
||||
Bauernhof=>Feld 3x3 50 (TileID=7)
|
||||
Dorfzentrum 4x4 109
|
||||
Kaserne 3x3 12
|
||||
Muehle 2x2 68
|
||||
Holzlager 2x2 562
|
||||
Stall 3x3 101
|
||||
|
||||
Bambus 348
|
||||
Baum A-L 399-410
|
||||
Baum TD 248
|
||||
Dschungelbaum 414
|
||||
Eiche 349
|
||||
Kiefer 350
|
||||
Palme 351
|
||||
Verschneiter Kiefer 413
|
||||
Waldbaum 411
|
||||
|
||||
Wald Gelaende TileID=10:
|
||||
411
|
||||
|
||||
Palmenhain Gelaende TileID=13:
|
||||
351
|
||||
|
||||
Dschungel TileID=17:
|
||||
414
|
||||
|
||||
Kiefernwald TileID=19:
|
||||
350
|
||||
|
||||
Bambus TileID=18:
|
||||
348
|
||||
|
||||
Eichenwald TileID=20:
|
||||
349
|
||||
|
||||
Fisch Barsch 53
|
||||
Fisch Dorado 455
|
||||
Fisch Lachs 456
|
||||
Fisch Schnapper 458
|
||||
Fisch Thun 457
|
||||
|
||||
Fisch Marlin 1 451
|
||||
Fisch Marlin 2 450
|
||||
Fisch Kueste 69
|
||||
|
||||
Tiere:
|
||||
Vogel Falke 96
|
||||
Jaguar 812
|
||||
Wildes Pferd 835
|
||||
Pferd 814
|
||||
Reh 65
|
||||
Schaf 594
|
||||
Truthahn 833
|
||||
Urwolf 89
|
||||
Wolf 126
|
||||
Wilder Eber 810
|
||||
Wildschwein 48
|
|
@ -36,6 +36,9 @@
|
|||
<Compile Include="src\CompressCommand.cs" />
|
||||
<Compile Include="src\ExtractCommand.cs" />
|
||||
<Compile Include="src\DumpCommand.cs" />
|
||||
<Compile Include="src\CopymapCommand.cs" />
|
||||
<Compile Include="src\DumpunitsCommand.cs" />
|
||||
<Compile Include="src\CopymapConverter.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
@ -50,6 +53,10 @@
|
|||
<Project>{662FDCF9-3F6C-48DA-BFE9-F317BEFED692}</Project>
|
||||
<Name>ExUtil</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\MainUtil.cs\src\main\MainUtil.csproj">
|
||||
<Project>{8306E345-3A99-4F22-AF14-3CEA7425C2EF}</Project>
|
||||
<Name>MainUtil</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace AdrianKousz.GenieEngine
|
|||
var reader = new ScnReader(file);
|
||||
var writer = new ScnWriter(outfile);
|
||||
|
||||
var header = reader.ReadScenarioHeader(null);
|
||||
var header = reader.ReadScenarioHeader();
|
||||
reader.ReadSeparator("Custom");
|
||||
writer.Write(header);
|
||||
writer.Flush();
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class CopymapCommand : BaseCommand
|
||||
{
|
||||
override public void Run()
|
||||
{
|
||||
Data.Scenario result;
|
||||
using (var dststream = File.OpenRead(args[0]))
|
||||
using (var srcstream = File.OpenRead(args[1]))
|
||||
{
|
||||
var srcreader = new ScnReader(srcstream);
|
||||
var src = srcreader.ReadScenario();
|
||||
var dstreader = new ScnReader(dststream);
|
||||
var dst = dstreader.ReadScenario();
|
||||
var converter = new CopymapConverter();
|
||||
dst.PlayerNames = src.PlayerNames;
|
||||
dst.StringTablePlayerNames = src.StringTablePlayerNames;
|
||||
dst.Players = src.Players;
|
||||
dst.Resources = src.Resources;
|
||||
dst.ResourcesCopy = src.ResourcesCopy;
|
||||
dst.Messages = src.Messages;
|
||||
converter.Convert(dst, src);
|
||||
result = dst;
|
||||
}
|
||||
using (var outstream = File.OpenWrite(args[2])) {
|
||||
var outwriter = new ScnWriter(outstream);
|
||||
outwriter.Write(result);
|
||||
}
|
||||
}
|
||||
|
||||
override public int GetArgumentCount()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
override public string GetDescription()
|
||||
{
|
||||
return "Copy parts of scenarios";
|
||||
}
|
||||
|
||||
override public string GetHelp()
|
||||
{
|
||||
return "Copy the parts below from scenario file 2 into scenario file 1."
|
||||
+ "\nThe result is written to scenario file 3."
|
||||
+ "\n- Messages"
|
||||
+ "\n- Player information"
|
||||
+ "\n- Resources"
|
||||
+ "\n- Map"
|
||||
+ "\n- Units"
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class CopymapConverter
|
||||
{
|
||||
public void Convert(Scenario dst, Scenario src)
|
||||
{
|
||||
dst.Map = src.Map;
|
||||
dst.Units = ChangeUnits_AOE1_AOE2(src.Units);
|
||||
MoveUnits_AOE1_AOE2(dst.Units);
|
||||
ChangeTiles_AOE1_AOE2(dst.Units, dst.Map);
|
||||
RandomizeTrees_AOE2(dst.Units);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some buildings are not the same size.
|
||||
* They need to be moved by half a unit.
|
||||
*/
|
||||
private void MoveUnits_AOE1_AOE2(IList<UnitInfo>[] units)
|
||||
{
|
||||
var mapping = new int[] {
|
||||
// Towers
|
||||
79, 199, 69, 278,
|
||||
// Other Buildings
|
||||
109, 68, 103,
|
||||
};
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
mapping.ForEach((k, buildingid) => {
|
||||
if (unit.UnitId == buildingid) {
|
||||
unit.PosX -= 0.5f;
|
||||
unit.PosY -= 0.5f;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple mapping of unit IDs
|
||||
*/
|
||||
private List<UnitInfo>[] ChangeUnits_AOE1_AOE2(IList<UnitInfo>[] units)
|
||||
{
|
||||
var array = new int[] {
|
||||
66, 66,
|
||||
59, 59,
|
||||
102, 102,
|
||||
264, 264,
|
||||
83, 83,
|
||||
125, 125,
|
||||
|
||||
// Buildings
|
||||
72, 72,
|
||||
117, 117,
|
||||
155, 155,
|
||||
79, 598,
|
||||
199, 79,
|
||||
69, 79,
|
||||
278, 79,
|
||||
70, 70,
|
||||
159, 285,
|
||||
109, 109,
|
||||
12, 12,
|
||||
68, 68,
|
||||
103, 562,
|
||||
101, 101,
|
||||
|
||||
// Trees
|
||||
141, 349,
|
||||
144, 349,
|
||||
145, 349,
|
||||
146, 349,
|
||||
197, 350,
|
||||
194, 350,
|
||||
193, 350,
|
||||
192, 350,
|
||||
135, 350,
|
||||
137, 350,
|
||||
138, 350,
|
||||
139, 350,
|
||||
161, 350,
|
||||
198, 350,
|
||||
203, 350,
|
||||
226, 350,
|
||||
391, 350,
|
||||
392, 350,
|
||||
150, 351,
|
||||
151, 351,
|
||||
152, 351,
|
||||
153, 351,
|
||||
134, 411,
|
||||
140, 411,
|
||||
148, 411,
|
||||
136, 411,
|
||||
142, 411,
|
||||
143, 411,
|
||||
147, 411,
|
||||
195, 411,
|
||||
365, 411,
|
||||
366, 411,
|
||||
367, 411,
|
||||
393, 411,
|
||||
|
||||
// Fish
|
||||
260, 69,
|
||||
263, 69,
|
||||
53, 456,
|
||||
52, 457,
|
||||
370, 451,
|
||||
|
||||
// Animals
|
||||
48, 48,
|
||||
90, 48,
|
||||
65, 65,
|
||||
384, 65,
|
||||
126, 126,
|
||||
89, 126,
|
||||
96, 96,
|
||||
|
||||
// Keep and process later
|
||||
50, 50,
|
||||
113, 113,
|
||||
114, 114,
|
||||
121, 121,
|
||||
129, 129,
|
||||
};
|
||||
var mapping = new Dictionary<int, int>();
|
||||
var ai = 0;
|
||||
while (ai < array.Length)
|
||||
mapping.Add(array[ai++], array[ai++]);
|
||||
|
||||
var result = new List<UnitInfo>[Scenario.NumPlayerSections];
|
||||
result.Fill();
|
||||
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
if (mapping.ContainsKey(unit.UnitId)) {
|
||||
unit.UnitId = (short)mapping[unit.UnitId];
|
||||
result[i].Add(unit);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Farms need to be converted including the underlying terrain.
|
||||
*/
|
||||
private void ChangeTiles_AOE1_AOE2(IList<UnitInfo>[] units, Map map)
|
||||
{
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
var posx = (int)(unit.PosX - 0.5);
|
||||
var posy = (int)(unit.PosY - 0.5);
|
||||
var linearpos = posy * map.SizeX + posx;
|
||||
if (false) {
|
||||
// switch
|
||||
} else if (unit.UnitId == 50) {
|
||||
map.LinearTiles[linearpos].Id = 7;
|
||||
map.LinearTiles[linearpos - 1].Id = 7;
|
||||
map.LinearTiles[linearpos + 1].Id = 7;
|
||||
map.LinearTiles[linearpos - map.SizeX].Id = 7;
|
||||
map.LinearTiles[linearpos - map.SizeX - 1].Id = 7;
|
||||
map.LinearTiles[linearpos - map.SizeX + 1].Id = 7;
|
||||
map.LinearTiles[linearpos + map.SizeX].Id = 7;
|
||||
map.LinearTiles[linearpos + map.SizeX - 1].Id = 7;
|
||||
map.LinearTiles[linearpos + map.SizeX + 1].Id = 7;
|
||||
} else if (unit.UnitId == 113 || unit.UnitId == 114 || unit.UnitId == 121 || unit.UnitId == 129) {
|
||||
if (map.LinearTiles[linearpos].Id == 20) {
|
||||
map.LinearTiles[linearpos].Id = 17;
|
||||
unit.UnitId = 414;
|
||||
} else {
|
||||
unit.UnitId = 351;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forests would contain the same tree graphic
|
||||
* without this function
|
||||
*/
|
||||
private void RandomizeTrees_AOE2(IList<UnitInfo>[] units)
|
||||
{
|
||||
var treeids = new int[] {
|
||||
411, 351, 414, 350, 348, 349,
|
||||
};
|
||||
units.ForEach((i, list) => {
|
||||
list.ForEach((j, unit) => {
|
||||
treeids.ForEach((k, treeid) => {
|
||||
if (unit.UnitId == treeid) {
|
||||
unit.InitialFrame = (short)Util.Math.Rand(0, 13); // Whats the maximum?
|
||||
unit.Rotation = unit.InitialFrame;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,9 +12,9 @@ namespace AdrianKousz.GenieEngine
|
|||
var reader = new ScnReader(file);
|
||||
var writer = new ScnWriter(outfile);
|
||||
|
||||
var header = reader.ReadScenarioHeader(null);
|
||||
var header = reader.ReadScenarioHeader();
|
||||
writer.Write(header);
|
||||
writer.WriteSeperator();
|
||||
writer.WriteSeperator("Custom");
|
||||
writer.Flush();
|
||||
|
||||
using (var comp = new DeflateStream(file, CompressionMode.Decompress)) {
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
using (var stream = File.OpenRead(args[0])) {
|
||||
var aoereader = new ScnReader(stream);
|
||||
var scn = aoereader.ReadScenario(null);
|
||||
var scn = aoereader.ReadScenario();
|
||||
var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
|
||||
var result = ser.Serialize(scn);
|
||||
Console.WriteLine(result);
|
||||
|
@ -23,7 +23,7 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
override public string GetDescription()
|
||||
{
|
||||
return "Dump a scenario file to XML";
|
||||
return "Dump a scenario file to JSON";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class DumpunitsCommand : BaseCommand
|
||||
{
|
||||
override public void Run()
|
||||
{
|
||||
Scenario scn;
|
||||
using (var stream = File.OpenRead(args[0])) {
|
||||
var aoereader = new ScnReader(stream);
|
||||
scn = aoereader.ReadScenario();
|
||||
}
|
||||
|
||||
Console.WriteLine("{0,-8} {1,-8} {2,-8} {3}", "ID", "UnitID", "TileID", "Position");
|
||||
Console.WriteLine();
|
||||
scn.Units.ForEach((i, list) => {
|
||||
Console.WriteLine("Units of player {0}:", i);
|
||||
list.ForEach((j, unit) => {
|
||||
var tilex = (int)(unit.PosX - 0.5);
|
||||
var tiley = (int)(unit.PosY - 0.5);
|
||||
var tile = scn.Map.LinearTiles[tiley * scn.Map.SizeX + tilex];
|
||||
Console.WriteLine("{0,-8} {1,-8} {2,-8} ({3,6:0.##},{4,6:0.##})", unit.Id, unit.UnitId, tile.Id, unit.PosX, unit.PosY);
|
||||
});
|
||||
Console.WriteLine();
|
||||
});
|
||||
}
|
||||
|
||||
override public int GetArgumentCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override public string GetDescription()
|
||||
{
|
||||
return "Dump units and map tiles below";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,11 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
System.Threading.Thread.CurrentThread.Name = "main";
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached) {
|
||||
debug();
|
||||
return;
|
||||
}
|
||||
|
||||
new CmdApp(new Program(), args).Run();
|
||||
}
|
||||
|
||||
|
@ -20,11 +25,23 @@ namespace AdrianKousz.GenieEngine
|
|||
public IDictionary<string, ICommand<string[]>> GetCommands()
|
||||
{
|
||||
var result = new Dictionary<string, ICommand<string[]>>();
|
||||
result.Add("copymap", new CopymapCommand());
|
||||
result.Add("compress", new CompressCommand());
|
||||
result.Add("decompress", new DecompressCommand());
|
||||
result.Add("extract", new ExtractCommand());
|
||||
result.Add("dump", new DumpCommand());
|
||||
result.Add("dumpunits", new DumpunitsCommand());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void debug()
|
||||
{
|
||||
var fn = "";
|
||||
using (var istream = System.IO.File.OpenRead(fn)) {
|
||||
var ireader = new ScnReader(istream);
|
||||
var scn = ireader.ReadScenario();
|
||||
System.Diagnostics.Debugger.Break(); // Great to inspect scn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace AdrianKousz.GenieEngine.Data
|
|||
public String[] PlayerCustomAIs;
|
||||
public String[] PlayerCustomCTYs;
|
||||
public String[] PlayerCustomPERs;
|
||||
public Byte[] RawAITypes;
|
||||
public Byte[] AITypes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ namespace AdrianKousz.GenieEngine.Data
|
|||
public String CinemaLossFn;
|
||||
public String BackgroundFn;
|
||||
|
||||
public Int32 BitmapWidth;
|
||||
public Int32 BitmapHeight;
|
||||
public Int16 BitmapUnknown;
|
||||
|
||||
public Byte[] RawBitmap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace AdrianKousz.GenieEngine.Data
|
||||
{
|
||||
public static class Consts
|
||||
{
|
||||
public const Int32 Separator = -99;
|
||||
public const Int32 NumPlayers = 16;
|
||||
public const Int32 NumUnitSections = 9;
|
||||
public static readonly Encoding Encoding = Encoding.GetEncoding(1252);
|
||||
public static readonly Char[] NullChar = new Char[] { '\0' };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace AdrianKousz.GenieEngine.Data
|
||||
{
|
||||
public class GlobalVictoryInfo
|
||||
{
|
||||
public Boolean RequireConquest;
|
||||
public Int32 Ruins;
|
||||
public Int32 Artifacts;
|
||||
public Int32 Discovery;
|
||||
public Int32 PercentExplored;
|
||||
public Int32 Unknown;
|
||||
public Boolean RequireAllCustom;
|
||||
public Int32 Mode;
|
||||
public Int32 Score;
|
||||
public Int32 Time;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,6 @@ namespace AdrianKousz.GenieEngine.Data
|
|||
{
|
||||
public const Int32 ExpectedUnknown = 4;
|
||||
|
||||
public String Name;
|
||||
public Int32 StringTable;
|
||||
public Boolean Active;
|
||||
public Boolean Human;
|
||||
public Int32 Civ;
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
using System.Text;
|
||||
|
||||
namespace AdrianKousz.GenieEngine.Data
|
||||
{
|
||||
public class Scenario
|
||||
{
|
||||
public const Int32 PlayerSections = 9;
|
||||
public const Int32 Separator = -99;
|
||||
public const Int32 NumPlayers = 16;
|
||||
public const Int32 NumPlayerSections = 9;
|
||||
public static readonly Encoding Encoding = Encoding.GetEncoding(1252);
|
||||
|
||||
public ScenarioHeader Header;
|
||||
|
||||
|
@ -15,22 +18,36 @@ namespace AdrianKousz.GenieEngine.Data
|
|||
public Int32 NextId;
|
||||
public Single OriginalVersion;
|
||||
|
||||
public String[] PlayerNames;
|
||||
public Int32[] StringTablePlayerNames;
|
||||
public PlayerInfo[] Players;
|
||||
public Messages Messages;
|
||||
public Cinematics Cinematics;
|
||||
public AIData AIData;
|
||||
|
||||
// Seperator "Resources"
|
||||
|
||||
public ResourceInfo[] Resources;
|
||||
|
||||
// Seperator "Victory"
|
||||
|
||||
public GlobalVictoryInfo GlobalVictory;
|
||||
public Int32[] LinearDiplomacy;
|
||||
public Byte[] RawIndividualVictory;
|
||||
|
||||
// Seperator "Player Settings"
|
||||
|
||||
public Int32[] AlliedVictory;
|
||||
public Byte[] RawDisables;
|
||||
public Int32[] StartingAges;
|
||||
|
||||
// Seperator "Map"
|
||||
|
||||
public Map Map;
|
||||
public ResourceInfoCopy[] ResourcesCopy;
|
||||
public IList<UnitInfo>[] Units;
|
||||
|
||||
public Byte[] RawGlobalVictory;
|
||||
public Byte[] RawDiplomacy;
|
||||
public Byte[] RawIndividualVictory;
|
||||
public Byte[] RawAlliedVictory;
|
||||
public Byte[] RawDisables;
|
||||
|
||||
public Int32[] StartingAges;
|
||||
public byte[] RawRemaining;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,14 @@ namespace AdrianKousz.GenieEngine.Data
|
|||
{
|
||||
public class UnitInfo
|
||||
{
|
||||
public const Single ExpectedUnknown = 2f;
|
||||
public const Single ExpectedUnknown1 = 1f;
|
||||
public const Byte ExpectedUnknown2 = 2;
|
||||
|
||||
public Single PosX;
|
||||
public Single PosY;
|
||||
public Single Unknown1;
|
||||
public Int32 Id;
|
||||
public Int32 UnitId;
|
||||
public Int16 UnitId;
|
||||
public Byte Unknown2;
|
||||
public Single Rotation;
|
||||
public Int16 InitialFrame;
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
public CpnReader(Stream input)
|
||||
{
|
||||
reader = new ExtendedBinaryReader(input, Data.Consts.Encoding);
|
||||
reader = new ExtendedBinaryReader(input, Scenario.Encoding);
|
||||
}
|
||||
|
||||
public void ExtractFiles()
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public interface IScnFactory
|
||||
{
|
||||
Scenario MakeScenario(bool deep);
|
||||
ScenarioHeader MakeScenarioHeader();
|
||||
PlayerInfo MakePlayerInfo();
|
||||
Messages MakeMessages();
|
||||
Cinematics MakeCinematics();
|
||||
AIData MakeAIData();
|
||||
ResourceInfo MakeResourceInfo();
|
||||
ResourceInfoCopy MakeResourceInfoCopy();
|
||||
GlobalVictoryInfo MakeGlobalVictoryInfo();
|
||||
Map MakeMap();
|
||||
UnitInfo MakeUnitInfo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class ScnConvert
|
||||
{
|
||||
public void Convert(Scenario value, float version)
|
||||
{
|
||||
|
||||
}
|
||||
public void Convert(UnitInfo value, float from, float to)
|
||||
{
|
||||
if (from < 1.18f && to >= 1.18f) {
|
||||
value.InitialFrame = 0;
|
||||
value.GarrisonnedInId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class ScnDefaultFactory : IScnFactory
|
||||
{
|
||||
public Scenario MakeScenario(bool deep)
|
||||
{
|
||||
var result = new Scenario();
|
||||
result.OriginalVersion = 0;
|
||||
result.NextId = 1;
|
||||
|
||||
result.StringTablePlayerNames = new int[Scenario.NumPlayers];
|
||||
|
||||
result.Units = new IList<UnitInfo>[Scenario.NumPlayerSections]
|
||||
.Fill(() => new List<UnitInfo>());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ScenarioHeader MakeScenarioHeader()
|
||||
{
|
||||
var result = new ScenarioHeader();
|
||||
result.Unknown1 = ScenarioHeader.ExpectedUnknown1;
|
||||
result.Unknown2 = ScenarioHeader.ExpectedUnknown2;
|
||||
result.OriginalVersion = "0.00";
|
||||
result.Timestamp = System.DateTime.Now;
|
||||
result.Instructions = "";
|
||||
result.PlayerCount = 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
public PlayerInfo MakePlayerInfo()
|
||||
{
|
||||
var result = new PlayerInfo();
|
||||
result.Unknown = PlayerInfo.ExpectedUnknown;
|
||||
result.Active = false;
|
||||
result.Human = false;
|
||||
result.Civ = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Messages MakeMessages()
|
||||
{
|
||||
var result = new Messages();
|
||||
result.Unknown1 = Messages.ExpectedUnknown1;
|
||||
result.Unknown2 = Messages.ExpectedUnknown2;
|
||||
result.Unknown3 = Messages.ExpectedUnknown3;
|
||||
result.OriginalFilename = "";
|
||||
result.TextInstructions = "";
|
||||
result.TextHints = "";
|
||||
result.TextVictory = "";
|
||||
result.TextLoss = "";
|
||||
result.TextHistory = "";
|
||||
result.TextScouts = "";
|
||||
result.StringTableInstructions = -1;
|
||||
result.StringTableHints = -1;
|
||||
result.StringTableVictory = -1;
|
||||
result.StringTableLoss = -1;
|
||||
result.StringTableHistory = -1;
|
||||
result.StringTableScouts = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Cinematics MakeCinematics()
|
||||
{
|
||||
var result = new Cinematics();
|
||||
result.CinemaPregameFn = "";
|
||||
result.CinemaVictoryFn = "";
|
||||
result.CinemaLossFn = "";
|
||||
result.BackgroundFn = "";
|
||||
result.RawBitmap = new byte[0];
|
||||
return result;
|
||||
}
|
||||
|
||||
public AIData MakeAIData()
|
||||
{
|
||||
var result = new AIData();
|
||||
result.PlayerAIs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.PlayerCTYs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.PlayerPERs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.PlayerCustomAIs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.PlayerCustomCTYs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.PlayerCustomPERs = new string[Scenario.NumPlayers].Fill("");
|
||||
result.AITypes = new byte[Scenario.NumPlayers].Fill((byte)1);
|
||||
return result;
|
||||
}
|
||||
|
||||
public GlobalVictoryInfo MakeGlobalVictoryInfo()
|
||||
{
|
||||
var result = new GlobalVictoryInfo();
|
||||
result.RequireConquest = true;
|
||||
result.RequireAllCustom = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceInfo MakeResourceInfo()
|
||||
{
|
||||
// AOE2 standard
|
||||
var result = new ResourceInfo();
|
||||
result.Unknown = ResourceInfo.ExpectedUnknown;
|
||||
result.Food = 200;
|
||||
result.Wood = 200;
|
||||
result.Gold = 100;
|
||||
result.Stone = 200;
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceInfoCopy MakeResourceInfoCopy()
|
||||
{
|
||||
// AOE2 standard
|
||||
var result = new ResourceInfoCopy();
|
||||
result.Unknown = ResourceInfoCopy.ExpectedUnknown;
|
||||
result.Food = 200;
|
||||
result.Wood = 200;
|
||||
result.Gold = 100;
|
||||
result.Stone = 200;
|
||||
result.PopulationLimit = 75;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map MakeMap()
|
||||
{
|
||||
var result = new Map();
|
||||
var size = 144;
|
||||
result.CameraX = -1;
|
||||
result.CameraY = -1;
|
||||
result.GeneratorId = 2;
|
||||
result.SizeX = size;
|
||||
result.SizeY = size;
|
||||
result.LinearTiles = new Map.Tile[size*size].Fill(() => new Map.Tile(0, 1, 0));
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnitInfo MakeUnitInfo()
|
||||
{
|
||||
var result = new UnitInfo();
|
||||
result.Unknown1 = UnitInfo.ExpectedUnknown1;
|
||||
result.Unknown2 = UnitInfo.ExpectedUnknown2;
|
||||
result.GarrisonnedInId = -1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
namespace AdrianKousz.GenieEngine
|
||||
{
|
||||
public class ScnFactory
|
||||
{
|
||||
public Scenario GetScenario()
|
||||
{
|
||||
var result = new Scenario();
|
||||
result.OriginalVersion = -1;
|
||||
result.NextId = 1;
|
||||
|
||||
result.Header = GetScenarioHeader();
|
||||
|
||||
result.Players = new PlayerInfo[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.Players.Fill(GetPlayerInfo);
|
||||
|
||||
result.Messages = GetMessages();
|
||||
result.Cinematics = GetCinematics();
|
||||
result.AIData = GetAIData();
|
||||
|
||||
result.Resources = new ResourceInfo[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.Resources.Fill(GetResourceInfo);
|
||||
result.Units = new List<UnitInfo>[Scenario.PlayerSections];
|
||||
result.Units.Fill(() => new List<UnitInfo>());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ScenarioHeader GetScenarioHeader()
|
||||
{
|
||||
var result = new ScenarioHeader();
|
||||
result.Unknown1 = ScenarioHeader.ExpectedUnknown1;
|
||||
result.Unknown2 = ScenarioHeader.ExpectedUnknown2;
|
||||
result.OriginalVersion = "0.99";
|
||||
result.Timestamp = System.DateTime.Now;
|
||||
result.Instructions = "";
|
||||
result.PlayerCount = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
public PlayerInfo GetPlayerInfo(int number)
|
||||
{
|
||||
var result = new PlayerInfo();
|
||||
result.Unknown = PlayerInfo.ExpectedUnknown;
|
||||
result.Name = "Player " + number;
|
||||
result.StringTable = -1;
|
||||
result.Active = true;
|
||||
result.Human = true;
|
||||
result.Civ = number;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Messages GetMessages()
|
||||
{
|
||||
var result = new Messages();
|
||||
result.Unknown1 = Messages.ExpectedUnknown1;
|
||||
result.Unknown2 = Messages.ExpectedUnknown2;
|
||||
result.Unknown3 = Messages.ExpectedUnknown3;
|
||||
result.OriginalFilename = "";
|
||||
result.TextInstructions = "";
|
||||
result.TextHints = "";
|
||||
result.TextVictory = "";
|
||||
result.TextLoss = "";
|
||||
result.TextHistory = "";
|
||||
result.TextScouts = "";
|
||||
result.StringTableInstructions = -1;
|
||||
result.StringTableHints = -1;
|
||||
result.StringTableVictory = -1;
|
||||
result.StringTableLoss = -1;
|
||||
result.StringTableHistory = -1;
|
||||
result.StringTableScouts = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Cinematics GetCinematics()
|
||||
{
|
||||
var result = new Cinematics();
|
||||
result.CinemaPregameFn = "";
|
||||
result.CinemaVictoryFn = "";
|
||||
result.CinemaLossFn = "";
|
||||
result.BackgroundFn = "";
|
||||
return result;
|
||||
}
|
||||
|
||||
public AIData GetAIData()
|
||||
{
|
||||
var result = new AIData();
|
||||
result.PlayerAIs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCTYs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerPERs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomAIs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomCTYs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomPERs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerAIs.Fill("");
|
||||
result.PlayerCTYs.Fill("");
|
||||
result.PlayerPERs.Fill("");
|
||||
result.PlayerCustomAIs.Fill("");
|
||||
result.PlayerCustomCTYs.Fill("");
|
||||
result.PlayerCustomPERs.Fill("");
|
||||
result.RawAITypes = new byte[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.RawAITypes.Fill((byte)1);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceInfo GetResourceInfo()
|
||||
{
|
||||
// AOE2 standard
|
||||
var result = new ResourceInfo();
|
||||
result.Unknown = ResourceInfo.ExpectedUnknown;
|
||||
result.Food = 200;
|
||||
result.Wood = 200;
|
||||
result.Gold = 100;
|
||||
result.Stone = 200;
|
||||
result.Ore = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map GetMap()
|
||||
{
|
||||
var result = new Map();
|
||||
var size = 200;
|
||||
result.CameraX = 0;
|
||||
result.CameraY = 0;
|
||||
result.GeneratorId = 0;
|
||||
result.SizeX = size;
|
||||
result.SizeY = size;
|
||||
result.LinearTiles = new Map.Tile[size*size];
|
||||
result.LinearTiles.Fill();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,81 +8,90 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
public class ScnReader
|
||||
{
|
||||
private static readonly string TAG = typeof(ScnReader).Name;
|
||||
public float Version = 0;
|
||||
|
||||
private float version = 0.99f;
|
||||
private ExtendedBinaryReader reader;
|
||||
private IScnFactory factory;
|
||||
|
||||
public ScnReader(Stream input)
|
||||
public ScnReader(Stream input) : this (input, new ScnDefaultFactory())
|
||||
{
|
||||
reader = new ExtendedBinaryReader(input, Data.Consts.Encoding);
|
||||
}
|
||||
|
||||
public ScnReader(Stream input, IScnFactory factory)
|
||||
{
|
||||
reader = new ExtendedBinaryReader(input, Scenario.Encoding);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
#region Reader Methods
|
||||
|
||||
public Scenario ReadScenario(Scenario result)
|
||||
public Scenario ReadScenario()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeScenario(false);
|
||||
int number = 0;
|
||||
|
||||
result.Header = ReadScenarioHeader(result.Header);
|
||||
result.Header = ReadScenarioHeader();
|
||||
|
||||
var comp = new DeflateStream(reader.BaseStream, CompressionMode.Decompress);
|
||||
reader = new ExtendedBinaryReader(comp, Data.Consts.Encoding);
|
||||
reader = new ExtendedBinaryReader(comp, Scenario.Encoding);
|
||||
|
||||
result.NextId = reader.ReadInt32();
|
||||
|
||||
version = reader.ReadSingle();
|
||||
result.OriginalVersion = version;
|
||||
Log.i(TAG, "Detected version {0}", version);
|
||||
Version = reader.ReadSingle();
|
||||
result.OriginalVersion = Version;
|
||||
|
||||
|
||||
result.Players = FillArray(ReadPlayerInfo, result.Players, AdrianKousz.GenieEngine.Data.Consts.NumPlayers);
|
||||
result.Messages = ReadMessages(result.Messages);
|
||||
result.Cinematics = ReadCinematics(result.Cinematics);
|
||||
result.AIData = ReadAIData(result.AIData);
|
||||
result.PlayerNames = FillArray(() => reader.ReadZString(256), result.PlayerNames, Scenario.NumPlayers);
|
||||
if (Version >= 1.18f) {
|
||||
result.StringTablePlayerNames = FillArray(reader.ReadInt32, result.StringTablePlayerNames, Scenario.NumPlayers);
|
||||
}
|
||||
result.Players = FillArray(ReadPlayerInfo, result.Players, Scenario.NumPlayers);
|
||||
result.Messages = ReadMessages();
|
||||
result.Cinematics = ReadCinematics();
|
||||
result.AIData = ReadAIData();
|
||||
|
||||
ReadSeparator("Resources");
|
||||
|
||||
result.Resources = FillArray(ReadResourceInfo, result.Resources, AdrianKousz.GenieEngine.Data.Consts.NumPlayers);
|
||||
result.Resources = FillArray(ReadResourceInfo, result.Resources, Scenario.NumPlayers);
|
||||
|
||||
ReadSeparator("Victory");
|
||||
|
||||
result.RawGlobalVictory = reader.ReadBytes(10 * 4);
|
||||
result.RawDiplomacy = reader.ReadBytes(AdrianKousz.GenieEngine.Data.Consts.NumPlayers * AdrianKousz.GenieEngine.Data.Consts.NumPlayers * 4);
|
||||
result.GlobalVictory = ReadGlobalVictoryInfo();
|
||||
result.LinearDiplomacy = FillArray(reader.ReadInt32, result.LinearDiplomacy, Scenario.NumPlayers * Scenario.NumPlayers);
|
||||
result.RawIndividualVictory = reader.ReadBytes(11520);
|
||||
|
||||
ReadSeparator("Player Settings");
|
||||
|
||||
result.RawAlliedVictory = reader.ReadBytes(AdrianKousz.GenieEngine.Data.Consts.NumPlayers * 4);
|
||||
result.AlliedVictory = FillArray(reader.ReadInt32, result.AlliedVictory, Scenario.NumPlayers);
|
||||
|
||||
if (1.15f <= version) number = (AdrianKousz.GenieEngine.Data.Consts.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
if (1.18f <= version) number = (AdrianKousz.GenieEngine.Data.Consts.NumPlayers * (3 /*Lengths*/ + 80 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
if (1.30f <= version) number = (AdrianKousz.GenieEngine.Data.Consts.NumPlayers * (3 /*Lengths*/ + 180 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
if (Version >= 1.15f) number = (Scenario.NumPlayers * ( 20 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
if (Version >= 1.18f) number = (Scenario.NumPlayers * (3 /*Lengths*/ + 80 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
if (Version >= 1.30f) number = (Scenario.NumPlayers * (3 /*Lengths*/ + 180 /*Disables*/) + 3 /*Unknowns*/) * 4 /*Intsize*/;
|
||||
result.RawDisables = reader.ReadBytes(number);
|
||||
|
||||
result.StartingAges = new int[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.StartingAges.Fill(reader.ReadInt32);
|
||||
result.StartingAges = FillArray(reader.ReadInt32, result.StartingAges, Scenario.NumPlayers);
|
||||
|
||||
ReadSeparator("Map");
|
||||
|
||||
result.Map = ReadMap(result.Map);
|
||||
result.Map = ReadMap();
|
||||
|
||||
number = reader.ReadInt32();
|
||||
result.ResourcesCopy = FillArray(ReadResourceInfoCopy, result.ResourcesCopy, number - 1);
|
||||
|
||||
result.Units = new IList<UnitInfo>[number];
|
||||
result.Units.Fill(ReadUnitInfo);
|
||||
result.Units = FillArray(ReadUnitInfoList, result.Units, number);
|
||||
|
||||
var bytestream = new MemoryStream();
|
||||
reader.BaseStream.CopyTo(bytestream);
|
||||
result.RawRemaining = bytestream.ToArray();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ScenarioHeader ReadScenarioHeader(ScenarioHeader result)
|
||||
public ScenarioHeader ReadScenarioHeader()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeScenarioHeader();
|
||||
|
||||
result.OriginalVersion = reader.ReadString(4);
|
||||
Skip(4, "Header Length");
|
||||
reader.ReadInt32(); // Header Length
|
||||
result.Unknown1 = reader.ReadInt32();
|
||||
result.Timestamp = DateTimes.FromUnixTime(reader.ReadInt32());
|
||||
result.Instructions = reader.ReadZStringInt32();
|
||||
|
@ -92,14 +101,10 @@ namespace AdrianKousz.GenieEngine
|
|||
return result;
|
||||
}
|
||||
|
||||
public PlayerInfo ReadPlayerInfo(PlayerInfo result)
|
||||
public PlayerInfo ReadPlayerInfo()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakePlayerInfo();
|
||||
|
||||
result.Name = reader.ReadZString(256);
|
||||
if (1.18f <= version) {
|
||||
result.StringTable = reader.ReadInt32();
|
||||
}
|
||||
result.Active = reader.ReadBoolean();
|
||||
result.Human = reader.ReadBoolean();
|
||||
result.Civ = reader.ReadInt32();
|
||||
|
@ -108,23 +113,23 @@ namespace AdrianKousz.GenieEngine
|
|||
return result;
|
||||
}
|
||||
|
||||
public Messages ReadMessages(Messages result)
|
||||
public Messages ReadMessages()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeMessages();
|
||||
|
||||
result.Unknown1 = reader.ReadInt32();
|
||||
result.Unknown2 = reader.ReadByte();
|
||||
result.Unknown3 = reader.ReadSingle();
|
||||
result.OriginalFilename = reader.ReadStringInt16();
|
||||
|
||||
if (1.18f <= version) {
|
||||
if (Version >= 1.18f) {
|
||||
result.StringTableInstructions = reader.ReadInt32();
|
||||
result.StringTableHints = reader.ReadInt32();
|
||||
result.StringTableVictory = reader.ReadInt32();
|
||||
result.StringTableLoss = reader.ReadInt32();
|
||||
result.StringTableHistory = reader.ReadInt32();
|
||||
}
|
||||
if (1.22f <= version) {
|
||||
if (Version >= 1.22f) {
|
||||
result.StringTableScouts = reader.ReadInt32();
|
||||
}
|
||||
|
||||
|
@ -133,16 +138,16 @@ namespace AdrianKousz.GenieEngine
|
|||
result.TextVictory = reader.ReadZStringInt16();
|
||||
result.TextLoss = reader.ReadZStringInt16();
|
||||
result.TextHistory = reader.ReadZStringInt16();
|
||||
if (1.22f <= version) {
|
||||
if (Version >= 1.22f) {
|
||||
result.TextScouts = reader.ReadZStringInt16();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Cinematics ReadCinematics(Cinematics result)
|
||||
public Cinematics ReadCinematics()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeCinematics();
|
||||
|
||||
result.CinemaPregameFn = reader.ReadStringInt16();
|
||||
result.CinemaVictoryFn = reader.ReadStringInt16();
|
||||
|
@ -151,37 +156,31 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
var hasBitmap = reader.ReadBoolean();
|
||||
|
||||
Skip(4, "Bitmap width");
|
||||
Skip(4, "Bitmap height");
|
||||
Skip(2, "Bitmap Unknown");
|
||||
result.BitmapWidth = reader.ReadInt32();
|
||||
result.BitmapHeight = reader.ReadInt32();
|
||||
result.BitmapUnknown = reader.ReadInt16();
|
||||
|
||||
if (hasBitmap) {
|
||||
result.RawBitmap = BitmapUtil.ReadRawBitmap(reader.BaseStream);
|
||||
} else {
|
||||
result.RawBitmap = new byte[0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public AIData ReadAIData(AIData result)
|
||||
public AIData ReadAIData()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeAIData();
|
||||
|
||||
result.PlayerAIs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCTYs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerPERs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomAIs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomCTYs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerCustomPERs = new string[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.RawAITypes = new byte[AdrianKousz.GenieEngine.Data.Consts.NumPlayers];
|
||||
result.PlayerAIs = FillArray(reader.ReadStringInt16, result.PlayerAIs, Scenario.NumPlayers);
|
||||
result.PlayerCTYs = FillArray(reader.ReadStringInt16, result.PlayerCTYs, Scenario.NumPlayers);
|
||||
result.PlayerPERs = FillArray(reader.ReadStringInt16, result.PlayerPERs, Scenario.NumPlayers);
|
||||
|
||||
result.PlayerAIs.Fill(reader.ReadStringInt16);
|
||||
result.PlayerCTYs.Fill(reader.ReadStringInt16);
|
||||
result.PlayerPERs.Fill(reader.ReadStringInt16);
|
||||
result.PlayerCustomAIs = new string[Scenario.NumPlayers];
|
||||
result.PlayerCustomCTYs = new string[Scenario.NumPlayers];
|
||||
result.PlayerCustomPERs = new string[Scenario.NumPlayers];
|
||||
|
||||
int l1, l2, l3;
|
||||
for (var i = 0; i < AdrianKousz.GenieEngine.Data.Consts.NumPlayers; ++i) {
|
||||
for (var i = 0; i < Scenario.NumPlayers; ++i) {
|
||||
l1 = reader.ReadInt32();
|
||||
l2 = reader.ReadInt32();
|
||||
l3 = reader.ReadInt32();
|
||||
|
@ -190,88 +189,112 @@ namespace AdrianKousz.GenieEngine
|
|||
result.PlayerCustomPERs[i] = reader.ReadString(l3);
|
||||
}
|
||||
|
||||
if (1.18f <= version) {
|
||||
result.RawAITypes.Fill(reader.ReadByte);
|
||||
if (Version >= 1.18f) {
|
||||
result.AITypes = FillArray(reader.ReadByte, result.AITypes, Scenario.NumPlayers);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceInfo ReadResourceInfo(ResourceInfo result)
|
||||
public ResourceInfo ReadResourceInfo()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeResourceInfo();
|
||||
|
||||
result.Gold = reader.ReadInt32();
|
||||
result.Wood = reader.ReadInt32();
|
||||
result.Food = reader.ReadInt32();
|
||||
result.Stone = reader.ReadInt32();
|
||||
if (1.18f <= version) {
|
||||
if (Version >= 1.18f) {
|
||||
result.Ore = reader.ReadInt32();
|
||||
result.Unknown = reader.ReadInt32();
|
||||
if (Version < 1.3f) {
|
||||
result.Unknown = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map ReadMap(Map result)
|
||||
public ResourceInfoCopy ReadResourceInfoCopy()
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
|
||||
if (1.18f <= version) {
|
||||
result.CameraX = reader.ReadInt32();
|
||||
result.CameraY = reader.ReadInt32();
|
||||
}
|
||||
if (1.22f <= version) {
|
||||
result.GeneratorId = reader.ReadInt32();
|
||||
}
|
||||
|
||||
result.SizeX = reader.ReadInt32();
|
||||
result.SizeY = reader.ReadInt32();
|
||||
|
||||
result.LinearTiles = new Map.Tile[result.SizeX * result.SizeY];
|
||||
result.LinearTiles.Fill(() => new Map.Tile(reader.ReadByte(), reader.ReadByte(), reader.ReadByte()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceInfoCopy ReadResourceInfoCopy(ResourceInfoCopy result)
|
||||
{
|
||||
result = Misc.MayNew(result);
|
||||
var result = factory.MakeResourceInfoCopy();
|
||||
|
||||
result.Food = reader.ReadSingle();
|
||||
result.Wood = reader.ReadSingle();
|
||||
result.Gold = reader.ReadSingle();
|
||||
result.Stone = reader.ReadSingle();
|
||||
if (1.18f <= version) {
|
||||
if (Version >= 1.18f) {
|
||||
result.Ore = reader.ReadInt32();
|
||||
result.Unknown = reader.ReadInt32();
|
||||
if (Version < 1.3f) {
|
||||
result.Unknown = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
if (1.22f <= version) {
|
||||
if (Version >= 1.22f) {
|
||||
result.PopulationLimit = reader.ReadSingle();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IList<UnitInfo> ReadUnitInfo()
|
||||
public GlobalVictoryInfo ReadGlobalVictoryInfo()
|
||||
{
|
||||
var number = reader.ReadInt32();
|
||||
var result = new List<UnitInfo>(number);
|
||||
var result = factory.MakeGlobalVictoryInfo();
|
||||
|
||||
for (var i = 0; i < number; i++) {
|
||||
var unit = new UnitInfo();
|
||||
unit.PosX = reader.ReadSingle();
|
||||
unit.PosY = reader.ReadSingle();
|
||||
unit.Unknown1 = reader.ReadSingle();
|
||||
unit.Id = reader.ReadInt32();
|
||||
unit.UnitId = reader.ReadInt16();
|
||||
unit.Unknown2 = reader.ReadByte();
|
||||
unit.Rotation = reader.ReadSingle();
|
||||
if (1.18f <= version) {
|
||||
unit.InitialFrame = reader.ReadInt16();
|
||||
unit.GarrisonnedInId = reader.ReadInt32();
|
||||
}
|
||||
result.Add(unit);
|
||||
result.RequireConquest = reader.ReadBoolean();
|
||||
result.Ruins = reader.ReadInt32();
|
||||
result.Artifacts = reader.ReadInt32();
|
||||
result.Discovery = reader.ReadInt32();
|
||||
result.PercentExplored = reader.ReadInt32();
|
||||
result.Unknown = reader.ReadInt32();
|
||||
result.RequireAllCustom = reader.ReadBoolean();
|
||||
result.Mode = reader.ReadInt32();
|
||||
result.Score = reader.ReadInt32();
|
||||
result.Time = reader.ReadInt32();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map ReadMap()
|
||||
{
|
||||
var result = factory.MakeMap();
|
||||
|
||||
if (Version >= 1.18f) {
|
||||
result.CameraX = reader.ReadInt32();
|
||||
result.CameraY = reader.ReadInt32();
|
||||
}
|
||||
if (Version >= 1.22f) {
|
||||
result.GeneratorId = reader.ReadInt32();
|
||||
}
|
||||
|
||||
result.SizeX = reader.ReadInt32();
|
||||
result.SizeY = reader.ReadInt32();
|
||||
|
||||
result.LinearTiles = new Map.Tile[result.SizeX * result.SizeY]
|
||||
.Fill(() => new Map.Tile(reader.ReadByte(), reader.ReadByte(), reader.ReadByte()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IList<UnitInfo> ReadUnitInfoList()
|
||||
{
|
||||
var count = reader.ReadInt32();
|
||||
var result = new List<UnitInfo>().Fill(ReadUnitInfo, count);
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnitInfo ReadUnitInfo()
|
||||
{
|
||||
var result = factory.MakeUnitInfo();
|
||||
|
||||
result.PosX = reader.ReadSingle();
|
||||
result.PosY = reader.ReadSingle();
|
||||
result.Unknown1 = reader.ReadSingle();
|
||||
result.Id = reader.ReadInt32();
|
||||
result.UnitId = reader.ReadInt16();
|
||||
result.Unknown2 = reader.ReadByte();
|
||||
result.Rotation = reader.ReadSingle();
|
||||
if (Version >= 1.18f) {
|
||||
result.InitialFrame = reader.ReadInt16();
|
||||
result.GarrisonnedInId = reader.ReadInt32();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -279,7 +302,7 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
public void ReadSeparator(string name) {
|
||||
int v = reader.ReadInt32();
|
||||
if (v != AdrianKousz.GenieEngine.Data.Consts.Separator) {
|
||||
if (v != Scenario.Separator) {
|
||||
var msg = "Separator \"{0}\" = {1}";
|
||||
msg = string.Format(msg, name, v);
|
||||
throw new InvalidDataException(msg);
|
||||
|
@ -290,26 +313,14 @@ namespace AdrianKousz.GenieEngine
|
|||
|
||||
#region Debug Methods
|
||||
|
||||
private T[] FillArray<T>(System.Func<T, T> f, T[] array, int length) where T : new()
|
||||
private T[] FillArray<T>(System.Func<T> f, T[] array, int length)
|
||||
{
|
||||
if (array == null) {
|
||||
if (array == null || array.Length != length)
|
||||
array = new T[length];
|
||||
} else if (array.Length != length) {
|
||||
var temp = new T[length];
|
||||
System.Array.Copy(array, temp, System.Math.Min(array.Length, temp.Length));
|
||||
}
|
||||
|
||||
array.Fill(f);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
private void Skip(int count, string name)
|
||||
{
|
||||
Log.d(TAG, "Skipping {0} bytes in \"{1}\"", count, name);
|
||||
reader.ReadBytes(count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Collections.Generic;
|
||||
using AdrianKousz.Util;
|
||||
using AdrianKousz.GenieEngine.Data;
|
||||
|
||||
|
@ -6,18 +8,76 @@ namespace AdrianKousz.GenieEngine
|
|||
{
|
||||
public class ScnWriter
|
||||
{
|
||||
private static readonly string TAG = typeof(ScnWriter).Name;
|
||||
public float Version = 0;
|
||||
|
||||
private ExtendedBinaryWriter writer;
|
||||
|
||||
public ScnWriter(Stream input)
|
||||
public ScnWriter(Stream output)
|
||||
{
|
||||
writer = new ExtendedBinaryWriter(input, Data.Consts.Encoding);
|
||||
writer = new ExtendedBinaryWriter(output, Scenario.Encoding);
|
||||
}
|
||||
|
||||
public void Write(Scenario value)
|
||||
{
|
||||
Version = Version == 0 ? value.OriginalVersion : Version;
|
||||
|
||||
Write(value.Header);
|
||||
Flush();
|
||||
|
||||
// TODO: Make wrapper.
|
||||
// This is a workaround for now. A wrapper for the reader and writer will be created.
|
||||
var originalWriter = writer;
|
||||
var compressedPart = new MemoryStream();
|
||||
var comp = new DeflateStream(compressedPart, CompressionMode.Compress);
|
||||
writer = new ExtendedBinaryWriter(comp, Scenario.Encoding);
|
||||
|
||||
writer.Write(value.NextId);
|
||||
writer.Write(Version);
|
||||
|
||||
value.PlayerNames.ForEach((x) => writer.WriteStringPadded(x, 256));
|
||||
if (Version >= 1.18f) {
|
||||
value.StringTablePlayerNames.ForEach(writer.Write);
|
||||
}
|
||||
value.Players.ForEach(Write);
|
||||
Write(value.Messages);
|
||||
Write(value.Cinematics);
|
||||
Write(value.AIData);
|
||||
|
||||
WriteSeperator("Resources");
|
||||
|
||||
value.Resources.ForEach(Write);
|
||||
|
||||
WriteSeperator("Victory");
|
||||
|
||||
Write(value.GlobalVictory);
|
||||
value.LinearDiplomacy.ForEach(writer.Write);
|
||||
writer.Write(value.RawIndividualVictory);
|
||||
|
||||
WriteSeperator("Player Settings");
|
||||
|
||||
value.AlliedVictory.ForEach(writer.Write);
|
||||
writer.Write(value.RawDisables);
|
||||
value.StartingAges.ForEach(writer.Write);
|
||||
|
||||
WriteSeperator("Map");
|
||||
|
||||
Write(value.Map);
|
||||
|
||||
writer.Write((int)value.Units.Length);
|
||||
value.ResourcesCopy.ForEach(Write);
|
||||
value.Units.ForEach(Write);
|
||||
|
||||
writer.Write(value.RawRemaining);
|
||||
|
||||
Flush();
|
||||
|
||||
comp.Dispose();
|
||||
originalWriter.Write(compressedPart.ToArray());
|
||||
}
|
||||
|
||||
public void Write(ScenarioHeader value)
|
||||
{
|
||||
var instructionlength = writer.GetByteCount(value.Instructions + " ");
|
||||
var instructionlength = writer.GetZByteCount(value.Instructions);
|
||||
writer.WriteStringRaw(value.OriginalVersion);
|
||||
writer.Write(20 + instructionlength);
|
||||
writer.Write(value.Unknown1);
|
||||
|
@ -27,15 +87,180 @@ namespace AdrianKousz.GenieEngine
|
|||
writer.Write(value.PlayerCount);
|
||||
}
|
||||
|
||||
public void WriteSeperator()
|
||||
public void Write(PlayerInfo value)
|
||||
{
|
||||
writer.Write(AdrianKousz.GenieEngine.Data.Consts.Separator);
|
||||
writer.Write(value.Active);
|
||||
writer.Write(value.Human);
|
||||
writer.Write(value.Civ);
|
||||
writer.Write(value.Unknown);
|
||||
}
|
||||
|
||||
public void Write(Messages value)
|
||||
{
|
||||
writer.Write(value.Unknown1);
|
||||
writer.Write(value.Unknown2);
|
||||
writer.Write(value.Unknown3);
|
||||
writer.WriteStringInt16(value.OriginalFilename);
|
||||
|
||||
if (Version >= 1.18f) {
|
||||
writer.Write(value.StringTableInstructions);
|
||||
writer.Write(value.StringTableHints);
|
||||
writer.Write(value.StringTableVictory);
|
||||
writer.Write(value.StringTableLoss);
|
||||
writer.Write(value.StringTableHistory);
|
||||
}
|
||||
if (Version >= 1.22f) {
|
||||
writer.Write(value.StringTableScouts);
|
||||
}
|
||||
|
||||
writer.WriteZStringInt16(value.TextInstructions);
|
||||
writer.WriteZStringInt16(value.TextHints);
|
||||
writer.WriteZStringInt16(value.TextVictory);
|
||||
writer.WriteZStringInt16(value.TextLoss);
|
||||
writer.WriteZStringInt16(value.TextHistory);
|
||||
if (Version >= 1.22f) {
|
||||
writer.WriteZStringInt16(value.TextScouts);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(Cinematics value)
|
||||
{
|
||||
writer.WriteStringInt16(value.CinemaPregameFn);
|
||||
writer.WriteStringInt16(value.CinemaVictoryFn);
|
||||
writer.WriteStringInt16(value.CinemaLossFn);
|
||||
writer.WriteStringInt16(value.BackgroundFn);
|
||||
|
||||
var hasBitmap = value.RawBitmap.Length > 0;
|
||||
|
||||
writer.Write(hasBitmap);
|
||||
writer.Write(value.BitmapWidth);
|
||||
writer.Write(value.BitmapHeight);
|
||||
writer.Write(value.BitmapUnknown);
|
||||
|
||||
if (hasBitmap)
|
||||
writer.Write(value.RawBitmap);
|
||||
}
|
||||
|
||||
public void Write(AIData value)
|
||||
{
|
||||
value.PlayerAIs.ForEach(writer.WriteStringInt16);
|
||||
value.PlayerCTYs.ForEach(writer.WriteStringInt16);
|
||||
value.PlayerPERs.ForEach(writer.WriteStringInt16);
|
||||
|
||||
for (var i = 0; i < Scenario.NumPlayers; ++i) {
|
||||
var str1 = value.PlayerCustomAIs[i];
|
||||
var str2 = value.PlayerCustomCTYs[i];
|
||||
var str3 = value.PlayerCustomPERs[i];
|
||||
writer.Write(writer.GetByteCount(str1));
|
||||
writer.Write(writer.GetByteCount(str2));
|
||||
writer.Write(writer.GetByteCount(str3));
|
||||
writer.WriteStringRaw(str1);
|
||||
writer.WriteStringRaw(str2);
|
||||
writer.WriteStringRaw(str3);
|
||||
}
|
||||
|
||||
if (Version >= 1.18f) {
|
||||
value.AITypes.ForEach(writer.Write);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(ResourceInfo value)
|
||||
{
|
||||
writer.Write(value.Gold);
|
||||
writer.Write(value.Wood);
|
||||
writer.Write(value.Food);
|
||||
writer.Write(value.Stone);
|
||||
if (Version >= 1.18f) {
|
||||
writer.Write(value.Ore);
|
||||
if (Version < 1.3f) {
|
||||
writer.Write(value.Unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(ResourceInfoCopy value)
|
||||
{
|
||||
writer.Write(value.Food);
|
||||
writer.Write(value.Wood);
|
||||
writer.Write(value.Gold);
|
||||
writer.Write(value.Stone);
|
||||
if (Version >= 1.18f) {
|
||||
writer.Write(value.Ore);
|
||||
if (Version < 1.3f) {
|
||||
writer.Write(value.Unknown);
|
||||
}
|
||||
}
|
||||
if (Version >= 1.22f) {
|
||||
writer.Write(value.PopulationLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(GlobalVictoryInfo value)
|
||||
{
|
||||
writer.Write(value.RequireConquest);
|
||||
writer.Write(value.Ruins);
|
||||
writer.Write(value.Artifacts);
|
||||
writer.Write(value.Discovery);
|
||||
writer.Write(value.PercentExplored);
|
||||
writer.Write(value.Unknown);
|
||||
writer.Write(value.RequireAllCustom);
|
||||
writer.Write(value.Mode);
|
||||
writer.Write(value.Score);
|
||||
writer.Write(value.Time);
|
||||
}
|
||||
|
||||
public void Write(Map value)
|
||||
{
|
||||
if (Version >= 1.18f) {
|
||||
writer.Write(value.CameraX);
|
||||
writer.Write(value.CameraY);
|
||||
}
|
||||
if (Version >= 1.22f) {
|
||||
writer.Write(value.GeneratorId);
|
||||
}
|
||||
writer.Write(value.SizeX);
|
||||
writer.Write(value.SizeY);
|
||||
|
||||
value.LinearTiles.ForEach(x => { writer.Write(x.Id); writer.Write(x.Elevation); writer.Write(x.Unknown); });
|
||||
}
|
||||
|
||||
public void Write(IList<UnitInfo> value)
|
||||
{
|
||||
int number = value.Count;
|
||||
writer.Write(number);
|
||||
value.ForEach(Write);
|
||||
}
|
||||
|
||||
public void Write(UnitInfo value)
|
||||
{
|
||||
writer.Write(value.PosX);
|
||||
writer.Write(value.PosY);
|
||||
writer.Write(value.Unknown1);
|
||||
writer.Write(value.Id);
|
||||
writer.Write(value.UnitId);
|
||||
writer.Write(value.Unknown2);
|
||||
writer.Write(value.Rotation);
|
||||
if (Version >= 1.18f) {
|
||||
writer.Write(value.InitialFrame);
|
||||
writer.Write(value.GarrisonnedInId);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteSeperator(string name)
|
||||
{
|
||||
writer.Write(Scenario.Separator);
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
private void EnsureSetVersion()
|
||||
{
|
||||
if (Version <= 1)
|
||||
throw new System.InvalidOperationException("Set output version");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,13 +34,11 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="AdrianKousz.GenieEngine\BitmapUtil.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\CpnReader.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnFactory.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnReader.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnValidator.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnWriter.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\AIData.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\Cinematics.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\Consts.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\Map.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\Messages.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\PlayerInfo.cs" />
|
||||
|
@ -50,6 +48,10 @@
|
|||
<Compile Include="AdrianKousz.GenieEngine.Data\ScenarioHeader.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\UnitInfo.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine.Data\GlobalVictoryInfo.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnConvert.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\ScnDefaultFactory.cs" />
|
||||
<Compile Include="AdrianKousz.GenieEngine\IScnFactory.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue