diff --git a/restoration/source410/BT/BTPLAYER.CPP b/restoration/source410/BT/BTPLAYER.CPP index ded2d2a1..fcc9efc4 100644 --- a/restoration/source410/BT/BTPLAYER.CPP +++ b/restoration/source410/BT/BTPLAYER.CPP @@ -1,5 +1,11 @@ //===========================================================================// +// File: btplayer.cpp // // Project: BattleTech // +// Contents: Implementation details for the BT player // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // @@ -13,6 +19,27 @@ # include #endif +#if !defined(BTTEAM_HPP) +# include +#endif + +#if !defined(BTMSSN_HPP) +# include +#endif + +#if !defined(NTTMGR_HPP) +# include +#endif + +#if !defined(APP_HPP) +# include +#endif + +// +//############################################################################# +// Shared data support +//############################################################################# +// Derivation BTPlayer::ClassDerivations( Player::ClassDerivations, @@ -28,22 +55,167 @@ BTPlayer::SharedData (Entity::MakeHandler)BTPlayer::Make ); +// +//############################################################################# +// Constructor +// +// Copies the team name out of the creation message, resolves the owning +// BTTeam, caches the mission, and derives the game-mode display / heat-model +// flags from the mission's experience level and advanced-damage flag. +//############################################################################# +// BTPlayer::BTPlayer( MakeMessage *creation_message, SharedData &shared_data ): Player(creation_message, shared_data) { - Fail("BTPlayer -- btplayer.cpp not yet reconstructed"); + consoleAttached = False; + suppressConsole = False; + currentScore = 0; + deathPending = False; + + // + // Remember our team name from the creation message. + // + strcpy(teamName, creation_message->teamName); + + // + // Resolve the BTTeam entity that owns this team name. + // + teamEntity = NULL; + EntityGroup *teams = application->GetEntityManager()->FindGroup("Teams"); + if (teams) + { + ChainIteratorOf iterator(teams->groupMembers); + BTTeam *team; + while ((team = (BTTeam *)iterator.ReadAndNext()) != NULL) + { + if (strcmp(team->teamName, teamName) == 0) + { + teamEntity = team; + break; + } + } + } + + freeForAll = True; + + // + // Cache the mission (experience level / advanced-damage source). + // + BTMission *bt_mission = + Cast_Object(BTMission *, application->GetCurrentMission()); + btMission = bt_mission; + + if (GetInstance() == ReplicantInstance) + { + // + // Replicant: driven by console-update messages. + // + SetPerformance(&BTPlayer::PlayerSimulation); + } + else + { + // + // Master: derive the game-mode flags from the mission experience + // level (novice / standard / veteran / expert) and advanced-damage + // technician flag. See BTPLAYER.NOTES.md for the flag mapping. + // + Check(bt_mission); + switch (bt_mission->ExperienceLevel()) + { + case BTMission::NoviceMode: + showDamageReceived = 0; + showKills = 0; + roleReturnDelay2 = 0; + showScore = 0; + break; + case BTMission::StandardMode: + showDamageReceived = 1; + showKills = 0; + roleReturnDelay2 = 1; + showScore = 1; + break; + case BTMission::VeteranMode: + showDamageReceived = 1; + showKills = 1; + roleReturnDelay2 = 1; + showScore = 1; + break; + case BTMission::ExpertMode: + showDamageReceived = 1; + showKills = 1; + roleReturnDelay2 = 0; + showScore = 1; + break; + } + showDamageInflicted = bt_mission->AdvancedDamageOn(); + roleReturnDelay = bt_mission->AdvancedDamageOn(); + roleClassIndex = bt_mission->ExperienceLevel(); + } + + killCount = 0; + padScore = 0; + objectiveMech = NULL; + lastPerformance = lastConsoleUpdate = lastUpdate; + + Check_Fpu(); } +// +//############################################################################# +//############################################################################# +// BTPlayer::~BTPlayer() { + Check(this); + Check_Fpu(); } +// +//############################################################################# +// Make +//############################################################################# +// BTPlayer* - BTPlayer::Make(MakeMessage *) + BTPlayer::Make(MakeMessage *creation_message) { - Fail("BTPlayer::Make -- btplayer.cpp not yet reconstructed"); - return NULL; + return new BTPlayer(creation_message); +} + +// +//############################################################################# +//############################################################################# +// +Logical + BTPlayer::TestInstance() const +{ + return IsDerivedFrom(ClassDerivations); +} + +// +//############################################################################# +// GetExperienceLevel +//############################################################################# +// +Enumeration + BTPlayer::GetExperienceLevel() +{ + Check(this); + Check(btMission); + return Cast_Object(BTMission *, btMission)->ExperienceLevel(); +} + +// +//############################################################################# +// PlayerSimulation -- console-update performance (not yet reconstructed). +// The constructor installs this as the replicant Performance; its body is +// exercised only on a networked console-driven run. +//############################################################################# +// +void + BTPlayer::PlayerSimulation(Scalar) +{ + Fail("BTPlayer::PlayerSimulation -- btplayer.cpp not yet reconstructed"); } diff --git a/restoration/source410/BT/BTPLAYER.HPP b/restoration/source410/BT/BTPLAYER.HPP index 17c5cd8c..1ec0151c 100644 --- a/restoration/source410/BT/BTPLAYER.HPP +++ b/restoration/source410/BT/BTPLAYER.HPP @@ -22,6 +22,7 @@ //##################### Forward Class Declarations ####################### class Mech; class BTTeam; + class Mission; //########################################################################### //####################### BTPlayer Make Message ######################### @@ -106,11 +107,70 @@ Enumeration GetExperienceLevel(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Model Support + // + public: + typedef void + (BTPlayer::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Local Data // protected: - int reserved[38]; + Mission + *btMission; + char + teamName[64]; + BTTeam + *teamEntity; + Logical + freeForAll; + Logical + consoleAttached; + Logical + suppressConsole; + + // + // Game-mode flags derived in the constructor from the mission's + // experience level (novice / standard / veteran / expert) and + // advanced-damage technician flag. See BTPLAYER.NOTES.md. + // + Logical + showDamageReceived; + Logical + showKills; + Logical + showDamageInflicted; + Logical + showScore; + Scalar + roleReturnDelay; + Scalar + roleReturnDelay2; + int + roleClassIndex; + + int + killCount; + int + padScore; + Mech + *objectiveMech; + Time + lastConsoleUpdate; + Logical + deathPending; }; #endif diff --git a/restoration/source410/BT/BTPLAYER.NOTES.md b/restoration/source410/BT/BTPLAYER.NOTES.md new file mode 100644 index 00000000..47568293 --- /dev/null +++ b/restoration/source410/BT/BTPLAYER.NOTES.md @@ -0,0 +1,71 @@ +# 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), + 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.