diff --git a/restoration/source410/BT/MECH.CPP b/restoration/source410/BT/MECH.CPP index bb089aee..fbe89f5b 100644 --- a/restoration/source410/BT/MECH.CPP +++ b/restoration/source410/BT/MECH.CPP @@ -53,6 +53,9 @@ #include // Joint / JointSubsystem -- ResolveJoint #include // EntitySegment -- the skeleton segment table #include // Mech::DamageZone -- the hull zone fill (Pass 3) +#if !defined(BOXSOLID_HPP) +# include // BoxedSolid extents -- the ground-snap probe +#endif #include // DamageLookupTable -- the cylinder hit table #include // Player::VehicleDeadMessage -- the death notification #include // 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;