Wolfenstein Modloader Buy me a coffeeKaffee spendieren

Wiki / Latest research roundsNeueste Forschungsrunden

A Developer Map for Testing Mods (game/wolfsdk/modtest)

Partly solvedTeilweise gelöst Original page in the GitHub wikiOriginalseite im GitHub-Wiki

In plain wordsIn einfachen Worten

UpdateAktualisierung Newer than this page: the TNC Dev Menu and TNC Custom Map Status pages record that this map loads from the developer menu, confirmed in game on 2026-10-02. How the enemies behave and whether the developer loadout applies are still not confirmed.Neuer als diese Seite: Die Seiten TNC Dev Menu und TNC Custom Map Status verzeichnen, dass diese Karte aus dem Entwicklermenü lädt, im Spiel bestätigt am 02.10.2026. Wie sich die Gegner verhalten und ob die Entwickler-Ausrüstung greift, ist noch nicht bestätigt.

This round-10 report builds a developer map for trying out mods in Wolfenstein II: The New Colossus, named game/wolfsdk/modtest. Instead of a new room it copies the retail Gestapo office map (c2v1), because that already has working collision, lighting and the walkable navmesh enemies need; the mission is removed and test content is added. The build keeps every existing entry byte-identical and passes 79 of 79 checks. The report itself lists everything as not yet proven in game.

  • 304 of 9,206 entities are removed (mission scripts, hidden enemies, triggers, alarms, retail pickups); 8,902 stay unchanged.
  • The armoury gets 23 pickups (11 weapons plus ammo, health and armour) and 5 lights; the office hall gets 8 enemies with their backs to the door.
  • The new name needs 18 map-level files and 102 light-probe images copied; 120 entries are added to the archive.
  • The LKW and DKW weapons and grenades have no pickup in the game; they can only come from the developer loadout, which may not apply on the devmap path.
  • Not proven in game at the time: enemies without a spawner, collision of 91 shared shapes, pickup heights and the light probes; a robot enemy and respawns were left out.

Dieser Bericht aus Runde 10 baut eine Entwicklerkarte zum Ausprobieren von Mods in Wolfenstein II: The New Colossus, mit dem Namen game/wolfsdk/modtest. Statt eines neuen Raums kopiert er die Gestapo-Büro-Karte (c2v1) der Verkaufsversion, weil sie schon funktionierende Kollision, Beleuchtung und das begehbare Navmesh hat, das Gegner brauchen; die Mission ist entfernt und Testinhalt hinzugefügt. Der Build lässt jeden vorhandenen Eintrag byte-genau unverändert und besteht 79 von 79 Prüfungen. Der Bericht selbst führt alles als im Spiel noch nicht bewiesen.

  • 304 von 9.206 Entitäten werden entfernt (Missionsskripte, versteckte Gegner, Auslöser, Alarme, Original-Pickups); 8.902 bleiben unverändert.
  • Die Waffenkammer bekommt 23 Pickups (11 Waffen plus Munition, Gesundheit und Rüstung) und 5 Lichter; die Bürohalle bekommt 8 Gegner, die mit dem Rücken zur Tür stehen.
  • Der neue Name braucht 18 kopierte Dateien der Kartenebene und 102 Lightprobe-Bilder; 120 Einträge kommen ins Archiv.
  • Die Waffen LKW und DKW sowie Granaten haben im Spiel kein Pickup; sie kämen nur aus der Entwickler-Ausrüstung, die auf dem devmap-Weg vielleicht nicht greift.
  • Damals im Spiel nicht bewiesen: Gegner ohne Spawner, die Kollision von 91 geteilten Formen, Pickup-Höhen und die Lightprobes; ein Robotergegner und Respawns wurden weggelassen.

Technical detailsTechnische Details

Der technische Teil ist auf Englisch – so, wie er im Wiki steht. Unterstrichene Begriffe haben eine Erklärung auf Deutsch.

Round-10 pass: a developer map for testing mods, built on retail c2v1 geometry and added as a further map to the same dlc_0 chunk that already holds the kit level and the box map. The build keeps every kit-level entry byte-identical and passes all its checks. Not proven in game; the report lists what is unproven, worst first, and gives the install steps and the in-game test.

