diff --git a/README.md b/README.md
index af33243..73f6897 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 | No | No |
-| Project X Scheme | PXS | WA+PX | No | No |
+| Project X Library | PXL | WA+PX | Yes | No |
+| Project X Scheme | PXS | WA+PX | Yes | No |
| 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 a618a4e..a031d7b 100644
--- a/src/Syroot.Worms.Test/Program.cs
+++ b/src/Syroot.Worms.Test/Program.cs
@@ -1,9 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
-using Syroot.Worms.Gen2;
-using Syroot.Worms.Gen2.WorldParty;
-using Syroot.Worms.Gen2.Armageddon;
+using Syroot.Worms.Gen2.Armageddon.ProjectX;
namespace Syroot.Worms.Test
{
@@ -20,8 +18,8 @@ namespace Syroot.Worms.Test
private static void Main(string[] args)
{
- GeneratedMap genMap = new GeneratedMap(@"D:\Archive\Games\Worms\Worms Armageddon\3.7.2.1\User\SavedLevels\test.LEV");
-
+ Scheme pxScheme = new Scheme(@"D:\Archive\Games\Worms\Worms Armageddon\3.6.31.0\PXSchemes\PacStruction.pxs");
+
Console.WriteLine("Done.");
Console.ReadLine();
}
diff --git a/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs b/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
index 3393508..64801cb 100644
--- a/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
+++ b/src/Syroot.Worms.UnitTest/Common/TestHelpers.cs
@@ -15,7 +15,8 @@ namespace Syroot.Worms.UnitTest.Common
// ---- MEMBERS ------------------------------------------------------------------------------------------------
private static readonly string[] _gamePathsWorms2 = { @"C:\Games\Worms2" };
- private static readonly string[] _gamePathsWormsArmageddon = { @"C:\Games\Worms Armageddon 3.7.2.1" };
+ private static readonly string[] _gamePathsWormsArmageddon = { @"C:\Games\Worms Armageddon 3.6.31.0",
+ @"C:\Games\Worms Armageddon 3.7.2.1" };
private static readonly string[] _gamePathsWormsWorldParty = { @"C:\Games\Worms World Party" };
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs
new file mode 100644
index 0000000..3be23e7
--- /dev/null
+++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/LibraryTests.cs
@@ -0,0 +1,25 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Syroot.Worms.Gen2.Armageddon.ProjectX;
+using Syroot.Worms.UnitTest.Common;
+
+namespace Syroot.Worms.UnitTest.Gen2.Armageddon.ProjectX
+{
+ ///
+ /// Represents a collection of tests for the class.
+ ///
+ [TestCategory("Library")]
+ [TestClass]
+ public class LibraryTests
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads all files found in any game directories.
+ ///
+ [TestMethod]
+ public void LoadLibraries()
+ {
+ TestHelpers.LoadFiles(Game.WormsArmageddon, "*.pxl");
+ }
+ }
+}
diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs
new file mode 100644
index 0000000..be65214
--- /dev/null
+++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/ProjectX/SchemeTests.cs
@@ -0,0 +1,25 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Syroot.Worms.Gen2.Armageddon.ProjectX;
+using Syroot.Worms.UnitTest.Common;
+
+namespace Syroot.Worms.UnitTest.Gen2.Armageddon.ProjectX
+{
+ ///
+ /// Represents a collection of tests for the class.
+ ///
+ [TestCategory("Scheme (ProjectX)")]
+ [TestClass]
+ public class SchemeTests
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads all files found in any game directories.
+ ///
+ [TestMethod]
+ public void LoadSchemes()
+ {
+ TestHelpers.LoadFiles(Game.WormsArmageddon, "*.pxs");
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Core/BinaryReaderExtensions.cs b/src/Syroot.Worms/Core/BinaryReaderExtensions.cs
index a76ffaf..9283639 100644
--- a/src/Syroot.Worms/Core/BinaryReaderExtensions.cs
+++ b/src/Syroot.Worms/Core/BinaryReaderExtensions.cs
@@ -1,4 +1,6 @@
+using System.Diagnostics;
using System.IO;
+using System.Reflection;
using System.Runtime.InteropServices;
using Syroot.IO;
@@ -7,10 +9,41 @@ namespace Syroot.Worms.Core
///
/// Represents extension methods for instances.
///
+ [DebuggerStepThrough]
internal static class BinaryReaderExtensions
{
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
+ ///
+ /// Reads an instance from the current stream.
+ ///
+ /// The type of the class to instantiate.
+ /// The extended .
+ /// The instance.
+ internal static T Load(this BinaryDataReader self) where T : ILoadable, new()
+ {
+ T instance = new T();
+ instance.Load(self.BaseStream);
+ return instance;
+ }
+
+ ///
+ /// Reads instances from the current stream.
+ ///
+ /// The type of the class to instantiate.
+ /// The extended .
+ /// The number of instances to read.
+ /// The instances.
+ internal static T[] Load(this BinaryDataReader self, int count) where T : ILoadable, new()
+ {
+ T[] instances = new T[count];
+ for (int i = 0; i < count; i++)
+ {
+ instances[i] = Load(self);
+ }
+ return instances;
+ }
+
///
/// Reads a 0-terminated string which is stored in a fixed-size block of bytes.
///
diff --git a/src/Syroot.Worms/Core/BinaryWriterExtensions.cs b/src/Syroot.Worms/Core/BinaryWriterExtensions.cs
index 2cd894a..448b216 100644
--- a/src/Syroot.Worms/Core/BinaryWriterExtensions.cs
+++ b/src/Syroot.Worms/Core/BinaryWriterExtensions.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Syroot.IO;
@@ -7,10 +8,36 @@ namespace Syroot.Worms.Core
///
/// Represents extension methods for instances.
///
+ [DebuggerStepThrough]
internal static class BinaryWriterExtensions
{
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
+ ///
+ /// Writes the given instance into the current stream.
+ ///
+ /// The type of the class to write.
+ /// The extended .
+ /// The instance to write into the current stream.
+ internal static void Save(this BinaryDataWriter self, T value) where T : ISaveable
+ {
+ value.Save(self.BaseStream);
+ }
+
+ ///
+ /// Writes the given instances into the current stream.
+ ///
+ /// The type of the class to write.
+ /// The extended .
+ /// 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++)
+ {
+ Save(self, values[i]);
+ }
+ }
+
///
/// Writes the given string into a fixed-size block of bytes and 0-terminates it.
///
diff --git a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
index 5ab0da2..fc95815 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs
@@ -123,9 +123,9 @@ namespace Syroot.Worms.Gen2.Armageddon
ObjectLocations = reader.ReadStructs(reader.ReadInt32());
// Read the image data.
- Foreground = new Image(stream);
- CollisionMask = new Image(stream);
- Background = new Image(stream);
+ Foreground = reader.Load();
+ CollisionMask = reader.Load();
+ Background = reader.Load();
// Read the file paths.
LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
diff --git a/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs b/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs
index 4d2a9b5..b2b7ac8 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs
@@ -103,19 +103,18 @@ namespace Syroot.Worms.Gen2.Armageddon
public enum MapGeneratorVersion : short
{
///
- /// Game version 3.0. Special soil texture indices are 26 = Tribal, 27 = Tribal, 28 = Urban. Additionally,
- /// floor and ceiling trimming is more severe.
+ /// Game version 3.0. Last soil texture indices are 26 = Tribal, 27 = Tribal, 28 = Urban. Additionally, floor
+ /// and ceiling trimming is more severe.
///
Version_3_0_0_0 = -1,
///
- /// Game version 3.5. Special soil texture indices are 27 = Urban, 28 = undefined.
+ /// Game version 3.5. Last soil texture indices are 26 = Tribal, 27 = Urban, 28 = undefined.
///
Version_3_5_0_0 = 0,
///
- /// Game version 3.6.26.4. Special soil texture indices are 26 = Tools, 27 = Tribal, Urban = 28 (same as in
- /// WWP).
+ /// Game version 3.6.26.4. Last soil texture indices are 26 = Tools, 27 = Tribal, Urban = 28 (same as in WWP).
///
Version_3_6_26_4 = 1
}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/ActionBase.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/ActionBase.cs
new file mode 100644
index 0000000..6e6d0ab
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/ActionBase.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public abstract class ActionBase : ILoadable, ISaveable
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public abstract void Load(Stream stream);
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public abstract void Save(Stream stream);
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/BounceAction.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/BounceAction.cs
new file mode 100644
index 0000000..54e5daa
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/BounceAction.cs
@@ -0,0 +1,79 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class BounceAction : ActionBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public CollisionFlags Collisions { get; set; }
+
+ public int Bounciness { get; set; }
+
+ public int Acceleration { get; set; }
+
+ public int Sound { get; set; }
+
+ public int Unknown1 { get; set; }
+
+ public int Unknown2 { get; set; }
+
+ public int ExplosionBias { get; set; }
+
+ public int ExplosionPower { get; set; }
+
+ public int ExplosionDamage { get; set; }
+
+ public int DamageRandomness { get; set; }
+
+ public int BounceCount { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Collisions = reader.ReadEnum(true);
+ Bounciness = reader.ReadInt32();
+ Acceleration = reader.ReadInt32();
+ Sound = reader.ReadInt32();
+ Unknown1 = reader.ReadInt32();
+ Unknown2 = reader.ReadInt32();
+ ExplosionBias = reader.ReadInt32();
+ ExplosionPower = reader.ReadInt32();
+ ExplosionDamage = reader.ReadInt32();
+ DamageRandomness = reader.ReadInt32();
+ BounceCount = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Collisions, true);
+ writer.Write(Bounciness);
+ writer.Write(Acceleration);
+ writer.Write(Sound);
+ writer.Write(Unknown1);
+ writer.Write(Unknown2);
+ writer.Write(ExplosionBias);
+ writer.Write(ExplosionPower);
+ writer.Write(ExplosionDamage);
+ writer.Write(DamageRandomness);
+ writer.Write(BounceCount);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/DigAction.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/DigAction.cs
new file mode 100644
index 0000000..7997ffa
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/DigAction.cs
@@ -0,0 +1,63 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class DigAction : ActionBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Unknown1 {get; set; }
+
+ public int Unknown2 {get; set; }
+
+ public int DiggingSound {get; set; }
+
+ public int SpriteJumping {get; set; }
+
+ public int Sprite1 {get; set; }
+
+ public int Sprite2 {get; set; }
+
+ public int Sprite3 {get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Unknown1 = reader.ReadInt32();
+ Unknown2 = reader.ReadInt32();
+ DiggingSound = reader.ReadInt32();
+ SpriteJumping = reader.ReadInt32();
+ Sprite1 = reader.ReadInt32();
+ Sprite2 = reader.ReadInt32();
+ Sprite3 = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Unknown1);
+ writer.Write(Unknown2);
+ writer.Write(DiggingSound);
+ writer.Write(SpriteJumping);
+ writer.Write(Sprite1);
+ writer.Write(Sprite2);
+ writer.Write(Sprite3);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs
new file mode 100644
index 0000000..79c0b7a
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/HomeAction.cs
@@ -0,0 +1,61 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class HomeAction : ActionBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public Sprite Sprite { get; set; }
+
+ public HomeStyle HomeStyle { get; set; }
+
+ public int Delay { get; set; }
+
+ public int Duration { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ reader.Seek(4);
+ Sprite = reader.ReadStruct();
+ HomeStyle = reader.ReadEnum(true);
+ Delay = reader.ReadInt32();
+ Duration = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Seek(4);
+ writer.Write(Sprite);
+ writer.Write(HomeStyle);
+ writer.Write(Delay);
+ writer.Write(Duration);
+ }
+ }
+ }
+
+ public enum HomeStyle
+ {
+ None,
+ Straight,
+ Intelligent
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/RoamAction.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/RoamAction.cs
new file mode 100644
index 0000000..eeda7c4
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Actions/RoamAction.cs
@@ -0,0 +1,107 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class RoamAction : ActionBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public CollisionFlags RoamCollisions { get; set; }
+
+ public CollisionFlags ExplosionCollisions { get; set; }
+
+ public int WalkSpeed { get; set; }
+
+ public int Unknown { get; set; }
+
+ public int JumpAngleEdge { get; set; }
+
+ public int JumpVelocityEdge { get; set; }
+
+ public int JumpSoundEdge { get; set; }
+
+ public int JumpAngle { get; set; }
+
+ public int JumpVelocity { get; set; }
+
+ public int JumpSound { get; set; }
+
+ public int TerrainOffset { get; set; }
+
+ public bool Fart { get; set; }
+
+ public int DiseasePower { get; set; }
+
+ public int SpriteFarting { get; set; }
+
+ public int SpriteFlying { get; set; }
+
+ public int SpriteFlying2 { get; set; }
+
+ public int SpriteTakeOff { get; set; }
+
+ public int SpriteDuringFlight { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ RoamCollisions = reader.ReadEnum(true);
+ ExplosionCollisions = reader.ReadEnum(true);
+ WalkSpeed = reader.ReadInt32();
+ Unknown = reader.ReadInt32();
+ JumpAngleEdge = reader.ReadInt32();
+ JumpVelocityEdge = reader.ReadInt32();
+ JumpSoundEdge = reader.ReadInt32();
+ JumpAngle = reader.ReadInt32();
+ JumpVelocity = reader.ReadInt32();
+ JumpSound = reader.ReadInt32();
+ TerrainOffset = reader.ReadInt32();
+ Fart = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ DiseasePower = reader.ReadInt32();
+ SpriteFarting = reader.ReadInt32();
+ SpriteFlying = reader.ReadInt32();
+ SpriteFlying2 = reader.ReadInt32();
+ SpriteTakeOff = reader.ReadInt32();
+ SpriteDuringFlight = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(RoamCollisions, true);
+ writer.Write(ExplosionCollisions, true);
+ writer.Write(WalkSpeed);
+ writer.Write(Unknown);
+ writer.Write(JumpAngleEdge);
+ writer.Write(JumpVelocityEdge);
+ writer.Write(JumpSoundEdge);
+ writer.Write(JumpAngle);
+ writer.Write(JumpVelocity);
+ writer.Write(JumpSound);
+ writer.Write(TerrainOffset);
+ writer.Write(Fart, BinaryBooleanFormat.NonZeroDword);
+ writer.Write(DiseasePower);
+ writer.Write(SpriteFarting);
+ writer.Write(SpriteFlying);
+ writer.Write(SpriteFlying2);
+ writer.Write(SpriteTakeOff);
+ writer.Write(SpriteDuringFlight);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs
new file mode 100644
index 0000000..a363359
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/AttachedFile.cs
@@ -0,0 +1,27 @@
+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/CollisionFlags.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/CollisionFlags.cs
new file mode 100644
index 0000000..e2f26a4
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/CollisionFlags.cs
@@ -0,0 +1,43 @@
+using System;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ [Flags]
+ public enum CollisionFlags : int
+ {
+ None = 0,
+ Unused0 = 1 << 0,
+ Terrain = 1 << 1,
+ WormsOnTerrain = 1 << 2,
+ WormsUsingWeapon = 1 << 3,
+ WormsInAir = 1 << 4,
+ WormsOnRope = 1 << 5,
+ FrozenWorms = 1 << 6,
+ Unused7 = 1 << 7,
+ KamikazeBomber = 1 << 8,
+ GasCanisters = 1 << 9,
+ Mines = 1 << 10,
+ Crates = 1 << 11,
+ DonorCards = 1 << 12,
+ Gravestones = 1 << 13,
+ Unused14 = 1 << 14,
+ OtherWeapons = 1 << 15,
+ LongbowArrows = 1 << 16,
+ OilDrums = 1 << 17,
+ Unused18 = 1 << 18,
+ Unused19 = 1 << 19,
+ Unused20 = 1 << 20,
+ Unused21 = 1 << 21,
+ Skimming = 1 << 22,
+ Unused23 = 1 << 23,
+ Unused24 = 1 << 24,
+ Unused25 = 1 << 25,
+ Unused26 = 1 << 26,
+ Unused27 = 1 << 27,
+ Unused28 = 1 << 28,
+ Unused29 = 1 << 29,
+ Unknown = 1 << 30,
+ Unused31 = 1 << 31
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs
new file mode 100644
index 0000000..0c01c02
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Library.cs
@@ -0,0 +1,287 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ ///
+ /// Represents a library stored in a PXL file which contains reusable weapons, files and scripts.
+ /// Used by WA PX. S. https://worms2d.info/Project_X/Library_file.
+ ///
+ public class Library : List, ILoadableFile, ISaveableFile
+ {
+ // ---- CONSTANTS ----------------------------------------------------------------------------------------------
+
+ private const int _signature = 0x1BCD0102;
+ private const byte _version = 0x00;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Library()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given
+ /// .
+ ///
+ /// The to load the data from.
+ public Library(Stream stream)
+ {
+ Load(stream);
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public Library(string fileName)
+ {
+ Load(fileName);
+ }
+
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public byte Version { get; set; }
+
+ // ---- OPERATORS ----------------------------------------------------------------------------------------------
+
+ ///
+ /// Gets the library entries matching the given key.
+ ///
+ /// The key of the entries to match.
+ /// All matching entries.
+ public IEnumerable this[string key]
+ {
+ get
+ {
+ return this.Where(x => x.Key == key);
+ }
+ }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ // Read the header.
+ if (reader.ReadInt32() != _signature)
+ {
+ throw new InvalidDataException("Invalid PXL file signature.");
+ }
+ Version = reader.ReadByte();
+
+ // Read the items.
+ Clear();
+ int itemCount = reader.ReadInt32();
+ for (int i = 0; i < itemCount; i++)
+ {
+ LibraryItemType type = reader.ReadEnum(true);
+ string name = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ switch (type)
+ {
+ case LibraryItemType.File:
+ Add(new LibraryItem(name, reader.ReadBytes(reader.ReadInt32())));
+ break;
+ case LibraryItemType.Script:
+ Add(new LibraryItem(name, reader.ReadString(BinaryStringFormat.DwordLengthPrefix)));
+ break;
+ case LibraryItemType.Weapon:
+ Add(new LibraryItem(name, reader.Load()));
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Loads the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public void Load(string fileName)
+ {
+ using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ Load(stream);
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII))
+ {
+ // Write the header.
+ writer.Write(_signature);
+ writer.Write(Version);
+
+ // Write the items.
+ writer.Write(Count);
+ foreach (LibraryItem item in this)
+ {
+ writer.Write(item.Type);
+ writer.Write(item.Key, BinaryStringFormat.DwordLengthPrefix);
+ switch (item.Type)
+ {
+ case LibraryItemType.File:
+ byte[] value = (byte[])item.Value;
+ writer.Write(value.Length);
+ writer.Write(value);
+ break;
+ case LibraryItemType.Script:
+ writer.Write((string)item.Value, BinaryStringFormat.DwordLengthPrefix);
+ break;
+ case LibraryItemType.Weapon:
+ writer.Save((Weapon)item.Value);
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Saves the data in the given file.
+ ///
+ /// The name of the file to save the data in.
+ public void Save(string fileName)
+ {
+ using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ Save(stream);
+ }
+ }
+
+ ///
+ /// Gets all attached files.
+ ///
+ /// The enumeration of attached files.
+ public IEnumerable GetFiles()
+ {
+ return this.Where(x => x.Type == LibraryItemType.File).Select(x => (byte[])x.Value);
+ }
+
+ ///
+ /// Gets all attached scripts.
+ ///
+ /// The enumeration of attached scripts.
+ public IEnumerable GetScripts()
+ {
+ return this.Where(x => x.Type == LibraryItemType.Script).Select(x => (string)x.Value);
+ }
+
+ ///
+ /// Gets all attached weapons.
+ ///
+ /// The enumeration of attached weapons.
+ public IEnumerable GetWeapons()
+ {
+ return this.Where(x => x.Type == LibraryItemType.Weapon).Select(x => (Weapon)x.Value);
+ }
+ }
+
+ ///
+ /// Represents an entry in a Project X library.
+ ///
+ [DebuggerDisplay("LibraryItem Key={Key} Type={Type}")]
+ public class LibraryItem
+ {
+ // ---- MEMBERS ------------------------------------------------------------------------------------------------
+
+ private object _value;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ ///
+ /// Initializes a new instance of the class with the given and
+ /// .
+ ///
+ /// The key under which the item will be stored.
+ /// The value which will be stored under the key. The type is inferred from this.
+ public LibraryItem(string key, object value)
+ {
+ Key = key;
+ Value = value;
+ }
+
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ ///
+ /// Gets or sets the name under which this item is stored.
+ ///
+ public string Key { get; set; }
+
+ ///
+ /// Gets the type of the item.
+ ///
+ public LibraryItemType Type { get; private set; }
+
+ ///
+ /// Gets or sets the data of the item.
+ ///
+ public object Value
+ {
+ get
+ {
+ return _value;
+ }
+ set
+ {
+ // Validate the type.
+ if (value.GetType() == typeof(byte[]))
+ {
+ Type = LibraryItemType.File;
+ }
+ else if (value.GetType() == typeof(string))
+ {
+ Type = LibraryItemType.Script;
+ }
+ else if (value.GetType() == typeof(Weapon))
+ {
+ Type = LibraryItemType.Weapon;
+ }
+ else
+ {
+ throw new ArgumentException("Invalid LibraryItemType.", nameof(value));
+ }
+ _value = value;
+ }
+ }
+ }
+
+ ///
+ /// Represents the possible type of a library entry.
+ ///
+ public enum LibraryItemType : byte
+ {
+ ///
+ /// The entry is a raw file in form of a byte array.
+ ///
+ File = 2,
+
+ ///
+ /// The entry is a script in form of a string.
+ ///
+ Script = 4,
+
+ ///
+ /// The entry is a weapon in form of a instance.
+ ///
+ Weapon = 8
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Mine.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Mine.cs
new file mode 100644
index 0000000..0d4ce50
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Mine.cs
@@ -0,0 +1,22 @@
+using System.Runtime.InteropServices;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Mine
+ {
+ public int Sensitivity;
+
+ public int TimeBeforeOn;
+
+ public CollisionFlags SensitiveTo;
+
+ public int FuseTime;
+
+ public int ExplosionBias;
+
+ public int ExplosionPower;
+
+ public int MaxDamage;
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs
new file mode 100644
index 0000000..a7c7e99
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Scheme.cs
@@ -0,0 +1,171 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ ///
+ /// Represents a scheme stored in a PXS file which contains game settings, weapon tables, required libraries and
+ /// attached files and scripts.
+ /// Used by WA PX. S. https://worms2d.info/Project_X/Scheme_file.
+ ///
+ public class Scheme : ILoadableFile, ISaveableFile
+ {
+ // ---- CONSTANTS ----------------------------------------------------------------------------------------------
+
+ private const string _signature = "SCHM OF WAPX";
+ private const int _weaponsPerTable = 71;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Scheme()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given
+ /// .
+ ///
+ /// The to load the data from.
+ public Scheme(Stream stream)
+ {
+ Load(stream);
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public Scheme(string fileName)
+ {
+ Load(fileName);
+ }
+
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Version { get; set; }
+
+ public SchemeFlags Flags { get; set; }
+
+ public List WeaponTables { get; set; }
+
+ public Dictionary Files { get; set; }
+
+ public Dictionary Scripts { get; set; }
+
+ public List Libraries { get; set; }
+
+ public string GameSchemeName { get; set; }
+
+ public Armageddon.Scheme GameScheme { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ // Read the header.
+ if (reader.ReadString(_signature.Length) != _signature)
+ {
+ throw new InvalidDataException("Invalid PXS file signature.");
+ }
+ Version = reader.ReadInt32();
+
+ // Read the scheme flags.
+ Flags = reader.ReadStruct();
+
+ // Read the weapon tables.
+ int weaponTableCount = reader.ReadInt32();
+ WeaponTables = new List(weaponTableCount);
+ for (int i = 0; i < weaponTableCount; i++)
+ {
+ WeaponTables.Add(reader.Load(_weaponsPerTable));
+ }
+
+ // Read a placeholder array.
+ reader.Seek(sizeof(int));
+
+ // Read attached files.
+ int filesCount = reader.ReadInt32();
+ Files = new Dictionary(filesCount);
+ for (int i = 0; i < filesCount; i++)
+ {
+ string name = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ int length = reader.ReadInt32();
+ Files.Add(name, reader.ReadBytes(length));
+ }
+
+ // Read attached scripts.
+ int scriptsCount = reader.ReadInt32();
+ Scripts = new Dictionary(scriptsCount);
+ for (int i = 0; i < scriptsCount; i++)
+ {
+ Scripts.Add(reader.ReadString(BinaryStringFormat.DwordLengthPrefix),
+ reader.ReadString(BinaryStringFormat.DwordLengthPrefix));
+ }
+
+ // Read required libraries.
+ int librariesCount = reader.ReadInt32();
+ Libraries = new List(librariesCount);
+ for (int i = 0; i < librariesCount; i++)
+ {
+ Libraries.Add(reader.ReadString(BinaryStringFormat.DwordLengthPrefix));
+ }
+
+ // Read a possibly attached scheme file.
+ if (reader.ReadBoolean())
+ {
+ int schemeLength = reader.ReadInt32(); // TODO: Check if required due to intelligent loading.
+ GameScheme = reader.Load();
+ GameSchemeName = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ }
+ }
+ }
+
+ ///
+ /// Loads the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public void Load(string fileName)
+ {
+ using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ Load(stream);
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII))
+ {
+ // Write the header.
+ }
+ }
+
+ ///
+ /// Saves the data in the given file.
+ ///
+ /// The name of the file to save the data in.
+ public void Save(string fileName)
+ {
+ using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ Save(stream);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/SchemeFlags.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/SchemeFlags.cs
new file mode 100644
index 0000000..37cc06c
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/SchemeFlags.cs
@@ -0,0 +1,56 @@
+using System.Runtime.InteropServices;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ ///
+ /// Represents global Project X scheme flags affecting general game behavior.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SchemeFlags
+ {
+ [MarshalAs(UnmanagedType.I1)]
+ public bool CyclicMaps;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool UnderwaterJetpack;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool UnderwaterRope;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused1;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused2;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused3;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused4;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused5;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused6;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused7;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool Unused8;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool ShotDoesntEndTurn;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool LoseControlDoesntEndTurn;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool FiringPausesTimer;
+
+ [MarshalAs(UnmanagedType.I1)]
+ public bool EnableSchemePowers;
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sound.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sound.cs
new file mode 100644
index 0000000..90cd540
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sound.cs
@@ -0,0 +1,25 @@
+using System.Runtime.InteropServices;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Sound
+ {
+ [FieldOffset(0)]
+ public short SoundIndex;
+
+ // One byte goes unused here as marshalling does not support 2-byte booleans.
+
+ [FieldOffset(3)]
+ public bool RepeatSound;
+
+ [FieldOffset(4)]
+ public bool UseExplosionSound;
+
+ [FieldOffset(8)]
+ public int SoundBeforeExplosion;
+
+ [FieldOffset(12)]
+ public int DelayBeforeExplosion;
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sprite.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sprite.cs
new file mode 100644
index 0000000..cf99e18
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Sprite.cs
@@ -0,0 +1,31 @@
+using System.Runtime.InteropServices;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Sprite
+ {
+ public int SpriteNumber;
+
+ public SpriteAnimationType AnimationType;
+
+ public int TrailSprite;
+
+ public int TrailAmount;
+
+ public int TrailVanishSpeed;
+
+ public int Unknown;
+ }
+
+ public enum SpriteAnimationType : int
+ {
+ HorizontalVelocity,
+ Cycle,
+ TrackMovement,
+ TrackSpeed,
+ SlowCycle,
+ FasterCycle,
+ FastCycle
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/AirstrikeStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/AirstrikeStyle.cs
new file mode 100644
index 0000000..d8688f7
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/AirstrikeStyle.cs
@@ -0,0 +1,85 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class AirstrikeStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int PlaneSprite;
+
+ public int BombsCount;
+
+ public int DropDistance;
+
+ public int HorizontalSpeed;
+
+ public int Sound;
+
+ public WeaponAirstrikeAction Action;
+
+ public StyleBase Style;
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ PlaneSprite = reader.ReadInt32();
+ BombsCount = reader.ReadInt32();
+ DropDistance = reader.ReadInt32();
+ HorizontalSpeed = reader.ReadInt32();
+ Sound = reader.ReadInt32();
+
+ Action = reader.ReadEnum(true);
+ switch (Action)
+ {
+ case WeaponAirstrikeAction.Launcher:
+ Style = reader.Load();
+ break;
+ case WeaponAirstrikeAction.Mines:
+ Style = reader.Load();
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(PlaneSprite);
+ writer.Write(BombsCount);
+ writer.Write(DropDistance);
+ writer.Write(HorizontalSpeed);
+ writer.Write(Sound);
+
+ writer.Write(Action, true);
+ if (Action != WeaponAirstrikeAction.Worms)
+ {
+ writer.Save(Style);
+ }
+ }
+ }
+ }
+
+ public enum WeaponAirstrikeAction : int
+ {
+ Mines,
+ Worms,
+ Launcher
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BaseballBatStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BaseballBatStyle.cs
new file mode 100644
index 0000000..d8ff3b5
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BaseballBatStyle.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class BaseballBatStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ public int PushPower { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ PushPower = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ writer.Write(PushPower);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BattleAxeStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BattleAxeStyle.cs
new file mode 100644
index 0000000..972b9ad
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BattleAxeStyle.cs
@@ -0,0 +1,41 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class BattleAxeStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int PercentualDamage { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ PercentualDamage = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(PercentualDamage);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BlowtorchStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BlowtorchStyle.cs
new file mode 100644
index 0000000..828373f
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BlowtorchStyle.cs
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class BlowtorchStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ public int PushPower { get; set; }
+
+ public int ImpactAngle { get; set; }
+
+ public int TunellingTime { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ PushPower = reader.ReadInt32();
+ ImpactAngle = reader.ReadInt32();
+ TunellingTime = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ writer.Write(PushPower);
+ writer.Write(ImpactAngle);
+ writer.Write(TunellingTime);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BowStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BowStyle.cs
new file mode 100644
index 0000000..1a4477a
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/BowStyle.cs
@@ -0,0 +1,39 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class BowStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/CanisterStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/CanisterStyle.cs
new file mode 100644
index 0000000..8fdaa97
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/CanisterStyle.cs
@@ -0,0 +1,51 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class CanisterStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int SpriteInactive { get; set; }
+
+ public int SpriteActive { get; set; }
+
+ public int DiseasePoints { get; set; }
+
+ public int MaxDamage { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ SpriteInactive = reader.ReadInt32();
+ SpriteActive = reader.ReadInt32();
+ DiseasePoints = reader.ReadInt32();
+ MaxDamage = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(SpriteInactive);
+ writer.Write(SpriteActive);
+ writer.Write(DiseasePoints);
+ writer.Write(MaxDamage);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/DragonballStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/DragonballStyle.cs
new file mode 100644
index 0000000..153d344
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/DragonballStyle.cs
@@ -0,0 +1,65 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class DragonballStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int FiringSound { get; set; }
+
+ public int ImpactSound { get; set; }
+
+ public int BallSprite { get; set; }
+
+ public int Damage { get; set; }
+
+ public int Angle { get; set; }
+
+ public int Force { get; set; }
+
+ public int BallTime { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ FiringSound = reader.ReadInt32();
+ ImpactSound = reader.ReadInt32();
+ BallSprite = reader.ReadInt32();
+ Damage = reader.ReadInt32();
+ Angle = reader.ReadInt32();
+ Force = reader.ReadInt32();
+ BallTime = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(FiringSound);
+ writer.Write(ImpactSound);
+ writer.Write(BallSprite);
+ writer.Write(Damage);
+ writer.Write(Angle);
+ writer.Write(Force);
+ writer.Write(BallTime);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FirepunchStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FirepunchStyle.cs
new file mode 100644
index 0000000..b4b89a8
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FirepunchStyle.cs
@@ -0,0 +1,51 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class FirepunchStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ public int Angle { get; set; }
+
+ public int PushPower { get; set; }
+
+ public int JumpHeight { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ Angle = reader.ReadInt32();
+ PushPower = reader.ReadInt32();
+ JumpHeight = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ writer.Write(Angle);
+ writer.Write(PushPower);
+ writer.Write(JumpHeight);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FlamethrowerStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FlamethrowerStyle.cs
new file mode 100644
index 0000000..4242547
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/FlamethrowerStyle.cs
@@ -0,0 +1,55 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class FlamethrowerStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int FuelAmount { get; set; }
+
+ public int FireIntensity { get; set; }
+
+ public int FireAmount { get; set; }
+
+ public int FireBurnTime { get; set; }
+
+ public bool RemainOnTerrain { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ FuelAmount = reader.ReadInt32();
+ FireIntensity = reader.ReadInt32();
+ FireAmount = reader.ReadInt32();
+ FireBurnTime = reader.ReadInt32();
+ RemainOnTerrain = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(FuelAmount);
+ writer.Write(FireIntensity);
+ writer.Write(FireAmount);
+ writer.Write(FireBurnTime);
+ writer.Write(RemainOnTerrain, BinaryBooleanFormat.NonZeroDword);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/GunStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/GunStyle.cs
new file mode 100644
index 0000000..6c6ad99
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/GunStyle.cs
@@ -0,0 +1,92 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class GunStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int BulletCount { get; set; }
+
+ public int ReloadTime { get; set; }
+
+ public int BulletSpread { get; set; }
+
+ public int Burst { get; set; }
+
+ public int BurstSpread { get; set; }
+
+ public CollisionFlags Collisions { get; set; }
+
+ public int ExplosionBias { get; set; }
+
+ public int ExplosionPower { get; set; }
+
+ public int MaxDamage { get; set; }
+
+ public int DamageSpread { get; set; }
+
+ public int ExpEffect { get; set; }
+
+ public int Range1 { get; set; }
+
+ public int Range2 { get; set; }
+
+ public int Range3 { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ BulletCount = reader.ReadInt32();
+ ReloadTime = reader.ReadInt32();
+ BulletSpread = reader.ReadInt32();
+ Burst = reader.ReadInt32();
+ BurstSpread = reader.ReadInt32();
+ Collisions = reader.ReadEnum(true);
+ ExplosionBias = reader.ReadInt32();
+ ExplosionPower = reader.ReadInt32();
+ MaxDamage = reader.ReadInt32();
+ DamageSpread = reader.ReadInt32();
+ ExpEffect = reader.ReadInt32();
+ Range1 = reader.ReadInt32();
+ Range2 = reader.ReadInt32();
+ Range3 = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(BulletCount);
+ writer.Write(ReloadTime);
+ writer.Write(BulletSpread);
+ writer.Write(Burst);
+ writer.Write(BurstSpread);
+ writer.Write(Collisions, true);
+ writer.Write(ExplosionBias);
+ writer.Write(ExplosionPower);
+ writer.Write(MaxDamage);
+ writer.Write(DamageSpread);
+ writer.Write(ExpEffect);
+ writer.Write(Range1);
+ writer.Write(Range2);
+ writer.Write(Range3);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/JetpackStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/JetpackStyle.cs
new file mode 100644
index 0000000..0f478c4
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/JetpackStyle.cs
@@ -0,0 +1,41 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class JetpackStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Fuel { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Fuel = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Fuel);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/KamikazeStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/KamikazeStyle.cs
new file mode 100644
index 0000000..db7cf9e
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/KamikazeStyle.cs
@@ -0,0 +1,61 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class KamikazeStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int FlyingTime { get; set; }
+
+ public int ExplosionDamage { get; set; }
+
+ public int FireSound { get; set; }
+
+ public int Damage { get; set; }
+
+ public int ImpactForce { get; set; }
+
+ public int ImpactAngle { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ FlyingTime = reader.ReadInt32();
+ ExplosionDamage = reader.ReadInt32();
+ FireSound = reader.ReadInt32();
+ Damage = reader.ReadInt32();
+ ImpactForce = reader.ReadInt32();
+ ImpactAngle = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(FlyingTime);
+ writer.Write(ExplosionDamage);
+ writer.Write(FireSound);
+ writer.Write(Damage);
+ writer.Write(ImpactForce);
+ writer.Write(ImpactAngle);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs
new file mode 100644
index 0000000..85e5fcf
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/LauncherStyle.cs
@@ -0,0 +1,148 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class LauncherStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int SpriteSize { get; set; }
+
+ public int FixedSpeed { get; set; }
+
+ public bool RunAway { get; set; }
+
+ public CollisionFlags Collisions { get; set; }
+
+ public int ExplosionBias { get; set; }
+
+ public int ExplosionPushPower { get; set; }
+
+ public int ExplosionDamage { get; set; }
+
+ public int ExplosionDamageVariation { get; set; }
+
+ public int ExplosionUnknown { get; set; }
+
+ public Sprite Sprite { get; set; }
+
+ public int VariableSpeed { get; set; }
+
+ public int WindFactor { get; set; }
+
+ public int MotionRandomness { get; set; }
+
+ public int GravityFactor { get; set; }
+
+ public int ExplosionCountdown { get; set; }
+
+ public int ExplosionTimer { get; set; }
+
+ public Sound Sound { get; set; }
+
+ public bool ExplodeOnSpace { get; set; }
+
+ public ExplosionAction ExplosionAction { get; set; }
+
+ public ActionBase Action { get; set; }
+
+ public ExplosionTarget ExplosionTarget { get; set; }
+
+ public TargetBase Target { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ long offset = reader.Position;
+
+ SpriteSize = reader.ReadInt32();
+ FixedSpeed = reader.ReadInt32();
+ RunAway = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ Collisions = reader.ReadEnum(true);
+ ExplosionBias = reader.ReadInt32();
+ ExplosionPushPower = reader.ReadInt32();
+ ExplosionDamage = reader.ReadInt32();
+ ExplosionDamageVariation = reader.ReadInt32();
+ ExplosionUnknown = reader.ReadInt32();
+ Sprite = reader.ReadStruct();
+ VariableSpeed = reader.ReadInt32();
+ WindFactor = reader.ReadInt32();
+ MotionRandomness = reader.ReadInt32();
+ GravityFactor = reader.ReadInt32();
+ ExplosionCountdown = reader.ReadInt32();
+ ExplosionTimer = reader.ReadInt32();
+ Sound = reader.ReadStruct();
+ ExplodeOnSpace = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+
+ ExplosionAction = reader.ReadEnum(true);
+ switch (ExplosionAction)
+ {
+ case ExplosionAction.Bounce:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Dig:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Home:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Roam:
+ Action = reader.Load();
+ break;
+ }
+
+ reader.Position = offset + 180;
+ ExplosionTarget = reader.ReadEnum(true);
+ reader.Seek(4);
+ switch (ExplosionTarget)
+ {
+ case ExplosionTarget.Clusters:
+ Target = reader.Load();
+ break;
+ case ExplosionTarget.Fire:
+ Target = reader.Load();
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+
+ }
+ }
+ }
+
+ public enum ExplosionAction : int
+ {
+ None,
+ Home,
+ Bounce,
+ Roam,
+ Dig
+ }
+
+ public enum ExplosionTarget : int
+ {
+ None,
+ Clusters,
+ Fire
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/MineStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/MineStyle.cs
new file mode 100644
index 0000000..5c9f931
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/MineStyle.cs
@@ -0,0 +1,40 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class MineStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public Mine Mine;
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Mine = reader.ReadStruct();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Mine);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NinjaRopeStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NinjaRopeStyle.cs
new file mode 100644
index 0000000..0fd7be5
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NinjaRopeStyle.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class NinjaRopeStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int ShotCount { get; set; }
+
+ public int Length { get; set; }
+
+ public int AngleRestriction { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ ShotCount = reader.ReadInt32();
+ Length = reader.ReadInt32();
+ AngleRestriction = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(ShotCount);
+ writer.Write(Length);
+ writer.Write(AngleRestriction);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NuclearTestStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NuclearTestStyle.cs
new file mode 100644
index 0000000..b2d1715
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/NuclearTestStyle.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class NuclearTestStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int WaterRise { get; set; }
+
+ public int DiseasePoints { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ WaterRise = reader.ReadInt32();
+ DiseasePoints = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(WaterRise);
+ writer.Write(DiseasePoints);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ParachuteStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ParachuteStyle.cs
new file mode 100644
index 0000000..4474000
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ParachuteStyle.cs
@@ -0,0 +1,41 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class ParachuteStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int WindResponse { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ WindResponse = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(WindResponse);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/PneumaticDrillStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/PneumaticDrillStyle.cs
new file mode 100644
index 0000000..7b9191e
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/PneumaticDrillStyle.cs
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class PneumaticDrillStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ public int PushPower { get; set; }
+
+ public int ImpactAngle { get; set; }
+
+ public int TunellingTime { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ PushPower = reader.ReadInt32();
+ ImpactAngle = reader.ReadInt32();
+ TunellingTime = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ writer.Write(PushPower);
+ writer.Write(ImpactAngle);
+ writer.Write(TunellingTime);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ProdStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ProdStyle.cs
new file mode 100644
index 0000000..e7b05b1
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/ProdStyle.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class ProdStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Damage { get; set; }
+
+ public int Force { get; set; }
+
+ public int Angle { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Damage = reader.ReadInt32();
+ Force = reader.ReadInt32();
+ Angle = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Damage);
+ writer.Write(Force);
+ writer.Write(Angle);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/StyleBase.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/StyleBase.cs
new file mode 100644
index 0000000..8380447
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/StyleBase.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public abstract class StyleBase : ILoadable, ISaveable
+ {
+ public abstract void Load(Stream stream);
+
+ public abstract void Save(Stream stream);
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/SuicideBomberStyle.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/SuicideBomberStyle.cs
new file mode 100644
index 0000000..1d52099
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Styles/SuicideBomberStyle.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class SuicideBomberStyle : StyleBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int DiseasePoints { get; set; }
+
+ public int Damage { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ DiseasePoints = reader.ReadInt32();
+ Damage = reader.ReadInt32();
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(DiseasePoints);
+ writer.Write(Damage);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs
new file mode 100644
index 0000000..5b02468
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/ClusterTarget.cs
@@ -0,0 +1,139 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class ClusterTarget : TargetBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int ClusterCount { get; set; }
+
+ public int DispersionPower { get; set; }
+
+ public int Speed { get; set; }
+
+ public int EjectionAngle { get; set; }
+
+ public int DispersionAngle { get; set; }
+
+ public CollisionFlags Collisions { get; set; }
+
+ public int ExplosionBias { get; set; }
+
+ public int ExplosionPushPower { get; set; }
+
+ public int ExplosionDamage { get; set; }
+
+ public int ExplosionDamageVariation { get; set; }
+
+ public int SpriteCount { get; set; }
+
+ public Sprite Sprite { get; set; }
+
+ public int Acceleration { get; set; }
+
+ public int WindResponse { get; set; }
+
+ public int MotionRandomness { get; set; }
+
+ public int GravityFactor { get; set; }
+
+ public int Unused1 { get; set; }
+
+ public int Unused2 { get; set; }
+
+ public Sound Sound { get; set; }
+
+ public bool ExplodeOnSpace { get; set; }
+
+ public ExplosionAction ExplosionAction { get; set; }
+
+ public ActionBase Action { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ ClusterCount = reader.ReadInt32();
+ DispersionPower = reader.ReadInt32();
+ Speed = reader.ReadInt32();
+ EjectionAngle = reader.ReadInt32();
+ DispersionAngle = reader.ReadInt32();
+ Collisions = reader.ReadEnum(true);
+ ExplosionBias = reader.ReadInt32();
+ ExplosionPushPower = reader.ReadInt32();
+ ExplosionDamage = reader.ReadInt32();
+ ExplosionDamageVariation = reader.ReadInt32();
+ SpriteCount = reader.ReadInt32();
+ Sprite = reader.ReadStruct();
+ Acceleration = reader.ReadInt32();
+ WindResponse = reader.ReadInt32();
+ MotionRandomness = reader.ReadInt32();
+ GravityFactor = reader.ReadInt32();
+ Unused1 = reader.ReadInt32();
+ Unused2 = reader.ReadInt32();
+ Sound = reader.ReadStruct();
+ ExplodeOnSpace = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+
+ ExplosionAction = reader.ReadEnum(true);
+ switch (ExplosionAction)
+ {
+ case ExplosionAction.Bounce:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Dig:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Home:
+ Action = reader.Load();
+ break;
+ case ExplosionAction.Roam:
+ Action = reader.Load();
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(ClusterCount);
+ writer.Write(DispersionPower);
+ writer.Write(Speed);
+ writer.Write(EjectionAngle);
+ writer.Write(DispersionAngle);
+ writer.Write(Collisions, true);
+ writer.Write(ExplosionBias);
+ writer.Write(ExplosionPushPower);
+ writer.Write(ExplosionDamage);
+ writer.Write(ExplosionDamageVariation);
+ writer.Write(Sprite);
+ writer.Write(Acceleration);
+ writer.Write(WindResponse);
+ writer.Write(MotionRandomness);
+ writer.Write(GravityFactor);
+ writer.Write(Unused1);
+ writer.Write(Unused2);
+ writer.Write(Sound);
+ writer.Write(ExplodeOnSpace, BinaryBooleanFormat.NonZeroDword);
+
+ writer.Write(ExplosionAction);
+ writer.Save(Action);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/FireTarget.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/FireTarget.cs
new file mode 100644
index 0000000..e94b91d
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/FireTarget.cs
@@ -0,0 +1,51 @@
+using System.IO;
+using System.Text;
+using Syroot.IO;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public class FireTarget : TargetBase
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ public int Power { get; set; }
+
+ public int Spread { get; set; }
+
+ public int Time { get; set; }
+
+ public bool StayBetweenTurns { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public override void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ Power = reader.ReadInt32();
+ Spread = reader.ReadInt32();
+ Time = reader.ReadInt32();
+ StayBetweenTurns = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public override void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+ writer.Write(Power);
+ writer.Write(Spread);
+ writer.Write(Time);
+ writer.Write(StayBetweenTurns, BinaryBooleanFormat.NonZeroDword);
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/TargetBase.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/TargetBase.cs
new file mode 100644
index 0000000..44bd76c
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Targets/TargetBase.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms.Gen2.Armageddon.ProjectX
+{
+ public abstract class TargetBase : ILoadable, ISaveable
+ {
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public abstract void Load(Stream stream);
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public abstract void Save(Stream stream);
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs
new file mode 100644
index 0000000..652dd47
--- /dev/null
+++ b/src/Syroot.Worms/Gen2/Armageddon/ProjectX/Weapon.cs
@@ -0,0 +1,363 @@
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using Syroot.IO;
+using Syroot.Worms.Core;
+
+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 long Checksum { get; set; }
+
+ public int TableRow { get; set; }
+
+ public bool Remembered { get; set; }
+
+ public bool UsableInCavern { get; set; }
+
+ public int Shots { get; set; }
+
+ public bool ShotEndsTurn { get; set; }
+
+ public int RetreatTime { get; set; }
+
+ public int Unknown1 { get; set; }
+
+ public int CrateChance { get; set; }
+
+ public int CrateCount { get; set; }
+
+ public bool Unknown2 { get; set; }
+
+ public WeaponActivation Activation { get; set; }
+
+ public int ThrowHerdCount { get; set; }
+
+ public int AirstrikeSubtype { get; set; }
+
+ public WeaponSpacebarAction SpacebarAction { get; set; }
+
+ public WeaponCrosshairAction CrosshairAction { get; set; }
+
+ public WeaponThrowAction ThrowAction { get; set; }
+
+ public StyleBase Style { get; set; }
+
+ public bool AmmunitionOverride { get; set; }
+
+ public int Ammunition { get; set; }
+
+ public int Unknown3 { get; set; }
+
+ public int WeaponSprite { get; set; }
+
+ public string NameLong { get; set; }
+
+ public string Name { get; set; }
+
+ public string GridImageFile { get; set; }
+
+ public string GfxDirectoryFile { get; set; }
+
+ public string[] SpriteNames { get; set; }
+
+ public bool DelayOverride { get; set; }
+
+ public int Delay { get; set; }
+
+ public bool UseLibrary { get; set; }
+
+ public string LibraryName { get; set; }
+
+ public string LibraryWeaponName { get; set; }
+
+ public string AimSpriteEven { get; set; }
+
+ public string AimSpriteUphill { get; set; }
+
+ public string AimSpriteDownhill { get; set; }
+
+ public string PickSpriteEven { get; set; }
+
+ public string PickSpriteUphill { get; set; }
+
+ public string PickSpriteDownhill { get; set; }
+
+ public string FireSpriteEven { get; set; }
+
+ public string FireSpriteUphill { get; set; }
+
+ public string FireSpriteDownhill { get; set; }
+
+ public bool AimSpriteOverride { get; set; }
+
+ public bool PickSpriteOverride { get; set; }
+
+ public bool FireSpriteOverride { get; set; }
+
+ public bool Utility { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public void Load(Stream stream)
+ {
+ using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
+ {
+ // 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}.");
+ }
+ Checksum = reader.ReadInt64();
+
+ // Read general settings.
+ TableRow = reader.ReadInt32();
+ Remembered = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ UsableInCavern = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ Shots = reader.ReadInt32();
+ ShotEndsTurn = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ RetreatTime = reader.ReadInt32();
+ Unknown1 = reader.ReadInt32();
+ CrateChance = reader.ReadInt32();
+ CrateCount = reader.ReadInt32();
+ Unknown2 = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+
+ // Read the activation and the corresponding weapon settings.
+ Activation = reader.ReadEnum(true);
+ switch (Activation)
+ {
+ case WeaponActivation.Airstrike:
+ AirstrikeSubtype = reader.ReadInt32();
+ Style = reader.Load();
+ break;
+ case WeaponActivation.Crosshair:
+ reader.Seek(sizeof(int));
+ CrosshairAction = reader.ReadEnum(true);
+ switch (CrosshairAction)
+ {
+ case WeaponCrosshairAction.Bow:
+ Style = reader.Load();
+ break;
+ case WeaponCrosshairAction.Flamethrower:
+ Style = reader.Load();
+ break;
+ case WeaponCrosshairAction.Gun:
+ Style = reader.Load();
+ break;
+ case WeaponCrosshairAction.Launcher:
+ Style = reader.Load();
+ break;
+ }
+ break;
+ case WeaponActivation.Spacebar:
+ SpacebarAction = reader.ReadEnum(true);
+ switch (SpacebarAction)
+ {
+ case WeaponSpacebarAction.Armageddon:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.BaseballBat:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.BattleAxe:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Blowtorch:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Dragonball:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Firepunch:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Jetpack:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Kamikaze:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.NinjaRope:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.NuclearTest:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Parachute:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.PneumaticDrill:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Prod:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.SuicideBomber:
+ Style = reader.Load();
+ break;
+ case WeaponSpacebarAction.Bungee:
+ case WeaponSpacebarAction.Earthquake:
+ case WeaponSpacebarAction.Freeze:
+ case WeaponSpacebarAction.Girder:
+ case WeaponSpacebarAction.ScalesOfJustice:
+ case WeaponSpacebarAction.SelectWorm:
+ case WeaponSpacebarAction.SkipGo:
+ case WeaponSpacebarAction.Surrender:
+ case WeaponSpacebarAction.Teleport:
+ case WeaponSpacebarAction.Utility:
+ Style = null;
+ break;
+ }
+ break;
+ case WeaponActivation.Throw:
+ ThrowHerdCount = reader.ReadInt32();
+ ThrowAction = reader.ReadEnum(true);
+ switch (ThrowAction)
+ {
+ case WeaponThrowAction.Canister:
+ Style = reader.Load();
+ break;
+ case WeaponThrowAction.Launcher:
+ Style = reader.Load();
+ break;
+ case WeaponThrowAction.Mine:
+ Style = reader.Load();
+ break;
+ }
+ break;
+ }
+
+ // Read additional settings.
+ reader.Position = offset + 468;
+ AmmunitionOverride = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ Ammunition = reader.ReadInt32();
+ Unknown3 = reader.ReadInt32();
+ WeaponSprite = reader.ReadInt32();
+ NameLong = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ Name = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ GridImageFile = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ GfxDirectoryFile = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ SpriteNames = reader.ReadStrings(5, BinaryStringFormat.DwordLengthPrefix);
+ DelayOverride = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
+ Delay = reader.ReadInt32();
+
+ UseLibrary = reader.ReadBoolean();
+ if (UseLibrary)
+ {
+ LibraryName = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ LibraryWeaponName = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ }
+
+ AimSpriteEven = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ AimSpriteUphill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ AimSpriteDownhill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ PickSpriteEven = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ PickSpriteUphill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ PickSpriteDownhill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ FireSpriteEven = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ FireSpriteUphill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ FireSpriteDownhill = reader.ReadString(BinaryStringFormat.DwordLengthPrefix);
+ AimSpriteOverride = reader.ReadBoolean();
+ PickSpriteOverride = reader.ReadBoolean();
+ FireSpriteOverride = reader.ReadBoolean();
+ if (Version == _version_0_8_0)
+ {
+ Utility = reader.ReadBoolean();
+ }
+ }
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public void Save(Stream stream)
+ {
+ using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true))
+ {
+
+ }
+ }
+ }
+
+ public enum WeaponActivation : int
+ {
+ None,
+ Crosshair,
+ Throw,
+ Airstrike,
+ Spacebar
+ }
+
+ public enum WeaponSpacebarAction : int
+ {
+ None,
+ Firepunch,
+ BaseballBat,
+ Dragonball,
+ Kamikaze,
+ SuicideBomber,
+ NinjaRope,
+ Bungee,
+ PneumaticDrill,
+ Prod,
+ Teleport,
+ Blowtorch,
+ Parachute,
+ Surrender,
+ SkipGo,
+ SelectWorm,
+ NuclearTest,
+ Girder,
+ BattleAxe,
+ Utility,
+ Freeze,
+ Earthquake,
+ ScalesOfJustice,
+ Jetpack,
+ Armageddon
+ }
+
+ public enum WeaponCrosshairAction : int
+ {
+ None,
+ Flamethrower,
+ Gun,
+ Launcher,
+ Bow
+ }
+
+ public enum WeaponThrowAction : int
+ {
+ None,
+ Mine,
+ Launcher,
+ Canister
+ }
+
+ public enum WeaponSpriteNameIndex
+ {
+ Unknown0,
+ Launcher,
+ Cluster,
+ Home,
+ Unknown4
+ }
+}
diff --git a/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs b/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
index e6bff03..f503af7 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/Scheme.cs
@@ -870,7 +870,7 @@ namespace Syroot.Worms.Gen2.Armageddon
private void LoadRubberWormSettings()
{
- var earthquakeProb = (RwEarthquakeProb)Weapons[(int)SchemeWeapon.Earthquake].Probability;
+ RwEarthquakeProb earthquakeProb = (RwEarthquakeProb)Weapons[(int)SchemeWeapon.Earthquake].Probability;
RwAntiLockPower = earthquakeProb.HasFlag(RwEarthquakeProb.AntiLockPower);
RwAutoReaim = earthquakeProb.HasFlag(RwEarthquakeProb.AutoReaim);
RwCircularAim = earthquakeProb.HasFlag(RwEarthquakeProb.CircularAim);
@@ -881,7 +881,8 @@ namespace Syroot.Worms.Gen2.Armageddon
RwCrateLimit = (byte)Weapons[(int)SchemeWeapon.MagicBullet].Probability;
RwCrateRate = (byte)Weapons[(int)SchemeWeapon.NuclearTest].Probability;
- var moleSquadronProb = (RwMoleSquadronProb)Weapons[(int)SchemeWeapon.MoleSquadron].Probability;
+ RwMoleSquadronProb moleSquadronProb = (RwMoleSquadronProb)Weapons[(int)SchemeWeapon.MoleSquadron]
+ .Probability;
RwCrateShower = moleSquadronProb.HasFlag(RwMoleSquadronProb.CrateShower);
RwExtendedFuse = moleSquadronProb.HasFlag(RwMoleSquadronProb.ExtendedFuse);
RwFireDoesntPauseTimer = moleSquadronProb.HasFlag(RwMoleSquadronProb.FireDoesntPauseTimer);
@@ -895,7 +896,7 @@ namespace Syroot.Worms.Gen2.Armageddon
RwFriction = (byte)Weapons[(int)SchemeWeapon.SalvationArmy].Probability;
// 8th and 7th bit control constant / proportional black hole gravity, otherwise normal gravity.
- var mailStrikeProb = (byte)Weapons[(int)SchemeWeapon.MailStrike].Probability;
+ byte mailStrikeProb = (byte)Weapons[(int)SchemeWeapon.MailStrike].Probability;
if (mailStrikeProb.GetBit(7))
{
if (mailStrikeProb.GetBit(6))
diff --git a/src/Syroot.Worms/Gen2/Armageddon/SchemeEnums.cs b/src/Syroot.Worms/Gen2/Armageddon/SchemeEnums.cs
index 303c9d2..cc18d57 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/SchemeEnums.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/SchemeEnums.cs
@@ -1367,9 +1367,9 @@ namespace Syroot.Worms.Gen2.Armageddon
Longbow,
///
- /// The Air Strike weapon.
+ /// The Airstrike weapon.
///
- AirStrike,
+ Airstrike,
///
/// The Napalm Strike weapon.
@@ -1382,14 +1382,14 @@ namespace Syroot.Worms.Gen2.Armageddon
Mine,
///
- /// The Fire Punch weapon.
+ /// The Firepunch weapon.
///
- FirePunch,
+ Firepunch,
///
- /// The Dragon Ball weapon.
+ /// The Dragonball weapon.
///
- DragonBall,
+ Dragonball,
///
/// The Kamikaze weapon.
@@ -1407,9 +1407,9 @@ namespace Syroot.Worms.Gen2.Armageddon
BattleAxe,
///
- /// The Blow Torch weapon.
+ /// The Blowtorch weapon.
///
- BlowTorch,
+ Blowtorch,
///
/// The Pneumatic Drill weapon.
@@ -1459,7 +1459,7 @@ namespace Syroot.Worms.Gen2.Armageddon
///
/// The Flame Thrower weapon.
///
- FlameThrower,
+ Flamethrower,
///
/// The Homing Pigeon weapon.
@@ -1497,9 +1497,9 @@ namespace Syroot.Worms.Gen2.Armageddon
MoleBomb,
///
- /// The Jet Pack utility.
+ /// The Jetpack utility.
///
- JetPack,
+ Jetpack,
///
/// The Low Gravity utility.
diff --git a/src/Syroot.Worms/Gen2/Armageddon/Team.cs b/src/Syroot.Worms/Gen2/Armageddon/Team.cs
index 7592702..dd3e670 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/Team.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/Team.cs
@@ -328,7 +328,7 @@ namespace Syroot.Worms.Gen2.Armageddon
///
/// The Flame Thrower weapon.
///
- FlameThrower,
+ Flamethrower,
///
/// The Mole Bomb weapon.
diff --git a/src/Syroot.Worms/Gen2/Armageddon/TeamContainer.cs b/src/Syroot.Worms/Gen2/Armageddon/TeamContainer.cs
index 2372899..4bed234 100644
--- a/src/Syroot.Worms/Gen2/Armageddon/TeamContainer.cs
+++ b/src/Syroot.Worms/Gen2/Armageddon/TeamContainer.cs
@@ -91,13 +91,7 @@ namespace Syroot.Worms.Gen2.Armageddon
Unknown = reader.ReadByte();
// Read the teams.
- Teams = new List(teamCount);
- for (int i = 0; i < teamCount; i++)
- {
- Team team = new Team();
- team.Load(reader.BaseStream);
- Teams.Add(team);
- }
+ Teams = new List(reader.Load(teamCount));
}
}
diff --git a/src/Syroot.Worms/Gen2/WorldParty/Team.cs b/src/Syroot.Worms/Gen2/WorldParty/Team.cs
index 545464f..28cbe46 100644
--- a/src/Syroot.Worms/Gen2/WorldParty/Team.cs
+++ b/src/Syroot.Worms/Gen2/WorldParty/Team.cs
@@ -326,7 +326,7 @@ namespace Syroot.Worms.Gen2.WorldParty
///
/// The Flame Thrower weapon.
///
- FlameThrower,
+ Flamethrower,
///
/// The Mole Bomb weapon.
@@ -436,9 +436,9 @@ namespace Syroot.Worms.Gen2.WorldParty
Longbow,
///
- /// The Air Strike weapon.
+ /// The Airstrike weapon.
///
- AirStrike,
+ Airstrike,
///
/// The Napalm Strike weapon.
@@ -451,14 +451,14 @@ namespace Syroot.Worms.Gen2.WorldParty
Mine,
///
- /// The Fire Punch weapon.
+ /// The Firepunch weapon.
///
- FirePunch,
+ Firepunch,
///
- /// The Dragon Ball weapon.
+ /// The Dragonball weapon.
///
- DragonBall,
+ Dragonball,
///
/// The Kamikaze weapon.
@@ -476,9 +476,9 @@ namespace Syroot.Worms.Gen2.WorldParty
BattleAxe,
///
- /// The Blow Torch weapon.
+ /// The Blowtorch weapon.
///
- BlowTorch,
+ Blowtorch,
///
/// The Pneumatic Drill weapon.
@@ -528,7 +528,7 @@ namespace Syroot.Worms.Gen2.WorldParty
///
/// The Flame Thrower weapon.
///
- FlameThrower,
+ Flamethrower,
///
/// The Homing Pigeon weapon.
@@ -566,9 +566,9 @@ namespace Syroot.Worms.Gen2.WorldParty
MoleBomb,
///
- /// The Jet Pack utility.
+ /// The Jetpack utility.
///
- JetPack,
+ Jetpack,
///
/// The Low Gravity utility.
diff --git a/src/Syroot.Worms/Gen2/WorldParty/TeamContainer.cs b/src/Syroot.Worms/Gen2/WorldParty/TeamContainer.cs
index 404968c..3ef1377 100644
--- a/src/Syroot.Worms/Gen2/WorldParty/TeamContainer.cs
+++ b/src/Syroot.Worms/Gen2/WorldParty/TeamContainer.cs
@@ -97,13 +97,7 @@ namespace Syroot.Worms.Gen2.WorldParty
Unknown3 = reader.ReadBytes(840);
// Read the teams.
- Teams = new List(teamCount);
- for (int i = 0; i < teamCount; i++)
- {
- Team team = new Team();
- team.Load(reader.BaseStream);
- Teams.Add(team);
- }
+ Teams = new List(reader.Load(teamCount));
}
}
diff --git a/src/Syroot.Worms/Gen2/Worms2/LandData.cs b/src/Syroot.Worms/Gen2/Worms2/LandData.cs
index bb48deb..2ac3372 100644
--- a/src/Syroot.Worms/Gen2/Worms2/LandData.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/LandData.cs
@@ -122,10 +122,10 @@ namespace Syroot.Worms.Gen2.Worms2
Unknown = reader.ReadInt32();
// Read the image data.
- Foreground = new Image(stream);
- CollisionMask = new Image(stream);
- Background = new Image(stream);
- UnknownImage = new Image(stream);
+ Foreground = reader.Load();
+ CollisionMask = reader.Load();
+ Background = reader.Load();
+ UnknownImage = reader.Load();
// Read the file paths.
LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
diff --git a/src/Syroot.Worms/Gen2/Worms2/SchemeEnums.cs b/src/Syroot.Worms/Gen2/Worms2/SchemeEnums.cs
index 78e3e30..f6a82b4 100644
--- a/src/Syroot.Worms/Gen2/Worms2/SchemeEnums.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/SchemeEnums.cs
@@ -93,14 +93,14 @@ namespace Syroot.Worms.Gen2.Worms2
Minigun,
///
- /// The Fire Punch weapon.
+ /// The Firepunch weapon.
///
- FirePunch,
+ Firepunch,
///
- /// The Dragon Ball weapon.
+ /// The Dragonball weapon.
///
- DragonBall,
+ Dragonball,
///
/// The Kamikaze weapon.
@@ -123,14 +123,14 @@ namespace Syroot.Worms.Gen2.Worms2
MingVase,
///
- /// The Air Strike weapon.
+ /// The Airstrike weapon.
///
- AirStrike,
+ Airstrike,
///
- /// The Homing Air Strike weapon.
+ /// The Homing Airstrike weapon.
///
- HomingAirStrike,
+ HomingAirstrike,
///
/// The Napalm Strike weapon.
@@ -203,9 +203,9 @@ namespace Syroot.Worms.Gen2.Worms2
Mortar,
///
- /// The Blow Torch weapon.
+ /// The Blowtorch weapon.
///
- BlowTorch,
+ Blowtorch,
///
/// The Homing Pigeon weapon.
diff --git a/src/Syroot.Worms/Gen2/Worms2/SchemeWeaponSetting.cs b/src/Syroot.Worms/Gen2/Worms2/SchemeWeaponSetting.cs
index 9da1c7f..36de504 100644
--- a/src/Syroot.Worms/Gen2/Worms2/SchemeWeaponSetting.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/SchemeWeaponSetting.cs
@@ -57,12 +57,12 @@ namespace Syroot.Worms.Gen2.Worms2
///
/// The pushing power measured in percent.
///
- public int BlastPower;
+ public int ExplosionPower;
///
/// The offset to the bottom of an explosion, measured in percent.
///
- public int BlastBias;
+ public int ExplosionBias;
///
/// The milliseconds required before this weapon starts flying towards its target.
@@ -142,27 +142,27 @@ namespace Syroot.Worms.Gen2.Worms2
///
/// The height of the fire punch jump, measured in percent.
///
- public int FirePunchHeight;
+ public int FirepunchHeight;
///
/// The damage a dragon ball causes, measured in health points.
///
- public int DragonBallDamage;
+ public int DragonballDamage;
///
/// The power in which a dragon ball launches hit worms, measured in percent.
///
- public int DragonBallPower;
+ public int DragonballPower;
///
/// The angle in which a dragon ball launches hit worms, measured in degrees.
///
- public int DragonBallAngle;
+ public int DragonballAngle;
///
/// The life time of a launched dragon ball measured in milliseconds.
///
- public int DragonBallTime;
+ public int DragonballTime;
///
/// The length of digging measured in milliseconds. Applies to Kamikaze and digging tools.
diff --git a/src/Syroot.Worms/Gen2/Worms2/TeamContainer.cs b/src/Syroot.Worms/Gen2/Worms2/TeamContainer.cs
index 2e53ce0..c222bfc 100644
--- a/src/Syroot.Worms/Gen2/Worms2/TeamContainer.cs
+++ b/src/Syroot.Worms/Gen2/Worms2/TeamContainer.cs
@@ -61,9 +61,7 @@ namespace Syroot.Worms.Gen2.Worms2
Teams = new List();
while (!reader.EndOfStream)
{
- Team team = new Team();
- team.Load(reader.BaseStream);
- Teams.Add(team);
+ Teams.Add(reader.Load());
}
}
}