Reset-based respawn: reuse+heal the mech, not create-a-new-one (task #52)
The respawn glitches (2 mechs, on-fire respawn, camera-inside, can't-control, wreck-never-disappears) all traced to one architectural divergence: our respawn SEVERED playerVehicle on death and CREATED a new mech, leaving the old as a permanent wreck and building a duplicate viewpoint whose old render tree was never torn down. The authentic engine (FUN_0049fb74 + RPPlayer) REUSES the same mech entity: on respawn Mech::Reset heals it and moves it in place. Implemented faithfully, adapted to our layout (the 1995 raw offsets map to different 2007 engine fields, so reset the equivalent named members, not the offsets): - Mech::Reset (real, was a reposition-only stub): reposition + kill dead-reckon (projectedOrigin/projectedVelocity/updateVelocity + our relocated gait accumulators) so the replicant stops lerping to the death spot; clear the death latch (movementMode=1, graphicAlarm=0); Heal every damage zone (new Mech__DamageZone::Heal: full structure, intact skin); DeathReset (vtable+0x28) every subsystem; ForceUpdate to broadcast. - btplayer.cpp: VehicleDead no longer severs playerVehicle; the respawn re-post gates on the mech still being dead; DropZoneReply resets the EXISTING mech in place (heal+move) instead of creating a new one, then fires the warp. Warp moved to the shared placement (initial drop-in + respawn). Verified 2-node: mech entity ID stays 3:22 across 3 deaths (reused, not a new 3:32); each Reset logs alive=1, 20 zones healed, 33 subsystems reset; A sees ONE mech (no wreck+new pair). Warp fires each respawn. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
efa7aeb683
commit
247e51e1e1
@@ -161,38 +161,10 @@ void Mech::RaiseStatusAlarm(int /*alarm_id*/)
|
||||
{
|
||||
}
|
||||
|
||||
// Mech::Reset (@0049fb74) -- place the mech at a (re)spawn origin.
|
||||
// The shipped Reset additionally zeroes ~50 heat/damage/motion state fields and
|
||||
// resets every subsystem in the roster (slot vtable+0x28 with the reset mode);
|
||||
// that full sweep is deferred (TODO(bring-up)). For first spawn a freshly
|
||||
// constructed mech is already clean, so positioning it + refreshing the world
|
||||
// transform + forcing an update is enough to get it placed and rendering.
|
||||
void Mech::Reset(const Origin &origin, int /*mode*/)
|
||||
{
|
||||
Check(this);
|
||||
localOrigin = origin; // this+0x100 (FUN_0040a938 copy)
|
||||
localToWorld = localOrigin; // this+0xd0 (FUN_0040ab44 rebuild)
|
||||
ForceUpdate(); // FUN_004a4c54 family -- push to renderer/replicants
|
||||
|
||||
// BRING-UP (Tier-2 locomotion): get the player mech onto the per-frame
|
||||
// simulation path so it can walk. Two engine gates block a freshly spawned
|
||||
// master entity from being executed:
|
||||
// (1) Entity::Execute only calls PerformAndWatch when the app is in
|
||||
// RunningMission/EndingMission OR the entity IsPreRunnable()
|
||||
// (ENTITY.cpp:~549) -> set the pre-run flag.
|
||||
// (2) UpdateManager::Execute skips a master unless IsInteresting()
|
||||
// (interestCount!=0) && IsNonReplicantExecutable() (UPDATE.cpp:148)
|
||||
// -> force it interesting so the update manager ticks it.
|
||||
// Without these the mech renders but is never simulated (static
|
||||
// localToWorld). See Mech::PerformAndWatch (mech4.cpp).
|
||||
SetPreRunFlag();
|
||||
if (interestCount == 0) interestCount = 1; // Entity::interestCount (public)
|
||||
DEBUG_STREAM << "[drive] Mech::Reset spawn at ("
|
||||
<< localOrigin.linearPosition.x << ", "
|
||||
<< localOrigin.linearPosition.y << ", "
|
||||
<< localOrigin.linearPosition.z << ") -- prerun+interest forced\n" << std::flush;
|
||||
Check_Fpu();
|
||||
}
|
||||
// Mech::Reset (@0049fb74) is now the real faithful reconstruction in mech4.cpp
|
||||
// (reposition + kill dead-reckon + clear death/damage + ResetToInitialState every
|
||||
// subsystem + heal every damage zone + ForceUpdate) -- no longer the reposition-
|
||||
// only stub that lived here.
|
||||
|
||||
// (Mech__DamageZone::LoadCriticalSubsystems was a no-op stub here; it is now the
|
||||
// real type-0x1e damage-state descriptor-table loader in mechdmg.cpp.)
|
||||
|
||||
Reference in New Issue
Block a user