//===========================================================================//
// File:	mechtech.hpp                                                        //
// Project: BattleTech           Brick: Entity Manager                        //
// Contents: MechTech -- the mech's subsystem-monitor / diagnostics           //
//           ("technician") subsystem.  Watches every damageable MechSubsystem//
//           on the mech and drives the cockpit status / MFD readouts.        //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// GROUND TRUTH.  This header reproduces the surviving source header
//      410SRC/Telsa40/Rel410/CODE/BT/BT/MECHTECH.HPP
// verbatim (it is authoritative for the public interface).  The only
// additions are the "@0x.." byte-offset annotations and the provenance
// notes below, recovered by cross-referencing the shipped binary.  See
// mechtech.cpp for the per-method @ADDR evidence.
//
// Binary identity (corrects the placeholder labels emitted by mech.cpp):
//      MechTech                 ClassID  0xBDC        (NOT 0xBD6)
//      ctor                     @004ad228            (mech.cpp called this
//                                                      "HeatableSubsystem")
//      dtor                     @004ad1b8
//      vtable                   @0050e3a0  (12 slots; only the dtor is
//                                           overridden, the rest inherit
//                                           Subsystem's MUNGA base @0x41xxxx)
//      DefaultData    (SharedData)   @0050e270
//      ClassDerivations (Derivation) @0050e280
//      instance size            0x104
//
//      NOTE: mech.cpp's switch labelled 0xBD6 / @004b7f94 "MechTech"; that
//      class is actually the HUD torso-horizon gimbal display (parses
//      "FlickerRate"/"HorizontalMovementPerSecond"/"HorizontalLimit",
//      vtable @00511510) and is unrelated to MechTech.
//
//      "MechTech::SubsystemMonitors" and "AlarmModel" survive as literals at
//      @0050e2f3 / @0050e322 in the binary's .rdata.
//

#if !defined(MECHTECH_HPP)
#	define MECHTECH_HPP

