From 95687b273bcf825231ebf5040e3ca25c6b5851d6 Mon Sep 17 00:00:00 2001 From: Ray Koopa Date: Sat, 29 Apr 2017 16:50:34 +0200 Subject: [PATCH] Added support for saving Project X schemes and libraries. --- README.md | 4 +- src/Syroot.Worms.Test/Program.cs | 21 +-- .../Gen2/ArchiveTests.cs | 2 +- .../Gen2/Armageddon/GeneratedMapTests.cs | 2 +- .../Gen2/Armageddon/LandDataTests.cs | 2 +- .../Gen2/Armageddon/ProjectX/LibraryTests.cs | 2 +- .../Gen2/Armageddon/ProjectX/SchemeTests.cs | 2 +- .../Gen2/Armageddon/SchemeTests.cs | 2 +- .../Gen2/Armageddon/TeamContainerTests.cs | 2 +- src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs | 2 +- .../Gen2/PaletteTests.cs | 2 +- .../Gen2/WorldParty/LandDataTests.cs | 2 +- .../Gen2/WorldParty/TeamContainerTests.cs | 2 +- .../Gen2/Worms2/LandDataTests.cs | 2 +- .../Gen2/Worms2/SchemeOptionsTests.cs | 2 +- .../Gen2/Worms2/SchemeWeaponsTests.cs | 2 +- .../Gen2/Worms2/TeamContainerTests.cs | 2 +- .../Core/BinaryWriterExtensions.cs | 4 +- .../Armageddon/ProjectX/Actions/HomeAction.cs | 2 +- .../Gen2/Armageddon/ProjectX/AttachedFile.cs | 27 ---- .../Gen2/Armageddon/ProjectX/Library.cs | 2 +- .../Gen2/Armageddon/ProjectX/Scheme.cs | 57 +++++++- .../ProjectX/Styles/LauncherStyle.cs | 32 ++++- .../ProjectX/Targets/ClusterTarget.cs | 3 +- .../Gen2/Armageddon/ProjectX/Weapon.cs | 126 ++++++++++++++++-- 25 files changed, 222 insertions(+), 86 deletions(-) delete mode 100644 src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs diff --git a/README.md b/README.md index 73f6897..f92ff8a 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ Formats of the second generation 2D games are mostly focused right now. | Monochrome Map | LEV | W2 | No | No | | Monochrome Map | BIT | WA, WWP | No | No | | Palette | PAL | W2, WA, WWP | Yes | Yes | -| Project X Library | PXL | WA+PX | Yes | No | -| Project X Scheme | PXS | WA+PX | Yes | No | +| Project X Library | PXL | WA+PX | Yes | Yes | +| Project X Scheme | PXS | WA+PX | Yes | Yes | | Replay | WAGAME | WA | No | No | | Scheme | WSC | WA, WWP | Yes | Yes | | Scheme Options | OPT | W2 | Yes | Yes | diff --git a/src/Syroot.Worms.Test/Program.cs b/src/Syroot.Worms.Test/Program.cs index a031d7b..5d1400c 100644 --- a/src/Syroot.Worms.Test/Program.cs +++ b/src/Syroot.Worms.Test/Program.cs @@ -10,28 +10,17 @@ namespace Syroot.Worms.Test /// internal class Program { - // ---- CONSTANTS ---------------------------------------------------------------------------------------------- - - private static readonly string[] _testPaths = { @"C:\Games\Worms Armageddon 3.7.2.1" }; - // ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- private static void Main(string[] args) { - Scheme pxScheme = new Scheme(@"D:\Archive\Games\Worms\Worms Armageddon\3.6.31.0\PXSchemes\PacStruction.pxs"); - + Library library = new Library(@"D:\Archive\Games\Worms\Worms Armageddon\3.6.31.0\Libs\cnades.pxl"); + library.Save(@"D:\Pictures\saved.pxl"); + + //Scheme pxScheme = new Scheme(@"D:\Archive\Games\Worms\Worms Armageddon\3.6.31.0\PXSchemes\PacStruction.pxs"); + Console.WriteLine("Done."); Console.ReadLine(); } - - private static List GetFiles(string wildcard) - { - List files = new List(); - foreach (string testPath in _testPaths) - { - files.AddRange(Directory.GetFiles(testPath, wildcard, SearchOption.AllDirectories)); - } - return files; - } } } \ No newline at end of file diff --git a/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs b/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs index a2ced52..3cd6db0 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/ArchiveTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2 /// /// Represents a collection of tests for the class. /// - [TestCategory("Archive")] + [TestCategory("Gen2")] [TestClass] public class ArchiveTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs index a93dabb..554dc04 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon /// /// Represents a collection of tests for the class. /// - [TestCategory("GeneratedMap")] + [TestCategory("Armageddon")] [TestClass] public class GeneratedMapTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs index 37b955e..8741a71 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/LandDataTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon /// /// Represents a collection of tests for the class. /// - [TestCategory("LandData (Armageddon)")] + [TestCategory("Armageddon")] [TestClass] public class LandDataTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs index 3be23e7..da387d7 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon.ProjectX /// /// Represents a collection of tests for the class. /// - [TestCategory("Library")] + [TestCategory("ProjectX")] [TestClass] public class LibraryTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs index be65214..18422ff 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon.ProjectX /// /// Represents a collection of tests for the class. /// - [TestCategory("Scheme (ProjectX)")] + [TestCategory("ProjectX")] [TestClass] public class SchemeTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs index af9d3ec..320b025 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/SchemeTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon /// /// Represents a collection of tests for the class. /// - [TestCategory("Scheme")] + [TestCategory("Armageddon")] [TestClass] public class SchemeTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/TeamContainerTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/TeamContainerTests.cs index dbe41c7..adc7fcf 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/TeamContainerTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/TeamContainerTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon /// /// Represents a collection of tests for the class. /// - [TestCategory("TeamContainer (Armageddon)")] + [TestCategory("Armageddon")] [TestClass] public class TeamContainerTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs b/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs index 4924f63..fc60d2d 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/ImageTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2 /// /// Represents a collection of tests for the class. /// - [TestCategory("Image")] + [TestCategory("Gen2")] [TestClass] public class ImageTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs b/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs index 19243d3..6fb2866 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/PaletteTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2 /// /// Represents a collection of tests for the class. /// - [TestCategory("Palette")] + [TestCategory("Gen2")] [TestClass] public class PaletteTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/WorldParty/LandDataTests.cs b/src/Syroot.Worms.UnitTest/Gen2/WorldParty/LandDataTests.cs index bba37db..ebd8bbf 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/WorldParty/LandDataTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/WorldParty/LandDataTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.WorldParty /// /// Represents a collection of tests for the class. /// - [TestCategory("LandData (WorldParty)")] + [TestCategory("WorldParty")] [TestClass] public class LandDataTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/WorldParty/TeamContainerTests.cs b/src/Syroot.Worms.UnitTest/Gen2/WorldParty/TeamContainerTests.cs index 9a10001..3a2f9d1 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/WorldParty/TeamContainerTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/WorldParty/TeamContainerTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.WorldParty /// /// Represents a collection of tests for the class. /// - [TestCategory("TeamContainer (WorldParty)")] + [TestCategory("WorldParty")] [TestClass] public class TeamContainerTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs index a6b6d2d..9b1ca23 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/LandDataTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2 /// /// Represents a collection of tests for the class. /// - [TestCategory("LandData (Worms2)")] + [TestCategory("Worms2")] [TestClass] public class LandDataTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs index fdbab49..f2c0786 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeOptionsTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2 /// /// Represents a collection of tests for the class. /// - [TestCategory("SchemeOptions")] + [TestCategory("Worms2")] [TestClass] public class SchemeOptionsTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs index bba5410..5150b00 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/SchemeWeaponsTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2 /// /// Represents a collection of tests for the class. /// - [TestCategory("SchemeWeapons")] + [TestCategory("Worms2")] [TestClass] public class SchemeWeaponsTests { diff --git a/src/Syroot.Worms.UnitTest/Gen2/Worms2/TeamContainerTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Worms2/TeamContainerTests.cs index 84e1289..113ae0b 100644 --- a/src/Syroot.Worms.UnitTest/Gen2/Worms2/TeamContainerTests.cs +++ b/src/Syroot.Worms.UnitTest/Gen2/Worms2/TeamContainerTests.cs @@ -7,7 +7,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Worms2 /// /// Represents a collection of tests for the class. /// - [TestCategory("TeamContainer (Worms2)")] + [TestCategory("Worms2")] [TestClass] public class TeamContainerTests { diff --git a/src/Syroot.Worms/Core/BinaryWriterExtensions.cs b/src/Syroot.Worms/Core/BinaryWriterExtensions.cs index 448b216..538695b 100644 --- a/src/Syroot.Worms/Core/BinaryWriterExtensions.cs +++ b/src/Syroot.Worms/Core/BinaryWriterExtensions.cs @@ -32,9 +32,9 @@ namespace Syroot.Worms.Core /// The instances to write into the current stream. internal static void Save(this BinaryDataWriter self, T[] values) where T : ISaveable { - for (int i = 0; i < values.Length; i++) + foreach (T value in values) { - Save(self, values[i]); + Save(self, value); } } diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs index 79c0b7a..d3539e8 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs @@ -43,7 +43,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX { using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true)) { - writer.Seek(4); + writer.Write(0); writer.Write(Sprite); writer.Write(HomeStyle); writer.Write(Delay); diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs deleted file mode 100644 index a363359..0000000 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.IO; -using Syroot.Worms.Core; - -namespace Syroot.Worms.Gen2.Armageddon.ProjectX -{ - public class AttachedFile : ILoadable, ISaveable - { - // ---- PROPERTIES --------------------------------------------------------------------------------------------- - - public string Name { get; set; } - - public byte[] Data { get; set; } - - // ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- - - public void Load(Stream stream) - { - throw new NotImplementedException(); - } - - public void Save(Stream stream) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs index 0c01c02..5d0a6f6 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs @@ -135,7 +135,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX writer.Write(Count); foreach (LibraryItem item in this) { - writer.Write(item.Type); + writer.Write(item.Type, true); writer.Write(item.Key, BinaryStringFormat.DwordLengthPrefix); switch (item.Type) { diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs index a7c7e99..c06bef7 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs @@ -116,16 +116,12 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX // Read required libraries. int librariesCount = reader.ReadInt32(); - Libraries = new List(librariesCount); - for (int i = 0; i < librariesCount; i++) - { - Libraries.Add(reader.ReadString(BinaryStringFormat.DwordLengthPrefix)); - } + Libraries = new List(reader.ReadStrings(librariesCount, BinaryStringFormat.DwordLengthPrefix)); // Read a possibly attached scheme file. if (reader.ReadBoolean()) { - int schemeLength = reader.ReadInt32(); // TODO: Check if required due to intelligent loading. + reader.Seek(sizeof(int)); // Scheme length not required due to intelligent loading. GameScheme = reader.Load(); GameSchemeName = reader.ReadString(BinaryStringFormat.DwordLengthPrefix); } @@ -153,6 +149,55 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII)) { // Write the header. + writer.Write(_signature, BinaryStringFormat.NoPrefixOrTermination); + writer.Write(Version); + + // Write the scheme flags. + writer.Write(Flags); + + // Write the weapon tables. + writer.Write(WeaponTables.Count); + foreach (Weapon[] weaponTable in WeaponTables) + { + writer.Save(weaponTable); + } + + // Write a placeholder array. + writer.Write(0); + + // Write attached files. + writer.Write(Files.Count); + foreach (KeyValuePair file in Files) + { + writer.Write(file.Key, BinaryStringFormat.DwordLengthPrefix); + writer.Write(file.Value.Length); + writer.Write(file.Value); + } + + // Write attached scripts. + writer.Write(Scripts.Count); + foreach (KeyValuePair script in Scripts) + { + writer.Write(script.Key, BinaryStringFormat.DwordLengthPrefix); + writer.Write(script.Value, BinaryStringFormat.DwordLengthPrefix); + } + + // Write required libraries. + writer.Write(Libraries.Count); + writer.Write(Libraries.ToArray()); + + // Write a possibly attached scheme file. + if (GameScheme != null) + { + byte[] schemeBytes; + using (MemoryStream schemeStream = new MemoryStream()) + { + GameScheme.Save(schemeStream); + schemeBytes = schemeStream.ToArray(); + } + writer.Write(schemeBytes.Length); + writer.Write(GameSchemeName, BinaryStringFormat.DwordLengthPrefix); + } } } diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs index 85e5fcf..706685d 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs @@ -104,7 +104,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX reader.Position = offset + 180; ExplosionTarget = reader.ReadEnum(true); - reader.Seek(4); + reader.Seek(sizeof(int)); switch (ExplosionTarget) { case ExplosionTarget.Clusters: @@ -125,7 +125,37 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX { using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true)) { + long offset = writer.Position; + writer.Write(SpriteSize); + writer.Write(FixedSpeed); + writer.Write(RunAway, BinaryBooleanFormat.NonZeroDword); + writer.Write(Collisions, true); + writer.Write(ExplosionBias); + writer.Write(ExplosionPushPower); + writer.Write(ExplosionDamage); + writer.Write(ExplosionDamageVariation); + writer.Write(ExplosionUnknown); + writer.Write(Sprite); + writer.Write(VariableSpeed); + writer.Write(WindFactor); + writer.Write(MotionRandomness); + writer.Write(GravityFactor); + writer.Write(ExplosionCountdown); + writer.Write(ExplosionTimer); + writer.Write(Sound); + writer.Write(ExplodeOnSpace, BinaryBooleanFormat.NonZeroDword); + + writer.Write(ExplosionAction, true); + writer.Save(Action); + + writer.Position = offset + 180; + writer.Write(ExplosionTarget, true); + writer.Seek(sizeof(int)); + if (ExplosionTarget != ExplosionTarget.None) + { + writer.Save(Target); + } } } } diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs index 5b02468..101ae5e 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs @@ -121,6 +121,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX writer.Write(ExplosionPushPower); writer.Write(ExplosionDamage); writer.Write(ExplosionDamageVariation); + writer.Write(SpriteCount); writer.Write(Sprite); writer.Write(Acceleration); writer.Write(WindResponse); @@ -131,7 +132,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX writer.Write(Sound); writer.Write(ExplodeOnSpace, BinaryBooleanFormat.NonZeroDword); - writer.Write(ExplosionAction); + writer.Write(ExplosionAction, true); writer.Save(Action); } } diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs index 652dd47..1a4ed4e 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs @@ -9,14 +9,9 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX [DebuggerDisplay("Weapon Name={Name}")] public class Weapon : ILoadable, ISaveable { - // ---- CONSTANTS ---------------------------------------------------------------------------------------------- - - private const int _version_0_8_0_pre = 0x5ABBDD05; - private const int _version_0_8_0 = 0x5ABBDD06; - // ---- PROPERTIES --------------------------------------------------------------------------------------------- - public int Version { get; set; } + public WeaponVersion Version { get; set; } public long Checksum { get; set; } @@ -38,7 +33,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX public int CrateCount { get; set; } - public bool Unknown2 { get; set; } + public int Unknown2 { get; set; } public WeaponActivation Activation { get; set; } @@ -120,11 +115,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX { // Read the header. long offset = reader.Position; - Version = reader.ReadInt32(); - if (Version != _version_0_8_0_pre && Version != _version_0_8_0) - { - throw new InvalidDataException($"Unknown Project X weapon version 0x{Version:X8}."); - } + Version = reader.ReadEnum(true); Checksum = reader.ReadInt64(); // Read general settings. @@ -137,7 +128,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX Unknown1 = reader.ReadInt32(); CrateChance = reader.ReadInt32(); CrateCount = reader.ReadInt32(); - Unknown2 = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword); + Unknown2 = reader.ReadInt32(); // Read the activation and the corresponding weapon settings. Activation = reader.ReadEnum(true); @@ -277,7 +268,7 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX AimSpriteOverride = reader.ReadBoolean(); PickSpriteOverride = reader.ReadBoolean(); FireSpriteOverride = reader.ReadBoolean(); - if (Version == _version_0_8_0) + if (Version == WeaponVersion.Version_0_8_0) { Utility = reader.ReadBoolean(); } @@ -292,11 +283,118 @@ namespace Syroot.Worms.Gen2.Armageddon.ProjectX { using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true)) { + // Write the header. + long offset = writer.Position; + writer.Write(Version, true); + writer.Write(Checksum); + // Write the general settings. + writer.Write(TableRow); + writer.Write(Remembered, BinaryBooleanFormat.NonZeroDword); + writer.Write(UsableInCavern, BinaryBooleanFormat.NonZeroDword); + writer.Write(Shots); + writer.Write(ShotEndsTurn, BinaryBooleanFormat.NonZeroDword); + writer.Write(RetreatTime); + writer.Write(Unknown1); + writer.Write(CrateChance); + writer.Write(CrateCount); + writer.Write(Unknown2); + + // Write the activation and the corresponding weapon settings. + writer.Write(Activation, true); + switch (Activation) + { + case WeaponActivation.Airstrike: + writer.Write(AirstrikeSubtype); + writer.Save(Style); + break; + case WeaponActivation.Crosshair: + writer.Seek(sizeof(int)); + writer.Write(CrosshairAction, true); + if (CrosshairAction != WeaponCrosshairAction.None) + { + writer.Save(Style); + } + break; + case WeaponActivation.Spacebar: + writer.Write(SpacebarAction, true); + switch (SpacebarAction) + { + case WeaponSpacebarAction.Armageddon: + case WeaponSpacebarAction.BaseballBat: + case WeaponSpacebarAction.BattleAxe: + case WeaponSpacebarAction.Blowtorch: + case WeaponSpacebarAction.Dragonball: + case WeaponSpacebarAction.Firepunch: + case WeaponSpacebarAction.Jetpack: + case WeaponSpacebarAction.Kamikaze: + case WeaponSpacebarAction.NinjaRope: + case WeaponSpacebarAction.NuclearTest: + case WeaponSpacebarAction.Parachute: + case WeaponSpacebarAction.PneumaticDrill: + case WeaponSpacebarAction.Prod: + case WeaponSpacebarAction.SuicideBomber: + writer.Save(Style); + break; + } + break; + case WeaponActivation.Throw: + writer.Write(ThrowHerdCount); + writer.Write(ThrowAction, true); + if (ThrowAction != WeaponThrowAction.None) + { + writer.Save(Style); + } + break; + } + + // Write additional settings. + writer.Position = offset + 468; + writer.Write(AmmunitionOverride, BinaryBooleanFormat.NonZeroDword); + writer.Write(Ammunition); + writer.Write(Unknown3); + writer.Write(WeaponSprite); + writer.Write(NameLong, BinaryStringFormat.DwordLengthPrefix); + writer.Write(Name, BinaryStringFormat.DwordLengthPrefix); + writer.Write(GridImageFile, BinaryStringFormat.DwordLengthPrefix); + writer.Write(GfxDirectoryFile, BinaryStringFormat.DwordLengthPrefix); + writer.Write(SpriteNames, BinaryStringFormat.DwordLengthPrefix); + writer.Write(DelayOverride, BinaryBooleanFormat.NonZeroDword); + writer.Write(Delay); + + writer.Write(UseLibrary); + if (UseLibrary) + { + writer.Write(LibraryName, BinaryStringFormat.DwordLengthPrefix); + writer.Write(LibraryWeaponName, BinaryStringFormat.DwordLengthPrefix); + } + + writer.Write(AimSpriteEven, BinaryStringFormat.DwordLengthPrefix); + writer.Write(AimSpriteUphill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(AimSpriteDownhill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(PickSpriteEven, BinaryStringFormat.DwordLengthPrefix); + writer.Write(PickSpriteUphill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(PickSpriteDownhill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(FireSpriteEven, BinaryStringFormat.DwordLengthPrefix); + writer.Write(FireSpriteUphill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(FireSpriteDownhill, BinaryStringFormat.DwordLengthPrefix); + writer.Write(AimSpriteOverride); + writer.Write(PickSpriteOverride); + writer.Write(FireSpriteOverride); + if (Version == WeaponVersion.Version_0_8_0) + { + writer.Write(Utility); + } } } } + public enum WeaponVersion : int + { + Version_0_8_0_pre = 0x5ABBDD05, + Version_0_8_0 = 0x5ABBDD06 + } + public enum WeaponActivation : int { None,