Skip to content

ntre_subsurface_ctg: navmesh rework - #148

Merged
sunzenshen merged 5 commits into
NeotokyoRebuild:masterfrom
sunzenshen:navmesh-subsurface-release
Oct 14, 2026
Merged

sunzenshen merged 5 commits into
NeotokyoRebuild:masterfrom
sunzenshen:navmesh-subsurface-release

Conversation

@sunzenshen

@sunzenshen sunzenshen commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

ntre_subsurface_ctg: navmesh rework

One file, neo/maps/nav/ntre_subsurface_ctg.nav. It was measured on upstream master plus the draft NeotokyoRebuild/neo#2176 (then only its unwanted-ladder release, now its changes 1 and 7) and NeotokyoRebuild/neo#2186 ("Bots skip weapons they cannot reach", merged since), with harness logging added.

Dependencies and status

Needs (worse than master, or broken, without it):

Helped by (measured better with it; the mesh does not wait on it):

Pending before review:

  • Nothing: ready for review.

At a glance

master this PR
nav areas 1201 1064
file size 617,909 bytes 566,394 bytes (-8 %)
areas no spawn can reach 69 0
one-way walk links between level floor 1 0
nav ladders 8, two with an end connected to nothing 9, all connected at both ends
bot stuck events a match (see below) 59.1 19.4

What changed

  • Sliver areas merged into their neighbors on the same floor.
  • Walk links a player hull cannot cross are cut: a platform edge at the defender spawn, a robot cart, crates and a wall, and two pairs past spider tank legs, near (-812, -4175) and (-1350, -4025), blocked both ways (the second never crossed).
  • Props. Floor under props bots stood pressed against is cut out. This includes the legs of the four spider tanks in the corridor under the train line, which are prop_dynamic and never move, and the tank near (170, -4045) (below).
  • The raised barriers and the forklift. The corridor through an 18 u gap in a row of raised barriers is removed. Two strips past the forklift are PRECISE, so bots do not cut the corner into its crates.
  • Ladder 1 (the walkway near (-494,-1077)): its nav line runs 4 u east of the ladder's center. On the center line the walkway plate above reaches 1 u into a climbing bot's path, and bots stalled under it and stepped off the ladder's side.
  • The overhead train line is kept with its two maintenance platforms, as on master, and its ladders are connected. It is upside-down train cars and rails 300-430 u over the floor along y -4050, from x -1625 to 2125.
    • Ladder 3 (1630,-4414) now has a bottom: the platform floor below it. A player walking off the platform's lip catches the ladder. On master its bottom is connected to nothing.
    • Ladder 3's top lands on a small pad on the prop right behind the ladder, which links to the rails. With the rail strip 24 u above the ladder top as its landing, every bot that got up headed straight for the beam beyond it and fell.
    • Ladder 5's top is connected to the rails. On master it is connected to nothing.
    • The west rails are linked to the east part across a 5 u gap. Without that link only the east 17 areas can be reached.
    • Every train-line area is PRECISE + CLIFF, as narrow walkways high above the floor: 25-50 u rails and a 9 u beam. A fall from them is 290-433 u, which does up to 14 damage. The only way up is ladder 3; the ways down are ladder 3 and drop links off the east car and a platform (294-308 u).
  • A new ladder for the construction ladder leaning on the machine at (392,-2900), with a crouch-only area on the machine top (62 u under the ceiling).
  • One-way level links. Every pair was swept with a player hull both ways by an engine hull audit (a harness-only test build: a hull is stood every 4 u on every area and swept every 4 u across every link). The missing direction of two pairs clear on every lane is restored (near (362, -4038) and (1800, -4162)); the pair near (-812, -4175) above, blocked both ways, is cut both ways.
  • The drop from the platform near (3475, -4158) to the floor 39 u below, whose climb is kept, is linked (33 of 34 lanes clear).
  • Removed:
    • four strips on the top edges of plywood boards leaning on a wall, which nothing can reach
    • two stubs the engine blocks at every round start: one inside a barrier prop, the other on a blast door's lower tier
    • the top of the crate stack near (1438, -2937), 88 u up, 1 hiding spot, reached only by 87-88 u climbs (as on master): a flood fill of the map's collision from it finds no way on with jumps of up to 62 u
    • nine areas no player hull fits in, each with every stand sample blocked, no more than 2 bot position samples (bot positions from 24 matches on this mesh): four 12 u squares inside the wall at the fence row's ends (one of them at a fence-row corner, below; the corner square beside each keeps the way round), a square inside another wall, and the floor under two power suits, a barrier gate and a door frame
  • Kept from the same audit: the link past another spider tank leg near (775, -4104), the only link of a small pocket between the tank, a power suit rack and a robot cart; two links by a double post and a robot cart that bots cross.
  • Left for the runtime avoidance of physics props (a separate bot change): the floor and links blocked at round start by office chairs, flight suits, tech boxes, cardboard boxes and a barrel.
  • Re-analyzed in game after the edits, so the per-area visibility lists bots use for what they can see are current.

