diff --git a/game/reconstructed/heat.cpp b/game/reconstructed/heat.cpp index 9446f27..6ac3032 100644 --- a/game/reconstructed/heat.cpp +++ b/game/reconstructed/heat.cpp @@ -546,6 +546,19 @@ HeatSink::HeatSink( pendingHeat = 0.0f; + // #96 -- "each mech has a unique heating profile". The heat-family COUNT is + // identical on every chassis (6 condensers, 1 bank, 1 reservoir), so if + // per-mech cooling variation exists it must live in these authored values. + // Dump them so that is a measured fact rather than an assumption. + if (getenv("BT_MYO_LOG")) + DEBUG_STREAM << "[hsparm] " << (GetName() ? GetName() : "?") + << " startT=" << startingTemperature + << " degradeT=" << degradationTemperature + << " failT=" << failureTemperature + << " conductance=" << thermalConductance + << " thermalMass=" << thermalMass + << "\n" << std::flush; + // // A "master" heat sink (segment flagged 0x100, not a sub-/damaged copy) // drives the per-frame thermal simulation. diff --git a/game/reconstructed/myomers.cpp b/game/reconstructed/myomers.cpp index 659b32a..a981fc8 100644 --- a/game/reconstructed/myomers.cpp +++ b/game/reconstructed/myomers.cpp @@ -229,6 +229,25 @@ Myomers::Myomers( recommendedSeekVoltageIndex = resource->seekVoltageRecommendedIndex; // @0x324 res+0x1AC currentSeekVoltageIndex = recommendedSeekVoltageIndex; // @0x320 minSeekVoltageIndex = 0; // @0x328 + + // #96 -- "each mech has a unique heating profile". Dump what THIS mech's + // myomer record actually streamed, so per-chassis variation is a measured + // fact rather than an assumption. One line per myomer built. + if (getenv("BT_MYO_LOG")) + { + DEBUG_STREAM << "[myoparm] " << (GetName() ? GetName() : "?") + << " velEff=" << velocityEfficiency + << " accEff=" << accelerationEfficiency + << " gears=["; + for (int g = 0; g <= maxSeekVoltageIndex && g < 5; ++g) + DEBUG_STREAM << (g ? "," : "") << seekVoltage[g]; + DEBUG_STREAM << "] rec=" << recommendedSeekVoltageIndex + << " max=" << maxSeekVoltageIndex + << " degradeT=" << degradationTemperature + << " failT=" << failureTemperature + << " thermalMass=" << thermalMass + << "\n" << std::flush; + } } @@ -726,20 +745,31 @@ void Myomers::MyomersDriveHeat(Scalar time_slice) // 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 * mass * gravity * time_slice - + workComplement * work - + velComplement * velMag * accMag * mass * time_slice ); + // The three terms, kept separate for diagnosis (#96 "myomers run too hot"): + // two are POWER (x dt), one is an ENERGY added per TICK. + Scalar termClimb = velComplement * vy * mass * gravity * time_slice; + Scalar termKinetic = workComplement * work; // <-- no dt, per the binary + Scalar termAccel = velComplement * velMag * accMag * mass * time_slice; + Scalar gain = ratio * ratio * damageGain; + + pendingHeat /* @0x1C8 */ += gain * (termClimb + termKinetic + termAccel); if (getenv("BT_MYO_LOG")) { static int s_n = 0; if ((s_n++ % 120) == 0) + { + Scalar sum = termClimb + termKinetic + termAccel; DEBUG_STREAM << "[myoheat] v=" << velMag << " a=" << accMag << " m=" << mass << " g=" << gravity << " ratio=" << ratio << " dmgGain=" << damageGain + << " dt=" << time_slice + << " | climb=" << (gain * termClimb) + << " kinetic=" << (gain * termKinetic) + << " accel=" << (gain * termAccel) + << " kineticShare=" << (sum != 0.0f ? (termKinetic / sum) : 0.0f) << " pending=" << pendingHeat << "\n" << std::flush; + } } } diff --git a/scratchpad/night8/myocmp.sh b/scratchpad/night8/myocmp.sh new file mode 100644 index 0000000..ca3ff61 --- /dev/null +++ b/scratchpad/night8/myocmp.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# #96: compare myomer heat GENERATION between chassis at seek 4, flat out. +# Cooling capacity is identical across chassis (measured), and heat ~ m*v^2, so +# a light fast mech may out-heat a heavy slow one despite half the mass. +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +V="$1" +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +sed "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=$V/" MP.EGG > MYOC.EGG +LOG=myocmp_$V.log +rm -f "$LOG" +export BT_MYO_LOG=1 BT_FORCE_SEEK=3 +export BT_GOTO="1500 1500" +bt_launch "$LOG" MYOC.EGG 0x03 +sleep 100 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 diff --git a/scratchpad/night8/myoheat.sh b/scratchpad/night8/myoheat.sh new file mode 100644 index 0000000..caa4590 --- /dev/null +++ b/scratchpad/night8/myoheat.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# #96: WHY do the myomers run too hot? Split the heat into its three terms. +# +# The binary's integrator (FUN_004b8d18, constants 0.5 / 0.0 / 1.0 verified): +# heat += ratio^2 * (1+damage) * [ (1-effA)*|vy|*m*g*dt climb POWER +# + (1-effV)*(0.5*m*|v|^2) kinetic ENERGY, NO dt +# + (1-effA)*|v|*|a|*m*dt ] accel POWER +# Two terms are power (x dt); the kinetic one is an ENERGY added PER TICK, so its +# contribution per SECOND scales with the tick rate. On flat ground at steady +# speed vy~0 and |a|~0, which should leave the dt-less term carrying nearly all +# of the heat. BT_MYO_LOG now prints the split. +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +sed "s/^map=.*/map=grass/; s/^time=.*/time=day/" MP.EGG > MYO.EGG +LOG=myoheat_${1:-seek4}.log +rm -f "$LOG" +# Run flat out in the top gear, straight line, no combat. +export BT_MYO_LOG=1 BT_DRIVE_LOG=1 BT_FORCE_SEEK=${2:-3} +export BT_SPAWN_ENEMY=1 # a SECOND chassis -> one run dumps two myomer records +export BT_GOTO="1500 1500" +bt_launch "$LOG" MYO.EGG 0x03 +sleep 90 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +echo "=== heat term split ===" +grep -oE "\[myoheat\][^\n]*" "$LOG" | tail -6 diff --git a/scratchpad/night8/myoparm.sh b/scratchpad/night8/myoparm.sh new file mode 100644 index 0000000..42b8c0c --- /dev/null +++ b/scratchpad/night8/myoparm.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# #96 Q1: "each mech has a unique heating profile" -- is the myomer record +# per-chassis, or shared? Build one mech per run and dump what it streamed. +# Oracle's example is the pair thr1 (Thor, sustains seek 4) vs own1 (Owens, +# a light chicken-walker that cannot). +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +V="$1" +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +# swap the FIRST pilot's vehicle -- that is the one solo flies +sed "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=$V/" MP.EGG > MYOP.EGG +LOG=myoparm_$V.log +rm -f "$LOG" +export BT_MYO_LOG=1 BT_ROSTER=1 +bt_launch "$LOG" MYOP.EGG 0x03 +sleep 70 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2