Files
BT411/engine/MUNGA_L4/L4MPPR.cpp
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

370 lines
9.2 KiB
C++

#include "mungal4.h"
#pragma hdrstop
#include "l4mppr.h"
#include "l4ctrl.h"
#include "l4keybd.h"
#include "..\munga\app.h"
#define PEDAL_SCALE 2.0f
//##########################################################################
//#################### CameraL4Mapper #######################
//##########################################################################
//#############################################################################
// Shared Data Support
//
CameraL4Mapper::SharedData
CameraL4Mapper::DefaultData(
CameraL4Mapper::GetClassDerivations(),
CameraL4Mapper::MessageHandlers,
CameraL4Mapper::GetAttributeIndex(),
CameraL4Mapper::StateCount
);
Derivation* CameraL4Mapper::GetClassDerivations()
{
static Derivation classDerivations(CameraControlsMapper::GetClassDerivations(), "CameraL4Mapper");
return &classDerivations;
}
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
CameraL4Mapper::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(CameraL4Mapper, Keypress)
};
CameraL4Mapper::MessageHandlerSet
CameraL4Mapper::MessageHandlers(
ELEMENTS(CameraL4Mapper::MessageHandlerEntries),
CameraL4Mapper::MessageHandlerEntries,
CameraControlsMapper::GetMessageHandlers()
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraL4Mapper::KeypressMessageHandler(
ReceiverDataMessageOf<ControlsKey> *message
)
{
Check(this);
Check(message);
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
switch (message->dataContents)
{
case PCK_F1:
Tell("Aligning Joystick...\n");
controls->BeginAlignJoystick();
break;
case PCK_F2:
Tell("Joystick Aligned...\n");
controls->EndAlignJoystick();
break;
case '>':
rightPedal = 1.0f;
break;
case '<':
leftPedal = 1.0f;
break;
case ' ':
leftPedal = rightPedal = 0.0f;
break;
default:
CameraControlsMapper::KeypressMessageHandler(message);
break;
}
}
//#############################################################################
// Model Support
//
void
CameraL4Mapper::InterpretControls(Scalar)
{
//
//----------------------------------------
// Sum the pedal inputs
//----------------------------------------
//
pedalsPosition = rightPedal - leftPedal;
pedalsPosition *= PEDAL_SCALE;
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraL4Mapper::CameraL4Mapper(
CameraShip *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
)
: CameraControlsMapper(owner, subsystem_ID, subsystem_resource, shared_data)
{
SetPerformance(&CameraL4Mapper::InterpretControls);
leftPedal = 0.0f;
rightPedal = 0.0f;
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
controls
->joystickGroup[LBE4ControlsManager::JoystickPhysical]
.Add(ModeManager::ModeAlwaysActive, &stickPosition, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickTrigger]
.Add(ModeManager::ModeAlwaysActive, &driveCamera, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbHigh]
.Add(ModeManager::ModeAlwaysActive, &slideOrClamp, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft]
.Add(
ModeManager::ModeAlwaysActive,
this,
DecrementCameraMessageID,
this
);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight]
.Add(
ModeManager::ModeAlwaysActive,
this,
IncrementCameraMessageID,
this
);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickPinky]
.Add(
ModeManager::ModeAlwaysActive,
this,
DeleteCameraInstanceMessageID,
this
);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbLow]
.Add(
ModeManager::ModeAlwaysActive,
this,
CreateCameraInstanceMessageID,
this
);
controls
->keyboardGroup[LBE4ControlsManager::KeyboardPC]
.Add(
ModeManager::ModeAlwaysActive,
this,
KeypressMessageID,
this
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraL4Mapper::~CameraL4Mapper()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraL4Mapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}
//##########################################################################
//#################### CameraThrustmasterMapper #######################
//##########################################################################
//#############################################################################
// Shared Data Support
//
CameraThrustmasterMapper::SharedData
CameraThrustmasterMapper::DefaultData(
CameraThrustmasterMapper::GetClassDerivations(),
CameraThrustmasterMapper::MessageHandlers,
CameraThrustmasterMapper::GetAttributeIndex(),
CameraThrustmasterMapper::StateCount
);
Derivation* CameraThrustmasterMapper::GetClassDerivations()
{ static Derivation classDerivations(CameraL4Mapper::GetClassDerivations(), "CameraThrustmasterMapper");
return &classDerivations;
}
//#############################################################################
// Model Support
//
void
CameraThrustmasterMapper::InterpretControls(Scalar time_slice)
{
//
//----------------------------------------
// Use the hat buttons to set the throttle
//----------------------------------------
//
if (throttleUp > 0)
{
throttlePosition = 1.0f;
reverseThrust = 0;
}
else if (throttleDown > 0)
{
throttlePosition = 1.0f;
reverseThrust = 1;
}
else
{
throttlePosition = 0.0f;
reverseThrust = 0;
}
CameraL4Mapper::InterpretControls(time_slice);
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraThrustmasterMapper::CameraThrustmasterMapper(
CameraShip *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
)
: CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data)
{
SetPerformance(&CameraThrustmasterMapper::InterpretControls);
throttleUp = throttleDown = 0;
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp]
.Add(ModeManager::ModeAlwaysActive, &throttleUp, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown]
.Add(ModeManager::ModeAlwaysActive, &throttleDown, this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraThrustmasterMapper::~CameraThrustmasterMapper()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraThrustmasterMapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}
//#############################################################################
//################################ RIOMapper ##################################
//#############################################################################
//#############################################################################
// Shared Data Support
//
CameraRIOMapper::SharedData
CameraRIOMapper::DefaultData(
CameraRIOMapper::GetClassDerivations(),
CameraRIOMapper::MessageHandlers,
CameraRIOMapper::GetAttributeIndex(),
CameraRIOMapper::StateCount
);
Derivation* CameraRIOMapper::GetClassDerivations()
{ static Derivation classDerivations(CameraL4Mapper::GetClassDerivations(), "CameraRIOMapper");
return &classDerivations;
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraRIOMapper::CameraRIOMapper(
CameraShip *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
):
CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data)
{
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
//
//-----------------
// Throttle mapping
//-----------------
//
controls
->scalarGroup[LBE4ControlsManager::ScalarThrottle]
.Add(ModeManager::ModeAlwaysActive, &throttlePosition, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonThrottle1]
.Add(ModeManager::ModeAlwaysActive, &reverseThrust, this);
//
//--------------
// Pedal mapping
//--------------
//
controls
->scalarGroup[LBE4ControlsManager::ScalarLeftPedal]
.Add(ModeManager::ModeAlwaysActive, &leftPedal, this);
controls
->scalarGroup[LBE4ControlsManager::ScalarRightPedal]
.Add(ModeManager::ModeAlwaysActive, &rightPedal, this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraRIOMapper::~CameraRIOMapper()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraRIOMapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}