//===========================================================================//
// File:	sensor.hpp                                                          //
// Project: BattleTech                                                       //
// Contents: Sensor subsystem 										                 //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//  8/10/95  GDU Initial coding.                                             //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// This declaration is the SURVIVING SENSOR.HPP
// (410SRC/.../CODE/BT/BT/SENSOR.HPP) reproduced verbatim, with reconstruction
// annotations added in comments only.  The class body below is GROUND TRUTH;
// the @ADDR / @offset notes were recovered from the shipped binary and tie
// each declaration to the evidence used in sensor.cpp.
//
// Recovered binary facts (see sensor.cpp for per-method @ADDR evidence):
//   - Sensor IS-A PoweredSubsystem (powersub.hpp), object size 0x328.
//   - vtable @0050fb0c   ctor @004b1d18   dtor @004b1d90
//   - DefaultData @0050fa1c   ClassDerivations @0050fa2c
//   - AttributePointers @0050fa50  (three IndexEntry records, see below)
//   - RegisteredClass::SensorClassID == 0x0BC3  (resource +0x20),
//     streamed model size 0x190 (resource +0x24 -- same record as
//     PoweredSubsystem; the Sensor resource adds no fields).
//
//   IMPORTANT CONFLICT NOTE: the prior powersub.cpp/CLASSMAP reconstruction
//   labelled the class at vtable @0050fb0c / ctor @004b1d18 "Myomers" with
//   inferred members outputVoltage/powered/voltageAvailable.  That was a
//   misidentification.  The shipped attribute string pool (@0050fae0:
//   "Sensor", "RadarPercent", "SelfTest", "BadVoltage") and the surviving
//   SENSOR.HPP prove the class is Sensor.  classID 0xBC3 is Sensor, not
//   Myomers.  See CLASSMAP.md "Resolved conflict".
//
#if !defined(SENSOR_HPP)
#	define SENSOR_HPP

#if !defined(POWERSUB_HPP)
	#include "powersub.hpp"
#endif


//##########################################################################
//#################    SensorSubsystemResource    #######################
//##########################################################################
//
// Empty extension of the PoweredSubsystem resource.  Confirmed by
// CreateStreamedSubsystem @004b1dcc, which only chains to
// PoweredSubsystem::CreateStreamedSubsystem (@004b13ac) and stamps the
// classID/model-size -- it parses NO sensor-specific fields, and the streamed
// model size is 0x190 (identical to the PoweredSubsystem record).
//
	struct Sensor__SubsystemResource:
		public PoweredSubsystem::SubsystemResource
	{

	};