#	if !defined(MECHSUB_HPP)
#		include <mechsub.hpp>
#	endif

	//##########################################################################
	//######################    MechTech::StatusInfo    ########################
	//##########################################################################
	//
	// One per (subsystem, TechStatusType) cell.  16 bytes (0x10); the
	// SubsystemMonitor ctor (@004ad124) zero-inits all four words of each
	// entry and the per-frame monitor (@004ad33c) reads/writes them.
	//
	struct MechTech__StatusInfo SIGNATURED
	{
	public:
		int
			currentStatus,	// +0x00  last reported status bit for this cell
			wooHooed;		// +0x04  a "woo hoo!" alert is currently latched
		Time
			startTime,		// +0x08  when the alert began
			wooHooEnd;		// +0x0C  when the latched alert expires
	};

	//##########################################################################
	//###############3###    MechTech::SubsystemMonitor    #####################
	//##########################################################################
	//
	// One monitor per watched MechSubsystem.  Layout (@004ad124):
	//      Plug                base                        +0x00 (0x0C bytes)
	//      StatusInfo          statusArray[7]              +0x0C .. +0x7B
	//      MechSubsystem*      monitoredSubsystem          +0x7C
	//   => sizeof(SubsystemMonitor) == 0x80
	// Allocated from the static MemoryBlock at @0050e248.
	//
	struct MechTech__SubsystemMonitor:
		public Plug
	{
		friend class MechTech;

	//##########################################################################
	// Memory Allocation Support
	//
	private:
		static MemoryBlock AllocatedMemory;		// @0050e248

		void*
			operator new(size_t)
				{return AllocatedMemory.New();}			// FUN_00402f74(0x50e248)
		void
			operator delete(void *where)
				{AllocatedMemory.Delete(where);}		// FUN_00402f98(0x50e248)

	public:
		MechTech__StatusInfo statusArray[MechSubsystem::TechStatusTypeCount];	// +0x0C  (TechStatusTypeCount == 7)
		MechSubsystem *monitoredSubsystem;										// +0x7C

		MechTech__SubsystemMonitor(MechSubsystem *subsystem);	// @004ad124
		~MechTech__SubsystemMonitor();							// @004ad180
	};

	//##########################################################################
	//#####################    MechTech::ModelResource    ######################
	//##########################################################################
	//
	// Streamed resource record (sizeof == 0x40, classID 0xBDC), parsed by
	// CreateStreamedSubsystem @004ad48c.  Only "AlarmModel" is read from the
	// notation file; the three wooHoo scalars default to 0.
	//
	struct MechTech__SubsystemResource:
		public Subsystem::SubsystemResource
	{
		ResourceDescription::ResourceID
			alarmModel;					// +0x30  "AlarmModel" (resolved .mod id, -1 = none)
		Scalar
			wooHooMinimumDuration,		// +0x34
			wooHooDurationRange,		// +0x38
			wooHooChance;				// +0x3C
	};

	//##########################################################################
	//############################    MechTech    ##############################
	//##########################################################################

	class MechTech:
		public Subsystem
	{
	//##########################################################################
	// Shared Data Support
	//
	public:
		static Derivation ClassDerivations;		// @0050e280
		static SharedData DefaultData;			// @0050e270
		static Receiver::MessageHandlerSet MessageHandlers;
		static AttributeIndexSet AttributeIndex;

	//##########################################################################
	// BT segment / status-sink compatibility shims.
	//
	// CROSS-FAMILY: the per-segment "copy/template" + "damageable" flags and the
	// cockpit status-message sink logically belong on the shared Mech / Subsystem
	// bases and the HUD message brick.  Until they are exposed, they are backed
	// locally here so this module compiles.  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
	enum {
		SegmentDamageableFlag	= 0x08,	// segment bit 0x8 == damageable
		DormantInstanceFlag		= 0x02	// this[10] |= 2 -- copy/template instance
	};
	public:
		Word
			GetSegmentFlags() const			{ return segmentFlags; }
	protected:
		Word					segmentFlags;	// @this[0x28] segment flags (Mech-supplied)

	//##########################################################################
	// Attribute Support
	//
	public:
		typedef MechTech__StatusInfo StatusInfo;
		typedef MechTech__SubsystemMonitor SubsystemMonitor;
		typedef MechTech__SubsystemResource SubsystemResource;

	//##########################################################################
	// Construction and Destruction Support
	//
	public:
		~MechTech();							// @004ad1b8

		static Logical
			CreateStreamedSubsystem(			// @004ad48c
				NotationFile	*model_file,
				const char* model_name,
				const char* subsystem_name,
				SubsystemResource *subsystem_resource,
				NotationFile *subsystem_file,
				const ResourceDirectories *directories,
				ResourceFile *resource_file
			);

		MechTech(								// @004ad228
			Mech *entity,
			int subsystem_id,
			SubsystemResource *model,
			SharedData &shared_data = DefaultData
		);

		Logical
			TestInstance() const;			// @004ad470 (IsDerivedFrom ClassDerivations)

	//##########################################################################
	// Model support
	//
	public:
		typedef void
			(MechTech::*Performance)(Scalar time_slice);

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

		ChainOf<SubsystemMonitor*> subsystemMonitors;	// @0xE4 (this[0x39])
		Scalar
			wooHooMinimumDuration,		// @0xF4 (this[0x3D])  <- resource +0x34
			wooHooDurationRange,		// @0xF8 (this[0x3E])  <- resource +0x38
			wooHooChance;				// @0xFC (this[0x3F])  <- resource +0x3C

		ResourceDescription::ResourceID
			alarmModel;					// @0x100 (this[0x40]) <- resource +0x30

		void
			TechnicalAssistance(Scalar time_slice);		// @004ad33c (the Performance)

		Mech*
			GetEntity()
				{return (Mech*)Subsystem::GetEntity();}

	//##########################################################################
	// Status reporting support.
	//
	// CROSS-FAMILY: in the shipped binary these route through the running
	// Application/World status sink (DAT_004efc94 + 0x38) and the HUD message
	// builders (FUN_004366b8 / FUN_00436688 / FUN_004364e4), which live in the
	// (not-yet-reconstructed) cockpit-message brick.  Declared here with stub
	// bodies so MechTech compiles; see report "CROSS-FAMILY NEEDS".
	//
	public:
		Time
			GetTime() const;							// engine current time (Now())

	protected:
		void*
			StatusMessageSink();						// *(DAT_004efc94 + 0x38)
		void
			ReportStatusCleared(						// FUN_004366b8 + FUN_004364e4
				void			*sink,
				Mech			*owner,
				MechSubsystem	*sub,
				int				type
			);
		void
			ReportStatusSet(							// FUN_00436688 + FUN_004364e4
				void			*sink,
				Mech			*owner,
				MechSubsystem	*sub,
				int				type,
				ResourceDescription::ResourceID alarm_model
			);
	};

#endif
