BT410 5.3.98: the ground snap -- the mech walks the arena's actual terrain, and there is no gravity
The probe half of the master performance's ground model (binary
@4aa630-4aa6cc, via BT411's raw-asm decode), placed after Simulate's position
integration:
place the collision volume; drop a probe from the volume's authored bottom
(origin.y + collisionTemplate->minY); ask the zone's box tree what surface
lies under it (BoundingBoxTreeNode::FindBoundingBoxUnder); and if the query
hits (h > 1e-4), put the origin ON that surface exactly --
origin.y -= (h - lift).
The design is worth stating because it is not the obvious one: THERE IS NO
GRAVITY ANYWHERE IN THE MECH. Placement is absolute each frame. Walking
up-slope rides the lift window (an implicit step allowance), walking off a
roof drops instantly, and a probe MISS holds Y -- so a falling-through-the-
world runaway is structurally impossible rather than merely guarded against.
The engine side needed NOTHING reconstructed: Mover's own ctor already
builds collisionTemplate/collisionVolume from the model's BoxedSolidStream
resource and the zone tree was live all along. One include (boxsolid.hpp --
mover.hpp only forward-declares BoxedSolid, so the extents were an
incomplete type).
LIVE, arena run, no fault -- the y track tells the story by itself:
y = 20 -> 11.747 -> 10 -> 10 -> 0 -> 19.4049 -> 0
Spawn deck, down a ramp (caught mid-slope), an intermediate level, the arena
floor, up onto a structure, and off it. Every previous run had y pinned at
its spawn constant for the whole mission.
Deferred with the collision increment: frame rejection on blocking hits, the
crushable-icon sentinel, the crash clip (SetLegAnimation 0x20) on hard
impacts, and the gyro crunch feed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,9 @@
|
||||
#include <joint.hpp> // Joint / JointSubsystem -- ResolveJoint
|
||||
#include <segment.hpp> // EntitySegment -- the skeleton segment table
|
||||
#include <mechdmg.hpp> // Mech::DamageZone -- the hull zone fill (Pass 3)
|
||||
#if !defined(BOXSOLID_HPP)
|
||||
# include <boxsolid.hpp> // BoxedSolid extents -- the ground-snap probe
|
||||
#endif
|
||||
#include <dmgtable.hpp> // DamageLookupTable -- the cylinder hit table
|
||||
#include <player.hpp> // Player::VehicleDeadMessage -- the death notification
|
||||
#include <btplayer.hpp> // BTPlayer::ScoreMessage -- the kill credit
|
||||
@@ -1527,6 +1530,66 @@ void
|
||||
);
|
||||
localToWorld = localOrigin;
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// THE GROUND SNAP -- the probe half of the master performance's ground
|
||||
// model (binary @4aa630-4aa6cc, decoded from raw asm; there is NO
|
||||
// gravity anywhere in the mech). Place the collision volume, drop a
|
||||
// probe from the volume's authored bottom, ask the zone's box tree for
|
||||
// the surface under it, and place the origin ON that surface exactly.
|
||||
// Walking up-slope rides the lift window; walking off a roof drops
|
||||
// instantly; a probe MISS (h == -1) holds Y, so a runaway is
|
||||
// structurally impossible.
|
||||
//
|
||||
// The COLLISION half (frame rejection, crush sentinel, crash clip) is a
|
||||
// separate increment -- it hangs off ProcessCollisionList.
|
||||
//
|
||||
// Gated on the engine having built a collision volume for this model
|
||||
// (Mover's ctor does when the resource carries one); logged once if
|
||||
// absent so a silent no-op is visible.
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
if (
|
||||
GetCollisionVolumeCount() > 0 &&
|
||||
collisionVolume != NULL &&
|
||||
collisionTemplate != NULL
|
||||
)
|
||||
{
|
||||
MoveCollisionVolume();
|
||||
|
||||
BoundingBoxTreeNode
|
||||
*ground_node = GetMoverCollisionRoot();
|
||||
if (ground_node != NULL)
|
||||
{
|
||||
Point3D
|
||||
probe = localOrigin.linearPosition;
|
||||
probe.y += collisionTemplate->minY;
|
||||
|
||||
Scalar
|
||||
height = -1.0f;
|
||||
ground_node->FindBoundingBoxUnder(probe, &height);
|
||||
|
||||
if (height > 0.0001f)
|
||||
{
|
||||
Scalar
|
||||
drop = height - collisionTemplate->minY;
|
||||
localOrigin.linearPosition.y -= drop;
|
||||
collisionVolume->minY -= drop;
|
||||
collisionVolume->maxY -= drop;
|
||||
localToWorld = localOrigin;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (getenv("BT_MECH_LOG"))
|
||||
{
|
||||
static int noVolumeOnce = 0;
|
||||
if (!noVolumeOnce++)
|
||||
{
|
||||
DEBUG_STREAM << "[ground] mech has NO collision volume -- "
|
||||
<< "snap inactive (model streams none?)" << endl << flush;
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("BT_MECH_LOG"))
|
||||
{
|
||||
static Scalar reportAccum = 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user