//##########################################################################
//##########################    Sensor	     ###############################
//##########################################################################

	class Sensor:
		public PoweredSubsystem
	{

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Death and Damage Support
	//
	// NOTE: the Sensor vtable @0050fb0c carries the inherited (PoweredSubsystem
	// / HeatSink) addresses in the damage/death slots -- no Sensor-specific
	// bodies were captured in the decomp.  The definitions in sensor.cpp are
	// BEST-EFFORT (chain to base) and flagged accordingly.
	//
	public:

	void
		TakeDamage(Damage &damage);

	void
		DeathReset(Logical full_recovery);
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	// DefaultData @0050fa1c, ClassDerivations @0050fa2c.
	//
	public:
		static Derivation ClassDerivations;
		static SharedData DefaultData;
		static Receiver::MessageHandlerSet MessageHandlers;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// BT segment / base-state compatibility shims.
	//
	// CROSS-FAMILY: these accessors and segment-flag constants logically belong
	// on the shared bases (Mech::GetSegmentFlags, HeatSink::HeatStateLevel /
	// HeatModelOff / heatEnergy, PoweredSubsystem::ElectricalStateLevel) plus a
	// real multi-level AlarmIndicator.  Until the heat/powersub/mech families
	// expose them, they are backed locally here so this module compiles; the
	// backing fields are written by the (cross-family) base simulation once the
	// real accessors land.  See report "CROSS-FAMILY NEEDS".
	//
#if !defined(BT_SEGMENT_FLAG_CONSTS)
#	define BT_SEGMENT_FLAG_CONSTS
	enum {
		SegmentCopyMask		= 0x0C,		// (flags & 0xC): 0 == primary, 4 == damaged copy
		SegmentLiveFlag		= 0x01,
		MasterHeatSinkFlag	= 0x0100
	};
#endif
	public:
		// De-shimmed (WAVE 4 un-stub): the 5 CROSS-FAMILY backing fields
		// (segmentFlags/hasActivePerformance/heatStateLevel/heatModelOff/
		// electricalState) are DELETED -- they over-sized the object past its
		// zero-headroom 0x328 factory alloc AND duplicated engine-base state.
		// The accessors now read the REAL inherited base members:
		//   HeatStateLevel   <- HeatSink::heatAlarm level                   (this+0x170)
		//   ElectricalState  <- PoweredSubsystem::electricalStateAlarm level (this+0x278)
		//   HeatModelOff     <- MechSubsystem::simulationState == Destroyed  (this+0x40)
		//   HeatMasterEnergy <- inherited HeatSink::heatEnergy              (this+0x158)
		//   SetHasPerformanceFlag -> engine Simulation::simulationFlags |= 8 (this+0x28)
		// GetSegmentFlags() removed (unused; the ctor gate reads owner->simulationFlags).
		HeatSink::HeatState
			HeatStateLevel() const			{ return (HeatSink::HeatState)heatAlarm.GetLevel(); }
		Logical
			HeatModelOff() const			{ return simulationState == 1; /* MechSubsystem::DestroyedState */ }
		Scalar
			HeatMasterEnergy() const		{ return heatEnergy; }	// inherited HeatSink sink
		PoweredSubsystem::ElectricalState
			ElectricalStateLevel() const	{ return (PoweredSubsystem::ElectricalState)electricalStateAlarm.GetLevel(); }
		void
			SetHasPerformanceFlag()			{ simulationFlags |= 8; }	// engine Simulation flag bit 3

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
// Recovered IndexEntry table @0050fa50 (one {nameptr, attribID, offset+1}
// record each).  The offset field is encoded as (byte_offset | 1):
//     RadarPercent -> id 0x12, 0x31d => radarPercent @0x31C
//     SelfTest     -> id 0x13, 0x321 => selfTest     @0x320
//     BadVoltage   -> id 0x14, 0x325 => badVoltage   @0x324
// (PoweredSubsystem::NextAttributeID == 0x12, so the enum below resolves to
//  RadarPercent=0x12, SelfTest=0x13, BadVoltage=0x14, NextAttributeID=0x15.)
//
	public:
		enum {
			RadarPercentAttributeID  = PoweredSubsystem::NextAttributeID,
			SelfTestAttributeID,
			BadVoltageAttributeID,
			NextAttributeID
		};

	private:
		static const IndexEntry AttributePointers[];

	protected:
		static AttributeIndexSet AttributeIndex;



	public:
		Scalar
			radarPercent;		// @0x31C  ctor init 1.0f
		Logical
			selfTest,			// @0x320  ctor init 0
			badVoltage;			// @0x324  ctor init 0


//##########################################################################
// Simulation Support
//
	public:

		typedef void
			(Sensor::*Performance)(Scalar time_slice);

		void
			SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

		void
			SensorSimulation(Scalar time_slice);	// @004b1c4c (Performance, PTR @0050fa94)

//##########################################################################
// Test Class Support
//
	public:
		static	Logical
			TestClass(Mech&);
		void
			ResetToInitialState();					// slot 10, @004b1c18

//##########################################################################
// Construction and Destruction
//
	public:
		typedef Sensor__SubsystemResource SubsystemResource;

		Sensor(
			Mech 				*owner,
			int				subsystem_ID,
			SubsystemResource	*subsystem_resource
		);											// @004b1d18
		~Sensor();									// @004b1d90

		Logical
      	TestInstance() const;					// @004b1e18

		static int
			CreateStreamedSubsystem(				// @004b1dcc
				NotationFile					*model_file,
				const char						*model_name,
				const char						*subsystem_name,
				SubsystemResource *subsystem_resource,
				NotationFile					*subsystem_file,
				const ResourceDirectories	*directories,
				int 								passes = 1
			);
};





#endif
