Skip to content

Commit

Permalink
greatly increasing Infinity Ward support to cover CoD2 & CoD4:MW
Browse files Browse the repository at this point in the history
  • Loading branch information
snake-biscuits committed Nov 26, 2021
1 parent 0c5574f commit 017406b
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 72 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Full documentation: [snake-biscuits.github.io/bsp_tool/](https://snake-biscuits.
- [Quake Live](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/id_software/quake3.py)
* [Infinity Ward](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/infinity_ward)
- [Call of Duty](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/infinity_ward/call_of_duty1.py)
- Call of Duty 2 :x:
- [Call of Duty 2](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/infinity_ward/call_of_duty2.py)
- Call of Duty 4: Modern Warfare :o:
- Call of Duty: Modern Warfare 2 :o:
* [Ion Storm](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/ion_storm)
Expand Down Expand Up @@ -135,7 +135,7 @@ Full documentation: [snake-biscuits.github.io/bsp_tool/](https://snake-biscuits.
- [Black Mesa](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/valve/sdk_2013.py)
- [Blade Symphony](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/valve/sdk_2013.py)
- Call of Duty: Black Ops III :o:
- Call of Duty: United Offensive :o:
- [Call of Duty: United Offensive](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/infinity_ward/call_of_duty1.py) :o:
- Call of Duty: World at War :o:
- [Fortress Forever](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/valve/orange_box.py)
- [G-String](https://github.com/snake-biscuits/bsp_tool/tree/master/bsp_tool/branches/valve/orange_box.py)
Expand Down Expand Up @@ -166,6 +166,8 @@ Full documentation: [snake-biscuits.github.io/bsp_tool/](https://snake-biscuits.
- Keeping records of the credits on so many games, helping to pin down engine origins
* [pakextract](https://github.com/yquake2/pakextract)
- Super useful tool for `.pak` files
* [PCGamingWiki](https://community.pcgamingwiki.com/files/category/16-official-patches/)
- Archiving old patches to help install old modding tools
* [REDxEYE](https://github.com/REDxEYE)
- Being very open and actively collaborating on SourceIO & Titanfall .bsps
* [Taskinoz](https://github.com/taskinoz)
Expand Down
9 changes: 6 additions & 3 deletions bsp_tool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from . import lumps
from .arkane import ArkaneBsp
from .id_software import QuakeBsp, IdTechBsp
from .infinity_ward import InfinityWardBsp
from .infinity_ward import InfinityWardBsp, D3DBsp
from .raven import RavenBsp
from .respawn import RespawnBsp
from .ritual import RitualBsp
Expand Down Expand Up @@ -50,10 +50,13 @@ def load_bsp(filename: str, branch_script: ModuleType = None) -> base.Bsp:
file_magic = bsp_file.read(4)
version = int.from_bytes(bsp_file.read(4), "little")
# identify BspVariant
if filename.lower().endswith(".d3dbsp"): # CoD2
if filename.lower().endswith(".d3dbsp"): # CoD2 & CoD4
assert file_magic == b"IBSP", "Mystery .d3dbsp!"
assert version in InfinityWard_versions, "Unexpected .d3dbsp format version!"
BspVariant = InfinityWardBsp
if version >= branches.infinity_ward.call_of_duty4.BSP_VERSION:
BspVariant = D3DBsp
else:
BspVariant = InfinityWardBsp
elif filename.lower().endswith(".bsp"):
if file_magic not in BspVariant_from_file_magic: # Quake / GoldSrc
version = int.from_bytes(file_magic, "little")
Expand Down
6 changes: 3 additions & 3 deletions bsp_tool/branches/infinity_ward/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""Infinity Ward created the Call of Duty Franchise, built on the idTech3 (RTCW) engine.
.bsp format shares IdTech's b'IBSP' FILE_MAGIC"""
from . import call_of_duty1 # (.bsp in .pk3)
# TODO: call_of_duty2 # (.d3dbsp in .iwd)
# TODO: call_of_duty4 # (.bsp in .ff)
from . import call_of_duty2 # (.d3dbsp in .iwd)
from . import call_of_duty4 # (.d3dbsp in .ff)
# TODO: blops3

# NOTE: I'm not buying any CoDs until Kotick is gone


scripts = [call_of_duty1]
scripts = [call_of_duty1, call_of_duty2, call_of_duty4]
86 changes: 45 additions & 41 deletions bsp_tool/branches/infinity_ward/call_of_duty1.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
from typing import List

from .. import base
from .. import shared # special lumps
from .. import shared
from ..id_software import quake
# from ..id_software import quake3


FILE_MAGIC = b"IBSP"

BSP_VERSION = 59

GAME_PATHS = ["Call of Duty"]
GAME_PATHS = ["Call of Duty", "Call of Duty: United Offensive"]

GAME_VERSIONS = {GAME: BSP_VERSION for GAME in GAME_PATHS}

Expand All @@ -24,32 +26,30 @@ class LUMP(enum.Enum):
TRIANGLE_SOUPS = 6
DRAW_VERTICES = 7
DRAW_INDICES = 8
CULL_GROUPS = 9 # visibility
CULL_GROUPS = 9
CULL_GROUP_INDICES = 10
PORTAL_VERTICES = 11 # areaportals; doors & windows
PORTAL_VERTICES = 11
OCCLUDERS = 12
OCCLUDER_PLANES = 13
OCCLUDER_EDGES = 14
OCCLUDER_INDICES = 15
AABB_TREES = 16 # Physics? or Vis Nodes?
AABB_TREES = 16
CELLS = 17
PORTALS = 18
LIGHT_INDICES = 19
NODES = 20
LEAVES = 21
LEAF_BRUSHES = 22
LEAF_SURFACES = 23
PATCH_COLLISION = 24 # decal clipping? reference for painting bullet holes?
PATCH_COLLISION = 24
COLLISION_VERTICES = 25
COLLISION_INDICES = 26
MODELS = 27
VISIBILITY = 28 # SPECIAL: Binary Partition tree (read bit by bit, with masks?)
LIGHTS = 29 # SPECIAL: string (typically ENTITIES would be #0)
VISIBILITY = 28
LIGHTS = 29
ENTITIES = 30
UNKNOWN_31 = 31 # FOGS ?
# big 32nd lump at ed of file, not in header?
# likely a zip / pakfile
# checking for file-magic would confirm this
# big "32nd lump" at end of file, not in header?


# struct InfinityWardBspHeader { char file_magic[4]; int version; QuakeLumpHeader headers[32]; };
Expand All @@ -60,24 +60,28 @@ class LUMP(enum.Enum):
# NOTE: all are incomplete guesses
class AxisAlignedBoundingBox(base.Struct): # LUMP 16
"""AABB tree"""
# too small to be mins & maxs of an AABB; probably indices (hence: AABB_TREE)
data: bytes
__slots__ = ["data"]
_format = "12s" # size may be incorrect
# not floats. some kind of node indices?
unknown: List[int]
__slots__ = ["unknown"]
_format = "3I"
_arrays = {"unknown": 3}


class Brush(base.Struct): # LUMP 4
first_side: int # index into the BrushSide lump
num_sides: int # number of sides after first_side in this Brush
__slots__ = ["first_side", "num_sides"]
_format = "2i"
class Brush(base.MappedArray): # LUMP 6
# NOTE: first side is calculated via: sum([b.num_sides for b in bsp.BRUSHES[-i]]) - 1
num_sides: int
material_id: int # Brush's overall contents flag?
_mapping = ["num_sides", "material_id"]
_format = "2H"


class BrushSide(base.Struct): # LUMP 3
plane: int # index into Plane lump
# NOTE: in some cases the plane index is a distance instead (float)
# "first 6 entries indicated by an entry in lump 6 [brushes] are distances (float), rest is plane ID's"
shader: int # index into Texture lump
__slots__ = ["plane", "shader"]
_format = "2i"
_format = "2I"


class Cell(base.Struct): # LUMP 17
Expand All @@ -87,14 +91,6 @@ class Cell(base.Struct): # LUMP 17
_format = "52s"


class CollisionVertex(base.MappedArray): # LUMP 25
x: float
y: float
z: float
_mapping = [*"xyz"]
_format = "3f"


class CullGroup(base.Struct): # LUMP 9
data: bytes
__slots__ = ["data"]
Expand Down Expand Up @@ -169,6 +165,7 @@ class Occluder(base.Struct): # LUMP 12


class PatchCollision(base.Struct): # LUMP 24
"""'Patches' are the CoD version of Source's Displacements (think of a fabric patch on torn clothes)"""
data: bytes
__slots__ = ["data"]
_format = "16s"
Expand All @@ -189,28 +186,33 @@ class Portal(base.Struct): # LUMP 18


class Shader(base.Struct): # LUMP 0
# assuming the same as Quake3 TEXTURE
"""possibly based on Quake3 Texture LumpClass"""
texture: str
flags: int
contents: int
__slots__ = ["texture", "flags", "contents"]
flags: List[int]
__slots__ = ["texture", "flags"]
_format = "64s2i"
_arrays = {"flags": ["surface", "contents"]}


class TriangleSoup(base.Struct): # LUMP 5
data: bytes
__slots__ = ["data"]
_format = "16s"
class TriangleSoup(base.MappedArray): # LUMP 5
material: int
draw_order: int # ?
first_vertex: int
num_vertices: int
first_triangle: int
num_triangles: int
_mapping = ["material", "draw_order", "first_vertex", "num_vertices",
"first_triangle", "num_triangles"]
_format = "2HI2HI"


# {"LUMP_NAME": {version: LumpClass}}
# {"LUMP_NAME": LumpClass}
BASIC_LUMP_CLASSES = {"COLLISION_INDICES": shared.UnsignedShorts,
"CULL_GROUP_INDICES": shared.UnsignedInts,
"DRAW_INDICES": shared.UnsignedShorts,
"LEAF_BRUSHES": shared.UnsignedInts,
"LEAF_SURFACES": shared.UnsignedInts,
"LIGHT_INDICES": shared.UnsignedShorts,
"OCCLUDER_EDGES": shared.UnsignedShorts,
"OCCLUDER_INDICES": shared.UnsignedShorts,
"OCCLUDER_PLANES": shared.UnsignedInts}

Expand All @@ -219,7 +221,7 @@ class TriangleSoup(base.Struct): # LUMP 5
# "BRUSHES": Brush,
"BRUSH_SIDES": BrushSide,
# "CELLS": Cell,
# "COLLISION_VERTICES": CollisionVertex,
# "COLLISION_VERTICES": quake.Vertex,
# "CULL_GROUPS": CullGroup,
# "DRAW_VERTICES": DrawVertex,
"LEAVES": Leaf,
Expand All @@ -228,6 +230,7 @@ class TriangleSoup(base.Struct): # LUMP 5
# "MODELS": Model,
# "NODES": Node,
# "OCCLUDERS": Occluder,
"OCCLUDER_EDGES": quake.Edge,
# "PATCH_COLLISION": PatchCollision,
"PLANES": Plane,
# "PORTALS": Portal,
Expand All @@ -236,4 +239,5 @@ class TriangleSoup(base.Struct): # LUMP 5

SPECIAL_LUMP_CLASSES = {"ENTITIES": shared.Entities}

methods = []

methods = [shared.worldspawn_volume]
Loading

0 comments on commit 017406b

Please sign in to comment.