The master perf's opening scan maxes the myomer chain's speedEffect into the mobility scale and applies it straight to the pilot's command cells: the throttle is multiplied by it, and a scale inside the 1e-4 deadzone zeroes the turn outright -- a mech with dead muscles cannot even pivot. It is the same cell the duck driver already read as "the legs still work", so that gate stops being a constant. THE CHAIN IDENTITY IS NOW PROVEN RATHER THAN INFERRED. My 5.3.122 note pinned mech+0x7ac to Myomers "by adjacency to the string pool", which nearly went wrong: the very cell the scan reads, +0x31c, is a MechWeapon trigger over in the weapon TU. The decisive evidence is arithmetic -- the Myomers cap-raise reads seekVoltage at +0x330 indexed by maxSeekVoltageIndex at +0x32c, and walking our own member order backwards from there lands speedEffect exactly on +0x31c. The ctor's myomer sweep also carries the other half: walking the chain is what sets the "I computed my own top speed" flag, so a mech WITH myomers broadcasts its cap and one without adopts the streamed value. Safe by construction against the obvious hazard: the mapper reassigns its demands from scratch in InterpretControls, which ticks before the mech's performance, so multiplying its cell in place cannot compound frame to frame. Soak: [mobility] scale 1 over 1 myomers on an undamaged bhk1 -- throttle unscaled, drive unchanged, zero faults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
139 lines
4.5 KiB
C++
139 lines
4.5 KiB
C++
//===========================================================================//
|
|
// File: myomers.hpp //
|
|
// Project: BattleTech Brick: Mech subsystems //
|
|
// Contents: Myomers -- the artificial-muscle (locomotion power) subsystem //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#if !defined(MYOMERS_HPP)
|
|
# define MYOMERS_HPP
|
|
|
|
# if !defined(POWERSUB_HPP)
|
|
# include <powersub.hpp>
|
|
# endif
|
|
|
|
//##################### Forward Class Declarations #######################
|
|
class Mech;
|
|
|
|
//###########################################################################
|
|
//#################### Myomers Model Resource ##########################
|
|
//###########################################################################
|
|
|
|
struct Myomers__SubsystemResource:
|
|
public PoweredSubsystem::SubsystemResource
|
|
{
|
|
Scalar velocityEfficiency;
|
|
Scalar accelerationEfficiency;
|
|
Scalar seekVoltage[5];
|
|
int seekVoltageRecommendedIndex;
|
|
};
|
|
|
|
//###########################################################################
|
|
//############################## Myomers ###############################
|
|
//###########################################################################
|
|
|
|
class Myomers:
|
|
public PoweredSubsystem
|
|
{
|
|
public:
|
|
static Derivation ClassDerivations;
|
|
static SharedData DefaultData;
|
|
|
|
typedef void
|
|
(Myomers::*Performance)(Scalar time_slice);
|
|
void
|
|
SetPerformance(Performance performance)
|
|
{
|
|
Check(this);
|
|
activePerformance = (Simulation::Performance)performance;
|
|
}
|
|
|
|
static Logical
|
|
TestClass(Mech &);
|
|
Logical
|
|
TestInstance() const;
|
|
void
|
|
MyomersSimulation(Scalar time_slice);
|
|
|
|
public:
|
|
typedef Myomers__SubsystemResource SubsystemResource;
|
|
|
|
Myomers(
|
|
Mech *owner,
|
|
int subsystem_ID,
|
|
SubsystemResource *subsystem_resource,
|
|
SharedData &shared_data = DefaultData
|
|
);
|
|
~Myomers();
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Attribute publication. The shipped binary's string pool lists this
|
|
// class's attribute names contiguously, immediately after the class name
|
|
// "Myomers" and its ToggleSeekVoltage message:
|
|
//
|
|
// SpeedEffect CurrentSeekVoltageIndex RecommendedSeekVoltageIndex
|
|
// MinSeekVoltageIndex MaxSeekVoltageIndex SeekVoltage
|
|
//
|
|
// -- which is EXACTLY the order of the members below, so the
|
|
// reconstruction's layout matches the original and the ids can be
|
|
// pinned faithfully rather than guessed. SpeedEffect is the one an
|
|
// authored AttributeWatcher in BTL4.RES binds (the myomer whine).
|
|
//
|
|
public:
|
|
enum {
|
|
SpeedEffectAttributeID = PoweredSubsystem::NextAttributeID,
|
|
CurrentSeekVoltageIndexAttributeID,
|
|
RecommendedSeekVoltageIndexAttributeID,
|
|
MinSeekVoltageIndexAttributeID,
|
|
MaxSeekVoltageIndexAttributeID,
|
|
SeekVoltageAttributeID,
|
|
NextAttributeID
|
|
};
|
|
|
|
static const IndexEntry AttributePointers[];
|
|
static AttributeIndexSet AttributeIndex;
|
|
|
|
public:
|
|
//
|
|
// The drive computation (@004b8ac0): the locomotion output available
|
|
// for an input voltage -- the mech base speed scaled by the gear
|
|
// ratio, degraded by heat past the degradation band and by the
|
|
// subsystem's own accumulated zone damage.
|
|
//
|
|
Scalar
|
|
AvailableOutput(Scalar input_voltage);
|
|
|
|
//
|
|
// Raise the owner mech's run-speed cap to this myomer's full-throttle
|
|
// output (@004b8ef0) -- idempotent max(), the binary calls it from
|
|
// the assembly loop.
|
|
//
|
|
void
|
|
RegisterMaxOutput();
|
|
|
|
//
|
|
// The mobility contribution (binary myomers+0x31c). The master
|
|
// perf maxes this across the mech's myomer chain into the mobility
|
|
// scale -- see Mech::UpdateMobilityScale.
|
|
//
|
|
Scalar
|
|
SpeedEffectOf() const { Check(this); return speedEffect; }
|
|
|
|
protected:
|
|
Scalar speedEffect;
|
|
int currentSeekVoltageIndex;
|
|
int recommendedSeekVoltageIndex;
|
|
int minSeekVoltageIndex;
|
|
int maxSeekVoltageIndex;
|
|
Scalar seekVoltage[5];
|
|
Scalar heatRange;
|
|
Scalar heatRangeSquared;
|
|
Scalar velocityEfficiency;
|
|
Scalar accelerationEfficiency;
|
|
};
|
|
|
|
#endif
|