Add enums for simple team file editing, fix LandData for WWP.

This commit is contained in:
Ray Koopa 2017-04-26 11:05:53 +02:00
parent e5b1b9441f
commit ade95d4cd0
8 changed files with 365 additions and 31 deletions

View File

@ -19,7 +19,7 @@ namespace Syroot.Worms.UnitTest.Gen2.Armageddon
[TestMethod]
public void LoadLandData()
{
TestHelpers.LoadFiles<LandData>(Game.Armageddon, "land.dat");
TestHelpers.LoadFiles<LandData>(Game.WormsArmageddon, "land.dat");
}
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Syroot.Worms.Gen2.WorldParty;
using Syroot.Worms.UnitTest.Common;
namespace Syroot.Worms.UnitTest.Gen2.WorldParty
{
/// <summary>
/// Represents a collection of tests for the <see cref="LandData"/> class.
/// </summary>
[TestCategory("LandData (WorldParty)")]
[TestClass]
public class LandDataTests
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Loads all files found in any game directories.
/// </summary>
[TestMethod]
public void LoadLandData()
{
TestHelpers.LoadFiles<LandData>(Game.WormsWorldParty, "land.dat");
}
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Syroot.Worms.Gen2.WorldParty;
using Syroot.Worms.UnitTest.Common;
namespace Syroot.Worms.UnitTest.Gen2.WorldParty
{
/// <summary>
/// Represents a collection of tests for the <see cref="TeamContainer"/> class.
/// </summary>
[TestCategory("TeamContainer (WorldParty)")]
[TestClass]
public class TeamContainerTests
{
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Loads all files found in any game directories.
/// </summary>
[TestMethod]
public void LoadTeamContainers()
{
TestHelpers.LoadFiles<TeamContainer>(Game.WormsWorldParty, "*.wwp");
}
}
}

View File

@ -114,7 +114,7 @@ namespace Syroot.Worms.Gen2.Armageddon
WaterHeight = reader.ReadInt32();
// Read the possible object coordinate array.
int badObjectLocations = reader.ReadInt32(); // TODO: Check what this is used for.
int unknown = reader.ReadInt32();
ObjectLocations = new Vector2[reader.ReadInt32()];
for (int i = 0; i < ObjectLocations.Length; i++)
{

View File

@ -15,6 +15,7 @@ namespace Syroot.Worms.Gen2.Armageddon
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
private const int _missionCount = 33;
private const int _trainingMissionCount = 6;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
@ -25,9 +26,9 @@ namespace Syroot.Worms.Gen2.Armageddon
{
WormNames = new string[8];
MissionStatuses = new TeamMissionStatus[_missionCount];
TrainingMissionTimes = new int[6];
TrainingMissionTimes = new int[_trainingMissionCount];
Unknown1 = new int[10];
TrainingMissionMedals = new byte[6];
TrainingMissionMedals = new byte[_trainingMissionCount];
Unknown2 = new byte[10];
Unknown3 = new int[7];
}
@ -85,7 +86,7 @@ namespace Syroot.Worms.Gen2.Armageddon
/// <summary>
/// Gets or sets the team's special weapon.
/// </summary>
public byte TeamWeapon { get; set; }
public TeamWeapon TeamWeapon { get; set; }
/// <summary>
/// Gets or sets the number of games lost.
@ -158,7 +159,7 @@ namespace Syroot.Worms.Gen2.Armageddon
public byte DeathmatchRank { get; set; }
/// <summary>
/// Gets or sets the seconds the team required to finish all 6 training missions.
/// Gets or sets the seconds the team required to finish all 6 training missions.
/// </summary>
public int[] TrainingMissionTimes { get; set; }
@ -217,8 +218,8 @@ namespace Syroot.Worms.Gen2.Armageddon
Data = reader.ReadBytes(24 * 32)
};
}
TeamWeapon = reader.ReadByte();
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
@ -241,9 +242,9 @@ namespace Syroot.Worms.Gen2.Armageddon
};
DeathmatchRank = reader.ReadByte();
TrainingMissionTimes = reader.ReadInt32s(6);
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
Unknown1 = reader.ReadInt32s(10);
TrainingMissionMedals = reader.ReadBytes(6);
TrainingMissionMedals = reader.ReadBytes(_trainingMissionCount);
Unknown2 = reader.ReadBytes(10);
Unknown3 = reader.ReadInt32s(7);
Unknown4 = reader.ReadByte();
@ -274,7 +275,7 @@ namespace Syroot.Worms.Gen2.Armageddon
writer.Write(Grave.Data);
}
writer.Write(TeamWeapon);
writer.Write(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
@ -302,10 +303,66 @@ namespace Syroot.Worms.Gen2.Armageddon
}
}
/// <summary>
/// Represents a team's progress in a mission.
/// </summary>
[DebuggerDisplay("TeamMissionStatus Attemps={Attempts} Medal={Medal}")]
public struct TeamMissionStatus
{
/// <summary>
/// The number of attempts the team required to solve the mission.
/// </summary>
public int Attempts;
/// <summary>
/// The medal the team got to solve the mission.
/// </summary>
public int Medal;
}
/// <summary>
/// Represents the special weapon of a team.
/// </summary>
public enum TeamWeapon : byte
{
/// <summary>
/// The Flame Thrower weapon.
/// </summary>
FlameThrower,
/// <summary>
/// The Mole Bomb weapon.
/// </summary>
MoleBomb,
/// <summary>
/// The Old Woman weapon.
/// </summary>
OldWoman,
/// <summary>
/// The Homing Pigeon weapon.
/// </summary>
HomingPigeon,
/// <summary>
/// The Sheep Launcher weapon.
/// </summary>
SheepLauncher,
/// <summary>
/// The Mad Cow weapon.
/// </summary>
MadCow,
/// <summary>
/// The Holy Hand Grenade weapon.
/// </summary>
HolyHandGrenade,
/// <summary>
/// The Super Sheep or Aqua Sheep weapon.
/// </summary>
SuperSheep
}
}

View File

@ -45,13 +45,25 @@ namespace Syroot.Worms.Gen2
Load(fileName);
}
/// <summary>
/// Initializes a new instance of the <see cref="Image"/> class, loading the data from the given
/// <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
/// <param name="alignData"><c>true</c> to start reading the image data at a 4-byte boundary. Used by WWP in
/// LAND.DAT files.</param>
internal Image(Stream stream, bool alignData)
{
Load(stream);
}
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets an optional description of the image contents.
/// </summary>
public string Description { get; private set; }
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
@ -59,6 +71,24 @@ namespace Syroot.Worms.Gen2
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public void Load(Stream stream)
{
}
/// <summary>
/// Loads the data from the given file.
/// </summary>
/// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Load(stream);
}
}
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
private void Load(Stream stream, bool alignData)
{
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
{
@ -98,6 +128,10 @@ namespace Syroot.Worms.Gen2
}
Size = new Vector2(reader.ReadInt16(), reader.ReadInt16());
if (alignData)
{
reader.Align(4);
}
// Read the bytes, which might be compressed.
byte[] data = new byte[Size.X * Size.Y * BitsPerPixel / 8];
@ -114,18 +148,6 @@ namespace Syroot.Worms.Gen2
}
}
/// <summary>
/// Loads the data from the given file.
/// </summary>
/// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Load(stream);
}
}
// ---- ENUMERATIONS -------------------------------------------------------------------------------------------
[Flags]

View File

@ -0,0 +1,146 @@
using System.IO;
using System.Text;
using Syroot.IO;
using Syroot.Maths;
using Syroot.Worms.Core;
namespace Syroot.Worms.Gen2.WorldParty
{
/// <summary>
/// Represents map configuration stored by the land generator in LAND.DAT files.
/// Used by WWP. S. https://worms2d.info/Land_Data_file.
/// </summary>
public class LandData : ILoadableFile
{
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
private const int _signature = 0x1A444E4C; // "LND", 0x1A
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="LandData"/> class.
/// </summary>
public LandData()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given
/// <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
public LandData(Stream stream)
{
Load(stream);
}
/// <summary>
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file.
/// </summary>
/// <param name="fileName">The name of the file to load the data from.</param>
public LandData(string fileName)
{
Load(fileName);
}
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets or sets the size of the landscape in pixels.
/// </summary>
public Vector2 Size { get; set; }
/// <summary>
/// Gets or sets a value indicating whether an indestructible top border will be enabled.
/// </summary>
public bool TopBorder { get; set; }
/// <summary>
/// Gets or sets the height of the water in pixels.
/// </summary>
public int WaterHeight { get; set; }
/// <summary>
/// Gets or sets an array of coordinates at which objects can be placed.
/// </summary>
public Vector2[] ObjectLocations { get; set; }
/// <summary>
/// Gets or sets the visual foreground image.
/// </summary>
public Image Foreground { get; set; }
/// <summary>
/// Gets or sets the collision mask of the landscape.
/// </summary>
public Image CollisionMask { get; set; }
/// <summary>
/// Gets or sets the visual background image.
/// </summary>
public Image Background { get; set; }
/// <summary>
/// Gets or sets the path to the land image file.
/// </summary>
public string LandTexturePath { get; set; }
/// <summary>
/// Gets or sets the path to the Water.dir file.
/// </summary>
public string WaterDirPath { get; set; }
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
/// <summary>
/// Loads the data from the given <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
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 LND file signature.");
}
int fileLength = reader.ReadInt32();
// Read the data.
Size = reader.ReadStruct<Vector2>();
TopBorder = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
WaterHeight = reader.ReadInt32();
// Read the possible object coordinate array.
ObjectLocations = new Vector2[reader.ReadInt32()];
for (int i = 0; i < ObjectLocations.Length; i++)
{
ObjectLocations[i] = reader.ReadStruct<Vector2>();
}
// Read the image data.
Foreground = new Image(stream, true);
CollisionMask = new Image(stream, true);
Background = new Image(stream, true);
// Read the file paths.
LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
WaterDirPath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
}
}
/// <summary>
/// Loads the data from the given file.
/// </summary>
/// <param name="fileName">The name of the file to load the data from.</param>
public void Load(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Load(stream);
}
}
}
}

