//===========================================================================//
// File:	hud.hpp                                                             //
// Project: BattleTech                                                       //
// Contents: Cockpit Heads-Up Display subsystem                              //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//  --/--/95  ??   Initial coding.                                           //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, recovered shard
// part_013.c) cross-referenced with the sibling subsystem sources
// (powersub.hpp/.cpp, heat.hpp/.cpp, sensor.hpp/.cpp).  NO HUD.HPP survived;
// the class body below is inferred from usage, the embedded string pool and
// the streamed-resource / attribute tables.  Each method cites its @ADDR.
//
// ---------------------------------------------------------------------------
// IDENTIFICATION (resolves a CLASSMAP "gap")
// ---------------------------------------------------------------------------
//   * mech3.cpp factory map: HUD::CreateStreamedSubsystem @004b81d4,
//     DefaultData &DAT_00511078.
//   * vtable @0050511510 (slot0 dtor @004b816c), ctor @004b7f94.
//   * CreateStreamedSubsystem @004b81d4 stamps classID 0x0BD6 and streamed
//     model size 0x104 (resource +0x20 / +0x24), and parses the HUD-specific
//     model fields "FlickerRate" / "HorizontalMovementPerSecond" /
//     "HorizontalLimit" plus a "SegmentPageName" index.
//   * String pool @005112d0..@00511390 ("HUD", "FlickerRate",
//     "RotationOfTorsoHorizontal", "HorizontalTorsoLimitRight/Left",
//     "SpeedOfTorsoHorizontal", "RangeToTarget", "Visible", "Lock",
//     "HotBoxVector", "ThreatVector", "CompassHeading") names the gauge
//     read-out attributes.
//
//   CLASSMAP.md "Resolved conflict" already flagged @004b7f94 / vtable
//   @00511510 as "the HUD torso-horizon gimbal display" mis-labelled
//   "MechTech" by mech.cpp's factory switch (case 0xBD6).  This file confirms
//   that: classID 0xBD6, base PowerWatcher.
//
// ---------------------------------------------------------------------------
// BASE CLASS
// ---------------------------------------------------------------------------
//   HUD IS-A PowerWatcher (powersub.hpp): the ctor @004b7f94 chains to the
//   PowerWatcher ctor FUN_004b18a4 and CreateStreamedSubsystem chains to
//   PowerWatcher::CreateStreamedSubsystem FUN_004b198c.  PowerWatcher is a
//   HeatWatcher/HeatableSubsystem-derived *monitor* subsystem (NOT a
//   PoweredSubsystem); the HUD therefore inherits the heat/voltage watchdog
//   state (heat-state level @0x140, watched-voltage alarm level @0x198) used
//   by the per-frame update.  The shared base object occupies bytes 0..0x1D8;
//   HUD's own members begin at 0x1D8.  Total object size 0x2A4 (matches
//   mech.cpp factory allocation for the 0xBD6 case).
//
#if !defined(HUD_HPP)
#	define HUD_HPP

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

//##########################################################################
//#######################    HUD::SubsystemResource    #####################
//##########################################################################
//
// Extends the PowerWatcher/HeatableSubsystem resource record.  The HUD fields
// begin at +0xF4 (see CreateStreamedSubsystem @004b81d4).
//
	struct HUD__SubsystemResource:
		public PowerWatcher::SubsystemResource
	{
		Scalar	flickerRate;					// +0xF4  "FlickerRate"  (defaults to -1.0 in the SegmentPage form)
		int		segmentPageIndex;				// +0xF8  resolved "SegmentPageName" (copied from +0x28)
		Scalar	horizontalMovementPerSecond;	// +0xFC  "HorizontalMovementPerSecond"
		Scalar	horizontalLimit;				// +0x100 "HorizontalLimit"
	};

