Reconstructs the binary's five-state LOOK machine (controls mapper tail, part_013.c:396-459) as proper members/methods: - MECHMPPR: LookState enum (None/Left/Right/Behind/Down) + lookState/ previousLookState (out of reserved[24] -> [22]). InterpretControls picks the state from the look buttons each frame and on a CHANGE calls Mech::CommitLookState. BT_FORCE_LOOK=<1..4> dev hook. - MECH: authored look angles lookLeft/Right/Front/BackAngle (deg->rad from the GameModel resource, guarded) + lookPitch/lookYaw + CommitLookState(int): side looks yaw by the authored angle, look-behind = yaw pi + lookBackAngle pitch, look-down = lookFrontAngle pitch, forward = identity. The per-frame eyepoint compose in Simulate adds the live Torso elevation on top. (reservedState [208] -> [202].) - Deferred inside the commit (needs MechWeapon viewFireEnable/rearFiring): per-view weapon fire re-arm + HUD pip group-mask flip. Verified headlessly: model reads clean authored angles (L=60 R=-60 F=-10 B=0 deg -- ModelResource layout confirmed again); BT_FORCE_LOOK=3 fires ONE commit ([look] state=3 yaw=3.14159 pitch=0) and the per-frame compose holds eyeYaw=pi with eyePitch=0.349066 (lookBackAngle + the 20deg-clamped elevation). Zero Fail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
420 lines
13 KiB
C++
420 lines
13 KiB
C++
//===========================================================================//
|
|
// File: mech.hpp //
|
|
// Project: BattleTech Brick: Entity Manager //
|
|
// Contents: Implementation details for the Mech entity //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#if !defined(MECH_HPP)
|
|
# define MECH_HPP
|
|
|
|
# if !defined(JMOVER_HPP)
|
|
# include <jmover.hpp>
|
|
# endif
|
|
|
|
# if !defined(RETICLE_HPP)
|
|
# include <reticle.hpp>
|
|
# endif
|
|
|
|
# if !defined(ALARM_HPP)
|
|
# include <alarm.hpp>
|
|
# endif
|
|
|
|
# if !defined(STATE_HPP)
|
|
# include <state.hpp>
|
|
# endif
|
|
|
|
# if !defined(CHAIN_HPP)
|
|
# include <chain.hpp>
|
|
# endif
|
|
|
|
# if !defined(AVERAGE_HPP)
|
|
# include <average.hpp>
|
|
# endif
|
|
|
|
# if !defined(CSTR_HPP)
|
|
# include <cstr.hpp>
|
|
# endif
|
|
|
|
# if !defined(SEQCTL_HPP)
|
|
# include <seqctl.hpp>
|
|
# endif
|
|
|
|
# if !defined(NAMEFILT_HPP)
|
|
# include <namefilt.hpp>
|
|
# endif
|
|
|
|
# if !defined(ROTATION_HPP)
|
|
# include <rotation.hpp>
|
|
# endif
|
|
|
|
//##################### Forward Class Declarations #######################
|
|
class Mech;
|
|
class Subsystem;
|
|
class SubsystemMessageManager;
|
|
class ControlsMapping;
|
|
class PlatformTool;
|
|
class MechControlsMapper;
|
|
class Mech__DamageZone;
|
|
class Joint;
|
|
|
|
//###########################################################################
|
|
//######################### Mech Model Resource #########################
|
|
//###########################################################################
|
|
|
|
struct Mech__ModelResource:
|
|
public JointedMover::ModelResource
|
|
{
|
|
char animationPrefix[4];
|
|
Scalar maxAcceleration;
|
|
Scalar superStopAcceleration;
|
|
Scalar throttleAdjustment;
|
|
Scalar lookLeftAngle;
|
|
Scalar lookRightAngle;
|
|
Scalar lookFrontAngle;
|
|
Scalar lookBackAngle;
|
|
Scalar walkingTurnRate;
|
|
Scalar runningTurnRate;
|
|
Scalar reticleX;
|
|
Scalar reticleY;
|
|
Scalar relativeMechValue;
|
|
int deathEffectResourceID;
|
|
Scalar deathSplashDamage;
|
|
Scalar deathSplashRadius;
|
|
Scalar maxUnstableAcceleration;
|
|
Scalar unstableAccelerationEffect;
|
|
Scalar unstableGunTheEngineEffect;
|
|
Scalar unstableSuperStopEffect;
|
|
Scalar unstableHighVelocityEffect;
|
|
Scalar unstableStopedTurnEffect;
|
|
Scalar updatePositionDiffrence;
|
|
Scalar updateTurnVelocityDiffrence;
|
|
Scalar updateTurnDegreeDiffrence;
|
|
Scalar timeDelay;
|
|
Vector3D cameraOffset;
|
|
char shadowJointName[20];
|
|
};
|
|
|
|
//###########################################################################
|
|
//########################## Mech Make Message ##########################
|
|
//###########################################################################
|
|
|
|
class Mech__MakeMessage:
|
|
public JointedMover::MakeMessage
|
|
{
|
|
public:
|
|
char resourceNameA[20];
|
|
char resourceNameB[20];
|
|
char resourceNameC[20];
|
|
|
|
Mech__MakeMessage(
|
|
Receiver::MessageID message_ID,
|
|
size_t length,
|
|
const EntityID &entity_ID,
|
|
Entity::ClassID class_ID,
|
|
const EntityID &owner_ID,
|
|
ResourceDescription::ResourceID resource_ID,
|
|
LWord instance_flags,
|
|
const Origin &origin,
|
|
const Motion &velocity,
|
|
const Motion &acceleration,
|
|
const char *badge,
|
|
const char *color,
|
|
const char *patch
|
|
):
|
|
JointedMover::MakeMessage(
|
|
message_ID, length, entity_ID, class_ID, owner_ID,
|
|
resource_ID, instance_flags, origin, velocity, acceleration
|
|
)
|
|
{
|
|
Str_Copy(resourceNameA, badge, sizeof(resourceNameA));
|
|
Str_Copy(resourceNameB, color, sizeof(resourceNameB));
|
|
Str_Copy(resourceNameC, patch, sizeof(resourceNameC));
|
|
}
|
|
};
|
|
|
|
//###########################################################################
|
|
//############################## Mech ###############################
|
|
//###########################################################################
|
|
|
|
class Mech:
|
|
public JointedMover
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Shared Data Support
|
|
//
|
|
public:
|
|
static Derivation ClassDerivations;
|
|
static SharedData DefaultData;
|
|
|
|
static const HandlerEntry
|
|
MessageHandlerEntries[];
|
|
static MessageHandlerSet
|
|
MessageHandlers;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Test Class Support
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass(Mech &);
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
public:
|
|
typedef Mech__ModelResource ModelResource;
|
|
typedef Mech__MakeMessage MakeMessage;
|
|
typedef Mech__DamageZone DamageZone;
|
|
|
|
static Mech*
|
|
Make(MakeMessage *creation_message);
|
|
|
|
Mech(
|
|
MakeMessage *creation_message,
|
|
SharedData &shared_data = DefaultData
|
|
);
|
|
~Mech();
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// App interface
|
|
//
|
|
public:
|
|
void
|
|
SetMappingSubsystem(Subsystem *mapper);
|
|
|
|
//
|
|
// Resolve a skeleton joint by name (the shared resolver the subsystems
|
|
// use to bind their animated joints -- Torso twist, etc.):
|
|
// GetSegment(name) -> segment jointIndex -> JointSubsystem::GetJoint.
|
|
//
|
|
Joint*
|
|
ResolveJoint(const char *joint_name);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Per-frame simulation (the mech's body Performance; installed by the ctor
|
|
// and dispatched each frame from Simulation::PerformAndWatch).
|
|
//
|
|
public:
|
|
typedef void
|
|
(Mech::*Performance)(Scalar time_slice);
|
|
void
|
|
SetPerformance(Performance performance)
|
|
{
|
|
Check(this);
|
|
activePerformance = (Simulation::Performance)performance;
|
|
}
|
|
|
|
void
|
|
Simulate(Scalar time_slice);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Resource creation
|
|
//
|
|
public:
|
|
static void
|
|
CreateMakeMessage(
|
|
MakeMessage *creation_message,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
static ResourceDescription::ResourceID
|
|
CreateModelResource(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories,
|
|
ModelResource *model = 0
|
|
);
|
|
|
|
static ResourceDescription::ResourceID
|
|
CreateSubsystemStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
static ResourceDescription::ResourceID
|
|
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 ResourceDescription::ResourceID
|
|
CreateExplosionTableStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
);
|
|
|
|
typedef Logical (*FindNameFunction)(
|
|
const char *control_name, ControlsMapping *mapping);
|
|
|
|
static ResourceDescription::ResourceID
|
|
CreateControlMappingStream(
|
|
const char *mapping_name,
|
|
NotationFile *mapping_file,
|
|
FindNameFunction find_name,
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories,
|
|
PlatformTool *current_tool
|
|
);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Subsystem roster accessors (the roster itself -- subsystemArray /
|
|
// subsystemCount -- lives in the base Entity)
|
|
//
|
|
public:
|
|
Subsystem*
|
|
GetGyroSubsystem() { Check(this); return gyroSubsystem; }
|
|
Subsystem*
|
|
GetTorsoSubsystem() { Check(this); return sinkSourceSubsystem; }
|
|
Subsystem*
|
|
GetHudSubsystem() { Check(this); return hudSubsystem; }
|
|
Subsystem*
|
|
GetSensorSubsystem() { Check(this); return sensorSubsystem; }
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Locomotion parameters (read by MechControlsMapper::InterpretControls to
|
|
// shape the demands, and by the drive in Simulate). reverseStrideLength is
|
|
// the top/run cycle speed the throttle scales (the naming is the 1995
|
|
// field's; LoadLocomotionClips measures it from the run clips), walkStride
|
|
// Length the walk speed. Turn rates are radians/sec.
|
|
//
|
|
public:
|
|
Scalar GetReverseStrideLength() const { Check(this); return reverseStrideLength; }
|
|
Scalar GetWalkStrideLength() const { Check(this); return walkStrideLength; }
|
|
Scalar GetForwardThrottleScale() const { Check(this); return forwardThrottleScale; }
|
|
void SetForwardThrottleScale(Scalar s){ Check(this); forwardThrottleScale = s; }
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Eyepoint / aim-ray composition. The pilot's torso-elevation aim (stick
|
|
// pitch) does NOT tilt any skeleton joint on this mech family -- it pitches
|
|
// the COCKPIT EYE and the weapon boresight (pixel-calibrated in the BT411
|
|
// reverse-engineering: "pitch does not work" turned out to mean nothing
|
|
// consumed Torso's currentElevation, not that a joint was un-animated).
|
|
// Composed each frame in Simulate; DPLEyeRenderable / the aim ray read it.
|
|
//
|
|
public:
|
|
const EulerAngles&
|
|
GetEyepointRotation() const { Check(this); return eyepointRotation; }
|
|
|
|
//
|
|
// Look-state commit (called by the controls mapper on a look-button
|
|
// state change): re-aim the eyepoint from the model's authored look
|
|
// angles. look_state = MechControlsMapper::LookState.
|
|
//
|
|
void
|
|
CommitLookState(int look_state);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Local Data
|
|
//
|
|
protected:
|
|
//
|
|
// Cached subsystem back-pointers (also held in the base roster).
|
|
//
|
|
Subsystem *sensorSubsystem;
|
|
Subsystem *gyroSubsystem;
|
|
Subsystem *sinkSourceSubsystem; // the real Torso
|
|
Subsystem *hudSubsystem;
|
|
SubsystemMessageManager *messageManager;
|
|
int weaponCount;
|
|
|
|
//
|
|
// Capability sub-rosters (Socket views onto the subsystem roster;
|
|
// populated per-frame -- phase 5).
|
|
//
|
|
ChainOf<Subsystem*> controllableSubsystems;
|
|
ChainOf<Subsystem*> watchedSubsystems;
|
|
ChainOf<Subsystem*> heatableSubsystems;
|
|
ChainOf<Subsystem*> weaponRoster;
|
|
ChainOf<Subsystem*> damageableSubsystems;
|
|
|
|
//
|
|
// Embedded status / animation / naming state.
|
|
//
|
|
NameFilter mechNameFilter;
|
|
AlarmIndicator masterAlarm;
|
|
AlarmIndicator heatAlarm;
|
|
AlarmIndicator stabilityAlarm;
|
|
AlarmIndicator statusAlarm;
|
|
Reticle targetReticle;
|
|
StateIndicator animationState;
|
|
StateIndicator replicantAnimationState;
|
|
StateIndicator collisionState;
|
|
SequenceController legAnimation;
|
|
SequenceController bodyAnimation;
|
|
AverageOf<Scalar> telemetryFilter[5];
|
|
CString resourceNameA;
|
|
CString resourceNameB;
|
|
CString resourceNameC;
|
|
|
|
//
|
|
// Locomotion state (Phase 5.3). Turn rates in rad/s, speeds/strides in
|
|
// world-units/s. reverseStrideLength = top (run) speed; walkStrideLength
|
|
// = walk speed; reverseSpeedMax = the low-speed turn-rate gate; forward
|
|
// ThrottleScale multiplies the forward demand; bodyTargetSpeed = the
|
|
// demanded speed; currentBodySpeed = the accel-tracked actual speed.
|
|
//
|
|
Scalar walkingTurnRate;
|
|
Scalar runningTurnRate;
|
|
Scalar reverseStrideLength;
|
|
Scalar walkStrideLength;
|
|
Scalar reverseSpeedMax;
|
|
Scalar forwardThrottleScale;
|
|
Scalar maxBodyAcceleration;
|
|
Scalar bodyTargetSpeed;
|
|
Scalar currentBodySpeed;
|
|
|
|
//
|
|
// Composed each frame in Simulate: the look-state eye component
|
|
// (lookPitch/lookYaw, set by CommitLookState from the authored look
|
|
// angles) plus the Torso elevation.
|
|
//
|
|
EulerAngles eyepointRotation;
|
|
Scalar lookPitch;
|
|
Scalar lookYaw;
|
|
|
|
//
|
|
// The model's authored look-view angles (rad; deg in the resource).
|
|
//
|
|
Scalar lookLeftAngle;
|
|
Scalar lookRightAngle;
|
|
Scalar lookFrontAngle;
|
|
Scalar lookBackAngle;
|
|
|
|
//
|
|
// Remaining per-frame targeting / animation state, advanced by the
|
|
// mech2/mech3/mech4 simulation. Reserved until that path is
|
|
// reconstructed with named fields.
|
|
//
|
|
int reservedState[202];
|
|
};
|
|
|
|
#endif
|