Files
TeslaRel410/restoration/source410/BT/BTPLAYER.HPP
T
CydandClaude Fable 5 f65a3259ce BT410 Phase 5.3.25: scoring + the COMPLETE mission lifecycle -- egg to GAME-RC
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>
2026-07-24 17:18:41 -05:00

296 lines
8.2 KiB
C++

//===========================================================================//
// File: btplayer.hpp //
// Project: BattleTech //
// Contents: Implementation details for the BT player //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(BTPLAYER_HPP)
# define BTPLAYER_HPP
# if !defined(PLAYER_HPP)
# include <player.hpp>
# endif
//##################### Forward Class Declarations #######################
class Mech;
class BTTeam;
class Mission;
//###########################################################################
//####################### BTPlayer Make Message #########################
//###########################################################################
class BTPlayer__MakeMessage:
public Player__MakeMessage
{
public:
CString roleName;
CString teamName;
BTPlayer__MakeMessage(
Receiver::MessageID message_ID,
size_t length,
Entity::ClassID class_ID,
const EntityID &owner_ID,
ResourceDescription::ResourceID resource_ID,
LWord instance_flags,
const Origin &origin,
int player_bitmap_index,
CString role_name,
CString team_name
):
Player__MakeMessage(
message_ID,
length,
class_ID,
owner_ID,
resource_ID,
instance_flags,
origin,
player_bitmap_index
)
{
roleName = role_name;
teamName = team_name;
}
};
//###########################################################################
//###########################################################################
//###################### BTPlayer Score Message #########################
//###########################################################################
//
// The BT wire layout (extends the engine ScoreMessage's scoreAward
// @+0x1c): scoreType @+0x20, damageAmount @+0x24 (the input every award
// derives from), the point-source handles @+0x28..0x30 (console VTV
// feed -- headless zeros), senderMechID @+0x34 (the inflicting / victim
// mech, resolved via the host manager).
//
class BTPlayer__ScoreMessage:
public Player__ScoreMessage
{
public:
int scoreType;
Scalar damageAmount;
int pointSenderHi;
int pointSenderLo;
int auxID;
EntityID senderMechID;
BTPlayer__ScoreMessage(
Receiver::MessageID message_ID,
size_t length,
Scalar score,
int score_type,
Scalar damage_amount,
const EntityID &sender_mech_ID
):
Player__ScoreMessage(message_ID, length, score),
scoreType(score_type),
damageAmount(damage_amount),
pointSenderHi(0),
pointSenderLo(0),
auxID(0),
senderMechID(sender_mech_ID)
{}
};
//############################# BTPlayer ################################
//###########################################################################
class BTPlayer:
public Player
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum {
ScoreInflictedMessageID = Player::NextMessageID,
ScoreUpdateMessageID,
NextMessageID
};
//
// The score types the BT ScoreMessage carries (branch selector
// @004c02e4; type 0 has its own handler @004c0200).
//
enum {
DamageInflictedScore = 0,
DamageReceivedScore = 1,
KillScore = 2
};
public:
typedef BTPlayer__ScoreMessage ScoreMessage;
//
// The shared damage -> points converter (binary @004c052c):
// (damage + bias) x role damageInflictedModifier x factor, where a
// friendly hit flips to -friendlyFirePenalty. Role-less players
// degrade to raw damage (the dev-mission shape).
//
Scalar
CalcInflictedScore(
Scalar damage_amount,
Entity *other_mech,
Scalar bias
);
protected:
void
DropZoneReplyMessageHandler(DropZone__ReplyMessage *message);
void
VehicleDeadMessageHandler(VehicleDeadMessage *message);
void
ScoreMessageHandler(ScoreMessage *message);
void
ScoreInflictedMessageHandler(ScoreMessage *message);
void
ScoreUpdateMessageHandler(ScoreMessage *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Vehicle creation
//
protected:
virtual void
CreatePlayerVehicle(Origin mech_location);
void
InitializePlayerLink();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
typedef BTPlayer__MakeMessage MakeMessage;
static BTPlayer*
Make(MakeMessage *creation_message);
BTPlayer(
MakeMessage *creation_message,
SharedData &shared_data = DefaultData
);
~BTPlayer();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Experience support
//
public:
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:
Mission
*btMission;
char
teamName[64];
BTTeam
*teamEntity;
Logical
freeForAll;
Logical
consoleAttached;
Logical
suppressConsole;
//
// EXPERIENCE-LEVEL game-mode flags, derived in the constructor from the
// mission's experience level (novice / standard / veteran / expert) and
// advanced-damage technician flag. TRUE SEMANTICS (the early "display
// toggles" reading of this block was wrong -- see BTPLAYER.NOTES.md):
// binary rows for (simLive, heatModelOn, levelFlag26c, levelFlag270) =
// nov 0,0,0,0 / std 1,0,1,1 / vet 1,1,1,1 / exp 1,1,0,1.
// simLive -- the novice lockout: jams, searchlight, powersub
// short events (CheckForJam's LiveFireEnabled gate);
// heatModelOn -- THE heat-model master switch (HeatModelActive):
// weapon-fire heat, the heat sim, coolant, movement
// heat. Standard mode has NO heat consequences --
// authentic, not a gap;
// advancedDamageOn/2 -- the egg's technician flag (an int pair in the
// binary; NOT part of the level switch);
// experienceLevel -- the raw 0..3 (the ==0 novice-lockout predicate).
//
Logical
simLive;
Logical
heatModelOn;
Logical
advancedDamageOn;
Logical
advancedDamageOn2;
Logical
levelFlag26c;
Logical
levelFlag270;
int
experienceLevel;
public:
Logical
IsSimLive() const { Check(this); return simLive; }
Logical
IsHeatModelOn() const { Check(this); return heatModelOn; }
Logical
IsAdvancedDamageOn() const { Check(this); return advancedDamageOn; }
protected:
int
killCount;
int
padScore;
Mech
*objectiveMech;
Time
lastConsoleUpdate;
Logical
deathPending;
};
#endif