The fence-row corners

A row of static fences, a round-bar barrier and plywood signs runs along y -1124, from x -70 to 254 and from 779 to 1300. Behind it are two narrow strips (the one west of the opening leads to ladder 1). They are entered only round the row's two ends from the open floor between them. Without marks there, bots bound for a strip were pushed round the curb at the row's end to the wrong side. They then pressed on against the fence toward the path point behind it until the stuck monitor fired. At the west end this was worse than master: 2.5-3.0 stuck events a match against master's 1.3-1.6.

The three corner areas (583 and 3172 at the west end, 847 at the east end) are PRECISE. Under #2168 a bot there follows its path points without skipping ahead or steering round teammates. Attributes only. With it the two corners are at master's level: west 1.1 against master's 1.3, east 0.6 against 1.0 a match. Against the same mesh without the marks: x0.80 [0.55, 1.14] overall, and at the two fence corners x0.38 [0.26, 0.56] (14 pairs down, 2 up).

The spider tank near (170, -4045)

The mesh ran under this tank's six legs, and a link walker (one bot of each class sent across a single nav link from 128 u back, in the server) found Assault and Support stuck against a leg on every try from area 6 to 3571. The six leg footprints, grown by half a player hull, are cut out of the areas under them. The pieces keep their links, the largest piece of each area keeps its id (15 small pieces get new ids), and every link round the tank is crossed by every class in the walker.

Id alignment

1019 of the 1064 areas carry the id of the master area they match, so an id-keyed diff against master reads sensibly. Master's 8 ladders keep ids 1-8, and the new ladder is 10. Areas are matched only within 64 u of height. The alignment changes ids only: geometry, connections, attributes and the analysis data are unchanged by it (verified topology-identical).

How it was tested

  • Reachability:
    • every spawn can reach every other spawn
    • every objective is reachable
    • every area can be reached from a spawn (master: 69 cannot), and by each class's climb limit (the most a bot plans: Recon 68 u, Assault 48 u, Support 43 u) Recon reaches every area too; Assault and Support do not reach 66 and 70: the platform at ladder 3's foot with the train line above it (60 areas), whose way up from the floor near (1865, -4275) is a 56 u step only a Recon climbs, and raised tops 48-60 u up
    • no area a class can enter and not leave; no one-way link between level floor
    • no area is blocked at round start. The offline check predicts one, an area along a prop's edge, which the engine did not block in 36 matches on an earlier research revision of this mesh, where it is the same area. The two stubs it blocked every round are removed.
  • Engine hull audit: no linked area a player hull cannot stand in. BLOCKED_LINKS map=ntre_subsurface_ctg level_pairs=1712 oneway=0 keep=0 cut=4 area=0 check=1 entity=13: the four are the kept links above, the entities the physics props.
  • Falls. The map has no trigger_hurt and no other hurt volume, and no drop that kills a bot at full health. The deepest drop off the train line is 433 u, 14 damage. In the comparison below each mesh had one death from a fall: a bot on 2-8 health dropping 313 u from the mezzanine near (-370,-3600), a drop link master also has.
  • Master against this mesh, same bot code. Byte-identical copies of the map, one carrying each .nav, run back to back. CTG, 2 rounds of 3 minutes with the ghost pinned at each of the 8 ghost spawns in turn, 3 runs each, 30 bots, default weapon damage, 8 matches at a time. Every match reached match end with 0 asserts and no crash (241 matches in all, probes and earlier revisions included). The stuck count is OnStuck plus FAIL_STUCK move failures, excluding the spawn crush at round start and the weapon-scavenging behavior. This comparison ran on the mesh without the audit edits (one-way links, the platform drop, the removed crate top and areas no hull fits in) and the cut at the tank near (170, -4045); those were measured against the mesh without them, below.
    • stuck events 59.1 -> 19.4 a match (paired x0.29, 95 % interval [0.22, 0.40], 23 of 24 pairs down, 1 up); all OnStuck 64.0 -> 19.9
    • FAIL_NO_PATH_EXISTS move failures 4.4 -> 4.1 a match (paired x1.02 [0.72, 1.49]). They come from attack chase paths that refuse areas the path reservations mark as hazardous, on both meshes. "Fell off the path" failures 0.08 -> 0.04
    • kills 50.3 -> 50.7 a match; ghost captures 6 of 65 rounds -> 8 of 64; team kill ratio (Jinrai / NSF enemy kills) 0.97 -> 0.98
    • bots still see and shoot across the mesh: 89 % of kills are between bots in different nav areas and 72 % in non-adjacent ones, the same as on master (kill distance median 309 u against 310 u)
    • at the spots: the spider-tank legs 16.7 -> 1.6 stuck events a match; the foot of ladder 1 10.1 -> 2.8; the defender spawn exit 8.7 -> 0
    • without #2176 (the unwanted-ladder release switched off in both arms; 8 spawns x 2, 16 pairs): 37.5 -> 19.0 a match, x0.50 [0.37, 0.67], 12 pairs down, 2 up
  • The audit edits against the mesh without them, the same design, 24 pairs: stuck events 23.3 -> 15.3 a match (paired x0.73, 95 % interval [0.53, 1.00], 17 down / 6 up); kills 50.2 -> 49.7; ghost captures 11 -> 10 of 48 rounds; fall deaths 2 -> 0; 88 / 91 % of kills between bots in different areas; every match reached match end with 0 asserts and no crash. At the edited spots 6 -> 11, nearly all at the corner by one restored link near (362, -4038), where events swing between batches on either mesh: with a second batch of the same restore, 33 -> 39 there over 48 matches each.
  • The cut at the tank near (170, -4045) against the mesh without it, on the harness research build (neo bot-navmesh-generation-research with logging, its research switches at their defaults), the same design (each of the 8 ghost spawns pinned, 3 runs each, 30 bots, default weapon damage, 8 matches at a time), 24 pairs, every match to match end with 0 asserts:
    • at the tank, within 220 u: 0.71 -> 0.29 stuck events a match (17 -> 7; 6 pairs down, 2 up, 16 with none)
    • whole map 13.4 -> 15.0 a match (paired x1.20, 95 % interval [0.77, 1.93], 11 pairs down, 13 up); the differences are spread over the map, none within 400 u of the tank
    • FAIL_NO_PATH_EXISTS 0.6 -> 0.8 a match; kills 49.5 -> 49.7; fall deaths 2 -> 0 in 24 matches
    • the connectivity check against master: no new defect, as without the cut; objectives unchanged

