Files
TeslaRel410/restoration/source410/BT/BTPLAYER.NOTES.md
T
CydandClaude Fable 5 c43e6d873a 4.10 reconstruction: real BTPlayer ctor (binary-accurate experience-level flags)
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>
2026-07-19 20:18:37 -05:00

3.7 KiB

BTPLAYER.CPP / .HPP — reconstruction notes

Status: constructor / dtor / Make / TestInstance / GetExperienceLevel RECONSTRUCTED; message-handler table + handlers + PlayerSimulation + CreatePlayerVehicle still staged.

Sources

  • BT411 game/reconstructed/btplayer.cpp (Ghidra-recovered ctor @004c0bc8, Make @004c0ecc, dtor @004c0efc, TestInstance @004c0f28) — byte-offset annotated body.
  • Surviving 1995 headers pin every base API: PLAYER.HPP (base members currentScore/scenarioRole/deathCount/playerMission, GetMission), SIMULATE.HPP (lastPerformance/lastUpdate/simulationFlags/activePerformance — lastPerformance is a BASE member, not BT-own), ENTITY.HPP (GetInstance/ReplicantInstance), NTTMGR.HPP (EntityManager::FindGroup, EntityGroup::groupMembers = ChainOf<Node*>), TEAM.HPP (Team::teamName[64], public — BTTeam inherits it), BTMSSN.HPP (BTMission::ExperienceLevel()/AdvancedDamageOn(), enum Novice/Standard/ Veteran/Expert = 0..3), SCNROLE.HPP.

Member layout note

The staged header's int reserved[38] placeholder was replaced with the real BT-own members (btMission, teamName[64], teamEntity, freeForAll, consoleAttached, suppressConsole, the experience-flag block, killCount/padScore, objectiveMech, lastConsoleUpdate, deathPending). Byte offsets do NOT need to match the shipped 0x294-byte object — this is a fresh self-consistent build; only wire-format structs (MakeMessage) must match the binary, and those are unchanged.

Experience-level flag mapping — the [T1] correction

The ctor derives the game-mode flags from btMission->ExperienceLevel() (mission+0xe4, the egg's per-pilot "experience" key), NOT from the scenario role's returnFromDeath — see bt-experience-levels. BT411's ported ctor uses scenarioRole->GetReturnFromDeath() as a stand-in and marks it [T3]; this 1995 reconstruction encodes the binary-accurate reading instead.

Binary switch rows (member ← value per level), from the [T1] disassembly:

level showDamageReceived (0x25c) showKills (0x260) roleReturnDelay2 (0x26c) showScore (0x270)
novice 0 0 0 0
standard 1 0 1 1
veteran 1 1 1 1
expert 1 1 0 1

Plus showDamageInflicted (0x264) = roleReturnDelay (0x268) = advancedDamageOn.

Member NAMES are wrong-but-kept (they date from the earlier scoring work): showKills is really the HEAT-MODEL master switch (FUN_004ad7d4), showDamageReceived is the "sim live / novice lockout" gate, showScore/roleReturnDelay2 consumers not fully located ([T4]). Rename is a follow-up wiring task; the VALUES are correct.

Deliberate differences from BT411's port

  • Make: the 1995 return new BTPlayer(creation_message); — BT411's replicant SetValidFlag() is a P6 network-bring-up addition, dropped.
  • Replicant-mission caching uses application->GetCurrentMission() (the real 1995 accessor, PLAYER.CPP:689) instead of BT411's raw application+0xc8.

Still staged (next bricks, in boot order)

  1. Message-handler table — DefaultData currently reuses Player::MessageHandlers, so BTPlayer's own handlers are unwired and the base Player::DropZoneReplyMessageHandler Fails ("should not be handled by base player class!", PLAYER.CPP:179). Next brick = BTPlayer MessageHandlerEntries[]
    • MessageHandlers + real DropZoneReplyMessageHandler (spawn handshake).
  2. DropZoneReply → CreatePlayerVehicle → Mech::Make — the spawn chain pulls in the mech subsystem (Mech::Make still Fail-staged).
  3. VehicleDead / Score / ScoreInflicted / ScoreUpdate handlers (scoring wave), PlayerSimulation (console update), InitializePlayerLink, CalcInflictedScore.