diff --git a/LibBSP/LibBSP.csproj b/LibBSP/LibBSP.csproj
index 84eebd6..eb7e73c 100644
--- a/LibBSP/LibBSP.csproj
+++ b/LibBSP/LibBSP.csproj
@@ -68,6 +68,7 @@
+
diff --git a/LibBSP/Source/Extensions/UIVertexExtensions.cs b/LibBSP/Source/Extensions/UIVertexExtensions.cs
index ccead1d..c449317 100644
--- a/LibBSP/Source/Extensions/UIVertexExtensions.cs
+++ b/LibBSP/Source/Extensions/UIVertexExtensions.cs
@@ -107,9 +107,17 @@ namespace LibBSP {
}
UIVertex result = new UIVertex();
switch (type) {
+ case MapType.CoD: {
+ if (version == 0) {
+ goto case MapType.Quake3;
+ } else if (version == 1) {
+ result.color = Color32Extensions.FromArgb(255, 255, 255, 255);
+ goto case MapType.DMoMaM;
+ }
+ break;
+ }
case MapType.MOHAA:
case MapType.Quake3:
- case MapType.CoD:
case MapType.CoD2:
case MapType.CoD4:
case MapType.FAKK: {
@@ -194,9 +202,16 @@ namespace LibBSP {
structLength = 12;
break;
}
+ case MapType.CoD: {
+ if (version == 0) {
+ goto case MapType.Quake3;
+ } else if (version == 1) {
+ goto case MapType.DMoMaM;
+ }
+ break;
+ }
case MapType.MOHAA:
case MapType.Quake3:
- case MapType.CoD:
case MapType.FAKK: {
structLength = 44;
break;
@@ -224,7 +239,7 @@ namespace LibBSP {
}
///
- /// Gets the index for this lump in the BSP file for a specific map format.
+ /// Gets the index for the vertices lump in the BSP file for a specific map format.
///
/// The map type.
/// Index for this lump, or -1 if the format doesn't have this lump.
@@ -260,6 +275,9 @@ namespace LibBSP {
case MapType.STEF2Demo: {
return 6;
}
+ case MapType.CoD: {
+ return 7;
+ }
case MapType.Raven:
case MapType.Quake3: {
return 10;
@@ -270,5 +288,21 @@ namespace LibBSP {
}
}
+ ///
+ /// Gets the index for the patch vertices lump in the BSP file for a specific map format.
+ ///
+ /// The map type.
+ /// Index for this lump, or -1 if the format doesn't have this lump.
+ public static int GetIndexForPatchVertsLump(MapType type) {
+ switch (type) {
+ case MapType.CoD: {
+ return 25;
+ }
+ default: {
+ return -1;
+ }
+ }
+ }
+
}
}
diff --git a/LibBSP/Source/Structs/BSP/BSP.cs b/LibBSP/Source/Structs/BSP/BSP.cs
index 54c78ae..d5645a4 100644
--- a/LibBSP/Source/Structs/BSP/BSP.cs
+++ b/LibBSP/Source/Structs/BSP/BSP.cs
@@ -93,6 +93,10 @@ namespace LibBSP {
// MoHAA
private List _lodTerrains;
private List _staticModels;
+ // CoD
+ private List _patches;
+ private List _patchVerts;
+ private NumList _patchIndices;
// Nightfire
private Textures _materials;
private NumList _indices;
@@ -481,6 +485,52 @@ namespace LibBSP {
}
}
+ ///
+ /// A List of objects in the BSP file, if available.
+ ///
+ public List patches {
+ get {
+ if (_patches == null) {
+ int index = Patch.GetIndexForLump(version);
+ if (index >= 0) {
+ _patches = Patch.LumpFactory(reader.ReadLump(this[index]), version, this[index].version);
+ }
+ }
+ return _patches;
+ }
+ }
+
+ ///
+ /// A List of objects in the BSP file representing the patch vertices of the BSP, if available.
+ ///
+ public List patchVerts {
+ get {
+ if (_patchVerts == null) {
+ int index = UIVertexExtensions.GetIndexForPatchVertsLump(version);
+ if (index >= 0) {
+ _patchVerts = UIVertexExtensions.LumpFactory(reader.ReadLump(this[index]), version, 1);
+ }
+ }
+ return _patchVerts;
+ }
+ }
+
+ ///
+ /// A object containing the Patch Vertex Indices lump, if available.
+ ///
+ public NumList patchIndices {
+ get {
+ if (_patchIndices == null) {
+ NumList.DataType type;
+ int index = NumList.GetIndexForPatchIndicesLump(version, out type);
+ if (index >= 0) {
+ _patchIndices = NumList.LumpFactory(reader.ReadLump(this[index]), type);
+ }
+ }
+ return _patchIndices;
+ }
+ }
+
///
/// A object containing the Face Vertex Indices lump, if available.
///
@@ -772,8 +822,8 @@ namespace LibBSP {
}
// Get the index and length from the object
- int index = (int)indexProperty.GetGetMethod().Invoke(o, null);
- int count = (int)countProperty.GetGetMethod().Invoke(o, null);
+ int index = (int)(indexProperty.GetGetMethod().Invoke(o, null));
+ int count = (int)(countProperty.GetGetMethod().Invoke(o, null));
// Get the lump from this class
List theLump = targetLump.GetGetMethod().Invoke(this, null) as List;
diff --git a/LibBSP/Source/Structs/BSP/Face.cs b/LibBSP/Source/Structs/BSP/Face.cs
index 723fa44..a214c65 100644
--- a/LibBSP/Source/Structs/BSP/Face.cs
+++ b/LibBSP/Source/Structs/BSP/Face.cs
@@ -74,6 +74,14 @@ namespace LibBSP {
lightMaps = -1;
patchSize = new Vector2(Single.NaN, Single.NaN);
switch (type) {
+ case MapType.CoD: {
+ texture = BitConverter.ToInt16(data, 0);
+ firstVertex = BitConverter.ToInt32(data, 4);
+ numVertices = BitConverter.ToInt16(data, 8);
+ numIndices = BitConverter.ToInt16(data, 10);
+ firstIndex = BitConverter.ToInt32(data, 12);
+ break;
+ }
case MapType.Quake:
case MapType.Quake2:
case MapType.Daikatana:
@@ -180,6 +188,10 @@ namespace LibBSP {
}
int structLength = 0;
switch (type) {
+ case MapType.CoD: {
+ structLength = 16;
+ break;
+ }
case MapType.Quake:
case MapType.Quake2:
case MapType.Daikatana: {
@@ -272,7 +284,8 @@ namespace LibBSP {
case MapType.Quake2:
case MapType.SiN:
case MapType.Daikatana:
- case MapType.SoF: {
+ case MapType.SoF:
+ case MapType.CoD: {
return 6;
}
case MapType.Vindictus:
diff --git a/LibBSP/Source/Structs/BSP/LODTerrain.cs b/LibBSP/Source/Structs/BSP/LODTerrain.cs
index 3c87384..8c5438f 100644
--- a/LibBSP/Source/Structs/BSP/LODTerrain.cs
+++ b/LibBSP/Source/Structs/BSP/LODTerrain.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace LibBSP {
///
- /// Holds the data used by the brush structures of all formats of BSP.
+ /// Holds the data for a terrain object in MoHAA.
///
public struct LODTerrain {
diff --git a/LibBSP/Source/Structs/BSP/Leaf.cs b/LibBSP/Source/Structs/BSP/Leaf.cs
index 5e29740..f66c141 100644
--- a/LibBSP/Source/Structs/BSP/Leaf.cs
+++ b/LibBSP/Source/Structs/BSP/Leaf.cs
@@ -90,6 +90,13 @@ namespace LibBSP {
numMarkBrushes = BitConverter.ToInt32(data, 44);
break;
}
+ case MapType.CoD: {
+ firstMarkFace = BitConverter.ToInt32(data, 8);
+ numMarkFaces = BitConverter.ToInt32(data, 12);
+ firstMarkBrush = BitConverter.ToInt32(data, 16);
+ numMarkBrushes = BitConverter.ToInt32(data, 20);
+ break;
+ }
default: {
throw new ArgumentException("Map type " + type + " isn't supported by the Leaf class.");
}
@@ -209,6 +216,9 @@ namespace LibBSP {
case MapType.Nightfire: {
return 11;
}
+ case MapType.CoD: {
+ return 21;
+ }
default: {
return -1;
}
diff --git a/LibBSP/Source/Structs/BSP/Model.cs b/LibBSP/Source/Structs/BSP/Model.cs
index 002860d..40ff8ba 100644
--- a/LibBSP/Source/Structs/BSP/Model.cs
+++ b/LibBSP/Source/Structs/BSP/Model.cs
@@ -22,6 +22,8 @@ namespace LibBSP {
[Count("brushes")] public int numBrushes { get; private set; }
[Index("faces")] public int firstFace { get; private set; } // Quake/GoldSrc
[Count("faces")] public int numFaces { get; private set; }
+ [Index("markSurfaces")] public int firstLeafPatch { get; private set; } // CoD
+ [Count("markSurfaces")] public int numLeafPatches { get; private set; }
///
/// Creates a new object from a byte array.
@@ -42,6 +44,8 @@ namespace LibBSP {
numBrushes = -1;
firstFace = -1;
numFaces = -1;
+ firstLeafPatch = -1;
+ numLeafPatches = -1;
switch (type) {
case MapType.Quake: {
headNode = BitConverter.ToInt32(data, 36);
@@ -94,7 +98,13 @@ namespace LibBSP {
numBrushes = BitConverter.ToInt32(data, 36);
break;
}
- case MapType.CoD:
+ case MapType.CoD: {
+ firstFace = BitConverter.ToInt32(data, 24);
+ numFaces = BitConverter.ToInt32(data, 28);
+ firstLeafPatch = BitConverter.ToInt32(data, 32);
+ numLeafPatches = BitConverter.ToInt32(data, 36);
+ goto case MapType.CoD2;
+ }
case MapType.CoD2:
case MapType.CoD4: {
firstBrush = BitConverter.ToInt32(data, 40);
diff --git a/LibBSP/Source/Structs/BSP/Node.cs b/LibBSP/Source/Structs/BSP/Node.cs
index 506ab07..2f6561e 100644
--- a/LibBSP/Source/Structs/BSP/Node.cs
+++ b/LibBSP/Source/Structs/BSP/Node.cs
@@ -27,8 +27,8 @@ namespace LibBSP {
plane = BitConverter.ToInt32(data, 0); // All formats I've seen use the first 4 bytes as an int, plane index
switch (type) {
case MapType.Quake: {
- this.child1 = BitConverter.ToInt16(data, 4);
- this.child2 = BitConverter.ToInt16(data, 6);
+ child1 = BitConverter.ToInt16(data, 4);
+ child2 = BitConverter.ToInt16(data, 6);
break;
}
// These all use the first three ints for planenum and children
@@ -56,8 +56,8 @@ namespace LibBSP {
case MapType.Quake3:
case MapType.FAKK:
case MapType.CoD: {
- this.child1 = BitConverter.ToInt32(data, 4);
- this.child2 = BitConverter.ToInt32(data, 8);
+ child1 = BitConverter.ToInt32(data, 4);
+ child2 = BitConverter.ToInt32(data, 8);
break;
}
default: {
@@ -179,6 +179,9 @@ namespace LibBSP {
case MapType.STEF2Demo: {
return 11;
}
+ case MapType.CoD: {
+ return 20;
+ }
default: {
return -1;
}
diff --git a/LibBSP/Source/Structs/BSP/Patch.cs b/LibBSP/Source/Structs/BSP/Patch.cs
new file mode 100644
index 0000000..980e961
--- /dev/null
+++ b/LibBSP/Source/Structs/BSP/Patch.cs
@@ -0,0 +1,116 @@
+#if UNITY_2_6 || UNITY_2_6_1 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
+#define UNITY
+#endif
+
+using System;
+using System.Collections.Generic;
+#if UNITY
+using UnityEngine;
+#endif
+
+namespace LibBSP {
+#if !UNITY
+ using Vector2 = Vector2d;
+#endif
+
+ ///
+ /// Holds the data for a patch in a CoD BSP.
+ ///
+ public struct Patch {
+
+ public short shader { get; private set; }
+ public short type { get; private set; }
+ public Vector2 dimensions { get; private set; }
+ public int flags { get; private set; }
+ [Index("patchVerts")] public int firstVertex { get; private set; }
+ [Count("patchVerts")] public int numVertices { get; private set; }
+ [Count("patchIndices")] public int numIndices { get; private set; }
+ [Index("patchIndices")] public int firstIndex { get; private set; }
+
+ ///
+ /// Creates a new object from a byte array.
+ ///
+ /// byte array to parse.
+ /// The map type.
+ /// The version of this lump.
+ /// was null.
+ /// This structure is not implemented for the given maptype.
+ public Patch(byte[] data, MapType type, int version = 0) : this() {
+ if (data == null) {
+ throw new ArgumentNullException();
+ }
+ switch (type) {
+ case MapType.CoD: {
+ shader = BitConverter.ToInt16(data, 0);
+ this.type = BitConverter.ToInt16(data, 2);
+ if (this.type == 0) { // Patch
+ short x = BitConverter.ToInt16(data, 4);
+ short y = BitConverter.ToInt16(data, 6);
+ dimensions = new Vector2(x, y);
+ flags = BitConverter.ToInt32(data, 8);
+ firstVertex = BitConverter.ToInt32(data, 12);
+ numVertices = x * y;
+ } else if (this.type == 1) { // Terrain
+ numVertices = BitConverter.ToInt16(data, 4);
+ numIndices = BitConverter.ToInt16(data, 6);
+ firstVertex = BitConverter.ToInt32(data, 8);
+ firstIndex = BitConverter.ToInt32(data, 12);
+ }
+ break;
+ }
+ default: {
+ throw new ArgumentException("Map type " + type + " isn't supported by the Patch class.");
+ }
+ }
+ }
+
+ ///
+ /// Factory method to parse a byte array into a List of objects.
+ ///
+ /// The data to parse.
+ /// The map type.
+ /// The version of this lump.
+ /// A List of objects.
+ /// was null.
+ /// This structure is not implemented for the given maptype.
+ public static List LumpFactory(byte[] data, MapType type, int version = 0) {
+ if (data == null) {
+ throw new ArgumentNullException();
+ }
+ int structLength = 0;
+ switch (type) {
+ case MapType.CoD: {
+ structLength = 16;
+ break;
+ }
+ default: {
+ throw new ArgumentException("Map type " + type + " isn't supported by the Patch lump factory.");
+ }
+ }
+ List lump = new List(data.Length / structLength);
+ byte[] bytes = new byte[structLength];
+ for (int i = 0; i < data.Length / structLength; ++i) {
+ Array.Copy(data, (i * structLength), bytes, 0, structLength);
+ lump.Add(new Patch(bytes, type, version));
+ }
+ return lump;
+ }
+
+ ///
+ /// Gets the index for this lump in the BSP file for a specific map format.
+ ///
+ /// The map type.
+ /// Index for this lump, or -1 if the format doesn't have this lump or it's not implemented.
+ public static int GetIndexForLump(MapType type) {
+ switch (type) {
+ case MapType.CoD: {
+ return 24;
+ }
+ default: {
+ return -1;
+ }
+ }
+ }
+
+ }
+}
diff --git a/LibBSP/Source/Structs/Common/Lumps/NumList.cs b/LibBSP/Source/Structs/Common/Lumps/NumList.cs
index c658d05..2f9a0c5 100644
--- a/LibBSP/Source/Structs/Common/Lumps/NumList.cs
+++ b/LibBSP/Source/Structs/Common/Lumps/NumList.cs
@@ -150,6 +150,10 @@ namespace LibBSP {
dataType = DataType.UInt16;
return 16;
}
+ case MapType.CoD: {
+ dataType = DataType.UInt32;
+ return 23;
+ }
}
dataType = DataType.Invalid;
return -1;
@@ -239,6 +243,10 @@ namespace LibBSP {
dataType = DataType.UInt16;
return 17;
}
+ case MapType.CoD: {
+ dataType = DataType.UInt32;
+ return 22;
+ }
}
dataType = DataType.Invalid;
return -1;
@@ -266,6 +274,10 @@ namespace LibBSP {
dataType = DataType.UInt32;
return 7;
}
+ case MapType.CoD: {
+ dataType = DataType.UInt16;
+ return 8;
+ }
case MapType.Raven:
case MapType.Quake3: {
dataType = DataType.UInt32;
@@ -276,6 +288,23 @@ namespace LibBSP {
return -1;
}
+ ///
+ /// Gets the index for the patch indices lump in the BSP file for a specific map format, and the type of data the format uses.
+ ///
+ /// The map type.
+ /// out parameter that will contain the data type this version uses.
+ /// Index for this lump, or -1 if the format doesn't have this lump or it's not implemented.
+ public static int GetIndexForPatchIndicesLump(MapType version, out DataType dataType) {
+ switch (version) {
+ case MapType.CoD: {
+ dataType = DataType.UInt16;
+ return 26;
+ }
+ }
+ dataType = DataType.Invalid;
+ return -1;
+ }
+
///
/// Gets the index for the texture table lump in the BSP file for a specific map format, and the type of data the format uses.
///