Skip to content

maxpayne: stop the decal lift cracking surfaces, and spell the game's name - #38

Merged
Tatsh merged 2 commits into
masterfrom
maxpayne-fixes
Sep 2, 2026
Merged

maxpayne: stop the decal lift cracking surfaces, and spell the game's name#38
Tatsh merged 2 commits into
masterfrom
maxpayne-fixes

Conversation

@Tatsh

@Tatsh Tatsh commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Two follow-ups to #37.

The decal lift was cracking flat surfaces

A quad split into two triangles gives two faces with the same bounding box, so each read as
covering the other and the second rose DECAL_STEP off the plane. At a grazing angle the gap
shows as a hairline down the middle of every table top, wardrobe and picture frame.

Faces now stack only when they belong to different surfaces, keyed by the mesh and the material.
Two pieces of one wardrobe top share both and stay put; a tag on a wall, a lit sign over a dark
one, and two copies of the same prop differ in one or the other and still separate.

Keying on the material alone was not enough — it also stopped separating duplicated props, which
share a material across two meshes, and took Part1_Level1 from 139 exact depth ties to 3882. With
the mesh in the key it is 238.

Spelling

The module went in as maxpane, which is not a word and not the game. The package, the tests, the
docs page and the dade subcommand are renamed to maxpayne.

Checks

  • uv run pytest tests/maxpayne --cov=dade.maxpayne — 239 passed, 100% statement and branch
  • yarn gen-docs — builds; the only warning is the missing local graphviz binary
  • ruff, mypy, cspell — clean
  • dade maxpayne ldb2glb over the shipped data — 29/29 levels

A quad split into two triangles gives two faces with the same bounding box, so each read as
covering the other and the second rose eight millimetres off the plane. The gap shows as a
hairline down the middle of every table top, wardrobe and picture frame at a grazing angle.

Faces now stack only when they belong to different surfaces, keyed by the mesh and the material.
Two pieces of one wardrobe top share both and stay put; a tag on a wall, a lit sign over a dark
one, and two copies of the same prop differ in one or the other and still separate. Exact depth
ties on `Part1_Level1` are 238, against 3882 when the key was the material alone.
The module went in as `maxpane`, which is not a word and not the game. Renames the package, the
tests, the docs page and the `dade` subcommand.
Copilot AI lite review requested due to automatic review settings September 2, 2026 01:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The change set is large (module rename plus substantial moved/added logic), and it’s safer to have a final human review confirm packaging/CLI compatibility and behavior across real data.

Pull request overview

This pull request follows up on the Max Payne importer/converter by (1) fixing decal “lift” behavior that was splitting coplanar surfaces (e.g., diagonally split quads) and (2) renaming the module/CLI/docs from maxpane to maxpayne to match the game name and package intent.

Changes:

  • Adjust decal layering so faces only stack (lift) when they belong to different “surfaces” (now keyed by mesh + material), preventing visible cracks on flat geometry.
  • Rename the Max Payne package, CLI command, docs API page, and test imports from maxpane to maxpayne.
  • Update/extend tests to reflect the new layering key and ensure decal lifting still resolves true depth ties.
File summaries
File Description
tests/test_cli.py Updates expected CLI subcommand list to maxpayne.
tests/maxpayne/test_ras.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_models_command.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_model.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_memoryfile.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_ldb.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_gltf.py Renames imports and updates decal-lift test expectations for new stacking key.
tests/maxpayne/test_decals.py Updates layer_faces test inputs to include a surface key and adds regression coverage for split-surface triangles.
tests/maxpayne/test_crypto.py Renames imports to dade.maxpayne.*.
tests/maxpayne/test_commands.py Renames command/module references and patched import paths to dade.maxpayne.*.
tests/maxpayne/test_blocks.py Renames imports to dade.maxpayne.*.
tests/maxpayne/conftest.py Updates docstring reference to dade.maxpayne.crypto.decrypt.
README.md Updates CLI examples and references from maxpane to maxpayne.
docs/api/maxpayne.rst Adds new API docs page for dade.maxpayne.*.
docs/api/maxpane.rst Removes old API docs page for dade.maxpane.*.
docs/api/index.rst Updates API index to reference maxpayne.
dade/maxpayne/typing.py Updates module references in docstrings to dade.maxpayne.
dade/maxpayne/ras.py Adds/renames RAS archive reader under dade.maxpayne.
dade/maxpayne/model.py Adds/renames model reader under dade.maxpayne.
dade/maxpayne/memoryfile.py Adds/renames tagged stream decoder under dade.maxpayne.
dade/maxpayne/main.py Renames Click group from maxpane to maxpayne.
dade/maxpayne/ldb.py Adds/renames level database reader under dade.maxpayne.
dade/maxpayne/gltf.py Updates generator string and refines decal lifting inputs to include a surface key.
dade/maxpayne/decals.py Changes layer_faces signature to accept a surface key and prevents stacking within the same surface.
dade/maxpayne/crypto.py Adds/renames seeded stream cipher under dade.maxpayne.
dade/maxpayne/commands/utils.py Updates debug logger routing to dade.maxpayne.
dade/maxpayne/commands/sources.py Renames RAS magic import to dade.maxpayne.ras.
dade/maxpayne/commands/ras_list.py Updates help text and imports to dade.maxpayne.
dade/maxpayne/commands/ras_extract.py Updates help text and imports to dade.maxpayne.
dade/maxpayne/commands/models.py Renames imports/types to dade.maxpayne.
dade/maxpayne/commands/ldb2glb.py Updates help text and imports to dade.maxpayne.
dade/maxpayne/commands/ldb_textures.py Updates help text and imports to dade.maxpayne.
dade/maxpayne/commands/inspect_tags.py Updates help text and imports to dade.maxpayne.
dade/maxpayne/commands/init.py Adds package init for dade.maxpayne.commands.
dade/maxpayne/blocks.py Adds/renames block wrapper utilities under dade.maxpayne.
dade/maxpayne/init.py Adds package-level documentation for dade.maxpayne.
dade/main.py Switches main CLI wiring from maxpane to maxpayne.
.vscode/dictionary.txt Removes maxpane and keeps maxpayne in the spellcheck dictionary.
Review details
  • Files reviewed: 30/38 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Tatsh
Tatsh merged commit da8d6f3 into master Sep 2, 2026
18 checks passed
@Tatsh
Tatsh deleted the maxpayne-fixes branch September 2, 2026 01:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants