Skip to content

A Starfield navmesh vertex holds its Unknown only from form version 493 - #712

Merged
Noggog merged 4 commits into
Mutagen-Modding:devfrom
WhiskyTangoFawks:fix/starfield-navmesh-vertex-version
Oct 30, 2026
Merged

Noggog merged 4 commits into
Mutagen-Modding:devfrom
WhiskyTangoFawks:fix/starfield-navmesh-vertex-version

Conversation

@WhiskyTangoFawks

@WhiskyTangoFawks WhiskyTangoFawks commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Six NavigationMesh records in Starfield.esm (form versions 436–476) store NVNM vertices as three floats, 12 bytes. Every navmesh at 493 or later (56,570 in Starfield.esm, 5,352 in the other shipped masters) adds a trailing int, 16 bytes. Reading all of them as 16 bytes pulled the triangle count out of the vertex array, so the overlay threw OverflowException or ArgumentOutOfRangeException and the full import misread the geometry. No navmesh exists between 477 and 492, so the field is gated at 493. The navmeshes embedded in STAT, DOOR, ACTI and GBFM records of the shipped masters are all at 581 or later, so the gate leaves them as they were.

  • NavmeshVertex.Unknown gets <Versioning formVersion="493" action="Add" />.
  • The list overlay generator sizes a counted list's items by form version when the item holds a versioned field, so NavmeshGeometry.Vertices needs no custom overlay (Noggog's change).
  • The primitive overlay generator now gates a versioned field's read on its version, as the enum generator already does. Its only other effect is on Skyrim CriticalData.Unused3, which an overlay of a weapon below form version 44 read from the effect's FormID.

xEdit (wbDefinitionsSF1.pas) has no version switch either and misreads the same six.

Tests:

  • NavmeshVertexFormVersionTests covers form versions 476 and 493 by full import and overlay, and checks a write of each reproduces the input geometry byte for byte.
  • CriticalDataFormVersionTests covers the Skyrim overlay below form version 44.

Left open: three Starfield FormLink overlays read a versioned field without the gate (WeaponDamageType, and CurveTable on DamageTypeValue and ObjectProperty). No shipped record is old enough to reach them.

WhiskyTangoFawks and others added 2 commits October 24, 2026 15:27
Six NavigationMesh records in Starfield.esm (form versions 436 to 476)
store each NVNM vertex as three floats, 12 bytes. Every navmesh at form
version 493 or later (56,570 in Starfield.esm, 5,352 in the other
shipped masters) stores a fourth int, 16 bytes. Mutagen read every
vertex as 16 bytes, so for those six the triangle count came from inside
the vertex array: the overlay overflowed or sliced out of range, and the
deep parse misread the rest of the geometry. No navmesh exists between
form versions 477 and 492, so 493 is the lowest version known to carry
the field. The navmeshes embedded in STAT, DOOR, ACTI and GBFM records
of the shipped masters are all at 581 or later, so the gate leaves them
as they were. xEdit (wbDefinitionsSF1.pas) also reads every vertex as 16
bytes, so it misreads the same six.

NavmeshVertex.Unknown is now versioned at 493, and the overlay sizes
the vertex list by the record's form version. The primitive overlay
generator now gates a versioned field's read on its version, as the
enum generator already did; that also stops Skyrim CriticalData's
Unused3 reading past a record older than form version 44.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The navmesh overlay names the form version that adds the vertex Unknown,
the vertices' location, their count length and the two vertex lengths.
The generator builds the overlay's struct data slice once for its
neighbouring branches; its output is unchanged.

The critical data test writes a form version 43 Skyrim LE weapon through
the API and rereads it as overlay. The navmesh read tests build the
record with MutagenWriter, HeaderExport and GameConstants, taking the
geometry's other fields from a default NavmeshGeometry; the write tests
put a navmesh in a cell through the API and reread it. Each covers the
form version just before 493 and 493 itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@WhiskyTangoFawks
WhiskyTangoFawks force-pushed the fix/starfield-navmesh-vertex-version branch from b9efd83 to 3be2d3f Compare October 24, 2026 14:56
@Noggog

Noggog commented Oct 26, 2026

Copy link
Copy Markdown
Member

Made this PR with some proposed changes
WhiskyTangoFawks#1

@WhiskyTangoFawks

Copy link
Copy Markdown
Contributor Author

Thanks, that's cleaner than the custom overlay. I've pulled it into this branch and updated the description.

@Noggog

Noggog commented Oct 26, 2026

Copy link
Copy Markdown
Member

Cool! Just need some merge love, then

Mutagen-Modding#710 made every fallback in the primitive overlay answer ValueWhenAbsent().
This branch had added a version-gate branch answering GetDefault; it now
answers ValueWhenAbsent(), as the enum generator's version gate does.

Regenerating with Loqui 3.7.0 drops Mutagen-Modding#710's initializers on FO3 Weapon and
FO4 Weather until Noggog/Loqui#8 ships; those two files keep dev's output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@WhiskyTangoFawks

Copy link
Copy Markdown
Contributor Author

Merged dev. The one conflict was with #710 in PrimitiveBinaryTranslationGeneration. The new version-gate branch now answers ValueWhenAbsent(), as the enum generator's does. Unit tests pass.

@Noggog
Noggog merged commit 0755aaf into Mutagen-Modding:dev Oct 30, 2026
3 of 4 checks passed
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