diff --git a/Warcraft.NET.Docs/ChunkAvailability.cs b/Warcraft.NET.Docs/ChunkAvailability.cs
index f3d2d31..75169c5 100644
--- a/Warcraft.NET.Docs/ChunkAvailability.cs
+++ b/Warcraft.NET.Docs/ChunkAvailability.cs
@@ -107,7 +107,6 @@ internal static class ChunkAvailability
"M2", new()
{
"MD21",
- "PFID",
"SFID",
"AFID",
"BFID",
@@ -136,6 +135,32 @@ internal static class ChunkAvailability
}
},
}
+ },{
+ "phys", new ()
+ {
+ {
+ "PHYS", new()
+ {
+ "PHYS",
+ "PHYT",
+ "BDY4",
+ "SHP2",
+ "BOXS",
+ "CAPS",
+ "SPHS",
+ "PLYT",
+ "JOIN",
+ "WLJ3",
+ "SPHJ",
+ "SHJ2",
+ "PRS2",
+ "REV2",
+ "DSTJ",
+ "SHOJ",
+ "PHYV",
+ }
+ },
+ }
},
{
"tex", new ()
diff --git a/Warcraft.NET.Docs/Program.cs b/Warcraft.NET.Docs/Program.cs
index ce9d6ff..b4dde70 100644
--- a/Warcraft.NET.Docs/Program.cs
+++ b/Warcraft.NET.Docs/Program.cs
@@ -1,4 +1,5 @@
using Warcraft.NET.Docs.Steps;
+using Warcraft.NET.Files.Skel;
namespace Warcraft.NET.Docs
{
diff --git a/Warcraft.NET/Extensions/ExtendedIO.cs b/Warcraft.NET/Extensions/ExtendedIO.cs
index 296f792..4cd1c0a 100644
--- a/Warcraft.NET/Extensions/ExtendedIO.cs
+++ b/Warcraft.NET/Extensions/ExtendedIO.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
using Warcraft.NET.Exceptions;
using Warcraft.NET.Files.Interfaces;
@@ -78,6 +79,22 @@ public static Vector3 ReadVector3(this BinaryReader binaryReader, AxisConfigurat
}
}
+ ///
+ /// Reads a 48-byte structure from the data stream and advances the position of the stream by
+ /// 48 bytes.
+ ///
+ /// The Mat3x4.
+ /// The reader.
+ /// Which axis configuration the read mat3x4 should be converted to.
+ public static Matrix3x4 ReadMatrix3x4(this BinaryReader binaryReader, AxisConfiguration convertTo = AxisConfiguration.YUp)
+ {
+ var a = binaryReader.ReadVector3(convertTo);
+ var b = binaryReader.ReadVector3(convertTo);
+ var c = binaryReader.ReadVector3(convertTo);
+ var pos = binaryReader.ReadVector3(convertTo);
+ return new Matrix3x4(a, b, c, pos);
+ }
+
///
/// Reads a 12-byte from the data stream and advances the position of the stream by
/// 12 bytes.
@@ -283,37 +300,37 @@ public static ShortVector3 ReadShortVector3(this BinaryReader binaryReader, Axis
switch (convertTo)
{
case AxisConfiguration.Native:
- {
- return new ShortVector3(binaryReader.ReadInt16(), binaryReader.ReadInt16(), binaryReader.ReadInt16());
- }
+ {
+ return new ShortVector3(binaryReader.ReadInt16(), binaryReader.ReadInt16(), binaryReader.ReadInt16());
+ }
case AxisConfiguration.YUp:
- {
- var x1 = binaryReader.ReadInt16();
- var y1 = binaryReader.ReadInt16();
- var z1 = binaryReader.ReadInt16();
+ {
+ var x1 = binaryReader.ReadInt16();
+ var y1 = binaryReader.ReadInt16();
+ var z1 = binaryReader.ReadInt16();
- var x = x1;
- var y = z1;
- var z = (short)-y1;
+ var x = x1;
+ var y = z1;
+ var z = (short)-y1;
- return new ShortVector3(x, y, z);
- }
+ return new ShortVector3(x, y, z);
+ }
case AxisConfiguration.ZUp:
- {
- var x1 = binaryReader.ReadInt16();
- var y1 = binaryReader.ReadInt16();
- var z1 = binaryReader.ReadInt16();
+ {
+ var x1 = binaryReader.ReadInt16();
+ var y1 = binaryReader.ReadInt16();
+ var z1 = binaryReader.ReadInt16();
- var x = x1;
- var y = (short)-z1;
- var z = y1;
+ var x = x1;
+ var y = (short)-z1;
+ var z = y1;
- return new ShortVector3(x, y, z);
- }
+ return new ShortVector3(x, y, z);
+ }
default:
- {
- throw new ArgumentOutOfRangeException(nameof(convertTo), convertTo, null);
- }
+ {
+ throw new ArgumentOutOfRangeException(nameof(convertTo), convertTo, null);
+ }
}
}
@@ -432,6 +449,32 @@ public static void WriteChunkSignature(this BinaryWriter binaryWriter, string si
}
}
+ ///
+ /// Writes a struct to the BinaryWriter.
+ ///
+ /// The type of struct to write.
+ /// The BinaryWriter instance.
+ /// The struct value to write.
+ public static void WriteStruct(this BinaryWriter binaryWriter, T value) where T : struct
+ {
+ int size = Marshal.SizeOf();
+ byte[] bytes = new byte[size];
+
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(value, ptr, true);
+ Marshal.Copy(ptr, bytes, 0, size);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ // Write the padded bytes
+ binaryWriter.Write(bytes);
+ }
+
///
/// Writes a 12-byte value to the data stream in Pitch/Yaw/Roll order.
///
@@ -560,6 +603,25 @@ public static void WriteVector3(this BinaryWriter binaryWriter, Vector3 vector,
}
}
+ ///
+ /// Writes a 48-byte value to the data stream. This function
+ ///
+ /// The current object.
+ /// The Vector to write.
+ /// Which axis configuration the read vector should be stored as.
+ public static void WriteMatrix3x4(this BinaryWriter binaryWriter, Matrix3x4 matrix, AxisConfiguration storeAs = AxisConfiguration.ZUp)
+ {
+ var column1 = matrix.RotationX * matrix.Scale.X;
+ var column2 = matrix.RotationY * matrix.Scale.Y;
+ var column3 = matrix.RotationZ * matrix.Scale.Z;
+ var column4 = matrix.Position;
+
+ binaryWriter.WriteVector3(column1, storeAs);
+ binaryWriter.WriteVector3(column2, storeAs);
+ binaryWriter.WriteVector3(column3, storeAs);
+ binaryWriter.WriteVector3(column4, storeAs);
+ }
+
///
/// Writes a 16-byte to the data stream.
///
@@ -597,23 +659,23 @@ public static void WriteShortVector3(this BinaryWriter binaryWriter, ShortVector
{
case AxisConfiguration.Native:
case AxisConfiguration.YUp:
- {
- binaryWriter.Write(vector.X);
- binaryWriter.Write(vector.Y);
- binaryWriter.Write(vector.Z);
- break;
- }
+ {
+ binaryWriter.Write(vector.X);
+ binaryWriter.Write(vector.Y);
+ binaryWriter.Write(vector.Z);
+ break;
+ }
case AxisConfiguration.ZUp:
- {
- binaryWriter.Write(vector.X);
- binaryWriter.Write((short)(vector.Z * -1));
- binaryWriter.Write(vector.Y);
- break;
- }
+ {
+ binaryWriter.Write(vector.X);
+ binaryWriter.Write((short)(vector.Z * -1));
+ binaryWriter.Write(vector.Y);
+ break;
+ }
default:
- {
- throw new ArgumentOutOfRangeException(nameof(storeAs), storeAs, null);
- }
+ {
+ throw new ArgumentOutOfRangeException(nameof(storeAs), storeAs, null);
+ }
}
}
diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs b/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs
new file mode 100644
index 0000000..44a7e33
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/BfA/LDV1.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.BfA
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)]
+ public class LDV1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "LDV1";
+
+ ///
+ /// Gets or sets the Lod Data Version 1 Entries
+ ///
+ public List LDV1Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public LDV1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public LDV1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var LDV1count = br.BaseStream.Length / LDV1Entry.GetSize();
+ for (var i = 0; i < LDV1count; ++i)
+ {
+ LDV1Entries.Add(new LDV1Entry(br.ReadBytes(LDV1Entry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (LDV1Entry obj in LDV1Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs b/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs
index 37daeb6..4f06227 100644
--- a/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/BfA/TXID.cs
@@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0)
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs b/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs
new file mode 100644
index 0000000..ee2e459
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/BfA/WFV1.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.BfA
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)]
+ public class WFV1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "WFV1";
+
+ ///
+ /// Gets or sets the full data (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public WFV1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public WFV1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs b/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs
new file mode 100644
index 0000000..3eacdc2
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/BfA/WFV2.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.BfA
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterLegion, AutoDocChunkVersionHelper.VersionBeforeBfA)]
+ public class WFV2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "WFV2";
+
+ ///
+ /// Gets or sets the full data (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public WFV2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public WFV2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs b/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs
new file mode 100644
index 0000000..3225f66
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/DF/AFRA.cs
@@ -0,0 +1,49 @@
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.DF
+{
+ public class AFRA : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "AFRA";
+
+ ///
+ /// Gets or sets the full data (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public AFRA() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public AFRA(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize()
+ {
+ return (uint)Serialize().Length;
+ }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs
index 91d0185..5be18b2 100644
--- a/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/AFID.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.IO;
using Warcraft.NET.Attribute;
using Warcraft.NET.Files.Interfaces;
@@ -43,7 +44,6 @@ public void LoadBinaryData(byte[] inData)
using (var br = new BinaryReader(ms))
{
var animCount = br.BaseStream.Length / AFIDEntry.GetSize();
-
for (var i = 0; i < animCount; ++i)
{
AFIDEntries.Add(new AFIDEntry(br.ReadBytes(AFIDEntry.GetSize())));
@@ -61,9 +61,8 @@ public byte[] Serialize(long offset = 0)
{
bw.Write(obj.Serialize());
}
-
return ms.ToArray();
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs
index 26b13ca..888cdc6 100644
--- a/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/BFID.cs
@@ -42,7 +42,6 @@ public void LoadBinaryData(byte[] inData)
using (var br = new BinaryReader(ms))
{
uint nBone = (uint)inData.Length / 4;
-
for (var i = 0; i < nBone; i++)
BoneFileDataIds.Add(br.ReadUInt32());
}
@@ -56,9 +55,8 @@ public byte[] Serialize(long offset = 0)
{
foreach(uint boneFileDataId in BoneFileDataIds)
bw.Write(boneFileDataId);
-
return ms.ToArray();
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs b/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs
new file mode 100644
index 0000000..155bdbc
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/EXP2.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ public class EXP2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "EXP2";
+
+ ///
+ /// Gets or sets the EXP2 Data
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public EXP2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public EXP2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs b/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs
new file mode 100644
index 0000000..52fbf28
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/EXPT.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)]
+ public class EXPT : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "EXPT";
+
+ ///
+ /// Gets or sets the EXPT Entries
+ ///
+ public List EXP2Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public EXPT() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public EXPT(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var exp2count = br.BaseStream.Length / EXPTEntry.GetSize();
+ for (var i = 0; i < exp2count; ++i)
+ {
+ EXP2Entries.Add(new EXPTEntry(br.ReadBytes(EXPTEntry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (EXPTEntry obj in EXP2Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs
new file mode 100644
index 0000000..d010543
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PABC.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)]
+ public class PABC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PABC";
+
+ ///
+ /// Gets or sets the ParentSequenceBounds Entries
+ ///
+ public List PABCEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PABC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PABC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var PABCcount = br.BaseStream.Length / 2;
+ for (var i = 0; i < PABCcount; ++i)
+ {
+ PABCEntries.Add(br.ReadUInt16());
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (ushort obj in PABCEntries)
+ {
+ bw.Write(obj);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs
new file mode 100644
index 0000000..ec885fb
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PADC.cs
@@ -0,0 +1,46 @@
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ public class PADC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PADC";
+
+ ///
+ /// Gets or sets the ParentAnimationData (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PADC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PADC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs
new file mode 100644
index 0000000..3881430
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PEDC.cs
@@ -0,0 +1,48 @@
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)]
+ public class PEDC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PEDC";
+
+ ///
+ /// Gets or sets the ParentEventData (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PEDC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PEDC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Data = inData;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs
index f92f272..729142a 100644
--- a/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PFID.cs
@@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0)
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs
new file mode 100644
index 0000000..dba0ea2
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PGD1.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)]
+ public class PGD1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PGD1";
+
+ ///
+ /// Gets or sets the ParticleGeosetData1 Entries
+ ///
+ public List PGD1Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PGD1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PGD1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var PGD1count = br.BaseStream.Length / 2;
+ for (var i = 0; i < PGD1count; ++i)
+ {
+ PGD1Entries.Add(br.ReadUInt16());
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (UInt16 obj in PGD1Entries)
+ {
+ bw.Write(obj);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs
new file mode 100644
index 0000000..570981b
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/PSBC.cs
@@ -0,0 +1,51 @@
+using System.IO;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ public class PSBC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PSBC";
+
+ ///
+ /// Gets or sets the ParentSequenceBounds (deserialization NYI)
+ ///
+ public byte[] Data;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PSBC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PSBC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ Data = inData;
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return Data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs
index bf6b4c3..90ff088 100644
--- a/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/SFID.cs
@@ -61,4 +61,4 @@ public byte[] Serialize(long offset = 0)
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs b/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs
index abcda1d..1908f10 100644
--- a/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/SKID.cs
@@ -51,9 +51,8 @@ public byte[] Serialize(long offset = 0)
using (var bw = new BinaryWriter(ms))
{
bw.Write(SkeletonFileDataId);
-
return ms.ToArray();
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs b/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs
new file mode 100644
index 0000000..3ffe3d4
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/Legion/TXAC.cs
@@ -0,0 +1,71 @@
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using System.Collections.Generic;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterWoD, AutoDocChunkVersionHelper.VersionBeforeLegion)]
+ public class TXAC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "TXAC";
+
+ ///
+ /// 2 byte array
+ /// From Wiki:
+ /// likely used in CM2SceneRender::SetupTextureTransforms and uploaded to the shader directly. 0 otherwise.
+ /// This chunk doesn't seem to be used directly. Inside CParticleEmitter2 class there are non-null checks that deal with selection of VertexBufferFormat for particles. Apart from that, the usage of these fields is unknown
+ ///
+ public List TXACEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public TXAC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public TXAC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ for (int i = 0; i < inData.Length / 2; i++)
+ {
+ var entry = new byte[2];
+ entry[0] = br.ReadByte();
+ entry[1] = br.ReadByte();
+ TXACEntries.Add(entry);
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (var entry in TXACEntries)
+ {
+ bw.Write(entry);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs b/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs
new file mode 100644
index 0000000..912a6e0
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/DBOC.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class DBOC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "DBOC";
+
+ ///
+ /// Gets or sets the DBOC Entries
+ ///
+ public List DBOCEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public DBOC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public DBOC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var DBOCcount = br.BaseStream.Length / DBOCEntry.GetSize();
+ for (var i = 0; i < DBOCcount; ++i)
+ {
+ DBOCEntries.Add(new DBOCEntry(br.ReadBytes(DBOCEntry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (DBOCEntry obj in DBOCEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs b/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs
new file mode 100644
index 0000000..6a477a0
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/DETL.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.SL
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class DETL : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "DETL";
+
+ ///
+ /// Gets or sets the DETL Entries
+ ///
+ public List DETLEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public DETL() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public DETL(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var DETLcount = br.BaseStream.Length / DETLEntry.GetSize();
+ for (var i = 0; i < DETLcount; ++i)
+ {
+ DETLEntries.Add(new DETLEntry(br.ReadBytes(DETLEntry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (DETLEntry obj in DETLEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs b/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs
new file mode 100644
index 0000000..23634a1
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/EDGF.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class EDGF : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "EDGF";
+
+ ///
+ /// Gets or sets the EdgeFade Entries
+ ///
+ public List EDGFEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public EDGF() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public EDGF(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var EDGFcount = br.BaseStream.Length / EDGFEntry.GetSize();
+ for (var i = 0; i < EDGFcount; ++i)
+ {
+ EDGFEntries.Add(new EDGFEntry(br.ReadBytes(EDGFEntry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (EDGFEntry obj in EDGFEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs b/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs
new file mode 100644
index 0000000..cdc76a2
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/NERF.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.M2.Chunks.Legion
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class NERF : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "NERF";
+
+ ///
+ /// Gets or sets the NERF Entries
+ ///
+ public List NERFEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public NERF() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public NERF(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var NERFcount = br.BaseStream.Length / 8;
+ for (var i = 0; i < NERFcount; ++i)
+ {
+ NERFEntries.Add(new Vector2(br.ReadSingle(), br.ReadSingle()));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (Vector2 obj in NERFEntries)
+ {
+ bw.Write(obj.X);
+ bw.Write(obj.Y);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs b/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs
new file mode 100644
index 0000000..5c8bb6b
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/PFDC.cs
@@ -0,0 +1,64 @@
+using System;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys;
+
+namespace Warcraft.NET.Files.M2.Chunks.SL
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PFDC : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PFDC";
+
+ ///
+ /// Gets or sets the Physics for the M2
+ ///
+ public Physics Physics { get; set; } = null;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PFDC() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PFDC(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ Physics = new Physics(inData);
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ return PadTo8Bytes(Physics.Serialize());
+ }
+
+ static byte[] PadTo8Bytes(byte[] input)
+ {
+ int paddingNeeded = 8 - (input.Length % 8);
+ if (paddingNeeded == 8)
+ paddingNeeded = 0;
+ byte[] paddedArray = new byte[input.Length + paddingNeeded];
+ Array.Copy(input, paddedArray, input.Length);
+ for (int i = input.Length; i < paddedArray.Length; i++)
+ {
+ paddedArray[i] = 0x00;
+ }
+ return paddedArray;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs b/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs
new file mode 100644
index 0000000..c37dd2a
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Chunks/SL/WFV3.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.M2.Chunks.SL
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class WFV3 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "WFV3";
+
+ ///
+ /// Gets or sets the WaterFallVersion3 Entries
+ ///
+ public List WFV3Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public WFV3() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public WFV3(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var WFV3count = br.BaseStream.Length / WFV3Entry.GetSize();
+ for (var i = 0; i < WFV3count; ++i)
+ {
+ WFV3Entries.Add(new WFV3Entry(br.ReadBytes(WFV3Entry.GetSize())));
+ }
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (WFV3Entry obj in WFV3Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs b/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs
index 45bb227..6c85f43 100644
--- a/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs
+++ b/Warcraft.NET/Files/M2/Entries/AFIDEntry.cs
@@ -9,7 +9,6 @@ public class AFIDEntry
///
public ushort AnimationId { get; set; }
-
///
/// Gets or sets the sub animation id.
///
@@ -20,7 +19,6 @@ public class AFIDEntry
///
public uint FileDataId { get; set; }
-
///
/// Initializes a new instance of the class.
///
@@ -68,4 +66,4 @@ public byte[] Serialize(long offset = 0)
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs b/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs
new file mode 100644
index 0000000..58a8bf5
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/DBOCEntry.cs
@@ -0,0 +1,70 @@
+using System.IO;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class DBOCEntry
+ {
+ ///
+ /// unknown float
+ ///
+ public float Unk0;
+ ///
+ /// unknown float
+ ///
+ public float Unk1;
+ ///
+ /// unknown int
+ ///
+ public uint Unk2;
+ ///
+ /// unknown int
+ ///
+ public uint Unk3;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DBOCEntry(){}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public DBOCEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ Unk0 = br.ReadSingle();
+ Unk1 = br.ReadSingle();
+ Unk2 = br.ReadUInt32();
+ Unk3 = br.ReadUInt32();
+ }
+ }
+
+ ///
+ /// Gets the size of a DBOC Entry
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Unk0);
+ bw.Write(Unk1);
+ bw.Write(Unk2);
+ bw.Write(Unk3);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/DETLEntry.cs b/Warcraft.NET/Files/M2/Entries/DETLEntry.cs
new file mode 100644
index 0000000..da70cdc
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/DETLEntry.cs
@@ -0,0 +1,82 @@
+using System.IO;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class DETLEntry
+ {
+ ///
+ /// unknown Flags
+ ///
+ public ushort Flags;
+
+ ///
+ /// multiplier for M2Light.diffuse_color
+ ///
+ public ushort PackedFloat0;
+
+ ///
+ /// multiplier for M2Light.diffuse_color
+ ///
+ public ushort PackedFloat1;
+
+ ///
+ /// unknown field
+ ///
+ public ushort Unk0;
+
+ ///
+ /// unknown field
+ ///
+ public uint Unk1;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DETLEntry()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public DETLEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ Flags = br.ReadUInt16();
+ PackedFloat0 = br.ReadUInt16();
+ PackedFloat1 = br.ReadUInt16();
+ Unk0 = br.ReadUInt16();
+ Unk1 = br.ReadUInt32();
+ }
+ }
+
+ ///
+ /// Gets the size of a AFRA Entry
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 12;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Flags);
+ bw.Write(PackedFloat0);
+ bw.Write(PackedFloat1);
+ bw.Write(Unk0);
+ bw.Write(Unk1);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs b/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs
new file mode 100644
index 0000000..346c50f
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/EDGFEntry.cs
@@ -0,0 +1,71 @@
+using System.IO;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class EDGFEntry
+ {
+ ///
+ /// unknown 2-floats array
+ ///
+ public float[] Unk0;
+
+ ///
+ /// unknown float
+ ///
+ public float Unk1;
+
+ ///
+ /// unknown 4 byte array
+ ///
+ public byte[] Unk2;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public EDGFEntry()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public EDGFEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ Unk0 = new float[2];
+ Unk0[0] = br.ReadSingle();
+ Unk0[1] = br.ReadSingle();
+ Unk1 = br.ReadSingle();
+ Unk2 = br.ReadBytes(4);
+ }
+ }
+
+ ///
+ /// Gets the size of a EDGF Entry
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Unk0[0]);
+ bw.Write(Unk0[1]);
+ bw.Write(Unk1);
+ bw.Write(Unk2);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs b/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs
new file mode 100644
index 0000000..ece3be3
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/EXPTEntry.cs
@@ -0,0 +1,64 @@
+using System.IO;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class EXPTEntry
+ {
+ ///
+ /// replaces zSource from ParticleEmitter
+ ///
+ public float ZSource;
+ ///
+ /// colorMult is applied against particle's diffuse color
+ ///
+ public float ColorMult;
+ ///
+ ///alphaMult is applied against particle's opacity.
+ ///
+ public float AlphaMult;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public EXPTEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public EXPTEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ ZSource = br.ReadSingle();
+ ColorMult = br.ReadSingle();
+ AlphaMult = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a animation file id entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 12;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(ZSource);
+ bw.Write(ColorMult);
+ bw.Write(AlphaMult);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs b/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs
new file mode 100644
index 0000000..007466f
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/LDV1Entry.cs
@@ -0,0 +1,80 @@
+using System.IO;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class LDV1Entry
+ {
+ ///
+ /// unknown field
+ ///
+ public ushort Unk0;
+
+ ///
+ /// the maximum lod count
+ ///
+ public ushort LodCount;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk1;
+
+ ///
+ /// lod serves as indes into this array
+ ///
+ public byte[] ParticleBoneLod;
+
+ ///
+ /// unknown field
+ ///
+ public uint Unk2;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public LDV1Entry()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public LDV1Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ Unk0 = br.ReadUInt16();
+ LodCount = br.ReadUInt16();
+ Unk1 = br.ReadSingle();
+ ParticleBoneLod = br.ReadBytes(4);
+ Unk2 = br.ReadUInt32();
+ }
+ }
+
+ ///
+ /// Gets the size of a LDV1 Entry
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Unk0);
+ bw.Write(LodCount);
+ bw.Write(Unk1);
+ bw.Write(ParticleBoneLod);
+ bw.Write(Unk2);
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs b/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs
new file mode 100644
index 0000000..12d0463
--- /dev/null
+++ b/Warcraft.NET/Files/M2/Entries/WFV3Entry.cs
@@ -0,0 +1,196 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.M2.Entries
+{
+ public class WFV3Entry
+ {
+ ///
+ /// BumpScale -> Passed to vertex shader
+ ///
+ public float BumpScale;
+
+ ///
+ /// value 0 x
+ ///
+ public float Value0X;
+
+ ///
+ /// value 0 y
+ ///
+ public float Value0Y;
+
+ ///
+ /// value 0 z
+ ///
+ public float Value0Z;
+
+ ///
+ /// value 1 W
+ ///
+ public float Value1W;
+
+ ///
+ /// value 0 W
+ ///
+ public float Value0W;
+
+ ///
+ /// value 1 x
+ ///
+ public float Value1X;
+
+ ///
+ /// value 1 y
+ ///
+ public float Value1Y;
+
+ ///
+ /// value 2 w
+ ///
+ public float Value2W;
+
+ ///
+ /// value 3 y
+ ///
+ public float Value3Y;
+
+ ///
+ /// value 3 x
+ ///
+ public float Value3X;
+
+ ///
+ /// BaseColor in rgba (not bgra)
+ ///
+ public RGBA BaseColor;
+
+ ///
+ /// unknown Flags
+ ///
+ public ushort Flags;
+
+ ///
+ /// unknown field
+ ///
+ public ushort Unk0;
+
+ ///
+ /// value 3 W
+ ///
+ public float Value3W;
+
+ ///
+ /// value 3 Z
+ ///
+ public float Value3Z;
+
+ ///
+ /// value 4 y
+ ///
+ public float Value4Y;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk1;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk2;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk3;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk4;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WFV3Entry()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public WFV3Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ BumpScale = br.ReadSingle();
+ Value0X = br.ReadSingle();
+ Value0Y = br.ReadSingle();
+ Value0Z = br.ReadSingle();
+ Value1W = br.ReadSingle();
+ Value0W = br.ReadSingle();
+ Value1X = br.ReadSingle();
+ Value1Y = br.ReadSingle();
+ Value2W = br.ReadSingle();
+ Value3Y = br.ReadSingle();
+ Value3X = br.ReadSingle();
+ BaseColor = br.ReadRGBA();
+ Flags = br.ReadUInt16();
+ Unk0 = br.ReadUInt16();
+ Value3W = br.ReadSingle();
+ Value3Z = br.ReadSingle();
+ Value4Y = br.ReadSingle();
+ Unk1 = br.ReadSingle();
+ Unk2 = br.ReadSingle();
+ Unk3 = br.ReadSingle();
+ Unk4 = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a WFV3 Entry
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 80;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(BumpScale);
+ bw.Write(Value0X);
+ bw.Write(Value0Y);
+ bw.Write(Value0Z);
+ bw.Write(Value1W);
+ bw.Write(Value0W);
+ bw.Write(Value1X);
+ bw.Write(Value1Y);
+ bw.Write(Value2W);
+ bw.Write(Value3Y);
+ bw.Write(Value3X);
+ bw.WriteRGBA(BaseColor);
+ bw.Write(Flags);
+ bw.Write(Unk0);
+ bw.Write(Value3W);
+ bw.Write(Value3Z);
+ bw.Write(Value4Y);
+ bw.Write(Unk1);
+ bw.Write(Unk2);
+ bw.Write(Unk3);
+ bw.Write(Unk4);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/M2/Model.cs b/Warcraft.NET/Files/M2/Model.cs
index 9c251bf..e92e642 100644
--- a/Warcraft.NET/Files/M2/Model.cs
+++ b/Warcraft.NET/Files/M2/Model.cs
@@ -1,7 +1,9 @@
using Warcraft.NET.Attribute;
using Warcraft.NET.Files.M2.Chunks;
using Warcraft.NET.Files.M2.Chunks.BfA;
+using Warcraft.NET.Files.M2.Chunks.DF;
using Warcraft.NET.Files.M2.Chunks.Legion;
+using Warcraft.NET.Files.M2.Chunks.SL;
namespace Warcraft.NET.Files.M2
{
@@ -15,53 +17,161 @@ public class Model : ChunkedFile
public MD21 ModelInformation { get; set; }
///
- /// Gets or sets the model phys file ids
+ /// Gets or sets the CParticleEmitter2 data
///
- [ChunkOrder(2), ChunkOptional]
- public PFID PhysFileIds { get; set; }
+ [ChunkOrder(2),ChunkOptional]
+ public TXAC CParticleEmitter2 { get; set; }
///
- /// Gets or sets the model skin file ids
+ /// Gets or sets the ParentEventData
///
- [ChunkOrder(3), ChunkOptional]
- public SFID SkinFileIds { get; set; }
+ [ChunkOrder(3),ChunkOptional]
+ public PEDC M2InitParentEventData { get; set; }
///
- /// Gets or sets the model anim file ids
+ /// Gets or sets the ExtendedParticle
///
[ChunkOrder(4), ChunkOptional]
+ public EXPT ExtendedParticle { get; set; }
+
+ ///
+ /// Gets or sets the ExtendedParticle2
+ ///
+ [ChunkOrder(5),ChunkOptional]
+ public EXP2 ExtendedParticle2 { get; set; }
+
+ ///
+ /// Gets or sets the ParticleGeosetData
+ ///
+ [ChunkOrder(6),ChunkOptional]
+ public PGD1 ParticleGeosetData { get; set; }
+
+ ///
+ /// Gets or sets the model anim file ids
+ ///
+ [ChunkOrder(7), ChunkOptional]
public AFID AnimFileIds { get; set; }
///
/// Gets or sets the model bone file ids
///
- [ChunkOrder(5), ChunkOptional]
+ [ChunkOrder(8), ChunkOptional]
public BFID BoneFileIds { get; set; }
///
- /// Gets or sets the model recursive particle file ids
+ /// Gets or sets the BlacklistAnimData
///
- [ChunkOrder(6), ChunkOptional]
- public RPID RecursiveParticleFileIds { get; set; }
+ [ChunkOrder(9), ChunkOptional]
+ public PABC M2InitBlacklistAnimData { get; set; }
///
- /// Gets or sets the model geometry particle file ids
+ /// Gets or sets the LodDataVersion1
///
- [ChunkOrder(7), ChunkOptional]
- public GPID GeometryParticleFileIds { get; set; }
+ [ChunkOrder(10), ChunkOptional]
+ public LDV1 LodDataVersion1 { get; set; }
+
+ ///
+ /// Gets or sets the EdgeFade
+ ///
+ [ChunkOrder(11), ChunkOptional]
+ public EDGF EdgeFade { get; set; }
+
+ ///
+ /// Gets or sets the Physics of the M2
+ ///
+ [ChunkOrder(12),ChunkOptional]
+ public PFDC ModelPhysics { get; set; }
///
/// Gets or sets the model skeleton file ids
///
- [ChunkOrder(8), ChunkOptional]
+ [ChunkOrder(13), ChunkOptional]
public SKID SkeletonFileIds { get; set; }
+ ///
+ /// Gets or sets the WaterFallVersion1
+ ///
+ [ChunkOrder(14),ChunkOptional]
+ public WFV1 WaterFallVersion1 { get; set; }
+
+ ///
+ /// Gets or sets the WaterFallVersion2
+ ///
+ [ChunkOrder(15),ChunkOptional]
+ public WFV2 WaterFallVersion2 { get; set; }
+
+ ///
+ /// Gets or sets the WaterFallVersion3
+ ///
+ [ChunkOrder(16),ChunkOptional]
+ public WFV3 WaterFallVersion3 { get; set; }
+
+ ///
+ /// Gets or sets the DBOC
+ ///
+ [ChunkOrder(17), ChunkOptional]
+ public DBOC DBOC { get; set; }
+
+ ///
+ /// Gets or sets the model skin file ids
+ ///
+ [ChunkOrder(18), ChunkOptional]
+ public SFID SkinFileIds { get; set; }
+
+ ///
+ /// Gets or sets the model phys file ids
+ ///
+ [ChunkOrder(19), ChunkOptional]
+ public PFID PhysFileIds { get; set; }
+
///
/// Gets or sets the model texture file ids
///
- [ChunkOrder(9), ChunkOptional]
+ [ChunkOrder(20), ChunkOptional]
public TXID TextureFileIds { get; set; }
+ ///
+ /// Gets or sets the ParentSequenceBoundsData
+ ///
+ [ChunkOrder(21),ChunkOptional]
+ public PSBC M2InitParentSequenceBoundsData { get; set; }
+
+ ///
+ /// Gets or sets the model recursive particle file ids
+ ///
+ [ChunkOrder(22), ChunkOptional]
+ public RPID RecursiveParticleFileIds { get; set; }
+
+ ///
+ /// Gets or sets the model geometry particle file ids
+ ///
+ [ChunkOrder(23), ChunkOptional]
+ public GPID GeometryParticleFileIds { get; set; }
+
+ ///
+ /// Gets or sets the ParentAnimData
+ ///
+ [ChunkOrder(24),ChunkOptional]
+ public PADC M2InitParentAnimData { get; set; }
+
+ ///
+ /// Gets or sets the NERF
+ ///
+ [ChunkOrder(25),ChunkOptional]
+ public NERF NERF { get; set; }
+
+ ///
+ /// Gets or sets the DETL (light related)
+ ///
+ [ChunkOrder(26),ChunkOptional]
+ public DETL DETL { get; set; }
+
+ ///
+ /// Gets or sets the AFRA
+ ///
+ [ChunkOrder(27),ChunkOptional]
+ public AFRA AFRA { get; set; }
+
///
/// Initializes a new instance of the class.
///
diff --git a/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs b/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs
new file mode 100644
index 0000000..51ceec7
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Entries/SPHSEntry.cs
@@ -0,0 +1,52 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SPHSEntry
+ {
+ ///
+ /// Gets or Sets the local position of the Sphere shape
+ ///
+ public Vector3 LocalPosition;
+
+ ///
+ /// Gets or Sets the radius of the Sphere shape
+ ///
+ public float Radius;
+
+ public SPHSEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ LocalPosition = br.ReadVector3();
+ Radius = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a Sphere entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteVector3(LocalPosition);
+ bw.Write(Radius);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/Phys/Enums/BodyType.cs b/Warcraft.NET/Files/Phys/Enums/BodyType.cs
new file mode 100644
index 0000000..070e59b
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Enums/BodyType.cs
@@ -0,0 +1,9 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum BodyType : ushort
+ {
+ Root = 0,
+ Dynamic = 1,
+ Unk = 2,
+ }
+}
diff --git a/Warcraft.NET/Files/Phys/Enums/JointType.cs b/Warcraft.NET/Files/Phys/Enums/JointType.cs
new file mode 100644
index 0000000..0ea6327
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Enums/JointType.cs
@@ -0,0 +1,12 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum JointType : ushort
+ {
+ SphericalJoint = 0,
+ ShoulderJoint = 1,
+ WeldJoint = 2,
+ RevoluteJoint = 3,
+ PrismaticJoint = 4,
+ DistanceJoint = 5,
+ }
+}
diff --git a/Warcraft.NET/Files/Phys/Enums/ShapeType.cs b/Warcraft.NET/Files/Phys/Enums/ShapeType.cs
new file mode 100644
index 0000000..1f599e5
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Enums/ShapeType.cs
@@ -0,0 +1,10 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum ShapeType : short
+ {
+ Box = 0,
+ Caps = 1,
+ Sphere = 2,
+ Polytope = 3,
+ }
+}
diff --git a/Warcraft.NET/Files/Phys/Structures/PlytData.cs b/Warcraft.NET/Files/Phys/Structures/PlytData.cs
new file mode 100644
index 0000000..65ddf95
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Structures/PlytData.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Numerics;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+ [Serializable]
+ public struct PlytData
+ {
+ ///
+ /// gets or sets the vertices. Amount is defined by header.VertexCount
+ ///
+ public Vector3[] Vertices; //amount = VertexCount in Header
+
+ ///
+ /// gets or sets the Unk1 array. Unknown purpose. Amount is defined by header.Count10
+ ///
+ public byte[] Unk1; //multiple of 16 -> amount = count_10 in Header
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.Count10
+ ///
+ public byte[] Unk2; //amount = count_10 in Header
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.NodeCount
+ ///
+ public PlytNode[] Nodes;
+ }
+}
diff --git a/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs b/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs
new file mode 100644
index 0000000..c6b871a
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Structures/PlytHeader.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+ public struct PlytHeader
+ {
+ ///
+ /// gets or sets the amount of vertices for this polytope
+ ///
+ public uint VertexCount;
+
+ ///
+ /// gets or sets unknown data
+ ///
+ public byte[] Unk0;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME08ptrData0;
+
+ ///
+ /// gets or sets the count10, which defines how many Unk1[] and Unk2[] there are inside the Data.
+ ///
+ public uint Count10;
+
+ ///
+ /// gets or sets the Unk1 array. Unknown purpose
+ ///
+ public byte[] Unk1;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME18ptrData1;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME20ptrData2;
+
+ ///
+ /// gets or sets the amount of nodes. Defines how Vertices are connected
+ ///
+ public uint NodeCount;
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose
+ ///
+ public byte[] Unk2;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME30ptrData3;
+
+ ///
+ /// gets or sets the Unk3 array. Unknown purpose
+ ///
+ public float[] Unk3;
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/Phys/Structures/PlytNode.cs b/Warcraft.NET/Files/Phys/Structures/PlytNode.cs
new file mode 100644
index 0000000..c727e69
--- /dev/null
+++ b/Warcraft.NET/Files/Phys/Structures/PlytNode.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+
+ [Serializable]
+ public struct PlytNode
+ {
+ ///
+ /// Unknown byte. Always 1 or -1
+ ///
+ public byte Unk; // 1 or -1
+
+ ///
+ /// Index into the data.Vertices
+ ///
+ public byte VertexIndex; // index in vertex list
+
+ ///
+ /// Index into data.Nodes
+ ///
+ public byte UnkIndex0; // index into the nodes
+
+ ///
+ /// Index into data.Nodes
+ ///
+ public byte UnkIndex1; // index into the nodes
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/SKIN/Skin.cs b/Warcraft.NET/Files/SKIN/Skin.cs
new file mode 100644
index 0000000..10e4511
--- /dev/null
+++ b/Warcraft.NET/Files/SKIN/Skin.cs
@@ -0,0 +1,179 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.Skin
+{
+ [AutoDocFile("skin")]
+ public class Skin
+ {
+ ///
+ /// The list of Vertices used for this skin
+ /// indexed into M2s vertex list with offset 'GlobalVertexOffset'
+ ///
+ public List Vertices { get; set; }
+
+ ///
+ /// the triangles used for this skin (Right Handed)
+ /// indexed into the local list of vertices
+ ///
+ public List Triangles { get; set; }
+
+ ///
+ /// the bones used for this skin.
+ /// indexed into the bone lookup table of the m2
+ ///
+ public List BoneIndices { get; set; }
+
+ ///
+ /// the submeshes used for this skin
+ ///
+ public List Submeshes { get; set; }
+
+ ///
+ /// the texture units used for this skin.
+ ///
+ public List TextureUnits { get; set; }
+
+ ///
+ /// start offset into M2.Vertices -> something else in wotlk
+ ///
+ public uint GlobalVertexOffset;
+
+ ///
+ /// the shadowbatches used in this skin
+ ///
+ public List ShadowBatches;
+
+ ///
+ /// unknown field. Maybe padding?
+ ///
+ public byte[] Unk0;
+
+ public Skin(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var magic = br.ReadUInt32();
+ var nVertices = br.ReadUInt32();
+ var ofsVertices = br.ReadUInt32();
+ var nIndices = br.ReadUInt32();
+ var ofsIndices = br.ReadUInt32();
+ var nBones = br.ReadUInt32();
+ var ofsBones = br.ReadUInt32();
+ var nSubmeshes = br.ReadUInt32();
+ var ofsSubmeshes = br.ReadUInt32();
+ var nBatches = br.ReadUInt32();
+ var ofsBatches = br.ReadUInt32();
+ GlobalVertexOffset = br.ReadUInt32();
+
+ ShadowBatches = new List();
+ Unk0 = new byte[8];
+ var nShadow_batches = br.ReadUInt32();
+ var ofsShadow_batches = br.ReadUInt32();
+ Unk0 = br.ReadBytes(8);
+ ShadowBatches = ReadStructList(nShadow_batches, ofsShadow_batches, br);
+ Vertices = ReadStructList(nVertices, ofsVertices, br);
+ Triangles = ReadStructList(nIndices / 3, ofsIndices, br);
+ BoneIndices = ReadStructList(nBones, ofsBones, br);
+ Submeshes = ReadStructList(nSubmeshes, ofsSubmeshes, br);
+ TextureUnits = ReadStructList(nBatches, ofsBatches, br);
+
+ }
+ }
+ private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct
+ {
+ br.BaseStream.Position = offset;
+ List list = new List();
+
+ for (var i = 0; i < count; i++)
+ list.Add(br.ReadStruct());
+
+ return list;
+ }
+
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(new byte[64]);
+ foreach (ushort vertex in Vertices)
+ {
+ bw.Write(vertex);
+ }
+
+ int _ofsTriangles = (int)bw.BaseStream.Position;
+ foreach (M2Triangle triangle in Triangles)
+ {
+ bw.WriteStruct(triangle);
+ }
+
+ int _ofsBones = (int)bw.BaseStream.Position;
+ foreach (M2SkinBoneStruct bone in BoneIndices)
+ {
+ bw.WriteStruct(bone);
+ }
+
+ int _ofsSubmeshes = (int)bw.BaseStream.Position;
+ foreach (M2SkinSection submesh in Submeshes)
+ {
+ bw.WriteStruct(submesh);
+ }
+
+ int _ofsTexUnits = (int)bw.BaseStream.Position;
+ foreach (M2Batch texUnit in TextureUnits)
+ {
+ bw.WriteStruct(texUnit);
+ }
+
+ int _ofsShadowBatches = (int)bw.BaseStream.Position;
+ foreach (M2ShadowBatch shadowBatch in ShadowBatches)
+ {
+ bw.WriteStruct(shadowBatch);
+ }
+ //Writing actual header data
+ bw.BaseStream.Position = 0;
+ bw.Write('S');
+ bw.Write('K');
+ bw.Write('I');
+ bw.Write('N');
+
+ bw.Write(Vertices.Count);
+ var _ofsVertices = 64;
+ _ofsVertices = 48;
+ bw.Write(_ofsVertices);
+
+ bw.Write(Triangles.Count * 3);
+ bw.Write(_ofsTriangles);
+
+ bw.Write(BoneIndices.Count);
+ bw.Write(_ofsBones);
+
+ bw.Write(Submeshes.Count);
+ bw.Write(_ofsSubmeshes);
+
+ bw.Write(TextureUnits.Count);
+ bw.Write(_ofsTexUnits);
+
+ bw.Write(GlobalVertexOffset);
+
+ bw.Write(ShadowBatches.Count);
+ bw.Write(_ofsShadowBatches);
+ bw.Write(Unk0);
+ return ms.ToArray();
+ }
+ }
+
+ ///
+ public uint GetSize()
+ {
+ return (uint)Serialize().Length;
+ }
+ }
+}
+
+
diff --git a/Warcraft.NET/Files/SKIN/SkinStructs.cs b/Warcraft.NET/Files/SKIN/SkinStructs.cs
new file mode 100644
index 0000000..eb386f1
--- /dev/null
+++ b/Warcraft.NET/Files/SKIN/SkinStructs.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.SKIN
+{
+ public struct M2SkinSection
+ {
+ public UInt16 skinSectionId; // Mesh part ID, see below.
+ public UInt16 Level; // (level << 16) is added (|ed) to startTriangle and alike to avoid having to increase those fields to uint32s.
+ public UInt16 vertexStart; // Starting vertex number.
+ public UInt16 vertexCount; // Number of vertices.
+ public UInt16 indexStart; // Starting triangle index (that's 3* the number of triangles drawn so far).
+ public UInt16 indexCount; // Number of triangle indices.
+ public UInt16 boneCount; // Number of elements in the bone lookup table. Max seems to be 256 in Wrath. Shall be ≠ 0.
+ public UInt16 boneComboIndex; // Starting index in the bone lookup table.
+ public UInt16 boneInfluences; // <= 4
+ // from <=BC documentation: Highest number of bones needed at one time in this Submesh --Tinyn (wowdev.org)
+ // In 2.x this is the amount of of bones up the parent-chain affecting the submesh --NaK
+ // Highest number of bones referenced by a vertex of this submesh. 3.3.5a and suspectedly all other client revisions. -- Skarn
+ public UInt16 centerBoneIndex;
+ public C3Vector centerPosition; // Average position of all the vertices in the sub mesh.
+ //≥BC
+ public C3Vector sortCenterPosition; // The center of the box when an axis aligned box is built around the vertices in the submesh.
+ public float sortRadius; // Distance of the vertex farthest from CenterBoundingBox.
+ }
+
+ public struct BoneStruct
+ {
+ public byte b1;
+ public byte b2;
+ public byte b3;
+ public byte b4;
+ }
+
+ public struct M2Batch
+ {
+ public byte flags; // Usually 16 for static textures, and 0 for animated textures. &0x1: materials invert something; &0x2: transform &0x4: projected texture; &0x10: something batch compatible; &0x20: projected texture?; &0x40: possibly don't multiply transparency by texture weight transparency to get final transparency value(?)
+ public sbyte priorityPlane;
+ public UInt16 shader_id; // See below.
+ public UInt16 skinSectionIndex; // A duplicate entry of a submesh from the list above.
+ public UInt16 geosetIndex; // See below. New name: flags2. 0x2 - projected. 0x8 - EDGF chunk in m2 is mandatory and data from is applied to this mesh
+ public UInt16 colorIndex; // A Color out of the Colors-Block or -1 if none.
+ public UInt16 materialIndex; // The renderflags used on this texture-unit.
+ public UInt16 materialLayer; // Capped at 7 (see CM2Scene::BeginDraw)
+ public UInt16 textureCount; // 1 to 4. See below. Also seems to be the number of textures to load, starting at the texture lookup in the next field (0x10).
+ public UInt16 textureComboIndex; // Index into Texture lookup table
+ public UInt16 textureCoordComboIndex; // Index into the texture mapping lookup table.
+ public UInt16 textureWeightComboIndex; // Index into transparency lookup table.
+ public UInt16 textureTransformComboIndex; // Index into uvanimation lookup table.
+ }
+
+ public struct M2ShadowBatch
+ {
+ byte flags; // if auto-generated: M2Batch.flags & 0xFF
+ byte flags2; // if auto-generated: (renderFlag[i].flags & 0x04 ? 0x01 : 0x00)
+ // | (!renderFlag[i].blendingmode ? 0x02 : 0x00)
+ // | (renderFlag[i].flags & 0x80 ? 0x04 : 0x00)
+ // | (renderFlag[i].flags & 0x400 ? 0x06 : 0x00)
+ public UInt16 _unknown1;
+ public UInt16 submesh_id;
+ public UInt16 texture_id; // already looked-up
+ public UInt16 color_id;
+ public UInt16 transparency_id; // already looked-up
+ }
+
+ public struct M2Triangle //Left handed
+ {
+ public ushort V1;
+ public ushort V3;
+ public ushort V2;
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Chunks/SKA1.cs b/Warcraft.NET/Files/Skel/Chunks/SKA1.cs
new file mode 100644
index 0000000..760f8a0
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Chunks/SKA1.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Mail;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.Skel.Chunks
+{
+ public class SKA1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SKA1";
+
+ ///
+ /// Gets or Sets the attachments
+ ///
+ public List Attachments { get; set; }
+ ///
+ /// Gets or Sets the AttachmentLookupTable
+ ///
+ public List AttachLookup { get; set; }
+ ///
+ /// Initializes a new instance of
+ ///
+ public SKA1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SKA1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var nAttachments = br.ReadUInt32();
+ var ofsAttachments = br.ReadUInt32();
+ var nAttachLookup = br.ReadUInt32();
+ var ofsAttachLookup = br.ReadUInt32();
+ Attachments = ReadStructList(nAttachments, ofsAttachments, br);
+ AttachLookup = ReadStructList(nAttachLookup, ofsAttachLookup, br);
+ }
+ Console.WriteLine("Finished SKA1");
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ return null;
+ }
+ }
+
+ private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct
+ {
+ br.BaseStream.Position = offset;
+ List list = new List();
+
+ for (var i = 0; i < count; i++)
+ list.Add(br.ReadStruct());
+
+ return list;
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Chunks/SKB1.cs b/Warcraft.NET/Files/Skel/Chunks/SKB1.cs
new file mode 100644
index 0000000..5d5a963
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Chunks/SKB1.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.Skel.Chunks
+{
+ public class SKB1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SKB1";
+
+ ///
+ /// Gets or Sets the bones
+ ///
+ public List Bones { get; set; }
+
+ ///
+ /// Gets or Sets the KeyBoneLookupTable
+ ///
+ public List KeyBoneLookup { get; set; }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SKB1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SKB1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var nBones = br.ReadUInt32();
+ var ofsBones = br.ReadUInt32();
+ var nKeyboneLookup = br.ReadUInt32();
+ var ofsKeyboneLookup = br.ReadUInt32();
+ Bones = ReadStructList(nBones, ofsBones, br);
+ KeyBoneLookup = ReadStructList(nKeyboneLookup, ofsKeyboneLookup, br);
+ }
+ Console.WriteLine("Finished SKB1");
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ return null;
+ }
+ }
+
+ private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct
+ {
+ br.BaseStream.Position = offset;
+ List list = new List();
+
+ for (var i = 0; i < count; i++)
+ list.Add(br.ReadStruct());
+
+ return list;
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Chunks/SKL1.cs b/Warcraft.NET/Files/Skel/Chunks/SKL1.cs
new file mode 100644
index 0000000..43d6309
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Chunks/SKL1.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Skel.Chunks
+{
+ public class SKL1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SKL1";
+
+ ///
+ /// Gets or Sets the Unk Field (always 256 so far, possibly flags?)
+ ///
+ public uint Unk0;
+
+ ///
+ /// Gets or Sets the KeyBoneLookupTable
+ ///
+ public List Name { get; set; }
+
+ public uint Unk1;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SKL1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SKL1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ Unk0 = br.ReadUInt32();
+ uint count = br.ReadUInt32();
+ uint offset = br.ReadUInt32();
+ if(count>0)
+ Name = ReadStructList(count, offset, br);
+ Unk1 = br.ReadUInt32();
+ }
+ Console.WriteLine("Finished SKL1");
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ return null;
+ }
+ }
+
+ private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct
+ {
+ br.BaseStream.Position = offset;
+ List list = new List();
+
+ for (var i = 0; i < count; i++)
+ list.Add(br.ReadStruct());
+
+ return list;
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Chunks/SKPD.cs b/Warcraft.NET/Files/Skel/Chunks/SKPD.cs
new file mode 100644
index 0000000..2005215
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Chunks/SKPD.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Skel.Chunks
+{
+ public class SKPD : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SKPD";
+
+ ///
+ /// unk
+ ///
+ public uint Unk0;
+
+ ///
+ /// unk
+ ///
+ public uint Unk1;
+
+ ///
+ /// unk
+ ///
+ public uint ParentSkeletonFileID;
+
+ ///
+ /// unk
+ ///
+ public uint Unk2;
+
+ ///
+ /// Gets or Sets the KeyBoneLookupTable
+ ///
+ public List Name { get; set; }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SKPD() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SKPD(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ Unk0 = br.ReadUInt32();
+ Unk1 = br.ReadUInt32();
+ ParentSkeletonFileID = br.ReadUInt32();
+ Unk2 = br.ReadUInt32();
+ }
+ Console.WriteLine("Finished SKPD");
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Chunks/SKS1.cs b/Warcraft.NET/Files/Skel/Chunks/SKS1.cs
new file mode 100644
index 0000000..0982c64
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Chunks/SKS1.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.M2.Entries;
+
+namespace Warcraft.NET.Files.Skel.Chunks
+{
+ public class SKS1 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SKS1";
+
+ ///
+ /// Gets or Sets the global sequences
+ ///
+ public List Sequences { get; set; }
+
+ ///
+ /// Gets or Sets the animations
+ ///
+ public List Animations { get; set; }
+
+ ///
+ /// Gets or Sets the animation lookups
+ ///
+ public List AnimationLookups { get; set; }
+
+ ///
+ /// Gets or Sets the Unknown field (padding?)
+ ///
+ public UInt64 Unk { get; set; }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SKS1() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SKS1(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var nSequences = br.ReadUInt32();
+ var ofsSequences = br.ReadUInt32();
+ var nAnimations = br.ReadUInt32();
+ var ofsAnimations = br.ReadUInt32();
+ var nAnimationLookup = br.ReadUInt32();
+ var ofsAnimationLookup = br.ReadUInt32();
+ Unk = br.ReadUInt64();
+ Sequences = ReadStructList(nSequences, ofsSequences, br);
+ Animations = ReadStructList(nAnimations, ofsAnimations, br);
+ AnimationLookups = ReadStructList(nAnimationLookup, ofsAnimationLookup, br);
+ }
+ Console.WriteLine("Finished SKS1");
+
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ return null;
+ }
+ }
+
+ private List ReadStructList(uint count, uint offset, BinaryReader br) where T : struct
+ {
+ br.BaseStream.Position = offset;
+ List list = new List();
+
+ for (var i = 0; i < count; i++)
+ list.Add(br.ReadStruct());
+
+ return list;
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Skel/Skel.cs b/Warcraft.NET/Files/Skel/Skel.cs
new file mode 100644
index 0000000..0d64f5b
--- /dev/null
+++ b/Warcraft.NET/Files/Skel/Skel.cs
@@ -0,0 +1,75 @@
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Skel.Chunks;
+using Warcraft.NET.Files.M2.Chunks.Legion;
+
+namespace Warcraft.NET.Files.Skel
+{
+ public class Skel : ChunkedFile
+ {
+ ///
+ /// contains the name and unknown data of the skeleton
+ ///
+ [ChunkOrder(1)]
+ public SKL1 Skeleton { get; set; }
+
+ ///
+ /// contains the animations of the skeleton
+ ///
+ [ChunkOptional]
+ public SKS1 Animations { get; set; }
+
+ ///
+ /// contains the attachments of the skeleton
+ ///
+ [ChunkOptional]
+ public SKA1 Attachments { get; set; }
+
+ ///
+ /// contains the bones of the skeleton
+ ///
+ [ChunkOptional]
+ public SKB1 Bones { get; set; }
+
+ ///
+ /// contains the animation file ids of the skeleton
+ ///
+ [ChunkOptional]
+ public AFID AnimationFileIDs { get; set; }
+
+ ///
+ /// contains the animations of the skeleton
+ ///
+ [ChunkOptional]
+ public SKPD ParentSkelFileID { get; set; }
+
+ ///
+ /// contains the bone file ids of the skeleton
+ ///
+ [ChunkOptional]
+ public BFID BoneFileIDs { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Skel()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The binary data.
+ public Skel(byte[] inData) : base(inData)
+ {
+
+ }
+ public override bool IsReverseSignature()
+ {
+ return false;
+ }
+
+ }
+}
+
+
diff --git a/Warcraft.NET/Files/Structures/C3Vector.cs b/Warcraft.NET/Files/Structures/C3Vector.cs
new file mode 100644
index 0000000..5f925ec
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/C3Vector.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Structures
+{
+ ///
+ /// A structure representing a 3D vector of floats.
+ ///
+ public struct C3Vector : IFlattenableData
+ {
+ public float X { get; set; }
+ public float Y { get; set; }
+ public float Z { get; set; }
+
+ public C3Vector(float inX, float inY, float inZ)
+ {
+ X = inX;
+ Y = inY;
+ Z = inZ;
+ }
+
+ public Vector3 asVec3(){
+ return new Vector3(X,Y,Z);
+ }
+
+ public byte[] asBytes(){
+ return BitConverter.GetBytes(X).Concat(BitConverter.GetBytes(Y)).Concat(BitConverter.GetBytes(Z)).ToArray();
+ }
+
+ public C3Vector(byte[] input)
+ {
+ if (input.Length == 12)
+ {
+ X = BitConverter.ToSingle(input,0);
+ Y = BitConverter.ToSingle(input,4);
+ Z = BitConverter.ToSingle(input,8);
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"{X}, {Y}, {Z}";
+ }
+
+ public IReadOnlyCollection Flatten()
+ {
+ return new[] { X, Y, Z };
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/Structures/CImVector.cs b/Warcraft.NET/Files/Structures/CImVector.cs
new file mode 100644
index 0000000..ad01d56
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/CImVector.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Structures
+{
+ public struct CImVector : IFlattenableData
+ {
+ public byte r, g, b, a;
+
+ public CImVector(byte _r, byte _g, byte _b, byte _a)
+ {
+ r = _r;
+ g = _g;
+ b = _b;
+ a = _a;
+ }
+
+ public byte[] toBytes()
+ {
+ byte[] arr = new byte[4] { r, g, b, a };
+ return arr;
+ }
+
+ public CImVector(byte[] input)
+ {
+ if (input.Length == 4)
+ {
+ r = input[0];
+ g = input[1];
+ b = input[2];
+ a = input[3];
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"{r}, {g}, {b}, {a}";
+ }
+
+ public IReadOnlyCollection Flatten()
+ {
+ return new[] { r,g,b,a };
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/M2Batch.cs b/Warcraft.NET/Files/Structures/M2Batch.cs
new file mode 100644
index 0000000..37040e8
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/M2Batch.cs
@@ -0,0 +1,73 @@
+namespace Warcraft.NET.Files.Structures
+{
+ public struct M2Batch
+ {
+ ///
+ /// Texture Flags
+ /// Usually 16 for static textures, and 0 for animated textures. &0x1: materials invert something; &0x2: transform &0x4: projected texture; &0x10: something batch compatible; &0x20: projected texture?; &0x40: possibly don't multiply transparency by texture weight transparency to get final transparency value(?)
+ ///
+ public byte Flags;
+
+ ///
+ /// Priority Plane
+ ///
+ public sbyte PriorityPlane;
+
+ ///
+ /// ShaderID
+ /// negative = direct selection
+ /// positive = selection trough a function. See wiki for more information
+ ///
+ public ushort ShaderId;
+
+ ///
+ /// A duplicate entry of a submesh from the list above.
+ ///
+ public ushort SkinSectionIndex;
+
+ ///
+ /// New name: flags2. 0x2 - projected. 0x8 - EDGF chunk in m2 is mandatory and data from is applied to this mesh
+ ///
+ public ushort GeosetIndex;
+
+ ///
+ /// A Color out of the Colors-Block or -1 if none.
+ ///
+ public ushort ColorIndex;
+
+ ///
+ /// The renderflags used on this texture-unit. Index into M2 Materials
+ ///
+ public ushort MaterialIndex;
+
+ ///
+ /// Capped at 7 (CM2Scene::BeginDraw)
+ ///
+ public ushort MaterialLayer;
+
+ ///
+ /// 1 to 4. See below. Also seems to be the number of textures to load, starting at the texture lookup in the next field (0x10).
+ ///
+ public ushort TextureCount;
+
+ ///
+ /// Index into Texture lookup table
+ ///
+ public ushort TextureComboIndex;
+
+ ///
+ /// Index into the texture mapping lookup table.
+ ///
+ public ushort TextureCoordComboIndex;
+
+ ///
+ /// Index into transparency lookup table.
+ ///
+ public ushort TextureWeightComboIndex;
+
+ ///
+ /// Index into uvanimation lookup table.
+ ///
+ public ushort TextureTransformComboIndex;
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/M2ShadowBatch.cs b/Warcraft.NET/Files/Structures/M2ShadowBatch.cs
new file mode 100644
index 0000000..db25b23
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/M2ShadowBatch.cs
@@ -0,0 +1,41 @@
+namespace Warcraft.NET.Files.Structures
+{
+ public struct M2ShadowBatch
+ {
+ ///
+ /// if auto-generated: M2Batch.Flags & 0xFF
+ ///
+ public byte Flags;
+
+ ///
+ /// gets auto generated if certain flags in TextureUnit are set
+ /// See wiki for more information
+ ///
+ public byte Flags2;
+
+ ///
+ /// unknown field
+ ///
+ public ushort Unk1;
+
+ ///
+ /// same as TextureUnit
+ ///
+ public ushort SubmeshId;
+
+ ///
+ /// same as TextureUnit
+ ///
+ public ushort TextureId; // already looked-up
+
+ ///
+ /// same as TextureUnit
+ ///
+ public ushort ColorId;
+
+ ///
+ /// same as TextureUnit
+ ///
+ public ushort TransparencyId; // already looked-up
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs b/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs
new file mode 100644
index 0000000..6f813ee
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/M2SkinBoneStruct.cs
@@ -0,0 +1,25 @@
+namespace Warcraft.NET.Files.Structures
+{
+ public struct M2SkinBoneStruct
+ {
+ ///
+ /// Bone 1 Index into BoneLookupTable from M2. see wiki for exact calculation
+ ///
+ public byte Bone1ID;
+
+ ///
+ /// Bone 2 Index into BoneLookupTable from M2. see wiki for exact calculation
+ ///
+ public byte Bone2ID;
+
+ ///
+ /// Bone 3 Index into BoneLookupTable from M2. see wiki for exact calculation
+ ///
+ public byte Bone3ID;
+
+ ///
+ /// Bone 4 Index into BoneLookupTable from M2. see wiki for exact calculation
+ ///
+ public byte Bone4ID;
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/M2SkinSection.cs b/Warcraft.NET/Files/Structures/M2SkinSection.cs
new file mode 100644
index 0000000..cbd4b55
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/M2SkinSection.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Text;
+
+namespace Warcraft.NET.Files.Structures
+{
+ public struct M2SkinSection
+ {
+ ///
+ /// Mesh part ID, see wiki for exact calculation
+ ///
+ public ushort SkinSectionId;
+
+ ///
+ /// (level << 16) is added (|ed) to startTriangle and alike to avoid having to increase those fields to uint32s.
+ ///
+ public ushort Level;
+
+ ///
+ /// Starting Vertex. Index into local vertex list
+ ///
+ public ushort VertexStart;
+
+ ///
+ /// Number of Vertices taken from local vertex list
+ ///
+ public ushort VertexCount;
+
+ ///
+ /// Starting triangle index.
+ ///
+ public ushort IndexStart;
+
+ ///
+ /// Number of triangle indices.
+ ///
+ public ushort IndexCount;
+
+ ///
+ /// Number of elements in the bone lookup table. Max seems to be 256 in Wrath. Shall be ≠ 0.
+ ///
+ public ushort BoneCount;
+
+ ///
+ /// Starting index in the bone lookup table.
+ ///
+ public ushort BoneComboIndex;
+
+ ///
+ /// <= 4
+ /// from <=BC documentation: Highest number of bones needed at one time in this Submesh --Tinyn (wowdev.org)
+ /// In 2.x this is the amount of of bones up the parent-chain affecting the submesh --NaK
+ /// Highest number of bones referenced by a vertex of this submesh. 3.3.5a and suspectedly all other client revisions. -- Skarn
+ ///
+ public ushort BoneInfluences;
+
+ ///
+ /// Index of the center bone
+ ///
+ public ushort CenterBoneIndex;
+
+ ///
+ /// Average position of all the vertices in the sub mesh.
+ ///
+ public Vector3 CenterPosition;
+
+ //≥BC
+ ///
+ /// The center of the box when an axis aligned box is built around the vertices in the submesh.
+ ///
+ public Vector3 SortCenterPosition;
+
+ ///
+ /// Distance of the vertex farthest from CenterBoundingBox.
+ ///
+ public float SortRadius;
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/M2Triangle.cs b/Warcraft.NET/Files/Structures/M2Triangle.cs
new file mode 100644
index 0000000..639055d
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/M2Triangle.cs
@@ -0,0 +1,25 @@
+namespace Warcraft.NET.Files.Structures
+{
+ ///
+ /// Triangle read from skin.
+ /// Default = Right Handed
+ /// To make it left handed, swap the second and third vertex
+ ///
+ public struct M2Triangle
+ {
+ ///
+ /// the first vertex of the Triangle
+ ///
+ public ushort Vertex1;
+
+ ///
+ /// the second vertex of the Triangle
+ ///
+ public ushort Vertex2;
+
+ ///
+ /// the third vertex of the Triangle
+ ///
+ public ushort Vertex3;
+ }
+}
diff --git a/Warcraft.NET/Files/Structures/Matrix3x4.cs b/Warcraft.NET/Files/Structures/Matrix3x4.cs
new file mode 100644
index 0000000..7c6e0d6
--- /dev/null
+++ b/Warcraft.NET/Files/Structures/Matrix3x4.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using Warcraft.NET.Files.Interfaces;
+using System.Numerics;
+
+public class Matrix3x4 : IFlattenableData
+{
+ ///
+ /// The directional vector 'right'
+ ///
+ public Vector3 RotationX { get; set; }
+
+ ///
+ /// The directional vector 'up'
+ ///
+ public Vector3 RotationY { get; set; }
+
+ ///
+ /// The directional vector 'forward'
+ ///
+ public Vector3 RotationZ { get; set; }
+
+ ///
+ /// The scale of the matrix
+ ///
+ public Vector3 Scale { get; set; }
+
+ ///
+ /// The position of the matrix
+ ///
+ public Vector3 Position { get; set; }
+
+ public Matrix3x4 (Vector3 column1, Vector3 column2, Vector3 column3, Vector3 column4)
+ {
+ float scaleX = column1.Length();
+ float scaleY = column2.Length();
+ float scaleZ = column3.Length();
+
+ RotationX = column1 / scaleX;
+ RotationY = column2 / scaleY;
+ RotationZ = column3 / scaleZ;
+
+ Scale = new Vector3(scaleX, scaleY, scaleZ);
+ Position = column4;
+ }
+
+ public Vector3 GetForward()
+ {
+ return Vector3.Normalize(RotationZ);
+ }
+
+ public Vector3 GetUp()
+ {
+ return Vector3.Normalize(RotationY);
+ }
+
+ public Vector3 GetRight()
+ {
+ return Vector3.Normalize(RotationX);
+ }
+
+ public IReadOnlyCollection Flatten()
+ {
+ return new[] {
+ GetForward().X,GetForward().Y,GetForward().Z,
+ Scale.X, Scale.Y, Scale.Z,
+ Position.X, Position.Y, Position.Z };
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Chunks/BDY4.cs b/Warcraft.NET/Files/phys/Chunks/BDY4.cs
new file mode 100644
index 0000000..7f90e83
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/BDY4.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class BDY4 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "BDY4";
+
+ ///
+ /// Gets or Sets the used rigidbodies(V4)
+ ///
+ public List BDY4Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public BDY4() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public BDY4(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var bdy4count = br.BaseStream.Length / BDY4Entry.GetSize();
+
+ for (var i = 0; i < bdy4count; ++i)
+ {
+ BDY4Entries.Add(new BDY4Entry(br.ReadBytes(BDY4Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (BDY4Entry obj in BDY4Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/BOXS.cs b/Warcraft.NET/Files/phys/Chunks/BOXS.cs
new file mode 100644
index 0000000..98128a9
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/BOXS.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class BOXS : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "BOXS";
+
+ ///
+ /// sets or gets the box shapes
+ ///
+ public List BOXSEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public BOXS() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public BOXS(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var boxscount = br.BaseStream.Length / BOXSEntry.GetSize();
+
+ for (var i = 0; i < boxscount; ++i)
+ {
+ BOXSEntries.Add(new BOXSEntry(br.ReadBytes(BOXSEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (BOXSEntry obj in BOXSEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/CAPS.cs b/Warcraft.NET/Files/phys/Chunks/CAPS.cs
new file mode 100644
index 0000000..26fab82
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/CAPS.cs
@@ -0,0 +1,68 @@
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using System.Collections.Generic;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class CAPS : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "CAPS";
+
+ ///
+ /// sets or gets the capsule shapes
+ ///
+ public List CAPSEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public CAPS() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public CAPS(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var capscount = br.BaseStream.Length / CAPSEntry.GetSize();
+
+ for (var i = 0; i < capscount; ++i)
+ {
+ CAPSEntries.Add(new CAPSEntry(br.ReadBytes(CAPSEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (CAPSEntry obj in CAPSEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/DSTJ.cs b/Warcraft.NET/Files/phys/Chunks/DSTJ.cs
new file mode 100644
index 0000000..32db762
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/DSTJ.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class DSTJ : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "DSTJ";
+
+ ///
+ /// sets or gets the distance joints
+ ///
+ public List DSTJEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public DSTJ() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public DSTJ(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var DSTJcount = br.BaseStream.Length / DSTJEntry.GetSize();
+
+ for (var i = 0; i < DSTJcount; ++i)
+ {
+ DSTJEntries.Add(new DSTJEntry(br.ReadBytes(DSTJEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (DSTJEntry obj in DSTJEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/JOIN.cs b/Warcraft.NET/Files/phys/Chunks/JOIN.cs
new file mode 100644
index 0000000..d378ac3
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/JOIN.cs
@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class JOIN : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "JOIN";
+
+ ///
+ /// sets or gets the joints
+ ///
+ public List JOINEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public JOIN() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public JOIN(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var JOINcount = br.BaseStream.Length / JOINEntry.GetSize();
+ for (var i = 0; i < JOINcount; ++i)
+ {
+ JOINEntries.Add(new JOINEntry(br.ReadBytes(JOINEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (JOINEntry obj in JOINEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/PHYS.cs b/Warcraft.NET/Files/phys/Chunks/PHYS.cs
new file mode 100644
index 0000000..7226e29
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/PHYS.cs
@@ -0,0 +1,58 @@
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PHYS : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PHYS";
+
+ ///
+ /// Gets or Sets the version of the physics
+ ///
+ public ushort Version;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PHYS() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PHYS(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ Version = br.ReadUInt16();
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Version);
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/PHYT.cs b/Warcraft.NET/Files/phys/Chunks/PHYT.cs
new file mode 100644
index 0000000..7e2d5c7
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/PHYT.cs
@@ -0,0 +1,58 @@
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PHYT : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PHYT";
+
+ ///
+ /// Gets or Sets PHYT (unknown)
+ ///
+ public uint Phyt = 0;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PHYT() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PHYT(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ Phyt = br.ReadUInt32();
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Phyt);
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/PHYV.cs b/Warcraft.NET/Files/phys/Chunks/PHYV.cs
new file mode 100644
index 0000000..690428a
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/PHYV.cs
@@ -0,0 +1,71 @@
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PHYV : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PHYV";
+
+ ///
+ /// Gets or Sets the PHYV (unknown)
+ ///
+ public float[] Values;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PHYV() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PHYV(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var PHYVcount = br.BaseStream.Length / 24;
+ Values = new float[PHYVcount * 6];
+ for (var i = 0; i < PHYVcount; ++i)
+ {
+ Values[i] = br.ReadSingle();
+ Values[i+1] = br.ReadSingle();
+ Values[i+2] = br.ReadSingle();
+ Values[i+3] = br.ReadSingle();
+ Values[i+4] = br.ReadSingle();
+ Values[i+5] = br.ReadSingle();
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (float f in Values)
+ {
+ bw.Write(f);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/PLYT.cs b/Warcraft.NET/Files/phys/Chunks/PLYT.cs
new file mode 100644
index 0000000..1316870
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/PLYT.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PLYT : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PLYT";
+
+ ///
+ /// sets or gets the polytope shapes
+ ///
+ public List PLYTEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PLYT() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PLYT(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var plyt_count = br.ReadUInt32();
+ for (var i = 0; i < plyt_count; i++)
+ {
+ PLYTEntry plyt_entry = new PLYTEntry(br.ReadBytes(80));
+ PLYTEntries.Add(plyt_entry);
+ }
+ for (var j = 0; j < plyt_count; j++)
+ {
+ PLYTEntry plyt_entry = PLYTEntries[j];
+ plyt_entry.DeserializeData(br.ReadBytes(plyt_entry.DataSize));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write((uint)PLYTEntries.Count);
+ foreach (PLYTEntry obj in PLYTEntries)
+ {
+ bw.Write(obj.SerializeHeader());
+ }
+ foreach (PLYTEntry obj in PLYTEntries)
+ {
+ bw.Write(obj.SerializeData());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/PRS2.cs b/Warcraft.NET/Files/phys/Chunks/PRS2.cs
new file mode 100644
index 0000000..7d1e742
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/PRS2.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class PRS2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "PRS2";
+
+ ///
+ /// sets or gets the prismatic(V2) joints
+ ///
+ public List PRS2Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public PRS2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public PRS2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var PRS2count = br.BaseStream.Length / PRS2Entry.GetSize();
+
+ for (var i = 0; i < PRS2count; ++i)
+ {
+ PRS2Entries.Add(new PRS2Entry(br.ReadBytes(PRS2Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (PRS2Entry obj in PRS2Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/REV2.cs b/Warcraft.NET/Files/phys/Chunks/REV2.cs
new file mode 100644
index 0000000..297898a
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/REV2.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class REV2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "REV2";
+
+ ///
+ /// sets or gets the revolute(V2) joints
+ ///
+ public List REV2Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public REV2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public REV2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var REV2count = br.BaseStream.Length / REV2Entry.GetSize();
+
+ for (var i = 0; i < REV2count; ++i)
+ {
+ REV2Entries.Add(new REV2Entry(br.ReadBytes(REV2Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (REV2Entry obj in REV2Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/SHJ2.cs b/Warcraft.NET/Files/phys/Chunks/SHJ2.cs
new file mode 100644
index 0000000..c8ae2e2
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/SHJ2.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class SHJ2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SHJ2";
+
+ ///
+ /// sets or gets the shoulder(V2) joints
+ ///
+ public List SHJ2Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SHJ2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SHJ2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var SHJ2count = br.BaseStream.Length / SHJ2Entry.GetSize();
+
+ for (var i = 0; i < SHJ2count; ++i)
+ {
+ SHJ2Entries.Add(new SHJ2Entry(br.ReadBytes(SHJ2Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (SHJ2Entry obj in SHJ2Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/SHOJ.cs b/Warcraft.NET/Files/phys/Chunks/SHOJ.cs
new file mode 100644
index 0000000..b1149ac
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/SHOJ.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class SHOJ : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SHOJ";
+
+ ///
+ /// sets or gets the shoulder joints
+ ///
+ public List SHOJEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SHOJ() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SHOJ(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var SHOJcount = br.BaseStream.Length / SHOJEntry.GetSize();
+
+ for (var i = 0; i < SHOJcount; ++i)
+ {
+ SHOJEntries.Add(new SHOJEntry(br.ReadBytes(SHOJEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (SHOJEntry obj in SHOJEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/SHP2.cs b/Warcraft.NET/Files/phys/Chunks/SHP2.cs
new file mode 100644
index 0000000..21f1265
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/SHP2.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class SHP2 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SHP2";
+
+ ///
+ /// sets or gets the shapes(V2)
+ ///
+ public List SHP2Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SHP2() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SHP2(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var SHP2count = br.BaseStream.Length / SHP2Entry.GetSize();
+
+ for (var i = 0; i < SHP2count; ++i)
+ {
+ SHP2Entries.Add(new SHP2Entry(br.ReadBytes(SHP2Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (SHP2Entry obj in SHP2Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/SPHJ.cs b/Warcraft.NET/Files/phys/Chunks/SPHJ.cs
new file mode 100644
index 0000000..4ec195f
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/SPHJ.cs
@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class SPHJ : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SPHJ";
+
+ ///
+ /// sets or gets the spherical joints
+ ///
+ public List SPHJEntries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SPHJ() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SPHJ(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var SPHJcount = br.BaseStream.Length / SPHJEntry.GetSize();
+ for (var i = 0; i < SPHJcount; ++i)
+ {
+ SPHJEntries.Add(new SPHJEntry(br.ReadBytes(SPHJEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (SPHJEntry obj in SPHJEntries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/SPHS.cs b/Warcraft.NET/Files/phys/Chunks/SPHS.cs
new file mode 100644
index 0000000..5b55a64
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/SPHS.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class SPHS : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "SPHS";
+
+ ///
+ /// sets or gets a list of sphere shapes
+ ///
+ public List Spheres = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public SPHS() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public SPHS(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var SHP2count = br.BaseStream.Length / SHP2Entry.GetSize();
+
+ for (var i = 0; i < SHP2count; ++i)
+ {
+ Spheres.Add(new SPHSEntry(br.ReadBytes(SPHSEntry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (SPHSEntry obj in Spheres)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Chunks/WLJ3.cs b/Warcraft.NET/Files/phys/Chunks/WLJ3.cs
new file mode 100644
index 0000000..b71e7a7
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Chunks/WLJ3.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.IO;
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Interfaces;
+using Warcraft.NET.Files.Phys.Entries;
+
+namespace Warcraft.NET.Files.Phys.Chunks
+{
+ [AutoDocChunk(AutoDocChunkVersionHelper.VersionAfterBfA, AutoDocChunkVersionHelper.VersionBeforeSL)]
+ public class WLJ3 : IIFFChunk, IBinarySerializable
+ {
+ ///
+ /// Holds the binary chunk signature.
+ ///
+ public const string Signature = "WLJ3";
+
+ ///
+ /// sets or gets a list of Weld(V3) Joints
+ ///
+ public List WLJ3Entries = new();
+
+ ///
+ /// Initializes a new instance of
+ ///
+ public WLJ3() { }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// ExtendedData.
+ public WLJ3(byte[] inData) => LoadBinaryData(inData);
+
+ ///
+ public string GetSignature() { return Signature; }
+
+ ///
+ public uint GetSize() { return (uint)Serialize().Length; }
+
+ ///
+ public void LoadBinaryData(byte[] inData)
+ {
+ using (var ms = new MemoryStream(inData))
+ using (var br = new BinaryReader(ms))
+ {
+ var WLJ3count = br.BaseStream.Length / WLJ3Entry.GetSize();
+
+ for (var i = 0; i < WLJ3count; ++i)
+ {
+ WLJ3Entries.Add(new WLJ3Entry(br.ReadBytes(WLJ3Entry.GetSize())));
+ }
+ }
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (WLJ3Entry obj in WLJ3Entries)
+ {
+ bw.Write(obj.Serialize());
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs b/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs
new file mode 100644
index 0000000..8fc497e
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/BDY4Entry.cs
@@ -0,0 +1,139 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Phys.Enums;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class BDY4Entry
+ {
+ ///
+ /// Sets or gets the BodyType of the rigidbody
+ /// 0=static
+ /// 1=dynamic
+ /// 2=unknown
+ ///
+ public BodyType BodyType { get; set; } // maps to dmBodyDef BodyType enum. 0 -> 1, 1 -> 0 = dm_dynamicBody, * -> 2. Only one should be of BodyType 0 (root). possibly only 0 and 1.
+
+ ///
+ /// Sets or gets the index of the bone, which is connected to this rigidbody
+ ///
+ public ushort BoneIndex { get; set; }
+
+ ///
+ /// sets or gets the default Position of the rigidbody
+ ///
+ public Vector3 Position { get; set; } = new Vector3(0, 0, 0);
+
+ ///
+ /// sets or gets the index of the shape, which is connected to this rigidbody
+ ///
+ public ushort ShapesIndex { get; set; }
+
+ ///
+ /// sets or gets a currently unknown field. Possibly 'Padding'
+ ///
+ public byte[] Unk0 { get; set; } = { 0, 0 };
+
+ ///
+ /// sets or gets the amount of shapes this rigidbody has
+ ///
+ public int ShapesCount { get; set; } // shapes_count shapes are in this body.
+
+ ///
+ /// sets or gets a currently unknown field. Possibly 'UpliftFactor'
+ ///
+ public float Unk1 { get; set; } = 0f;
+
+ //#if version >= 3 // BDY3
+ ///
+ /// sets or gets a currently unknown field. Possibly 'GravityScale'
+ ///
+ public float Unk2 { get; set; } = 1.0f;
+
+ ///
+ /// sets or gets the Drag value of the rigidbody.
+ ///
+ public float Drag { get; set; } = 0f;
+
+ ///
+ /// sets or gets a currently unknown field. Possibly 'Mass/Weight'
+ ///
+ public float Unk3 = 0f;
+
+ ///
+ /// sets or gets a currently unknown field.
+ ///
+ public float Unk4 { get; set; } = 0.89999998f;
+
+ ///
+ /// sets or gets a currently unknown field.
+ ///
+ public byte[] Unk5 { get; set; } = { 0, 0, 0, 0 };
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BDY4Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public BDY4Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ BodyType = (BodyType)br.ReadUInt16();
+ BoneIndex = br.ReadUInt16();
+ Position = br.ReadVector3(AxisConfiguration.ZUp);
+ ShapesIndex = br.ReadUInt16();
+ Unk0 = br.ReadBytes(2);
+ ShapesCount = br.ReadInt32();
+ Unk1 = br.ReadSingle();
+ Unk2 = br.ReadSingle();
+ Drag = br.ReadSingle();
+ Unk3 = br.ReadSingle();
+ Unk4 = br.ReadSingle();
+ Unk5 = br.ReadBytes(4);
+ }
+ }
+
+ ///
+ /// Gets the size of a bdy4 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 48;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write((ushort)BodyType);
+ bw.Write(BoneIndex);
+ bw.Write(Position.X);
+ bw.Write(Position.Y);
+ bw.Write(Position.Z);
+ bw.Write(ShapesIndex);
+ bw.Write(Unk0);
+ bw.Write(ShapesCount);
+ bw.Write(Unk1);
+ bw.Write(Unk2);
+ bw.Write(Drag);
+ bw.Write(Unk3);
+ bw.Write(Unk4);
+ bw.Write(Unk5);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs b/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs
new file mode 100644
index 0000000..8fffebd
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/BOXSEntry.cs
@@ -0,0 +1,52 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class BOXSEntry
+ {
+ ///
+ /// Gets or Sets the transformation matrix of the box shape
+ ///
+ public Matrix3x4 Dimensions;
+
+ ///
+ /// Gets or Sets the local position of the box shape
+ ///
+ public Vector3 Position;
+
+ public BOXSEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ Dimensions = br.ReadMatrix3x4();
+ Position = br.ReadVector3();
+ }
+ }
+
+ ///
+ /// Gets the size of a box entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 60;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(Dimensions);
+ bw.WriteVector3(Position);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs b/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs
new file mode 100644
index 0000000..dcfde2d
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/CAPSEntry.cs
@@ -0,0 +1,57 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class CAPSEntry
+ {
+ ///
+ /// Gets or Sets the local start position of this capsule shape
+ ///
+ public Vector3 LocalPosition1;
+
+ ///
+ /// Gets or Sets the local end position of this capsule shape
+ ///
+ public Vector3 LocalPosition2;
+
+ ///
+ /// Gets or Sets the Radius of this capsule shape
+ ///
+ public float Radius;
+
+ public CAPSEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ LocalPosition1 = br.ReadVector3(AxisConfiguration.ZUp);
+ LocalPosition2 = br.ReadVector3(AxisConfiguration.ZUp);
+ Radius = br.ReadSingle();
+ }
+ }
+ ///
+ /// Gets the size of a caps entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 28;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteVector3(LocalPosition1);
+ bw.WriteVector3(LocalPosition2);
+ bw.Write(Radius);
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs b/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs
new file mode 100644
index 0000000..6752e96
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/DSTJEntry.cs
@@ -0,0 +1,68 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class DSTJEntry
+ {
+ ///
+ /// sets or gets the local Anchor for Bone A from the Joint
+ ///
+ public Vector3 LocalAnchorA;
+
+ ///
+ /// sets or gets the local Anchor for Bone B from the Joint
+ ///
+ public Vector3 LocalAnchorB;
+
+ ///
+ /// sets or gets the currently unknown value for the distance joint calculation
+ ///
+ public float UnknownDistanceFactor;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DSTJEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public DSTJEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ LocalAnchorA = br.ReadVector3();
+ LocalAnchorB = br.ReadVector3();
+ UnknownDistanceFactor = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a DSTJ entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 28;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteVector3(LocalAnchorA);
+ bw.WriteVector3(LocalAnchorB);
+ bw.Write(UnknownDistanceFactor);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/JOINEntry.cs b/Warcraft.NET/Files/phys/Entries/JOINEntry.cs
new file mode 100644
index 0000000..03aaa3c
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/JOINEntry.cs
@@ -0,0 +1,87 @@
+using System.IO;
+using Warcraft.NET.Files.Phys.Enums;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class JOINEntry
+ {
+ ///
+ /// sets or gets the index of the first connected Rigidbody
+ ///
+ public uint BodyAIdx;
+
+ ///
+ /// sets or gets the index of the second connected Rigidbody
+ ///
+ public uint BodyBIdx;
+
+ ///
+ /// sets or gets a Unknown field.
+ ///
+ public byte[] Unk;
+
+ ///
+ /// sets or gets the JointType
+ /// 0 = SphericalJoint
+ /// 1 = ShoulderJoint
+ /// 2 = WeldJoint
+ /// 3 = RevoluteJoint
+ /// 4 = PrismaticJoint
+ /// 5 = DistanceJoint
+ ///
+ public JointType JointType;
+
+ ///
+ /// sets or gets the index of the joint into the joint list based on the JointType field
+ ///
+ public ushort JointID;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JOINEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public JOINEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ BodyAIdx = br.ReadUInt32();
+ BodyBIdx = br.ReadUInt32();
+ Unk = br.ReadBytes(4);
+ JointType = (JointType)br.ReadUInt16();
+ JointID = br.ReadUInt16();
+ }
+ }
+
+ ///
+ /// Gets the size of a JOIN entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(BodyAIdx);
+ bw.Write(BodyBIdx);
+ bw.Write(Unk);
+ bw.Write((ushort)JointType);
+ bw.Write(JointID);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs b/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs
new file mode 100644
index 0000000..5e5ce51
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/PLYTEntry.cs
@@ -0,0 +1,188 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Phys.Structures;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class PLYTEntry
+ {
+ ///
+ /// gets or set the Polytope Header
+ ///
+ public PlytHeader Header;
+
+ ///
+ /// gets or set the Polytope Data
+ ///
+ public PlytData Data;
+
+ ///
+ /// gets or set the Polytope Data
+ ///
+ public int DataSize { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PLYTEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Header Data
+ public PLYTEntry(byte[] header)
+ {
+ using (var ms = new MemoryStream(header))
+ using (var br = new BinaryReader(ms))
+ {
+ Header = new PlytHeader
+ {
+ VertexCount = br.ReadUInt32(),
+ Unk0 = br.ReadBytes(4),
+ RUNTIME08ptrData0 = br.ReadUInt64(),
+ Count10 = br.ReadUInt32(),
+ Unk1 = br.ReadBytes(4),
+ RUNTIME18ptrData1 = br.ReadUInt64(),
+ RUNTIME20ptrData2 = br.ReadUInt64(),
+ NodeCount = br.ReadUInt32(),
+ Unk2 = br.ReadBytes(4),
+ RUNTIME30ptrData3 = br.ReadUInt64(),
+ Unk3 = [br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()]
+ };
+ int size = 0;
+ size += (int)Header.VertexCount * 12;
+ size += (int)Header.Count10 * 16;
+ size += (int)Header.Count10;
+ size += (int)Header.NodeCount * 4;
+ DataSize = size;
+ }
+ }
+
+ ///
+ /// Deserialization of the Data Chunks
+ ///
+ ///
+ public void DeserializeData(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ uint vcount = Header.VertexCount;
+ uint count_10 = Header.Count10;
+ uint nodeCount = Header.NodeCount;
+
+ Data.Vertices = new Vector3[vcount];
+ for (int v = 0; v < vcount; v++)
+ {
+ Data.Vertices[v] = br.ReadVector3();
+ }
+ Data.Unk1 = br.ReadBytes((int)count_10 * 16);
+ Data.Unk2 = br.ReadBytes((int)count_10);
+ Data.Nodes = new PlytNode[nodeCount];
+ for (int n = 0; n < nodeCount; n++)
+ {
+ PlytNode node = new();
+ node.Unk = br.ReadByte();
+ node.VertexIndex = br.ReadByte();
+ node.UnkIndex0 = br.ReadByte();
+ node.UnkIndex1 = br.ReadByte();
+ Data.Nodes[n] = node;
+ }
+ }
+ }
+
+ ///
+ /// gets the data size of the polytope.
+ ///
+ /// The size.
+ public int GetDataSize()
+ {
+ return SerializeData().Length;
+ }
+
+ ///
+ /// gets the header size of the polytope.
+ ///
+ /// The size.
+ public int GetHeaderSize()
+ {
+ return SerializeHeader().Length;
+ }
+
+ ///
+ /// gets the full size of the polytope.
+ ///
+ /// The size.
+ public int GetSize()
+ {
+ return SerializeHeader().Length + SerializeData().Length;
+ }
+
+ ///
+ /// Serialize the Header
+ ///
+ ///
+ ///
+ public byte[] SerializeHeader(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(Header.VertexCount);
+ bw.Write(Header.Unk0);
+
+ bw.Write(Header.RUNTIME08ptrData0);
+
+ bw.Write(Header.Count10);
+ bw.Write(Header.Unk1);
+
+ bw.Write(Header.RUNTIME18ptrData1);
+
+ bw.Write(Header.RUNTIME20ptrData2);
+
+ bw.Write(Header.NodeCount);
+
+ bw.Write(Header.Unk2);
+
+ bw.Write(Header.RUNTIME30ptrData3);
+ foreach (float f in Header.Unk3)
+ {
+ bw.Write(f);
+ }
+ }
+ return ms.ToArray();
+ }
+ }
+
+ ///
+ /// Serialize the Data
+ ///
+ ///
+ ///
+ public byte[] SerializeData(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ foreach (var vertex in Data.Vertices)
+ {
+ bw.WriteVector3(vertex);
+ }
+ bw.Write(Data.Unk1);
+ bw.Write(Data.Unk2);
+ foreach (var node in Data.Nodes)
+ {
+ bw.Write(node.Unk);
+ bw.Write(node.VertexIndex);
+ bw.Write(node.UnkIndex0);
+ bw.Write(node.UnkIndex1);
+ }
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs b/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs
new file mode 100644
index 0000000..fc925a8
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/PRS2Entry.cs
@@ -0,0 +1,119 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class PRS2Entry
+ {
+ ///
+ /// The Transformation Matrix for Bone A of this Joint
+ ///
+ public Matrix3x4 FrameA;
+
+ ///
+ /// The Transformation Matrix for Bone B of this Joint
+ ///
+ public Matrix3x4 FrameB;
+
+ ///
+ /// The lower limit
+ ///
+ public float LowerLimit;
+
+ ///
+ /// The upper limit
+ ///
+ public float UpperLimit;
+
+ ///
+ /// Unknown value
+ ///
+ public float Unk0;
+
+ ///
+ /// Max motor force if enabled
+ ///
+ public float MaxMotorForce;
+
+ ///
+ /// unknown value
+ ///
+ public float Unk1;
+
+ ///
+ /// The MotorMode
+ /// 0 = disabled?
+ /// 1 = motorPositionMode (MotorFrequencyHz>0)
+ /// 2 = motorVelocityMode
+ ///
+ public uint MotorMode;
+
+ ///
+ /// how often per second the motor damps
+ ///
+ public float MotorFrequencyHz;
+
+ ///
+ /// the ratio how much the motor damps
+ ///
+ public float MotorDampingRatio;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PRS2Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public PRS2Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ FrameA = br.ReadMatrix3x4();
+ FrameB = br.ReadMatrix3x4();
+ LowerLimit = br.ReadSingle();
+ UpperLimit = br.ReadSingle();
+ Unk0 = br.ReadSingle();
+ MaxMotorForce = br.ReadSingle();
+ Unk1 = br.ReadSingle();
+ MotorMode = br.ReadUInt32();
+ MotorFrequencyHz = br.ReadSingle();
+ MotorDampingRatio = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a PRS2 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 128;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(FrameA);
+ bw.WriteMatrix3x4(FrameB);
+ bw.Write(LowerLimit);
+ bw.Write(UpperLimit);
+ bw.Write(Unk0);
+ bw.Write(MaxMotorForce);
+ bw.Write(Unk1);
+ bw.Write(MotorMode);
+ bw.Write(MotorFrequencyHz);
+ bw.Write(MotorDampingRatio);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/REV2Entry.cs b/Warcraft.NET/Files/phys/Entries/REV2Entry.cs
new file mode 100644
index 0000000..bc747ac
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/REV2Entry.cs
@@ -0,0 +1,101 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class REV2Entry
+ {
+ ///
+ /// The Transformation Matrix for Bone A of this Joint
+ ///
+ public Matrix3x4 FrameA;
+
+ ///
+ /// The Transformation Matrix for Bone B of this Joint
+ ///
+ public Matrix3x4 FrameB;
+
+ ///
+ /// The lower swing angle
+ ///
+ public float LowerAngle;
+ ///
+ /// The upper swing angle
+ ///
+ public float UpperAngle;
+
+ ///
+ /// The max motor torque
+ ///
+ public float MaxMotorTorque;
+ ///
+ /// The MotorMode
+ /// 0 = disabled?
+ /// 1 = motorPositionMode (MotorFrequencyHz>0)
+ /// 2 = motorVelocityMode
+ ///
+ public uint MotorMode; // 1: motorPositionMode → frequency > 0, 2: motorVelocityMode
+ ///
+ /// how often per second the motor damps
+ ///
+ public float MotorFrequencyHz;
+ ///
+ /// the ratio how much the motor damps
+ ///
+ public float MotorDampingRatio;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public REV2Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public REV2Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ FrameA = br.ReadMatrix3x4();
+ FrameB = br.ReadMatrix3x4();
+ LowerAngle = br.ReadSingle();
+ UpperAngle = br.ReadSingle();
+ MaxMotorTorque = br.ReadSingle();
+ MotorMode = br.ReadUInt32();
+ MotorFrequencyHz = br.ReadSingle();
+ MotorDampingRatio = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a REV2 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 120;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(FrameA);
+ bw.WriteMatrix3x4(FrameB);
+ bw.Write(LowerAngle);
+ bw.Write(UpperAngle);
+ bw.Write(MaxMotorTorque);
+ bw.Write(MotorMode);
+ bw.Write(MotorFrequencyHz);
+ bw.Write(MotorDampingRatio);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs b/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs
new file mode 100644
index 0000000..0586d11
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/SHJ2Entry.cs
@@ -0,0 +1,112 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SHJ2Entry
+ {
+ ///
+ /// The Transformation Matrix for Bone A of this Joint
+ ///
+ public Matrix3x4 FrameA;
+
+ ///
+ /// The Transformation Matrix for Bone B of this Joint
+ ///
+ public Matrix3x4 FrameB;
+
+ ///
+ /// The lower twist angle of the angular constraint
+ ///
+ public float LowerTwistAngle;
+
+ ///
+ /// The upper twist angle of the angular constraint
+ ///
+ public float UpperTwistAngle;
+
+ ///
+ /// The cone angle of the angular constraint
+ ///
+ public float ConeAngle;
+
+ ///
+ /// The max motor torque
+ ///
+ public float MaxMotorTorque;
+
+ ///
+ /// The MotorMode
+ /// 0 = disabled?
+ /// 1 = motorPositionMode (MotorFrequencyHz>0)
+ /// 2 = motorVelocityMode
+ ///
+ public uint MotorMode; // 1: motorPositionMode → frequency > 0, 2: motorVelocityMode
+
+ ///
+ /// how often per second the motor damps
+ ///
+ public float MotorFrequencyHz;
+
+ ///
+ /// the ratio how much the motor damps
+ ///
+ public float MotorDampingRatio;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHJ2Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public SHJ2Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ FrameA = br.ReadMatrix3x4();
+ FrameB = br.ReadMatrix3x4();
+ LowerTwistAngle = br.ReadSingle();
+ UpperTwistAngle = br.ReadSingle();
+ ConeAngle = br.ReadSingle();
+ MaxMotorTorque = br.ReadSingle();
+ MotorMode = br.ReadUInt32();
+ MotorFrequencyHz = br.ReadSingle();
+ MotorDampingRatio = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a SHJ2 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 124;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(FrameA);
+ bw.WriteMatrix3x4(FrameB);
+ bw.Write(LowerTwistAngle);
+ bw.Write(UpperTwistAngle);
+ bw.Write(ConeAngle);
+ bw.Write(MaxMotorTorque);
+ bw.Write(MotorMode);
+ bw.Write(MotorFrequencyHz);
+ bw.Write(MotorDampingRatio);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs b/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs
new file mode 100644
index 0000000..1c5bead
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/SHOJEntry.cs
@@ -0,0 +1,98 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SHOJEntry
+ {
+ ///
+ /// The Transformation Matrix for Bone A of this Joint
+ ///
+ public Matrix3x4 FrameA;
+
+ ///
+ /// The Transformation Matrix for Bone B of this Joint
+ ///
+ public Matrix3x4 FrameB;
+
+ ///
+ /// The lower twist angle for the angular constraint
+ ///
+ public float LowerTwistAngle;
+
+ ///
+ /// The upper twist angle for the angular constraint
+ ///
+ public float UpperTwistAngle;
+
+ ///
+ /// The cone angle for the angular constraint
+ ///
+ public float ConeAngle;
+
+ ///
+ /// The Maximum torque the motor can apply
+ ///
+ public float MaxMotorTorque;
+
+ ///
+ /// The MotorMode
+ /// 0 = disabled?
+ /// 1 = motorPositionMode (MotorFrequencyHz>0)
+ /// 2 = motorVelocityMode
+ ///
+ public uint MotorMode; // NO BACKWARDS COMPATIBILITY as of Legion (7.0.1.20979) and Legion (7.3.0.24931)! client always assumes new size!
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHOJEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public SHOJEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ FrameA = br.ReadMatrix3x4();
+ FrameB = br.ReadMatrix3x4();
+ LowerTwistAngle = br.ReadSingle();
+ UpperTwistAngle = br.ReadSingle();
+ ConeAngle = br.ReadSingle();
+ MaxMotorTorque = br.ReadSingle();
+ MotorMode = br.ReadUInt32();
+ }
+ }
+
+ ///
+ /// Gets the size of a SHOJ entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 116;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(FrameA);
+ bw.WriteMatrix3x4(FrameB);
+ bw.Write(LowerTwistAngle);
+ bw.Write(UpperTwistAngle);
+ bw.Write(ConeAngle);
+ bw.Write(MaxMotorTorque);
+ bw.Write(MotorMode);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs b/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs
new file mode 100644
index 0000000..e179c04
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/SHP2Entry.cs
@@ -0,0 +1,120 @@
+using System.IO;
+using Warcraft.NET.Files.Phys.Enums;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SHP2Entry
+ {
+ ///
+ /// The Shape Type
+ /// 0 = Box
+ /// 1 = Capsule
+ /// 2 = Sphere
+ /// 3 = Polytope
+ ///
+ public ShapeType ShapeType;
+
+ ///
+ /// The index into the corresponding chunk based on ShapeType
+ ///
+ public ushort ShapeIndex;
+
+ ///
+ /// unknown field
+ ///
+ public byte[] Unk0;
+
+ ///
+ /// the friction of the shape
+ ///
+ public float Friction;
+
+ ///
+ /// the restitution of the shape
+ ///
+ public float Restitution;
+
+ ///
+ /// the density of the shape
+ ///
+ public float Density;
+
+ ///
+ /// unknown field
+ ///
+ public uint Unk1 = 0;
+
+ ///
+ /// unknown field
+ ///
+ public float Unk2 = 1f;
+
+ ///
+ /// unknown field
+ ///
+ public ushort Unk3 = 0;
+
+ ///
+ /// unknown field
+ ///
+ public ushort Unk4; //no default, padding?
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHP2Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public SHP2Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ ShapeType = (ShapeType)br.ReadUInt16();
+ ShapeIndex = br.ReadUInt16();
+ Unk0 = br.ReadBytes(4);
+ Friction = br.ReadSingle();
+ Restitution = br.ReadSingle();
+ Density = br.ReadSingle();
+ Unk1 = br.ReadUInt32();
+ Unk2 = br.ReadSingle();
+ Unk3 = br.ReadUInt16();
+ Unk4 = br.ReadUInt16();
+ }
+ }
+
+ ///
+ /// Gets the size of a SHP2 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 32;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write((ushort)ShapeType);
+ bw.Write(ShapeIndex);
+ bw.Write(Unk0);
+ bw.Write(Friction);
+ bw.Write(Restitution);
+ bw.Write(Density);
+ bw.Write(Unk1);
+ bw.Write(Unk2);
+ bw.Write(Unk3);
+ bw.Write(Unk4);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs b/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs
new file mode 100644
index 0000000..1f0d175
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/SPHJEntry.cs
@@ -0,0 +1,69 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+using Warcraft.NET.Files.Structures;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SPHJEntry
+ {
+ ///
+ /// the local anchor of the Bone A of the joint
+ ///
+ public Vector3 AnchorA;
+
+ ///
+ /// the local anchor of the Bone B of the joint
+ ///
+ public Vector3 AnchorB;
+
+ ///
+ /// the friction torque
+ ///
+ public float FrictionTorque;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SPHJEntry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public SPHJEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ AnchorA = br.ReadVector3(AxisConfiguration.ZUp);
+ AnchorB = br.ReadVector3(AxisConfiguration.ZUp);
+ FrictionTorque = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a SPHJ entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 28;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteVector3(AnchorA);
+ bw.WriteVector3(AnchorB);
+ bw.Write(FrictionTorque);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs b/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs
new file mode 100644
index 0000000..51ceec7
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/SPHSEntry.cs
@@ -0,0 +1,52 @@
+using System.IO;
+using System.Numerics;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class SPHSEntry
+ {
+ ///
+ /// Gets or Sets the local position of the Sphere shape
+ ///
+ public Vector3 LocalPosition;
+
+ ///
+ /// Gets or Sets the radius of the Sphere shape
+ ///
+ public float Radius;
+
+ public SPHSEntry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ LocalPosition = br.ReadVector3();
+ Radius = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a Sphere entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 16;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ {
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteVector3(LocalPosition);
+ bw.Write(Radius);
+ }
+ return ms.ToArray();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs b/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs
new file mode 100644
index 0000000..396083e
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Entries/WLJ3Entry.cs
@@ -0,0 +1,93 @@
+using System.IO;
+using Warcraft.NET.Extensions;
+
+namespace Warcraft.NET.Files.Phys.Entries
+{
+ public class WLJ3Entry
+ {
+ ///
+ /// The Transformation Matrix for Bone A of this Joint
+ ///
+ public Matrix3x4 FrameA;
+
+ ///
+ /// The Transformation Matrix for Bone B of this Joint
+ ///
+ public Matrix3x4 FrameB;
+
+ ///
+ /// how often the angular dampening is applied per second
+ ///
+ public float AngularFrequencyHz;
+
+ ///
+ /// the ratio how strong the angular dampening is applied
+ ///
+ public float AngularDampingRatio;
+
+ ///
+ /// how often the linear dampening is applied per second
+ ///
+ public float LinearFrequencyHz; // default 0
+
+ ///
+ /// the ratio how linear the angular dampening is applied
+ ///
+ public float LinearDampingRatio; // default 0
+
+ ///
+ /// unknown field
+ ///
+ public float Unk0;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WLJ3Entry() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// ExtendedData.
+ public WLJ3Entry(byte[] data)
+ {
+ using (var ms = new MemoryStream(data))
+ using (var br = new BinaryReader(ms))
+ {
+ FrameA = br.ReadMatrix3x4();
+ FrameB = br.ReadMatrix3x4();
+ AngularFrequencyHz = br.ReadSingle();
+ AngularDampingRatio = br.ReadSingle();
+ LinearFrequencyHz = br.ReadSingle();
+ LinearDampingRatio = br.ReadSingle();
+ Unk0 = br.ReadSingle();
+ }
+ }
+
+ ///
+ /// Gets the size of a WLJ3 entry.
+ ///
+ /// The size.
+ public static int GetSize()
+ {
+ return 116;
+ }
+
+ ///
+ public byte[] Serialize(long offset = 0)
+ {
+ using (var ms = new MemoryStream())
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.WriteMatrix3x4(FrameA);
+ bw.WriteMatrix3x4(FrameB);
+ bw.Write(AngularFrequencyHz);
+ bw.Write(AngularDampingRatio);
+ bw.Write(LinearFrequencyHz);
+ bw.Write(LinearDampingRatio);
+ bw.Write(Unk0);
+ return ms.ToArray();
+ }
+ }
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Enums/BodyType.cs b/Warcraft.NET/Files/phys/Enums/BodyType.cs
new file mode 100644
index 0000000..070e59b
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Enums/BodyType.cs
@@ -0,0 +1,9 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum BodyType : ushort
+ {
+ Root = 0,
+ Dynamic = 1,
+ Unk = 2,
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Enums/JointType.cs b/Warcraft.NET/Files/phys/Enums/JointType.cs
new file mode 100644
index 0000000..0ea6327
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Enums/JointType.cs
@@ -0,0 +1,12 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum JointType : ushort
+ {
+ SphericalJoint = 0,
+ ShoulderJoint = 1,
+ WeldJoint = 2,
+ RevoluteJoint = 3,
+ PrismaticJoint = 4,
+ DistanceJoint = 5,
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Enums/ShapeType.cs b/Warcraft.NET/Files/phys/Enums/ShapeType.cs
new file mode 100644
index 0000000..1f599e5
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Enums/ShapeType.cs
@@ -0,0 +1,10 @@
+namespace Warcraft.NET.Files.Phys.Enums
+{
+ public enum ShapeType : short
+ {
+ Box = 0,
+ Caps = 1,
+ Sphere = 2,
+ Polytope = 3,
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Physics.cs b/Warcraft.NET/Files/phys/Physics.cs
new file mode 100644
index 0000000..45ec5ef
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Physics.cs
@@ -0,0 +1,129 @@
+using Warcraft.NET.Attribute;
+using Warcraft.NET.Files.Phys.Chunks;
+
+namespace Warcraft.NET.Files.Phys
+{
+ [AutoDocFile("phys")]
+ public class Physics : ChunkedFile
+ {
+ ///
+ /// contains the version of the physics
+ ///
+ [ChunkOrder(1)]
+ public PHYS Version{get; set;}
+
+ ///
+ /// contains an unknown uint
+ ///
+ [ChunkOrder(2),ChunkOptional]
+ public PHYT Phyt{get; set; }
+
+ ///
+ /// contains the used box shapes
+ ///
+ [ChunkOrder(3),ChunkOptional]
+ public BOXS BoxShapes{get;set;}
+
+ ///
+ /// contains the used sphere shapes
+ ///
+ [ChunkOrder(4),ChunkOptional]
+ public SPHS SphereShapes{get;set;}
+
+ ///
+ /// contains the used capsule shapes
+ ///
+
+ [ChunkOrder(5),ChunkOptional]
+ public CAPS CapsuleShapes{get;set;}
+
+ ///
+ /// contains the used polytope shapes
+ ///
+ [ChunkOrder(6),ChunkOptional]
+ public PLYT PolytopeShapes{get; set;}
+
+ ///
+ /// contains the used shapes
+ ///
+ [ChunkOrder(7),ChunkOptional]
+ public SHP2 Shapes2{get; set;} //SHAP nyi
+
+ ///
+ /// contains the used rigidbodies
+ ///
+ [ChunkOrder(8),ChunkOptional]
+ public BDY4 Rigidbodies4{get; set;} //BODY,BDY2,BDY3 NYI
+
+ ///
+ /// contains the used shoulder joints
+ ///
+ [ChunkOrder(9),ChunkOptional]
+ public SHOJ ShoulderJoints { get; set; }
+
+ ///
+ /// contains the used shoulder joints
+ ///
+ [ChunkOrder(10),ChunkOptional]
+ public SHJ2 ShoulderJoints2{get; set;}
+
+ ///
+ /// contains the used weld joints
+ ///
+ [ChunkOrder(11),ChunkOptional]
+ public WLJ3 WeldJoints3{get; set;} //WELJ,WLJ2 nyi
+
+ ///
+ /// contains the used spherical joints
+ ///
+ [ChunkOrder(12),ChunkOptional]
+ public SPHJ SphericalJoints{get; set;}
+
+ ///
+ /// contains the used prismatic joints
+ ///
+ [ChunkOrder(13),ChunkOptional]
+ public PRS2 PrismaticJoints2{get; set;} //PRSJ nyi
+
+ ///
+ /// contains the used revolute joints
+ ///
+ [ChunkOrder(14),ChunkOptional]
+ public REV2 RevoluteJoints2{get; set;} //REVJ nyi
+
+ ///
+ /// contains the used distance joints
+ ///
+ [ChunkOrder(15),ChunkOptional]
+ public DSTJ DistanceJoints{get; set;}
+
+ ///
+ /// contains the used joints
+ ///
+ [ChunkOrder(16),ChunkOptional]
+ public JOIN Joints{get; set;}
+
+ ///
+ /// contains the used phyv data (unknown)
+ ///
+ [ChunkOrder(17),ChunkOptional]
+ public PHYV Phyv { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Physics()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The binary data.
+ public Physics(byte[] inData) : base(inData)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Structures/PlytData.cs b/Warcraft.NET/Files/phys/Structures/PlytData.cs
new file mode 100644
index 0000000..65ddf95
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Structures/PlytData.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Numerics;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+ [Serializable]
+ public struct PlytData
+ {
+ ///
+ /// gets or sets the vertices. Amount is defined by header.VertexCount
+ ///
+ public Vector3[] Vertices; //amount = VertexCount in Header
+
+ ///
+ /// gets or sets the Unk1 array. Unknown purpose. Amount is defined by header.Count10
+ ///
+ public byte[] Unk1; //multiple of 16 -> amount = count_10 in Header
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.Count10
+ ///
+ public byte[] Unk2; //amount = count_10 in Header
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose.Amount is defined by header.NodeCount
+ ///
+ public PlytNode[] Nodes;
+ }
+}
diff --git a/Warcraft.NET/Files/phys/Structures/PlytHeader.cs b/Warcraft.NET/Files/phys/Structures/PlytHeader.cs
new file mode 100644
index 0000000..c6b871a
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Structures/PlytHeader.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+ public struct PlytHeader
+ {
+ ///
+ /// gets or sets the amount of vertices for this polytope
+ ///
+ public uint VertexCount;
+
+ ///
+ /// gets or sets unknown data
+ ///
+ public byte[] Unk0;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME08ptrData0;
+
+ ///
+ /// gets or sets the count10, which defines how many Unk1[] and Unk2[] there are inside the Data.
+ ///
+ public uint Count10;
+
+ ///
+ /// gets or sets the Unk1 array. Unknown purpose
+ ///
+ public byte[] Unk1;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME18ptrData1;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME20ptrData2;
+
+ ///
+ /// gets or sets the amount of nodes. Defines how Vertices are connected
+ ///
+ public uint NodeCount;
+
+ ///
+ /// gets or sets the Unk2 array. Unknown purpose
+ ///
+ public byte[] Unk2;
+
+ ///
+ /// gets or sets certain runtime data. Unknown purpose
+ ///
+ public UInt64 RUNTIME30ptrData3;
+
+ ///
+ /// gets or sets the Unk3 array. Unknown purpose
+ ///
+ public float[] Unk3;
+ }
+}
\ No newline at end of file
diff --git a/Warcraft.NET/Files/phys/Structures/PlytNode.cs b/Warcraft.NET/Files/phys/Structures/PlytNode.cs
new file mode 100644
index 0000000..c727e69
--- /dev/null
+++ b/Warcraft.NET/Files/phys/Structures/PlytNode.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Warcraft.NET.Files.Phys.Structures
+{
+
+ [Serializable]
+ public struct PlytNode
+ {
+ ///
+ /// Unknown byte. Always 1 or -1
+ ///
+ public byte Unk; // 1 or -1
+
+ ///
+ /// Index into the data.Vertices
+ ///
+ public byte VertexIndex; // index in vertex list
+
+ ///
+ /// Index into data.Nodes
+ ///
+ public byte UnkIndex0; // index into the nodes
+
+ ///
+ /// Index into data.Nodes
+ ///
+ public byte UnkIndex1; // index into the nodes
+ }
+}
\ No newline at end of file