Date: 2026-10-02. The game was not started. Nothing was written under <Steam library> or Saved Games; the install was only read. Builds went only to D:/wolf-decomp/tmp/modtestmap/. New files: tools/build_modtestmap.py and this report. No other file was changed. tools/build_boxmap.py and wolfsdk/mapinstall.py were reused without edits.

Result

python tools/build_modtestmap.py (about 8 minutes; --once skips the determinism builds) writes:

File Content
D:/wolf-decomp/tmp/modtestmap/modtest/dlc_0/base/chunk_22.resources 166,267,606 B, sha256 7c030b2a0c2c52605a87790c82f5edbcc422be5fee4c0488cc5c0b07b31c06be. Contains kit level H (c2v1, all 7,130 entries byte-identical), the box (29 entries, unchanged), and modtest (120 added entries).
.../modtest/dlc_0/base/packagemapspec.json c2v1_custom, c2v1, game/wolfsdk/box, game/wolfsdk/modtest (what mapinstall.install writes for this chunk)
.../modtest/dlc_0/dlcinfo.json {"dlcid": 4}
.../modtest/side_files.json The 14 dlc_2 side files, plus 2 textures.cache links (box, modtest) → dlc_2's c2v1 textures.cache
.../modtest/devmenu_entry.txt The dev menu item (below)
.../modtest/manifest.json Hashes, dropped classes, every new block with its donor and position, added entries and rows, check results
.../modtest/../box/ The stage: build_boxmap.run() output (H + box, sha 1fc43560…, its own 31 checks)
D:/wolf-decomp/tmp/modtestmap/build_log.txt The full run: 79 OK, 0 FAIL

How it composes with the box: build_modtestmap.run() calls build_boxmap.run() (H → H + box, all box checks), then adds modtest's entries to that chunk with the same build_kitmap.rebuild() and idclwrite.finalize(). Nothing in the box code is duplicated (maplevel(), ENGINE_NAMES, DEVMENU and clone logic are imported).

Design choice: retail c2v1 geometry, not a kit/glTF room

