//===========================================================================// // File: heat.hpp // // Project: BattleTech // // Contents: Implementation details for heatable subsystems // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // // //---------------------------------------------------------------------------// // Copyright (C) 1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #if !defined(HEAT_HPP) # define HEAT_HPP # if !defined(MECHSUB_HPP) # include # endif # if !defined(AVERAGE_HPP) # include # endif //##################### Forward Class Declarations ####################### class Mech; //########################################################################### //################## HeatableSubsystem Model Resource ################### //########################################################################### struct HeatableSubsystem__SubsystemResource: public MechSubsystem::SubsystemResource { Scalar startingTemperature; Scalar degradationTemperature; Scalar failureTemperature; Scalar thermalConductance; Scalar thermalMass; }; //########################################################################### //######################## HeatableSubsystem ############################ //########################################################################### class HeatableSubsystem: public MechSubsystem { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // public: static Derivation ClassDerivations; static SharedData DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Class Support // public: static Logical TestClass(Mech &); Logical TestInstance() const; void ResetToInitialState(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // public: typedef HeatableSubsystem__SubsystemResource SubsystemResource; HeatableSubsystem( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~HeatableSubsystem(); 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 currentTemperature; Scalar heatLoad; Scalar degradationTemperature; Scalar failureTemperature; }; //########################################################################### //########################## SubsystemConnection ######################## //########################################################################### // // A slot linking a heat sink to its master / linked heat sink. // class SubsystemConnection { public: SubsystemConnection() { linked = NULL; } void Add(Subsystem *s) { linked = s; } Subsystem* Resolve() const { return linked; } void Clear() { linked = NULL; } protected: Subsystem *linked; int reserved[2]; }; //########################################################################### //####################### HeatSink Model Resource ####################### //########################################################################### struct HeatSink__SubsystemResource: public HeatableSubsystem__SubsystemResource { // // WIRE-VERIFIED (raw-stream dump): the roster index of the sink this // one conducts its heat into -- the weapons/equipment link to the // Condenser bank (slots 4-9), the Condensers to the central HeatSink. // This was THE missing ancestry int that shifted every descendant // resource block +1 (PoweredSubsystem voltageSourceIndex, the MechWeapon // block, ...). // int linkedSinkIndex; }; //########################################################################### //############################## HeatSink ############################### //########################################################################### //########################################################################### //################### HeatWatcher Model Resource ####################### //########################################################################### struct HeatWatcher__SubsystemResource: public MechSubsystem__SubsystemResource { int watchedSubsystem; Scalar degradationTemperature; Scalar failureTemperature; }; //########################################################################### //############################# HeatWatcher ############################# //########################################################################### // // Watches another subsystem's temperature and drives a 3-level alarm. A // sibling branch to HeatableSubsystem (derives straight from MechSubsystem); // PowerWatcher and the Torso/HUD/Gyroscope leaves descend from it. // class HeatWatcher: public MechSubsystem { public: static Derivation ClassDerivations; static SharedData DefaultData; static Logical TestClass(Mech &); Logical TestInstance() const; void ResetToInitialState(Logical powered); void WatchSimulation(Scalar time_slice); public: typedef HeatWatcher__SubsystemResource SubsystemResource; HeatWatcher( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~HeatWatcher(); protected: SubsystemConnection watchedLink; int watchedSubsystem; Scalar degradationTemperature; Scalar failureTemperature; AlarmIndicator heatAlarm; }; class HeatSink: public HeatableSubsystem { friend class Condenser; friend class Reservoir; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 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); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Messaging Support. The cockpit cooling toggle rides the first // subsystem-family message slot (id 3 = Receiver::NextMessageID); the // per-class id-4 slot is claimed by each subclass (Condenser MoveValve, // Reservoir InjectCoolant, ...). // public: enum { ToggleCoolingMessageID = Receiver::NextMessageID, // 3 NextMessageID // 4 }; static const HandlerEntry MessageHandlerEntries[]; static MessageHandlerSet MessageHandlers; void ToggleCoolingMessageHandler(ReceiverDataMessageOf *message); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Heat state (carried in heatAlarm, 3 levels). The thresholds are the // authored degradation/failure temperatures. // public: enum { NormalHeat = 0, DegradationHeat, FailureHeat, HeatStateCount }; unsigned GetHeatState() { Check(this); return heatAlarm.GetLevel(); } Scalar CurrentTemperatureOf() { Check(this); return currentTemperature; } Scalar StartingTemperatureOf() { Check(this); return startingTemperature; } void AddPendingHeat(Scalar heat) { Check(this); pendingHeat += heat; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation Support // public: typedef void (HeatSink::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } // // The heat-model master switch (binary FUN_004ad7d4): the owning // BTPlayer's heatModelOn experience flag, reached through the mech's // playerLink. ON only for veteran / expert; a NULL player reads ON. // Logical HeatModelActive(); void HeatSinkSimulation(Scalar time_slice); void UpdateHeatLoad(); void ConductHeat(Scalar time_slice); Scalar ComputeHeatFlow(HeatSink *other, Scalar time_slice); void UpdateCoolant(Scalar time_slice); void BalanceCoolant(Scalar time_slice); virtual Scalar DrawCoolant(Scalar requested); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction and Destruction // public: typedef HeatSink__SubsystemResource SubsystemResource; HeatSink( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~HeatSink(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Local Data // protected: Scalar coolantEfficiency; Scalar thermalCapacity; Scalar coolantLevel; Scalar coolantDraw; int coolantAvailable; int coolantActive; Scalar startingTemperature; Scalar thermalConductance; Scalar filterDecay; Scalar thermalMass; Scalar heatEnergy; Scalar coolantFlowScale; Scalar massScale; Scalar pendingHeat; Scalar radiatedHeat; SubsystemConnection linkedSinks; AlarmIndicator heatAlarm; AverageOf heatFilter; }; //########################################################################### //#################### Condenser Model Resource ######################## //########################################################################### struct Condenser__SubsystemResource: public HeatSink__SubsystemResource { Scalar refrigerationFactor; }; //########################################################################### //############################## Condenser ############################# //########################################################################### // // A HeatSink with active refrigeration (a coolant loop's condenser). // class Condenser: public HeatSink { public: static Derivation ClassDerivations; static SharedData DefaultData; static Logical TestClass(Mech &); Logical TestInstance() const; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Messaging Support: the cockpit condenser-valve button (binary handler // table @0x50E52C, exactly one entry -- id 4, "MoveValve"). Each press // cycles this condenser's valve 1 -> 5 -> 50 -> 0 -> 1 and recomputes every // condenser's coolant flow share (valve / sum-of-valves). // public: enum { MoveValveMessageID = HeatSink::NextMessageID, // 4 NextMessageID }; static const HandlerEntry MessageHandlerEntries[]; static MessageHandlerSet MessageHandlers; void MoveValveMessageHandler(ReceiverDataMessageOf *message); // // Recompute every condenser's coolantFlowScale as its share of the // total valve opening (called by MoveValve, and once at mech spawn so // the initial all-1 valves yield equal shares). // static void RecomputeValves(Entity *owner_mech); public: typedef Condenser__SubsystemResource SubsystemResource; Condenser( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~Condenser(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Per-frame refrigeration (binary @4ae4d8): the condenser actively pumps // heat toward the central bank -- massScale is recomputed each frame as // (1 - own damage) * refrigerationFactor, clamped >= 1, so an undamaged // condenser behaves refrigerationFactor-times "hotter" in the conduction // exchange and chills itself below ambient (which is what cools the // weapons equalizing against it). Damage degrades it toward a plain sink. // public: typedef void (Condenser::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } void RefrigerationSimulation(Scalar time_slice); protected: int valveState; int condenserNumber; Scalar refrigerationFactor; }; //########################################################################### //##################### AggregateHeatSink Resource ###################### //########################################################################### struct AggregateHeatSink__SubsystemResource: public HeatSink__SubsystemResource { int heatSinkCount; }; //########################################################################### //######################### AggregateHeatSink ########################### //########################################################################### // // The mech's heat-sink BANK (binary classID 0x0BBE -- the value our VDATA // enum names HeatSinkClassID; there is no streamed plain-HeatSink class). // Holds the aggregate heat-sink count and the ambient-temperature setpoint, // and runs the AMBIENT RADIATOR -- the only place heat ever LEAVES the mech. // class AggregateHeatSink: public HeatSink { public: static Derivation ClassDerivations; static SharedData DefaultData; static Logical TestClass(Mech &); Logical TestInstance() const; public: typedef AggregateHeatSink__SubsystemResource SubsystemResource; AggregateHeatSink( Mech *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data = DefaultData ); ~AggregateHeatSink(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // The radiator (binary @4ae73c) -- replaces the base HeatSinkSimulation on // the bank: absorb, then relax toward the ambient setpoint (the heat EXIT), // then top the bank's coolant up from the attached store. // public: typedef void (AggregateHeatSink::*Performance)(Scalar time_slice); void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } void RadiatorSimulation(Scalar time_slice); int GetHeatSinkCount() const { Check(this); return heatSinkCount; } protected: int heatSinkCount; Scalar ambientTemperature; }; #endif