Files
TeslaRel410/restoration/source410/BT/RESERVR.HPP
T
CydandClaude Fable 5 afb9e3f5d9 BT410 5.3.46: the Reservoir crash solved -- *State names must be StateIndicators
The linker map named the faulting function: the crash address minus the CODE
base (0x410000) looked up in btl4opt.map's Publics-by-Value landed inside
AudioStateWatcher::AudioStateWatcher +0x2D.

AudioStateWatcher is AudioWatcherOf<StateIndicator> and its ctor immediately
runs Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this).
So every authored *State name must be published as a StateIndicator --
AlarmIndicator counts, it derives from one -- and pointing one at a plain int
sends that member call through garbage.

That explains both earlier failures: the AlarmIndicator attempt was the right
type but was tested with other bugs still in the batch, and the plain-int
attempt was simply the wrong type and crashed further along.

Published as state objects: Reservoir/ReservoirState -> reservoirAlarm,
Generator/GeneratorState -> stateAlarm, plus new StateIndicator members for
Condenser/CondenserState and Torso/MotionState.  StateIndicator has no
Initialize(); the default ctor suffices because the watcher only needs the
object to exist.

Verified on the pod rig: no crash, ladder advanced to ReportLeak.

Technique worth keeping: on an extender fault, subtract 0x410000 from the
dumped address and look it up in btl4opt.map -- it names the engine function,
and for this family of work that names the watcher class and hence the
required member type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 07:42:44 -05:00

131 lines
4.0 KiB
C++

//===========================================================================//
// File: reservr.hpp //
// Project: BattleTech Brick: Mech subsystems //
// Contents: Reservoir -- the coolant store //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(RESERVR_HPP)
# define RESERVR_HPP
# if !defined(HEAT_HPP)
# include <heat.hpp>
# endif
//##################### Forward Class Declarations #######################
class Mech;
//###########################################################################
//#################### Reservoir Model Resource #########################
//###########################################################################
//
// CoolantCapacity overlays the inherited HeatSink thermalCapacity slot at
// construction; CoolantSquirtMass is the per-second flush rate base.
//
struct Reservoir__SubsystemResource:
public HeatSink::SubsystemResource
{
Scalar coolantCapacity;
Scalar coolantSquirtMass;
};
//###########################################################################
//############################# Reservoir ###############################
//###########################################################################
//
// The coolant store: a HeatSink that holds the mech's coolant charge and
// "squirts" it into the other sinks on demand -- it is the DrawCoolant SOURCE
// (every sink's UpdateCoolant top-up resolves here through the virtual), and
// the manual coolant FLUSH (the InjectCoolant cockpit button) distributes
// charge into the condensers / weapons / heatables, crediting each a negative
// pending-heat chill.
//
class Reservoir:
public HeatSink
{
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
static Logical
TestClass(Mech &);
Logical
TestInstance() const;
public:
typedef Reservoir__SubsystemResource SubsystemResource;
Reservoir(
Mech *owner,
int subsystem_ID,
SubsystemResource *r,
SharedData &shared_data = DefaultData
);
~Reservoir();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support: the cockpit coolant-flush button (id 4,
// "InjectCoolant"). Press starts the flush (raises the inject alarm);
// release stops it. Novice-locked.
//
public:
enum {
InjectCoolantMessageID = HeatSink::NextMessageID, // 4
NextMessageID
};
static const HandlerEntry MessageHandlerEntries[];
static MessageHandlerSet MessageHandlers;
void
InjectCoolantMessageHandler(ReceiverDataMessageOf<int> *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The coolant-store interface.
//
public:
//
// The DrawCoolant SOURCE: hand out up to coolantLevel of the requested
// amount and deduct it from the charge.
//
virtual Scalar
DrawCoolant(Scalar requested);
typedef void
(Reservoir::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
CoolantSimulation(Scalar time_slice);
void
InjectCoolant(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Data. The inject flag is the reservoir alarm's level (1 = flushing).
//
public:
enum {
ReservoirStateAttributeID = HeatSink::NextAttributeID,
NextAttributeID
};
static const IndexEntry AttributePointers[];
static AttributeIndexSet AttributeIndex;
protected:
AlarmIndicator reservoirAlarm;
Scalar coolantSquirtMass;
Scalar injectAccumulator;
Scalar squirtEfficiency;
};
#endif