Chosen: copy the RETAIL c2v1 map (dlc_2's chunk_22) under the new name. The mission is removed and our test content is added.

Why:

  • Enemies need a navmesh. One cannot be generated (r3_navdata.md §6: no encoder; the engine only cuts holes, it never adds surface). A kit or glTF room has no navmesh under it, so AI would stand still at best. Retail c2v1 ships c2v1.hknavmesh. The build copies it byte-identical (gated) and checks every enemy against it.
  • Collision is solved there. The player walks on retail's playerclip carrier mesh (memory: tnc-custom-map-route, variant D analysis). New kit geometry needed the | 0x18 cm workaround and still had stair problems.
  • Lighting is solved there. Baked lightmaps (.proc), 102 light probes, 408 retail lights and the Umbra tome/pvs/shadows all match the geometry they were baked for. The kit/glTF route borrows single lightmap texels (r9 risk 5: "blotchy or dark").
  • Scene points can stay. The 176 combat, 54 roam, 41 search and 10 traversal scene points belong to the retail geometry. Enemies keep cover and search behaviour. A new room has none (r2_ainav.md §5).
  • Precedent: a retail-based c2v1 container served from dlc_0 loaded and played in game on 2026-09-24 (relit lights, normal mission start, memory tnc-custom-map-route). The kit/glTF route has no in-game AI evidence.

Cost: the map is the Gestapo office, not a clean white room. The test area uses two of its rooms (below). The rest of the building stays walkable and empty.

What the new name needs (and gets)

  • 18 map-level entries of retail c2v1, copied under the new name:
    • .entities and .mapresources (both our own payload);
    • _combo/modtest.proc, modtest.prockd;
    • _world.tome + -metadata.json, _world.bmodel, sky.bmodel, world.hkshape, _world.pvs, _world.bshadows;
    • modtest.ambientsh, modtest.hknavmesh, devmapinfo.json;
    • mega.decl, megatrans.decl, megafoliagetrans.decl;
    • generated/staticstreamtree/game/wolfsdk/modtest.bsstree.

These are retail bytes. H's modified tome and hkshape are not used, and H's removed _world.bshadows is taken from retail. - 102 light-probe images under maps/game/wolfsdk/modtest/lightprobes/<entity>_row.bimage. The engine builds that name from the map name ('maps/%s/lightprobes/%s_row.bimage', r9 #7). The box has no probes, so it did not need this; modtest keeps all 102 LIGHT_PROBE entities. - All 15 engine-derived names exist under the new name: the box's 14 format strings plus _combo/_world.bshadows. - Per-entity resources stay under c2v1's names. These are the 90 trigger/volume/collision-only cms; the text names them explicitly (clipModelName). Every such reference is checked to resolve. - mega*.decl keeps landpagefile on c2v1's VT pages (r9 #9). - textures.cache is one more hardlink, dlc_0/base/maps/game/wolfsdk/modtest/textures.cache. mapinstall.install already creates it for every extra map.

What was taken out of retail c2v1

8,902 of 9,206 entities are kept verbatim. 304 are dropped:

Removed n Why
idKisculeEntity 33 mission scripts
idAI2, idTarget_AISpawn, idScenePoint_Spawn 44, 9, 9 the mission's hidden enemies and their spawn chain
idAlarm, idAlarmSystem 11, 2 their reinforcement spawners are gone
idTrigger, idTrigger_Hurt, idWorldMarker 48, 1, 8 mission triggers, hurt volume, objective markers
idSoundClip, idEnvironmentSpeaker 38, 29 positional sound from c2v1's banks; no bank loads for a new map name (r9 #10)
idPlayerStart 2 replaced by modtest_start
idProp2 prop/pickup/* 67 retail pickups and collectibles (collectibles count as DLC progress)
challenge-layer-only 2 layer/dlc/c2v1_challenge1
bound to a dropped entity 1 Hans's cigarette (bindInfo.bindParent → the boss)

Five kept entities lost references to dropped ones (drop_refs):

  • the 4 automap images lose their loot-reveal reference to the map collectible;
  • the group manager loses its 2 alarmSystem references.

The world keeps everything except devmapInvLoadout. It changes from devinvloadout/dlc/c2v1 to devinvloadout/code_referenced/default_sp_devloadout (all 9 weapon families, r4_pickups §5.2).

Kept: geometry, lights, probes, props, doors, glass, decals, scene points, volumes and the group manager.

The kept layered entities, 54 in all, are all in layer/dlc/c2v1 (gated):

  • 46 door props;
  • 3 idAnimated;
  • 4 idInfo;
  • 1 idVolume.

What is placed where

Floor z = 0 in both rooms. The positions come from the retail collision grid (re_probes/viewer/collision.json via design_kitmap.retail_grid).

Armoury: the room the retail challenge start is in (x 23..35, y −66..−78).

  • Start: modtest_start at (29, −73), facing north toward the one door into the hall, which is at (29, −65.5).
  • 5 white fill lights (modtest_light_*), each a clone of the hall chandelier c2v1_lights_lights_light_point_1603252612 (point_frac40):
    • 2 over the pickup rows: z 3, radius 6, intensity 5;
    • 3 down the hall's centre aisle: z 4.5, radius 10, intensity 4.

23 pickups, all on the armoury floor. Each is a deep copy of a retail placement of the same inherit. Ammo is next to its weapon:

x, y Pickup (inherit) Gives (useableComponentDecl) Donor
24.6, −70.5 prop/pickup/weapons/handgun/handgun weapon/sp/handgun (Pistole) c0v2
25.8, −70.5 prop/pickup/ammo/handgun/medium ammo/sp/handgun/medium c2v1
24.6, −71.5 prop/pickup/weapons/smg/smg weapon/sp/smg (MP) c0v2
25.8, −71.5 prop/pickup/ammo/smg/medium ammo/sp/smg/medium c0v2
24.6, −72.5 prop/pickup/weapons/shotgun/shotgun weapon/sp/shotgun (Schockhammer) c1v3
25.8, −72.5 prop/pickup/ammo/shotgun/medium ammo/sp/shotgun/medium c07p2
24.6, −73.5 prop/pickup/weapons/battlerifle/battlerifle weapon/sp/battlerifle (Sturmgewehr) c11p1
25.8, −73.5 prop/pickup/ammo/battlerifle/medium ammo/sp/battlerifle/medium c07p2
24.6, −74.5 prop/pickup/weapons/kampf/kampf weapon/sp/kampf (Kampfpistole) c1v3
25.8, −74.5 prop/pickup/ammo/kampfpistol/medium ammo/sp/kampf/medium c07p2
33.4, −70.5 prop/pickup/weapons/lasergewehr weapon/sp/lasergewehr (heavy) c06p1d1
32.2, −70.5 prop/pickup/ammo/lkw/battery_medium ammo/sp/lkw/battery_medium (LKW) c06p1d1
33.4, −71.5 prop/pickup/weapons/dieselgewehr weapon/sp/dieselgewehr (heavy) c07p2
32.2, −71.5 prop/pickup/ammo/dkw/diesel_medium ammo/sp/dkw/medium (DKW) c06p1d1
33.4, −72.5 prop/pickup/weapons/hammergewehr weapon/sp/hammergewehr (heavy) c09p2
33.4, −73.5 prop/pickup/weapons/ubergewehr weapon/sp/ubergewehr (heavy) c09p2
33.4, −74.5 prop/pickup/weapons/axe/axe weapon/sp/hatchet bonusmap01
32.2, −74.5 prop/pickup/weapons/knife weapon/sp/knife_throw c2v1
32.2, −72.5 prop/pickup/armor/helmet/soldier armor/helmet/soldier c0v2
27.6, −70.5 prop/pickup/health/kits/medium health/medium c07p2
30.4, −70.5 prop/pickup/armor/medium armor/medium c09p1
27.6, −75.5 prop/pickup/health/kits/large health/large c07p2
30.4, −75.5 prop/pickup/armor/large armor/large c1v3_venus

How the donors were chosen:

  • Each donor is the first retail placement without a layer that has isStatic = false, so physics settles it. If no such placement exists, it is the first placement without a layer. The scan runs over base/*.resources, then dlc_1..dlc_3, in name order.
  • Static pickups get z + 0.03 (retail rests them at 0.02–0.04 in c2v1). Dynamic ones get z + 0.10 and drop onto the floor.

Not available as pickups:

  • LKW and DKW: there is no pickup entityDef, and no map in the corpus places one (r4_pickups). The world's dev loadout should give them; their ammo is above.
  • Grenades: there is no prop/pickup/weapons/grenade* entityDef.

Range: the two-storey office hall north of the armoury (x 21..37, y −35..−65). It has a centre aisle, two side aisles, cubicle desks and partitions. The retail chandeliers and wall lamps stay.

8 enemies, all of c2v1's own types:

  • each is a deep copy of the first retail c2v1 placement of that inherit;
  • flags.hide = false;
  • roam target (targets) removed;
  • facing north, with their backs to the door.
Name Inherit x, y From start
modtest_ai_soldier ai/dlc/silentdeath/soldier/generic/soldier_light 29, −60 13.0 m
modtest_ai_nailgun ai/dlc/silentdeath/soldier/generic/soldier_nailgun 22.5, −56 18.2 m
modtest_ai_heavy ai/dlc/silentdeath/soldier/generic/soldier_heavy 35.5, −56 18.2 m
modtest_ai_elite ai/dlc/silentdeath/elite/generic/elite_heavy 29, −50 23.0 m
modtest_ai_supersoldier ai/supersoldat/generic/supersoldat_lasergewehr 35.5, −48 25.8 m
modtest_ai_commander ai/dlc/silentdeath/commander/generic/commander_handgun 22.5, −43 30.7 m
modtest_ai_dog ai/kampfhund/generic/kampfhund 35.5, −41 32.7 m
modtest_ai_ubersoldat ai/dlc/silentdeath/ubersoldat/ubersoldat_cannon 29, −37.5 35.5 m

Their groupName values come from the donors and are kept groups of the retained idEncounterGroupMgr (FirstArea/SecondArea/ThirdArea/Commander), so an alerted group shares awareness.

Mapresources:

  • retail c2v1's 20,832 rows, with the 120 map-named rows renamed;
  • plus 34 always-load rows: every row a donor's own map lists for that donor's values (entityDef, propItem, model/cm, modelAsset, md6Def, propHealth) that c2v1 lacks. Example: shotgun, battlerifle-ammo and armour models.

Checks (build_log.txt: 79 OK, 0 FAIL)

Container

  • Before finalize, probe_idclhash rejects the file (negative control).
  • Finalize moves the data hash of exactly the 120 added entries.
  • Entry count is 7,159 + 120.
  • Every H + box entry is unchanged: payload, version, flags, dependencies.
  • Every one of H's 7,130 entries is byte-identical, compared directly against re_probes/kitmap/variants/H/chunk_22.resources.
  • The 120 entries are each present once, as written.
  • probe_datahash reports +0x50 7278/7278 (the 1 mode-4 entry is skipped, as in every build). probe_idclhash reports +0x08 1/1 +0x20 1/1.

New name complete

  • 18 map-level and 102 light-probe entries were copied.
  • naming_problems() returns []. It checks:
    • every retail map-named entry has a copy;
    • every LIGHT_PROBE entity has its image under the new name;
    • no mapresources row still names an old map-named resource;
    • every such row exists renamed, and the map list is the new name;
    • every quoted maps/game/dlc/c02/c2v1/... value in modtest's texts names an existing per-entity resource, never a map-named one;
    • the only exception is mega*.decl.
  • All 15 engine-derived names exist under the new name.
  • c2v1 and the box keep their own entries.
  • No map-named row is unresolved.

Controls, each of which fails as it should:

  • A: modtest.ambientsh left under the old name only;
  • B: _world.bshadows left under the old name only;
  • C: one light-probe image left under the old name only;
  • D: a mapresources row left on the old name;
  • E: the text names c2v1's own .proc;
  • F: the text names a nonexistent c2v1 cm;
  • G: the navmesh is missing → the engine-name check fails.

.entities

  • The authored text reads back unchanged and round-trips byte-exact.
  • build_custom_map.check finds nothing: no dangling references, and every inherit is among the 996 mounted entityDefs. Control: a fake inherit fails.
  • Every new block's donor is a retail block of the same inherit and class.
  • Every new block has its donor's exact field set. Only the documented edits differ: orientation, lightColor, targets, a foreign groupName. Control: an extra field fails.
  • Every decl, model and entityDef value resolves in the mounted archives (kit.json mount with our chunk). This covers the new blocks and the world's new loadout. A field counts as a decl reference when the retail donor's value there resolves. Control: a fake useableComponentDecl fails.
  • Kept retail blocks are verbatim except the world and the 5 with dropped references.
  • No mission class or retail pickup is left.
  • Every enemy has hide = false, no roam target, and a valid group.
  • Every kept layered entity is in layer/dlc/c2v1.

Placement

  • The modtest navmesh is byte-identical to retail's.
  • The start and the 23 pickups stand on retail-clear floor over the start's navmesh component, inside the armoury. The pickups are ≥ 1 m apart.
  • Each enemy:
    • has a navmesh disc in the start's component (radius 0.6 m, 0.9 m for the supersoldier, 1.2 m for the Übersoldat);
    • stands on clear floor;
    • has clear sight down its aisle from the hall's south cross aisle (no solid 1.3–1.8 m above the floor).
  • Sight straight from the door is 72–100 % (reported).

Placement controls, each of which fails as it should:

  • a point in the hall wall fails the enemy test;
  • the sight test across the cubicle partitions fails.

Mapresources

  • Retail rows are kept in order, the map-named ones renamed, plus the 34 rows.
  • Every added row resolves.
  • Every new entityDef is preloaded.

Install side

  • mapinstall.check_container returns ['game/wolfsdk/box', 'game/wolfsdk/modtest'].
  • tools/verify_mapinstall.py passes ("Alles in Ordnung").

Determinism: two builds give the same sha256, and the box stage passes its own determinism check.

Not proven in game (worst first)

  1. The dev menu command branch (tnc_devmenu_fix), devmap with a non-retail name, and the box itself have never run (r9 "Not proven" 1–2). modtest depends on the same chain.
  2. Enemies placed with hide = false and no spawner have no in-game evidence yet. The precedents are the kit map and a c2v2 debug dummy. They should idle and then fight, using the retail scene points, but this is unseen.
  3. Campaign mode with no chapter part makes the player the generic player. Whether devmapInvLoadout (all weapons) is applied on the devmap path is still open (r4_pickups open question 1). The pickups work either way.
  4. Collision of 91 shared cms: H's variant-D fix ORed 0x18 into 91 model-named cms that retail c2v1 also uses. Those cms are shared by name and cannot change without changing c2v1. Retail static instances with these models (floors, walls, caps, bookcases, chairs) now also block the player and AI.
    • Expected effect: none on the floors.
    • Possible effect: snagging on stairs. The test area has none.
  5. Pickup heights. A static pickup from another map may float or sink a few centimetres. Its rest height was taken from c2v1's measurements.
  6. Sound. There are no map sound banks: expect the warning [SOUND] No banks found for map 'game/wolfsdk/modtest'. Ambience is silent; weapons and VO use global banks.
  7. Light probes. The probes' images are byte copies under the new name. That the engine finds them there is read, not seen.

Install (game closed; Freedom Chronicles installed)

  1. Revert the mods in the loader (or python -m wolfsdk revert). While mods are applied, mapinstall may only swap the chunk; the new textures.cache link is a new file.
  2. Install the chunk: python -m wolfsdk map-install D:\wolf-decomp\tmp\modtestmap\modtest\dlc_0\base\chunk_22.resources This writes dlc_0's packagemapspec with all four maps, hardlinks both new textures.cache names, and records everything for uninstall.
  3. Dev menu: add the item below to devmenuoption/main in tools/build_devmenu_fix.py (another agent owns that file). It goes after the box item: num 4 → 5. Without the box, use item[3] and num 3 → 4.

As a dict next to BOX_ITEM:

python MODTEST_ITEM = {"devMenuDisplayName": "WolfSDK: Mod test map", "cmds": ['si_spawnspot "modtest_start"', 'si_nextlayeractive "layer/dlc/c2v1"', 'si_filllayeractive ""', 'si_devprogression ""', 'si_checkpointName ""', "si_gamemode 0", "devmap game/wolfsdk/modtest"]} Then rebuild that mod. 4. Apply the mods again and start the game.

Undo: python -m wolfsdk map-uninstall, or install the H or box chunk again.

In-game test

  1. Dev menu → "WolfSDK: console test" must show g_debugLayerChanges = 1. Otherwise the command branch is broken and nothing below means anything.
  2. Dev menu → "WolfSDK: Mod test map".
    • Pass: you stand in a lit room with weapons, ammo, health and armour on the floor to the left and right. A door to the north leads into an office hall with 8 enemies standing with their backs to you.
  3. Pick up each weapon. Open the weapon wheel and check whether all weapons, including LKW/DKW, are there from the start (the loadout question).
  4. Walk through the door and shoot:
    • the soldier at 13 m;
    • the elite at 23 m;
    • the Übersoldat at the far end at 35 m.

Do they react, take cover behind the desks, and come after you? God mode from cheats_gamemode helps. 5. condump modtest1.txt and send the file.

Log line Meaning
Map game/wolfsdk/modtest is not present in this package the spec is not installed
The map ... isn't present in the cache file the old chunk is still in dlc_0
MountMemoryDatabase: Failed to open ...modtest/textures.cache the link is missing
[SOUND] No banks found for map 'game/wolfsdk/modtest' expected
Failed to load player entityDef the player fallback broke
lines naming lightprobes/..._row.bimage the probe lookup does not use the map name the way it was read

Open (skipped for this version, per the coordinator)

  • Robot enemy (panzerhund): built and checked once, then left out as experimental.
    • It is retail c2v3 data in the same chunk, with the same mounts.
    • It needs the donor from c2v3's text plus 365 preload rows matched by name from c2v3's list. Every one of those rows resolved.
    • ROBOT in the builder is the ready entry: append it to ENEMIES and rebuild.
    • Its spot (24, −36.5) passed the 1.2 m navmesh-disc check.
  • Enemy respawn/reset:
    • Not built. No retail evidence says an idTarget_AISpawn can fire twice (r4_aispawnwaves §3).
    • A new kiscule decl entry is unproven.
    • Reloading the dev menu item is the reset.
  • Laserhund or other robots, and a second wave behind a trigger: not attempted.
  • LKW/DKW as world pickups: none exist in the game. They are only reachable through the dev loadout.

Related: Research Report: R3 Navdata, Research Report: R2 Ainav, Research Report: R4 Pickups, Research Report: R4 Ai Spawn Waves, Research Report: R9 Box Map, Research Report: R9 Dev Starts, TNC Custom Map Status.