Files
TeslaRel410/restoration/source410/BT/POWERSUB.HPP
T
CydandClaude Fable 5 bfff7fe874 BT410 Phase 5.3.22: the cockpit weapon-button column -- generator panel LIVE
The full per-receiver message chain, contiguous ids 3..0xb: PoweredSubsystem
4-8 (SelectGeneratorA-D + ToggleGeneratorMode, binary table @0x50F4EC)
chained on HeatSink's ToggleCooling(3); MechWeapon 9/10 (config buttons,
staged latch bodies); Emitter 0xb ToggleSeekVoltage (@0x511DB8).

SelectGenerator = release the old tap -> roster walk by generatorNumber ->
AttachToVoltageSource -> Connected; mode toggle cycles Manual->Auto->
(detach)->Manual; the seek dial steps the authored voltage ladder with wrap
(a step up re-enters Loading, charge persists).  All novice-locked.
Generator::UntapVoltageSource + PoweredSubsystem::DetachFromVoltageSource
added.  Dev harness: BT_PRESS_GEN=1..4 / BT_PRESS_SEEK.

Verified: PPC_1 retaps GeneratorB (tapped); seek index 2->3, target 9900V
(authored fraction x rated); novice presses INERT; missile fight 14/14 and
smoke green, zero faults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:36:32 -05:00

408 lines
12 KiB
C++