How the pinned-ghost probes work

The offline checks show that the mesh links an area to a spawn. They do not show that a bot will walk there. To test one spot in game, the ghost is placed on it and bots are sent to get it.

  • The ghost is placed on the spot by a server cvar. A harness-only neo patch, used on test builds and not part of this PR or any neo PR, adds sv_neo_ghost_spawn_pos "x y z", which replaces the position of the round's ghost spawn. The map file is not edited.
  • A spot counts as reached when a bot stands within 40 u of it, or picks the ghost up there rather than on the floor below, where a ghost that rolls off a narrow landing ends up. A wider radius would count a bot on a level above or below.
  • Master's mesh runs beside this one on a byte-identical copy of the .bsp under a second name that loads its own .nav, so the same pin runs on both meshes in one batch.

On this map

Each end of the restored and new ladders was probed, 3 matches each, 12 bots, at a tenth of weapon damage, on the same build. Reached, master against this mesh:

  • ladder 3 top: 0 of 3 -> 3 of 3 (first pickup at 28-30 s)
  • ladder 3 bottom: 3 -> 3
  • the east train car: 0 -> 1
  • ladder 4 bottom (the east platform): 0 -> 1
  • ladder 5 bottom (the far west platform): 0 -> 0
  • the new ladder's top (the machine top): 1 -> 3; its bottom: 3 -> 3

On the rails at the tops of ladders 4 and 5 the ghost rolled off onto the floor below on both meshes, so those probes say nothing about the rails. On master no bot reaches the train line at all. In an earlier test on this mesh (30 bots, a tenth of weapon damage), with the ghost pinned on the east or the west car, bots got it in 2 of 4 rounds and once carried it off the line to a capture. With the ghost at its real spawns, no bot climbed to the train line in 88 matches, so the line does not change ordinary rounds.

Known, not changed

  • Crossing the beam. From ladder 3's top, the way onto the train is a 9 u beam 355 u long. Bots climb the ladder cleanly, but several a match fall off the beam when the objective is up there. They walk with 8-way movement keys, so a heading that is not along the beam drifts sideways. The falls do at most 14 damage and happen only when the ghost is on the line; this is bot movement, not the mesh.
  • The foot of ladder 1 is the largest stuck spot left, 2.8 a match against master's 10.1. The ladder brush, which is solid to players, starts about 50 u above the floor. A bot that lands crouched under it cannot stand up, and its crouched hull never reaches the ladder, until it backs out. Bots crouch whenever they are in the air, for example after slipping off the ladder at the mount. This is ladder-mount code, not the mesh.
  • The spider tanks' legs held 1.6 stuck events a match in the master comparison (master 16.7), which ran without the cut at the tank near (170, -4045).
