Repository navigation
Research Report R2 Maplightstairs
A from-scratch "kit" level built inside an existing map's envelope has two cosmetic/functional problems: new static geometry has no baked lighting, and new stair geometry is not walkable. Both now have a structurally complete fix, combined in one container that has never been loaded in the game. For lighting, the fix reuses retail's own single-texel lightmap-atlas encoding — the same technique retail itself uses for thousands of small/flat objects — by pointing each new piece's lightmap record at one texel inside a same-or-similar donor model's real, retail-baked rect. For stairs, retail is shown to never let the player walk the raw stepped collision mesh at all; a separate, invisible ramp-shaped clip volume carries the player over every real stair in the game, so the fix adds one such box-shaped clip ramp per new stair flight, built procedurally with no new mesh format needed. Everything here is static/offline verification — disassembly, archive content, and a geometric slope simulation against the real collision mesh; nothing has been confirmed visually or physically in a running game.
Mechanism: every static-instance entity in this kind of world gets the lightmapped shader program unconditionally. A miss in the per-map lightmap-rect table just samples the whole atlas with a neutral scale/bias — not a flat/unlit fallback. A path to skip the lightmap program entirely does exist, but only for three hard-coded model-name string compares behind a global flag — a literal name comparison baked into the executable, unreachable for a new model name without binary-patching the game. The shader-program-key bit that selects the lightmapped variant is forced on for every static instance in this kind of world regardless of whether a lightmap rect was found — there is no reachable code path that drops a static instance to a non-lightmap program for new content.
Recipe: for each new static piece, append a lightmap-rect record to the map's per-map lightmap table (a plain text format, hash-looked-up by entity name) whose bias points at one texel inside a real retail donor model's own baked lightmap rect — chosen for same-or-matching model size, not a random placeholder — and whose scale is a single texel (retail's own standard encoding for a small/flat object, used on tens of thousands of retail objects; the exact tiny-scale value is not a single universal constant across the game, but any sufficiently small fixed value is safe, since the largest "tiny" scale measured anywhere in the game is still far below any plausible atlas texel footprint). This never falls back to a context-free placeholder — every new piece in the built fix has a real retail donor of matching size.
Other alternatives, checked and ruled out: a non-lightmap "vertex lighting" path is not reachable (see above — the program-key bit is forced regardless). Retail's separate per-instance "vertex paint" baked-color channel exists as a mechanism but is not used by any retail instance of the kit's own model family, so its absence from the fix is not a gap for this specific content.
Mechanism: retail's stair collision mesh is a plain stepped mesh (measured directly: 18 treads 0.125 m apart, 0.25 m deep, risers roughly 0.10 m each) that is never walked directly. Every real stair flight of this model in retail is covered by a separate, invisible, smooth ramp-shaped player-clip volume — one continuous mesh spanning the whole building, not a per-flight patch to the stair's own collision. A geometric slope simulation (rolling a player-capsule-radius sphere along the measured collision surface) confirms: the raw stair mesh produces repeated steep slope spikes well above anything a player capsule can climb, for both retail's and the kit's own copy of the identical stair model. The per-step climb allowance cvar does not explain retail's walkability at all — it is unrelated to the actual mechanism.
Recipe:
- Give the stair flight's existing render-model collision player/monster-clip contents too (otherwise the player falls through the geometry entirely).
- For each flight, add one new clip-only entity shaped as a box, sized and rotated to lie exactly on the flight's ramp line, pointed at the standard clip-only material. A box clip model needs no mesh file at all — it is built procedurally from a size value at load, and its slope comes for free from the entity's own rotation.
- Add one preload-list row for the clip material.
A geometric re-check after adding the ramp shows the same slope profile as retail's real ramps — the maximum contact slope drops from spiking well above the walkable threshold to a smooth ≤28°, with zero spikes and zero gaps.
Why an overlay box, not a re-authored stair mesh: the stair model's own collision is a single shared payload reused by every real flight of that model in the map — editing it in place would silently reshape collision under untouched retail flights too, and this project has no general wedge/convex collision-mesh writer, only a box writer, which is exactly what the ramp recipe needs anyway.
Side-access check: the kit's stair flights already have railings at both long edges carrying the same player/monster-clip fix, so a player cannot reach an exposed raw-stair edge from the side — the ramp box only needs to (and does) cover the one open approach axis, bottom to top.
- A material/program flag to disable the lightmap for a static instance — only the three hard-coded model names, unreachable for new content without a binary patch.
- A flag that supposedly also fixes albedo/virtual-texture sampling fixing the lighting too — disproven: that flag and the lightmap-program bit are set by unrelated code paths.
- The per-step climb-allowance cvar explaining stair walkability — checked against the live cvar value and a geometric simulation; it is not the mechanism.
- A from-scratch non-lightmapped dynamic-entity version of the kit instead of per-piece lightmap records — technically reachable and genuinely cheaper per piece, but retail never uses that entity class for anything wall/floor/room-scale (0 of 328 sampled retail instances of that class are architecture-scale), so it has no retail visual-quality precedent and is not recommended.
- Whether each new piece's chosen donor texel lands on a lit rather than shadowed part of its donor's rect — the design only guarantees "inside the rect," not "well-lit." If a kit piece looks plausible but dim in game, this is the first place to check.
- How the lightmapped shader program combines a per-vertex baked color channel with the sampled lightmap texel — not relevant to the current recipe since none of the kit's own models use vertex paint in retail, but would matter for a future piece drawn from a vertex-painted model family.
Swap the combined fix container into the proven override slot, start the map, and check two things at the kit building: whether the new furniture/walls/floors look plausibly lit (no solid black, no magenta/grey blotches), and whether the new stairs can be walked up normally without getting stuck or needing to jump.
English Wiki generated from the measured research notes in docs/. Evidence grades and uncertainty are preserved intentionally.
- WolfSDK Loader · DE
- WolfSDK Studio · DE
- FAQ · DE
- Mod format · DE
- Modding Guide
- Modding Surface
- CVar Catalog
- CVar Validation (old scrape)
- Texture Database
- Developer Mode
- Dev Menu
- Custom-Map Status