#85: myomer drive heat LIVE -- the five Mech motion operands were return-0
shims, so the reconstructed integrator @004b8d18 accumulated zero forever
The integrator, its gates and the heat plumbing were all reconstructed and
running -- but OwnerVelocityMag/OwnerDriveMag/OwnerVelocityY/OwnerMotionGain/
OwnerMass were cross-family compile shims returning 0.0f, so the myomers
priced ratio^2 * damageGain * 0 every tick: ice cold at any seek (Oracle's
night-7 panel-confirmed report).
Operands re-grounded against the raw disasm + decomp and mapped to NAMED
members via a complete-Mech-TU bridge (BTMechMyomerMotionSample, mech4.cpp),
per the databinding rule:
+0x1C4 vec -> localVelocity.linearMotion
+0x82C vec -> localAcceleration.linearMotion (the authentic 15-ring
smoothed AccelerationLastFrame the port already maintains)
+0x20C -> moverMass (the collision divert's cell; the old "motion
gain" label was a misread)
*(+0x250) -> environment gravity (FUN_00421e2c: vy -= **(+0x250)/tick),
via GetEnvironment()->gravityConstant
So the heat physics reads: 0.005 * 1/2 m v^2 (kinetic work, per-tick/no-dt
in the binary -- kept verbatim, frame-rate note documented) + 0.2 * m g
|vy| dt (climb power) + 0.2 * m |v||a| dt (acceleration power), all scaled
by ratio^2 and (1 + zone damage). Restored the binary's fabs(v.y) (the
draft had signed vy -- descending would have COOLED).
Authored tuning extracted from BTL4.RES (18 mech records, one shared
tuning): VelocityEfficiency=0.995, AccelerationEfficiency=0.8, gears
0.3/0.5/0.7/0.9999 rec idx 2; myomer thermal profile 77/1000/2000,
conductance 1.9e5, thermalMass 2.5e5.
Live-verified (solo arena, BT_MYO_LOG + BT_HEAT_LOG): standstill generates
~0; hard circling drove Myomers T 77 -> 1225 (past the 1000 degradation
line) and the coolant loop conducted it back to ~520 equilibrium on
slowing; damageGain live at 1.048 from grind rattle.
Known-inert remainder (filed in open-questions): the climb term reads g=0
because Mover::localEnvironment is never populated in the port
(EnvironmentZone res type 23 unwired); the mover feed (speedEffect ->
locomotion) stays WAVE 6.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Zh7PTkFy4KwTzVighLR9J
This commit is contained in:
co-authored by
Claude Fable 5
parent
37dd7f9663
commit
1570983fde
@@ -659,30 +659,62 @@ void Myomers::MyomersSimulation(Scalar time_slice)
|
||||
//
|
||||
void Myomers::MyomersDriveHeat(Scalar time_slice)
|
||||
{
|
||||
if (!OwnerAdvancedDamage()) // FUN_004ad7d4 gate
|
||||
return;
|
||||
if (!OwnerAdvancedDamage()) // FUN_004ad7d4 gate (binary
|
||||
return; // gates the ACCUMULATE; same outcome)
|
||||
|
||||
Scalar velMag = OwnerVelocityMag(); // |Mech velocity| (+0x1C4/0x1C8/0x1CC)
|
||||
Scalar accMag = OwnerDriveMag(); // |Mech drive vector| (+0x82C/0x830/0x834)
|
||||
Scalar vy = OwnerVelocityY(); // Mech +0x1C8
|
||||
Scalar k = OwnerMotionGain(); // Mech +0x20C
|
||||
Scalar m = OwnerMass(); // *Mech[0x250]
|
||||
// #85 fix (2026-07-31): the five Mech motion operands were `return 0.0f`
|
||||
// cross-family shims, so this integrator faithfully accumulated ratio^2 *
|
||||
// damageGain * ZERO every tick -- the myomers stayed ice cold at any seek
|
||||
// (Oracle's night-7 panel-confirmed report). Now sampled for real via the
|
||||
// complete-Mech-TU bridge (mech4.cpp), operands re-grounded against the
|
||||
// raw disasm of @004b8d18 + the authored resource (BTL4.RES 0x0BC6 records:
|
||||
// VelocityEfficiency=0.995, AccelerationEfficiency=0.8, gears
|
||||
// 0.3/0.5/0.7/0.9999 rec idx 2 -- one shared tuning across all 18 mechs).
|
||||
float velMag, accMag, vy, mass, gravity;
|
||||
{
|
||||
extern void BTMechMyomerMotionSample(void *mech,
|
||||
float *vel_mag, float *acc_mag, float *vel_y,
|
||||
float *mass, float *gravity);
|
||||
BTMechMyomerMotionSample(owner, &velMag, &accMag, &vy, &mass, &gravity);
|
||||
}
|
||||
|
||||
Scalar velComplement = 1.0f - accelerationEfficiency; // @0x354
|
||||
Scalar workComplement = 1.0f - velocityEfficiency; // @0x350
|
||||
Scalar velComplement = 1.0f - accelerationEfficiency; // @0x354 (= 0.2 authored)
|
||||
Scalar workComplement = 1.0f - velocityEfficiency; // @0x350 (= 0.005 authored)
|
||||
Scalar damageGain = 1.0f + DamageStructureLevel(); // this[0xE0]+0x158
|
||||
|
||||
Scalar ratio = seekVoltage[currentSeekVoltageIndex] // @0x330[@0x320]
|
||||
/ seekVoltage[recommendedSeekVoltageIndex];// @0x330[@0x324]
|
||||
if (ratio < 1.0f) ratio = 1.0f;
|
||||
|
||||
Scalar work = k * (velMag * velMag) * 0.5f; // dot(v,v)*0.5 == |v|^2*0.5 (_DAT_004b8ee4)
|
||||
// The binary fabs()es all three motion operands (the jbe/fchs pairs
|
||||
// @4b8dd5/@4b8df0/@4b8e16); |v| and |a| are sqrt-positive already, but
|
||||
// v.y is signed -- descending must heat like climbing, not cool.
|
||||
if (vy < 0.0f) vy = -vy;
|
||||
|
||||
// Physics (operands nailed 2026-07-31): mass@0x20C, gravity=**(0x250) --
|
||||
// work = 1/2 m v^2 (kinetic energy; NO dt in the
|
||||
// binary -- the accumulate is per-TICK, an authentic 1995
|
||||
// fixed-frame assumption, so heat/s scales with frame rate;
|
||||
// kept verbatim, field-calibrate if the pod veterans object)
|
||||
// velTerm = m g |vy| dt (climb power)
|
||||
// accTerm = m |v| |a| dt (acceleration power)
|
||||
Scalar work = mass * (velMag * velMag) * 0.5f; // dot(v,v)*0.5 (_DAT_004b8ee4)
|
||||
|
||||
pendingHeat /* @0x1C8 */ +=
|
||||
ratio * ratio * damageGain *
|
||||
( velComplement * vy * k * m * time_slice
|
||||
( velComplement * vy * mass * gravity * time_slice
|
||||
+ workComplement * work
|
||||
+ velComplement * velMag * accMag * k * time_slice );
|
||||
+ velComplement * velMag * accMag * mass * time_slice );
|
||||
|
||||
if (getenv("BT_MYO_LOG"))
|
||||
{
|
||||
static int s_n = 0;
|
||||
if ((s_n++ % 120) == 0)
|
||||
DEBUG_STREAM << "[myoheat] v=" << velMag << " a=" << accMag
|
||||
<< " m=" << mass << " g=" << gravity
|
||||
<< " ratio=" << ratio << " dmgGain=" << damageGain
|
||||
<< " pending=" << pendingHeat << "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -807,9 +839,11 @@ struct MyomersLayoutCheck
|
||||
// The real class at 0xBC6 (ctor @004b8fec) is Myomers (the mech's artificial-
|
||||
// muscle drive); the factory built an Actuator RECON_SUBSYS stub. alloc 0x358.
|
||||
// The subsystem constructs (resolves its Generator + builds the seek-voltage
|
||||
// gear table) and ticks its real Performance, but is currently INERT w.r.t.
|
||||
// locomotion/heat (no-op mover feed + the OwnerAdvancedDamage()==False sim gate)
|
||||
// -- so it cannot regress the gait/drive. Authentic coupling = a follow-up.
|
||||
// gear table) and ticks its real Performance. DRIVE HEAT IS LIVE (#85 fix
|
||||
// 2026-07-31: the motion operands are sampled from the real Mech). Still
|
||||
// inert: the LOCOMOTION coupling (no-op mover feed -- speedEffect is computed
|
||||
// but nothing consumes it; WAVE 6 cutover) and the climb heat term (the
|
||||
// environment gravity is unwired in the port, so g reads 0).
|
||||
//===========================================================================//
|
||||
Subsystem *CreateMyomersSubsystem(Mech *owner, int id, void *seg)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user