Earlier measurements (without the fence-row marks)

These ran on the mesh without the fence-row corner marks, the audit edits and the cut at the tank near (170, -4045): 1059 areas, of which 1029 carried master's ids. Master against it, the same design, 24 pairs: x0.38 [0.29, 0.50], and again x0.37 [0.29, 0.48].

One file. Against master: 1201 -> 1059 areas, 617,909 -> 541,649
bytes; areas no spawn can reach 69 -> 0; all 9 nav ladders connected
at both ends (master: 8, two of them with an end connected to
nothing).

- Sliver areas merged into their neighbors on the same floor.
- Walk links a player hull cannot cross are cut (a platform edge at
  the defender spawn, a robot cart, crates, a wall), and floor under
  props bots stood pressed against is cut out, including the legs of
  the four spider tanks (prop_dynamic, never move) in the corridor
  under the train line.
- The corridor through an 18 u gap in a row of raised barriers is
  removed; two strips past the forklift are PRECISE, so bots do not
  cut the corner into its crates.
- Ladder 1's nav line runs 4 u east of the brush center, clear of the
  walkway plate above it.
- The overhead train line is kept with its platforms, and its ladders
  are connected: ladder 3's bottom to the platform floor below it
  (master: none), its top to a pad on the prop behind the ladder;
  ladder 5's top to the rails (master: none); the west rails linked
  to the east part across a 5 u gap. Every train-line area is PRECISE
  + CLIFF: narrow rails and a 9 u beam 300-430 u over the floor.
- A new ladder for the construction ladder on the machine at
  (392,-2900), with a crouch area on the machine top.
- Removed: strips on the top edges of plywood boards leaning on a
  wall, which nothing can reach, and two stubs the engine blocks at
  every round start (inside a barrier prop; on a blast door's lower
  tier).
- Re-analyzed in game after the edits.
Renumbers area and ladder ids only, so an id-keyed diff against
master reads sensibly: 1029 of the 1059 areas carry the id of the
master area they match; master's 8 ladders keep ids 1-8, the new one
is 10. Areas are matched only within 64 u of height. Geometry,
connections, attributes and the analyzed visibility data are
unchanged (verified topology-identical).
A row of fences, a round-bar barrier and plywood signs runs along
y -1124, x -70..254 and 779..1300. The strips behind it are entered
only round its two ends. Bots bound for a strip steered round the
curb at the end to the wrong side of the row, then pressed on
against it toward the path point behind it.

The corner areas at both ends (583, 3171, 3172, 847) are PRECISE: a
bot there follows its path points without skipping ahead or
steering round teammates. Attributes only; re-analyzed in game.
An outside review of this mesh found walk links that run one way
only, a climb whose drop back was cut, and one area reached only by
climbs no bot plans. Each one-way pair was swept with a player hull
in both directions by the engine's hull audit:

- Restore the missing direction of the two pairs clear both ways;
  cut both ways the pair blocked by a spider tank's leg.
- Restore the drop from the platform near (3475, -4158) whose climb
  was kept.
- Delete the top of the crate stack near (1438, -2937), reached only
  by 87-88 u climbs: nothing a player can jump onto reaches it.

Beyond the review, from the same audit: delete nine areas no player
hull fits in: four 12 u squares inside the wall at the fence row's
ends (the corner beside each keeps the way round), a square inside
another wall, and the floor under two power suits, a barrier gate
and a door frame. Cut a pair blocked both ways by a spider tank's
legs.

Links past movable physics props are kept. Existing areas keep their
ids. Re-analyzed in game (same graph, fresh visibility).
The spider tank near (170, -4045) is a prop_dynamic that never moves,
but the mesh ran under its six legs: bots heading from area 6 to 3571
walked into a leg (link walker: Assault and Support stuck on every
try). Its leg footprints, grown by a half hull, are cut out of the
areas under them, as was done for the other tank; the pieces keep
their links, and the largest piece of each area keeps its id.

Every link round the tank is crossed by every class (link walker).
Re-analyzed in game (same graph, fresh visibility).
sunzenshen added a commit to sunzenshen/neoAssets that referenced this pull request Oct 4, 2026
As navmesh-subsurface-release e923bfd (NeotokyoRebuild#148): the six legs of the
spider tank near (170, -4045), grown by a half hull, cut out of the
areas under them.
@sunzenshen
sunzenshen requested a review from sunmachine October 9, 2026 05:05
@sunzenshen
sunzenshen marked this pull request as ready for review October 9, 2026 05:05

@sunmachine sunmachine 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.

No issues.

@sunmachine
sunmachine requested a review from a team October 14, 2026 02:25
@sunzenshen
sunzenshen merged commit d796f0a into NeotokyoRebuild:master Oct 14, 2026
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