View File

@ -15,6 +15,7 @@ namespace Syroot.Worms.Gen2.WorldParty
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
private const int _missionCount = 45;
private const int _trainingMissionCount = 35;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
@ -25,7 +26,7 @@ namespace Syroot.Worms.Gen2.WorldParty
{
WormNames = new string[8];
MissionStatuses = new TeamMissionStatus[_missionCount];
TrainingMissionTimes = new int[6];
TrainingMissionTimes = new int[_trainingMissionCount];
WeaponPoints = new byte[46];
Unknown2 = new int[7];
}
@ -83,7 +84,7 @@ namespace Syroot.Worms.Gen2.WorldParty
/// <summary>
/// Gets or sets the team's special weapon.
/// </summary>
public byte TeamWeapon { get; set; }
public TeamWeapon TeamWeapon { get; set; }
/// <summary>
/// Gets or sets the number of games lost.
@ -150,6 +151,9 @@ namespace Syroot.Worms.Gen2.WorldParty
/// </summary>
public Bitmap Flag { get; set; }
/// <summary>
/// Gets or sets an unknown value.
/// </summary>
public byte Unknown1 { get; set; }
/// <summary>
@ -158,7 +162,7 @@ namespace Syroot.Worms.Gen2.WorldParty
public byte DeathmatchRank { get; set; }
/// <summary>
/// Gets or sets the seconds the team required to finish all 6 training missions.
/// Gets or sets the seconds the team required to finish all 35 training missions. The last one is unused.
/// </summary>
public int[] TrainingMissionTimes { get; set; }
@ -214,7 +218,7 @@ namespace Syroot.Worms.Gen2.WorldParty
};
}
TeamWeapon = reader.ReadByte();
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
GamesLost = reader.ReadInt32();
DeathmatchesLost = reader.ReadInt32();
GamesWon = reader.ReadInt32();
@ -238,8 +242,7 @@ namespace Syroot.Worms.Gen2.WorldParty
Unknown1 = reader.ReadByte();
DeathmatchRank = reader.ReadByte();
TrainingMissionTimes = reader.ReadInt32s(34);
UnknownTrainingMissionTime = reader.ReadInt32(); // Possibly an unused time.
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
WeaponPoints = reader.ReadBytes(46);
Fort = reader.ReadByte();
Unknown2 = reader.ReadInt32s(7);
@ -270,7 +273,7 @@ namespace Syroot.Worms.Gen2.WorldParty
writer.Write(Grave.Data);
}
writer.Write(TeamWeapon);
writer.Write(TeamWeapon, true);
writer.Write(GamesLost);
writer.Write(DeathmatchesLost);
writer.Write(GamesWon);
@ -298,13 +301,69 @@ namespace Syroot.Worms.Gen2.WorldParty
}
}
/// <summary>
/// Represents a team's progress in a mission.
/// </summary>
[DebuggerDisplay("TeamMissionStatus Attemps={Attempts} Medal={Medal}")]
public struct TeamMissionStatus
{
/// <summary>
/// The number of attempts the team required to solve the mission.
/// </summary>
public int Attempts;
/// <summary>
/// The medal the team got to solve the mission.
/// </summary>
public int Medal;
}
/// <summary>
/// Represents the special weapon of a team.
/// </summary>
public enum TeamWeapon : byte
{
/// <summary>
/// The Flame Thrower weapon.
/// </summary>
FlameThrower,
/// <summary>
/// The Mole Bomb weapon.
/// </summary>
MoleBomb,
/// <summary>
/// The Old Woman weapon.
/// </summary>
OldWoman,
/// <summary>
/// The Homing Pigeon weapon.
/// </summary>
HomingPigeon,
/// <summary>
/// The Sheep Launcher weapon.
/// </summary>
SheepLauncher,
/// <summary>
/// The Mad Cow weapon.
/// </summary>
MadCow,
/// <summary>
/// The Holy Hand Grenade weapon.
/// </summary>
HolyHandGrenade,
/// <summary>
/// The Super Sheep or Aqua Sheep weapon.
/// </summary>
SuperSheep
}
/// <summary>
/// Represents the weapons and utilities being an index into the <see cref="Team.WeaponPoints"/> array to store the
/// amount the team bought.