Scoring roles bound (binary ctor tail @004c0bc8): the mission role dict ->
Player::scenarioRole; TEST.EGG's Role::Default = the baked dfltrole
(lives=1000, killBonus=500) -- authored data flowing. The three score
handlers are live per the decomp derivations (@004c02e4 / @004c0200 /
@004c02a8 + CalcInflictedScore @004c052c; tonnage/bias staged); the
producers post damage scores per delivered hit and the kill credit from
the death transition with the latched killing-blow magnitude. First live
kill: award=3.43, kills=1, score=123.6.
Out of lives -> the mission END: the binary's +10s review post sits in the
one decomp gap, so the staged stand-in enters the engine's own cascade
(StopMissionMessage +10s) -- EndingMission -> the 3s fade -> the second
Stop -> Application::Stop -> RunMissions exits. The BTL4/L4 stop layers
run authentically (plasma score display off, egress lamps).
VERIFIED END-TO-END: a 2-lives egg (role-page return=2 override) -- death
#1 debits and respawns healed; death #2 is OUT OF LIVES; +10s later the
mission ends and BTL4OPT.EXE exits CLEANLY to DOS (GAME-RC prints). The
full 1995 pod mission loop -- egg, boot, spawn, fight, score, die,
respawn, die, mission end, exit -- now runs from reconstructed source.
Zero faults; fight/smoke/novice regressions green. Dev knob:
BT_PLAYER_PASSIVE=1 (piloted mechs hold force-fire).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The player-experience system now gates the entire heat/jam economy, verified in
BOTH directions with a one-token egg edit (TESTNOV.EGG, experience=novice):
NOVICE = 212 fire cycles all pinned at T=77, zero jams, zero shutdowns (the
heat model authentically absent); EXPERT = the full economy (duty cycles, 119
shutdowns + 2 authentic jams under forced fire). Zero Fail in both.
- BTPLAYER: the flag block renamed to its TRUE semantics (simLive @0x25c,
heatModelOn @0x260 -- the FUN_004ad7d4 master switch, advancedDamageOn pair,
levelFlag26c/270, experienceLevel); the ctor rows were already
binary-accurate (nov 0000 / std 1011 / vet 1111 / exp 1101); accessors +
[exp] sentinel.
- HeatSink::HeatModelActive() + ProjectileWeapon::LiveFireEnabled(): owner
mech -> Entity::GetPlayerLink() -> the BTPlayer flags, NULL-permissive.
Gates: both HeatSinkSimulation phases, every weapon fire-heat dump, and
CheckForJam is now the AUTHENTIC form (LiveFireEnabled + heatLoad<=0
early-outs + the minJamChance floor; the interim heat-degraded gate retired).
- THE LOAD-BEARING FIX: Mech ctor SetValidFlag(). Every 1995 entity ctor tail
marks itself valid; ours didn't -- Entity::Dispatch routes messages to an
INVALID entity into the deferred event queue, so the PlayerLink bind (and
every directly-dispatched mech message) silently never landed and the gates
read a NULL player forever.
- THE COOLANT SYSTEM (authentic bodies, byte-verified constants: HeatLoadScale
0.002 -> heatLoad now in [0,1]; equalize eps 1e-4; draw floor/ON
0.0025/0.003): UpdateCoolant (damage-scaled draw -- an undamaged mech leaks
nothing), BalanceCoolant (full clamp chain from ConductHeat), DrawCoolant
base=0 with the RESERVOIR override as THE SOURCE; Reservoir reconstructed
(capacity overlays thermalCapacity, CoolantSimulation + the full
InjectCoolant flush distribution, BT_FORCE_FLUSH dev hook); Condenser
RefrigerationSimulation (massScale = (1-damage)*refrigerationFactor >= 1 --
the heat pump that chills the bank; valveState inits 1; digit-suffix number
fix). Deferred: AggregateHeatSink family, cockpit-button handlers
(MoveValve/ToggleCooling/InjectCoolant), TrackSeekVoltage charge model.
Research driven by a 4-agent workflow dossier over the BT411 RE (verbatim
bodies for every function above + the egg experience plumbing).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes the incorrect DefaultData reuse of Player::MessageHandlers -- BTPlayer now
has its own handler table (DropZoneReply, VehicleDead, Score, ScoreInflicted,
ScoreUpdate; the last two add BT message IDs) chained onto the base set, matching
the .data table recovered in BT411. A mission-start DropZoneReply now routes to
BTPlayer::DropZoneReplyMessageHandler (the real spawn/respawn dispatch skeleton)
instead of the base "should not be handled by base player class" Fail stub.
Boot ladder now runs the full engine + app + network + mission + player path and
reaches the spawn handshake, halting at CreatePlayerVehicle -> Mech::Make -- the
Mech subsystem frontier (Mech ctor + mech2/3/4 + subsystems + weapons), the next
major reconstruction milestone. Scoring/death handlers, PlayerSimulation, and the
mech-placement tail staged with documented Fail bodies (BTPLAYER.NOTES.md).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Boot ladder advances past player creation. BTPlayer ctor/dtor/Make/
TestInstance/GetExperienceLevel reconstructed from BT411's Ghidra-recovered
body (@004c0bc8) backdated to 1995 idiom; the reserved[38] placeholder in
BTPLAYER.HPP replaced with the real BT-own members.
Key fidelity call: the game-mode flags are derived from
btMission->ExperienceLevel() (the egg's per-pilot experience key) with the
binary-accurate switch rows from the [T1] disassembly -- NOT from the scenario
role's returnFromDeath, which BT411's port uses as a [T3] stand-in. Mapping and
residual naming/[T4] uncertainty documented in BTPLAYER.NOTES.md.
Live boot now runs: banner -> resources -> app ctor -> network single-user ->
egg -> mission -> SetPlayerData -> BTRegistry::MakePlayer -> BTPlayer ctor
(resolves team, seeds experience flags) -> halts at the base
Player::DropZoneReplyMessageHandler stub (BTPlayer's own message-handler table
is the next brick -- DefaultData still reuses Player::MessageHandlers).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All 10 surviving original TUs plus the reconstructed BTL4APP.CPP pilot build
clean with the authentic OPT.MAK flags (compile410.sh --sweep). First time
the 4.10 BattleTech source has compiled since 1996.
- layout_probe.cpp: the period compiler measures 1995 layouts from the
surviving headers; validated 3/3 against binary alloc sizes (BTMission
0xFC, BTL4ModeManager 0xC, BTRegistry 0x10). Base boundary: Simulation
0xD0 / Entity 0x1C4 / Mover 0x300 / JointedMover 0x328 => Mech-own region
0x328-0x854 (MECH-LAYOUT.md staging worksheet).
- 13 staged headers close the family ([T3] reserved[]-parked layouts;
interfaces PROVEN by the surviving consumers): MECH, MECHSUB, HEAT,
POWERSUB, MECHWEAP, EMITTER, MECHMPPR, BTPLAYER (BTPlayer__MakeMessage =
Player's 8 args + roleName/teamName [T1 via BTREG]), PROJTILE, MISSILE,
BTL4MPPR, BTL4VID + the round-2 BTCNSL/BTSCNRL.
- compile410.sh: PCH gate retired (bt.hpp/mungal4.hpp full include sets),
DPL SDK roots on the include line.
- BTL4APP.CPP: appmgr include + GetApplicationManager()->GetFrameRate() +
ResourceDescription:: scoping; Fail() held at its recorded line 400.
- Evidence ledgers: STAGED-HEADERS.NOTES.md, MECH-LAYOUT.md, BACKFILLS,
BTCNSL (binary-recovered console wire IDs), BTSCNRL.
Remaining for a linkable BTL4OPT: the ~40 missing TU bodies (917-function
manifest) - the header skeleton they grow into now exists and compiles.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>