Skip to content

Let a tank drive from a box onto an abutting mesh Fixes #395 - #396

Open
timriker wants to merge 1 commit into
2.4from
timriker
Open

timriker wants to merge 1 commit into
2.4from
timriker

Conversation

@timriker

Copy link
Copy Markdown
Member

BoxBuilding and MeshFace disagreed about whether an occupant resting exactly on top of an obstacle is inside it. BoxBuilding::inMovingBox is clear when the occupant's base equals the top (lowerZ >= top); MeshFace::inBox is not (extents.maxs[2] < p[2]).

That decides where a tank comes to rest, and doUpdateMotion gives it no gravity to escape with -- while OnGround or OnBuilding it sets newVelocity[2] = 0, so a tank keeps the height it landed at exactly. A tank driving on a box therefore sits at exactly the shared top, and every face of an abutting mesh of the same height then reports a hit at once: the flat top it is driving onto and the perimeter wall beneath it. The search for the last moment the tank was clear has no clear moment to find at any point in the step, so the tank stops dead at the seam.

A tank driving on a mesh is left a hair above the top instead, so every face of the next obstacle is below it and misses. That is why mesh to mesh and mesh to box both work and only box to mesh sticks.

Fixed in the motion path only. inBox keeps its inclusive contact for collectInsideBuildings, the physics driver lookup and the death check. A tank falling onto a mesh top is still caught, so landing is unchanged.

Fixes #395

BoxBuilding and MeshFace disagreed about whether an occupant resting
exactly on top of an obstacle is inside it. BoxBuilding::inMovingBox is
clear when the occupant's base equals the top (`lowerZ >= top`);
MeshFace::inBox is not (`extents.maxs[2] < p[2]`).

That decides where a tank comes to rest, and doUpdateMotion gives it no
gravity to escape with -- while OnGround or OnBuilding it sets
newVelocity[2] = 0, so a tank keeps the height it landed at exactly. A
tank driving on a box therefore sits at exactly the shared top, and every
face of an abutting mesh of the same height then reports a hit at once:
the flat top it is driving onto and the perimeter wall beneath it. The
search for the last moment the tank was clear has no clear moment to
find at any point in the step, so the tank stops dead at the seam.

A tank driving on a mesh is left a hair above the top instead, so every
face of the next obstacle is below it and misses. That is why mesh to
mesh and mesh to box both work and only box to mesh sticks.

Fixed in the motion path only. inBox keeps its inclusive contact for
collectInsideBuildings, the physics driver lookup and the death check.
A tank falling onto a mesh top is still caught, so landing is unchanged.

Fixes #395

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@blast007

Copy link
Copy Markdown
Member

This is a change that can't go into 2.4 because it would change behavior between compatible clients.

@timriker

timriker commented Sep 28, 2026 •

Copy link
Copy Markdown
Member Author

People are relying on not being able to drive on the same level plane? I'd call it a bug. If older clients see it, they should upgrade. :)
From what I've seen, map makers go out of their way to avoid triggering this issue. If the bug were fixed, it would only affect maps where it had not yet been noticed.
There are three hex obstacles on the bzo map that trigger this that I used to fix the bug there.
https://github.com/timriker/bzo/blob/main/maps/bzo.bzw

@blast007

Copy link
Copy Markdown
Member

I agree that it's a bug, but there have been plenty of times that we hold off fixing a bug until a protocol break.

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.

drive from box onto mesh

2 participants