//===========================================================================//
// File: powersub.hpp //
// Project: BattleTech //
// Contents: Implementation details for powered subsystems //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(POWERSUB_HPP)
# define POWERSUB_HPP
# if !defined(HEAT_HPP)
# include <heat.hpp>
# endif
//##################### Forward Class Declarations #######################
class Mech;
//###########################################################################
//################### PoweredSubsystem Model Resource ###################
//###########################################################################
struct PoweredSubsystem__SubsystemResource:
public HeatSink::SubsystemResource
{
int voltageSourceIndex;
Scalar thermalResistivityCoefficient;
int auxScreenNumber;
int auxScreenPlacement;
char auxScreenLabel[64];
char engScreenLabel[64];
Scalar startTime;
};
//###########################################################################
//######################### PoweredSubsystem ############################
//###########################################################################
class PoweredSubsystem:
public HeatSink
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Class Support
//
public:
static Logical
TestClass(Mech &);
Logical
TestInstance() const;
void
ResetToInitialState(Logical powered);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Electrical state machine (carried in electricalStateAlarm, 5 levels) and
// the connection-mode indicator (modeAlarm, 3 levels).
//
public:
enum ElectricalState {
Starting = 0, // powering up; startTimer counts toward startTime
NoVoltage = 1, // voltage source missing / unresolvable
Shorted = 2, // source generator shorted
GeneratorOff = 3, // source generator off / not ready
Ready = 4 // powered and operating
};
enum ConnectMode {
ManualConnect = 0,
Connected = 1,
AutoConnect = 2
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Power support
//
public:
//
// The cockpit generator-select buttons (binary handler table
// @0x50F4EC, ids 4-8, chained onto the HeatSink set so id 3
// ToggleCooling stays reachable through every powered subsystem).
//
enum {
SelectGeneratorAMessageID = HeatSink::NextMessageID, // 4
SelectGeneratorBMessageID, // 5
SelectGeneratorCMessageID, // 6
SelectGeneratorDMessageID, // 7
ToggleGeneratorModeMessageID, // 8
NextMessageID // 9
};
static const HandlerEntry MessageHandlerEntries[];
static MessageHandlerSet MessageHandlers;
void
SelectGeneratorAMessageHandler(ReceiverDataMessageOf<int> *message);
void
SelectGeneratorBMessageHandler(ReceiverDataMessageOf<int> *message);
void
SelectGeneratorCMessageHandler(ReceiverDataMessageOf<int> *message);
void
SelectGeneratorDMessageHandler(ReceiverDataMessageOf<int> *message);
void
ToggleGeneratorModeMessageHandler(ReceiverDataMessageOf<int> *message);
//
// The manual generator re-tap (binary @004b0b18/@004b0dd8 family):
// find generator N in the owner's roster, release the current tap,
// tap the new source, drop the connect mode to Connected.
//
void
SelectGenerator(int generator_number);
Subsystem*
FindGeneratorByNumber(int generator_number);
void
DetachFromVoltageSource();
Subsystem*
ResolveVoltageSource() { return voltageSource.Resolve(); }
int
AttachToVoltageSource(Subsystem *source);
unsigned
GetVoltageState() { Check(this); return electricalStateAlarm.GetLevel(); }
//
// The charge time-scale (binary @004b0d50) -- the heat/firepower
// feedback: the base voltageScale (the ctor-calibrated exponential
// charge constant) stretched by the powering generator's temperature
// rise above its start point.
//
Scalar
ChargeTimeScale();
//
// Short event (binary @004b11bc): drive the powering generator into
// the Shorted state and zero its output -- the electrical FSM then
// runs its short-recovery cycle. Gated on the not-novice experience
// predicate (both hops share the mech's player). Called by the
// special-damage path (a type-4 Energy hit on a zone with attached
// generator criticals).
//
void
ForceShortRecovery();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Per-frame simulation (heat step + the electrical state machine).
//
public:
typedef void
(PoweredSubsystem::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
PoweredSubsystemSimulation(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
typedef PoweredSubsystem__SubsystemResource SubsystemResource;
PoweredSubsystem(
Mech *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data = DefaultData
);
~PoweredSubsystem();
static int
CreateStreamedSubsystem(
NotationFile *model_file,
const char *model_name,
const char *subsystem_name,
SubsystemResource *subsystem_resource,
NotationFile *subsystem_file,
const ResourceDirectories *directories,
int passes = 1
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Data
//
protected:
Scalar inputVoltage;
Scalar outputVoltage;
Scalar ratedVoltage;
SubsystemConnection voltageSource;
AlarmIndicator electricalStateAlarm;
AlarmIndicator modeAlarm;
Scalar thermalResistivityCoefficient;
Scalar startTime;
Scalar startTimer;
Scalar voltageScale;
};
//###########################################################################
//################### PowerWatcher Model Resource ######################
//###########################################################################
struct PowerWatcher__SubsystemResource:
public HeatWatcher::SubsystemResource
{
Scalar minVoltagePercent;
};
//###########################################################################
//############################ PowerWatcher ############################
//###########################################################################
//
// A HeatWatcher that also watches its subject's supply voltage. Base of the
// Torso / HUD / Gyroscope cockpit subsystems.
//
class PowerWatcher:
public HeatWatcher
{
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
static Logical
TestClass(Mech &);
Logical
TestInstance() const;
void
ResetToInitialState(Logical powered);
void
Simulation(Scalar time_slice);
public:
typedef PowerWatcher__SubsystemResource SubsystemResource;
PowerWatcher(
Mech *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data = DefaultData
);
~PowerWatcher();
protected:
Scalar minVoltage;
AlarmIndicator watchdogAlarm;
};
//###########################################################################
//#################### Generator Model Resource ########################
//###########################################################################
struct Generator__SubsystemResource:
public HeatSink::SubsystemResource
{
Scalar ratedVoltage;
int maxTapCount;
Scalar startTime;
Scalar shortRecoveryTime;
};
//###########################################################################
//############################## Generator #############################
//###########################################################################
//
// The voltage SOURCE a PoweredSubsystem attaches to (currentTapCount tracks
// attached loads). A HeatSink that produces power.
//
class Generator:
public HeatSink
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
enum {
GeneratorOff = 0,
GeneratorStarting,
GeneratorReady,
GeneratorShorted,
GeneratorFailed,
GeneratorStateCount
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test / reset
//
public:
static Logical
TestClass(Mech &);
Logical
TestInstance() const;
void
ResetToInitialState();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Power interface
//
public:
Scalar MeasuredVoltage() { Check(this); return outputVoltage; }
Scalar RatedVoltageOf() { Check(this); return ratedVoltage; }
int GetGeneratorNumber(){ Check(this); return generatorNumber; }
unsigned
GeneratorStateOf() { Check(this); return stateAlarm.GetLevel(); }
//
// The short event landing ON this generator (the tail of binary
// @004b11bc): Shorted state + output killed; GeneratorSimulation
// runs the short-recovery timer back to Ready. Callers gate on the
// novice experience predicate.
//
void
ForceShort()
{
Check(this);
stateAlarm.SetLevel(GeneratorShorted);
outputVoltage = 0.0f;
}
//
// Tap the generator for one load (a PoweredSubsystem attaching): -1 when
// every tap is taken, else 0.
//
int
TapVoltageSource()
{
Check(this);
if (currentTapCount >= maxTapCount)
{
return -1;
}
++currentTapCount;
return 0;
}
void
UntapVoltageSource()
{
Check(this);
if (currentTapCount > 0)
{
--currentTapCount;
}
}
typedef void
(Generator::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
GeneratorSimulation(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
typedef Generator__SubsystemResource SubsystemResource;
Generator(
Mech *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data = DefaultData
);
~Generator();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Data
//
public:
Scalar percentVoltageAvailable;
int generatorOn;
Scalar ratedVoltage;
Scalar outputVoltage;
int generatorNumber;
int maxTapCount;
int currentTapCount;
Scalar startTime;
Scalar startTimer;
Scalar shortRecoveryTime;
Scalar shortTimer;
AlarmIndicator stateAlarm;
};
#endif