//##########################################################################
//##############################    HUD    #################################
//##########################################################################

	class HUD:
		public PowerWatcher
	{
		friend struct HUDLayoutCheck;		// live Watcher-branch re-base witness (hud.cpp)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	// DefaultData @00511078, ClassDerivations @00511088 ("HUD").
	//
	public:
		static Derivation *GetClassDerivations();	// @00511088 (engine moved to accessor form)
		static SharedData DefaultData;			// @00511078

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	// AttributePointers IndexEntry table @005110c0 (each record binds a name
	// to an attribute id and an object offset, the offset encoded as
	// byte_offset|1 -- the same scheme used by sensor.hpp).  Recovered:
	//      id 4  "RotationOfTorsoHorizontal"  -> @0x1D8
	//      id 5  "HorizontalTorsoLimitRight"  -> @0x1DC
	//      id 6  "HorizontalTorsoLimitLeft"   -> @0x1E0
	//      id 7  "SpeedOfTorsoHorizontal"     -> @0x1E4
	//      id 8  "RangeToTarget"              -> @0x1E8
	//      id 9  "Visible"                    -> @0x1EC
	//      id 10 "Lock"                       -> @0x1F4
	//      id 11 "HotBoxVector"               -> @0x1F8
	//      id 12 "ThreatVector"               -> @0x1FC  (Vec3)
	//      id 13 "CompassHeading"             -> @0x208  (Vec3)
	// (FlickerRate name ptr @005110bc heads the table as the category label.)
	//
	// UNCERTAIN: several of these attribute name<->offset bindings do not line
	// up cleanly with the way the ctor/HudSimulation actually use the same
	// offsets (e.g. the ctor seeds @0x1D8 from the resource FlickerRate, while
	// HudSimulation treats @0x1EC as the computed range-to-target and @0x1F8 as
	// a boolean visibility flag).  The names below follow usage where it is
	// unambiguous and are flagged where it is not.  A human should reconcile
	// the gauge attribute map against the original HUD.HPP.
	//
	public:
		enum {
			RotationOfTorsoHorizontalAttributeID = PowerWatcher::NextAttributeID,	// 4
			HorizontalTorsoLimitRightAttributeID,									// 5
			HorizontalTorsoLimitLeftAttributeID,									// 6
			SpeedOfTorsoHorizontalAttributeID,										// 7
			RangeToTargetAttributeID,												// 8
			VisibleAttributeID,														// 9
			LockAttributeID,														// 10
			HotBoxVectorAttributeID,												// 11
			ThreatVectorAttributeID,												// 12
			CompassHeadingAttributeID,												// 13
			NextAttributeID
		};

	private:
		static const IndexEntry AttributePointers[];	// @005110c0
	protected:
		static AttributeIndexSet AttributeIndex;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local data.  Offsets are byte offsets into the shipped object; names are
	// best-effort from the attribute pool + ctor/HudSimulation usage.
	//
	protected:
		Scalar	flickerRate;			// @0x1D8  resource +0xF4 (flicker / blink period threshold)
		// Torso / target read-outs sampled each construction from the linked
		// targeting entity (owner Mech +0x438 -> this->linkedEntity @0x234):
		Scalar	torsoLimitRight;		// @0x1DC  <- linkedEntity +0x1D8
		Scalar	torsoLimitLeft;			// @0x1E0  <- linkedEntity +0x1DC
		Scalar	torsoSpeed;				// @0x1E4  <- linkedEntity +0x1E0
		Scalar	rangeToTarget;			// @0x1E8  <- linkedEntity +0x1E8 (and recomputed in sim @0x1EC)
		Scalar	targetRange;			// @0x1EC  computed line-of-sight distance to the target
		int		lockFlag;				// @0x1F4  init 1
		int		visible;				// @0x1F8  set 0/1 from heat + line-of-sight each frame
		Point3D	threatVector;			// @0x1FC  init (0,0,0)   ("ThreatVector")
		Point3D	compassHeading;			// @0x208  init (0,0,0)   ("CompassHeading"); see SetCompassHeading
		Scalar	hotBoxScalar;			// @0x214  init 0
		Scalar	blinkTimer;				// @0x218  accumulates time, reset against flickerRate
		Scalar	flickerTimer;			// @0x21C
		int		blinkState;				// @0x224  init 1 (visible phase of the blink)
		int		transitionFlag;			// @0x22C  init 0
		Scalar	previousHorizontal;		// @0x230
		int		linkedEntity;			// @0x234  owner Mech +0x438 (active weapon/reticle source)
		HeatAlarm	statusAlarm;		// @0x238  2-level page/status indicator (Initialize/SetLevel surface)
		// Free-aim / reticle-slew demand: WRITTEN by MechControlsMapper::InterpretControls
	// (@004afd10 cockpit+0x28c <- stick yaw when the torso's horizontal twist is
	// disabled; zeroed in Basic mode).  Was placeholder-named flickerPhase (init-only).
	Scalar	freeAimSlew;			// @0x28C
	public:
		void	SetFreeAimSlew(Scalar v)	{ freeAimSlew = v; }	// mapper write (@004afd10 cockpit+0x28c)
	protected:
		Scalar	scratch290;				// @0x290  init 0
		Scalar	horizontalTorsoOffset;	// @0x294  init 0; clamped to +/- horizontalLimit, written to owner +0x36C
		Scalar	horizontalMovementPerSecond;	// @0x298  resource +0xFC
		Scalar	horizontalLimit;		// @0x29C  resource +0x100
		int		flickerActive;			// @0x2A0  current flicker on/off (UpdateFlicker @004b7ed4)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		typedef void
			(HUD::*Performance)(Scalar time_slice);

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

		void
			HudSimulation(Scalar time_slice);		// @004b7830 (Performance, PTR @00511170)

		void
			SetCompassHeading(const Point3D &heading);	// @004b7810 (writes compassHeading @0x208)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Subsystem virtual overrides (vtable @00511510)
	//
	public:
		Logical
			HandleMessage(int message);				// slot  9, @004b7780 (body not captured)
		void
			ResetToInitialState(Logical powered = True);	// slot 10, @004b77bc

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Class Support
	//
	public:
		static	Logical	TestClass(Mech&);
		Logical			TestInstance() const;		// @004b81b8

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:
		typedef HUD__SubsystemResource SubsystemResource;

		HUD(
			Mech				*owner,
			int					subsystem_ID,
			SubsystemResource	*subsystem_resource,
			SharedData			&shared_data = DefaultData
		);											// @004b7f94
		~HUD();										// @004b816c

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

	protected:
		// Flicker helper @004b7ed4: drives flickerActive (@0x2A0) toward 0,
		// returns non-zero while still flickering.
		Logical	UpdateFlicker(Scalar time_slice);	// @004b7ed4

		//
		// Reconstruction accessors for the inherited watchdog state read by
		// HudSimulation: heat-watcher flag (this+0x40), watched-voltage alarm
		// level (@0x198) and heat-state level (@0x140).  The PowerWatcher /
		// HeatWatcher base in this header set does not expose these, so they are
		// best-effort placeholders that let the per-frame page-gating logic
		// compile; a human should bind them to the real inherited members.
		// (See CROSS-FAMILY NEEDS.)
		//
		int	HeatWatcherFlag()     const { return 0; }
		int	WatchedVoltageLevel() const { return 0; }
		int	HeatStateLevel()      const { return 0; }
	};

#endif
