The podium crash dies in SocketIterator::DeletePlugs, calling through a segment whose vtable dword has been replaced by a small float. The three dumps prove the segment is wrong BY teardown; nothing in them says when it went wrong, and six configurations of the local repro rig - parked pods, driven pods, light and full page heap, two, four and six pods - reached the podium and tore down clean. So the next real playtest becomes the instrument. RP412SEGCHECK walks the segment table in ~JointedMover before the delete, guarded-reads each segment's first dword, and if one does not match the vtable captured from the very first segment ever built it writes the forensics into rpl4-fail.log, which is closed on the way down and survives the abort - rpl4.log does not. The report carries the entity and whether it was the local pod, which index went bad and what is in it, the first two rows of the object as hex and float, and the heap deltas to its neighbours on either side. Three bracket calls in the winners' circle answer the question the dumps cannot: at podium entry, and either side of the second MakeEntityRenderables on the own pod. Whichever fires first is recorded and travels inside the teardown report, so the log says whether the race broke the segment or the podium did. It deliberately does not skip the delete or repair the pointer. The ownership bug is unfixed and a guard would cost exactly the evidence this is here to collect - it stops on the same object, one step earlier, holding the forensics. On by default, a handful of pointer compares per pod per race; RP412SEGCHECK=0 turns it off, and the environ.ini template says so. tools/podium-repro is the rig itself, banked with what the dumps already established: page heap turned on through the PEB without gflags or elevation, N sandboxed installs, and a feeder that drives full races through them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
256 lines
5.5 KiB
C++
256 lines
5.5 KiB
C++
#pragma once
|
|
|
|
#include "mover.h"
|
|
#include "joint.h"
|
|
#include "slot.h"
|
|
#include "segment.h"
|
|
|
|
//
|
|
// RP412SEGCHECK - count corrupted segment plugs on one entity and remember
|
|
// the first moment any were seen, so the teardown report can say WHERE it
|
|
// went wrong rather than only that it did. Safe on any entity: returns 0
|
|
// for anything that is not a JointedMover. Reports; never aborts.
|
|
// See the block comment at the top of JMOVER.cpp.
|
|
//
|
|
extern int
|
|
RPCheckJointedMoverSegments(Entity *entity, const char *when);
|
|
|
|
//##############################################################################
|
|
//######################## JointedMover ##################################
|
|
//##############################################################################
|
|
|
|
class JointedMover:
|
|
public Mover
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Shared Data support
|
|
//
|
|
public:
|
|
static Derivation *GetClassDerivations();
|
|
|
|
static SharedData DefaultData;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Message Support
|
|
//
|
|
#if 0
|
|
private:
|
|
static const HandlerEntry MessageHandlerEntries[];
|
|
|
|
protected:
|
|
static MessageHandlerSet MessageHandlers;
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Attribute Support
|
|
//
|
|
public:
|
|
enum{
|
|
SegmentCountAttributeID = Mover::NextAttributeID,
|
|
SegmentTableAttributeID,
|
|
JointSubsystemAttributeID,
|
|
NextAttributeID
|
|
};
|
|
|
|
private:
|
|
static const IndexEntry AttributePointers[];
|
|
|
|
protected:
|
|
//static AttributeIndexSet AttributeIndex;
|
|
static AttributeIndexSet& GetAttributeIndex();
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Segment Support
|
|
//
|
|
public:
|
|
|
|
EntitySegment::SegmentTable
|
|
segmentTable;
|
|
|
|
int
|
|
segmentCount;
|
|
|
|
EntitySegment*
|
|
GetSegmentFromDamageZone(CString damage_zone);
|
|
|
|
EntitySegment*
|
|
GetSegment(CString segment_name);
|
|
|
|
EntitySegment*
|
|
GetSegment(int segment_index)
|
|
{
|
|
Check(this);
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
return iterator.GetNth(segment_index);
|
|
}
|
|
|
|
SlotOf<JointSubsystem*>
|
|
jointSubsystem;
|
|
|
|
JointSubsystem*
|
|
GetJointSubsystem()
|
|
{
|
|
Check(this); return jointSubsystem.GetCurrent();
|
|
}
|
|
|
|
void
|
|
GetSegmentToWorld(
|
|
EntitySegment &my_segment,
|
|
LinearMatrix *transform
|
|
);
|
|
|
|
protected:
|
|
void
|
|
InitializeChildPointers(EntitySegment *current_segment);
|
|
|
|
void
|
|
CalcSegmentTransforms(EntitySegment *final_segment);
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Animation Support
|
|
//
|
|
public:
|
|
|
|
typedef
|
|
Scalar (JointedMover::*AnimationCallback)(
|
|
ResourceDescription::ResourceID animation_number,
|
|
Scalar carryover,
|
|
Logical animate_joints
|
|
);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Model Support
|
|
//
|
|
public:
|
|
typedef void
|
|
(JointedMover::*Performance)(Scalar time_slice);
|
|
|
|
void
|
|
SetPerformance(Performance performance)
|
|
{
|
|
Check(this);
|
|
activePerformance = (Simulation::Performance)performance;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
public:
|
|
|
|
static JointedMover*
|
|
Make(MakeMessage *creation_message);
|
|
|
|
static int
|
|
CreateDamageZoneStream (
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
static ResourceDescription::ResourceID
|
|
CreateSkeletonStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
static Logical
|
|
InitDestroyedVideoObjectNames(
|
|
MemoryStream *segment_stream,
|
|
NotationFile *model_file,
|
|
CString page_name,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
|
|
static Logical
|
|
InitVideoObjectNames(
|
|
MemoryStream *segment_stream,
|
|
NotationFile *model_file,
|
|
CString page_name,
|
|
const ResourceDirectories *directories
|
|
);
|
|
static int
|
|
GetSegmentIndex(
|
|
CString segment_name,
|
|
NotationFile *skl_file
|
|
);
|
|
|
|
static int
|
|
GetDamageZoneIndex(
|
|
CString damage_zone_name,
|
|
NotationFile *skl_file
|
|
);
|
|
|
|
JointedMover(
|
|
MakeMessage *creation_message,
|
|
SharedData &virtual_data
|
|
);
|
|
~JointedMover();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
};
|
|
|
|
//##########################################################################
|
|
//########################## Animation ###############################
|
|
//##########################################################################
|
|
|
|
class AnimationInstance:
|
|
public Plug
|
|
{
|
|
private:
|
|
Logical lerpToZero;
|
|
Scalar deltaTime;
|
|
public:
|
|
AnimationInstance(JointedMover *jointed_mover);
|
|
~AnimationInstance();
|
|
|
|
Scalar Animate(Scalar time_slice, Logical move_joints = True);
|
|
|
|
Logical
|
|
LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True);
|
|
|
|
Logical LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True);
|
|
|
|
void SnapToRest(Logical move_joints = True);
|
|
|
|
void
|
|
SetAnimation(
|
|
ResourceDescription::ResourceID animation_number,
|
|
JointedMover::AnimationCallback finished_callback
|
|
);
|
|
|
|
int
|
|
frameCount,
|
|
jointCount,
|
|
*jointIndices;
|
|
float
|
|
*footStepThreshold;
|
|
Scalar
|
|
*frameStart;
|
|
|
|
void
|
|
*keyFrames;
|
|
|
|
void
|
|
*currentFrameTo;
|
|
|
|
Vector3D
|
|
*keyJointPos,
|
|
*rootTranslations;
|
|
|
|
JointSubsystem
|
|
*jointSubToAnimate;
|
|
|
|
protected:
|
|
int currentFrame;
|
|
JointedMover *moverToAnimate;
|
|
ResourceDescription *animationResource;
|
|
JointedMover::AnimationCallback finishedCallback;
|
|
Scalar currentTime;
|
|
};
|