//===========================================================================//
// File:	btl4gau2.hpp                                                        //
// Project: BattleTech          Brick: Gauge Renderer Manager                 //
// Contents: Cockpit instrument library, part 2 -- the COMPOSITE "panel"      //
//           gauges that the BattleTech engineering / weapon-status HUD is     //
//           assembled from.  Where btl4gaug.cpp holds the primitive widgets   //
//           (bars, dials, lamps, colour-mappers), btl4gau2.cpp holds the      //
//           higher-level gauges that AGGREGATE those primitives into a single  //
//           subsystem read-out:                                               //
//             * SeekVoltageGraph   -- energy-weapon seek-voltage curve         //
//             * ConfigMapGauge     -- joystick / config-manager state lamp     //
//             * GeneratorCluster   -- generator voltage + coolant + leak panel //
//             * PrepEngrScreen     -- per-weapon engineering screen builder    //
//             * SubsystemCluster    +-> HeatSinkCluster                        //
//                                    +-> WeaponCluster +-> EnergyWeaponCluster //
//                                                       +-> BallisticWeaponClu.//
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/22/96  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED.  No BTL4GAU2.HPP survived; recovered from the shipped binary
// (BTL4OPT.EXE).  Ghidra pseudo-C is in recovered/all/part_014.c.
//
// Translation-unit extent (BTL4.MAK link order:
//   btl4mode -> btl4rdr -> btl4gaug -> btl4gau2 -> btl4gau3 -> btl4grnd -> ...):
//      first gau2 code  @004c6798   (SeekVoltageGraph::SeekVoltageGraph)
//      last  gau2 code  @004c9b50   (BallisticWeaponCluster helpers)
//      btl4gau3 begins  @004c9bd0   (PlayerStatusMappingGroup -- not this TU)
//
// Class names recovered from the CODE name-string pool around 0x519760
// (the gauge name list) and the per-instance identification strings:
//   "GeneratorCluster"  0x519a8c   "PrepEngr"   0x519a9d
//   "ConfigMap"         0x519a38   "CoolingLoop" 0x519a42  "PowerSource" 0x519a4e
//   "GeneratorVoltage(scalar)" 0x519a73   "GeneratorVoltage(slotOf)" 0x519a5a
//   "EngrGraph" 0x519a2e   "WeaponCluster ... " 0x519dcb
// Field offsets in comments are byte offsets (e.g. "@0x90" == this[0x24]).
//
// Bases (MUNGA L4 gauge primitives, shared with btl4gaug.cpp):
//   GraphicGauge   ctor FUN_00444818  dtor FUN_00444870  (GraphicsView @+0x48)
//   Gauge group    ctor FUN_004440d4  dtor FUN_00443f7c  (owns a ChainOf<Gauge*>
//                  at +0x24; used by PrepEngrScreen -- it draws into a port and
//                  hosts no GraphicsView of its own)
//   ArcGauge/BarGraph primitives  FUN_00472ef0 (bar), FUN_004c6244 (SegmentArc270,
//                  in btl4gaug), FUN_004739d8 (TwoState), FUN_00471d00
//                  (BackgroundBitmap), FUN_004700bc (NumericDisplay),
//                  FUN_00470888 (NumericDisplayScalar),
//                  FUN_00473c94 (NumericDisplayScalarTwoState).
//
// Names flagged "(best-effort)" exist in the binary but their identification
// string could not be tied to them unambiguously.
//

#if !defined(BTL4GAU2_HPP)
#	define BTL4GAU2_HPP

#	if !defined(SLOT_HPP)
#		include <slot.hpp>
#	endif
#	if !defined(L4GREND_HPP)
#		include <l4grend.hpp>
#	endif
#	if !defined(L4GAUGE_HPP)
#		include <l4gauge.hpp>
#	endif
#	if !defined(BTL4GAUG_HPP)
#		include <btl4gaug.hpp>
#	endif
#	if !defined(HEAT_HPP)
#		include <heat.hpp>
#	endif
	// (see btl4gaug.hpp -- <powersub.hpp> intentionally not pulled in; the
	//  composite gauges reference subsystems by pointer/attribute, not by type.)

	//
	// Reconstruction type: the original referenced an "AttributeAccessor" handle
	// (a small object that samples one named subsystem attribute).  Only its
	// address is used here (it is immediately reinterpreted as an Entity*), so an
	// opaque forward declaration is sufficient for this translation unit.
	//
	class AttributeAccessor;


	//#######################################################################
	// SeekVoltageGraph -- the energy-weapon "seek voltage" curve display.
	// @004c6798 ctor / @004c68ac dtor / @004c6920 BecameActive / @004c6934 Execute.
	// vtable PTR_FUN_0051a1fc.  Reads the four SeekVoltage attribute indices off
	// the weapon subsystem ("CurrentSeekVoltageIndex" / "Min" / "Max" /
	// "SeekVoltage") and plots a 0..230 x 0..187 curve, with min/max tick marks
	// and a live cursor at the current seek index.  When the subsystem is
	// destroyed (subsys+0x40==1) it shows a centred "destroyed" bitmap instead.
	//#######################################################################
	class SeekVoltageGraph :
		public GraphicGauge
	{
	public:
		SeekVoltageGraph(						// @004c6798
			GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer,
			int graphics_port_number, Entity *subsystem,
			AttributeAccessor *seek_voltage_pointer,
			const char *destroyed_image, Logical draw_cursor,
			const char *identification_string);
		~SeekVoltageGraph();					// @004c68ac
		Logical	TestInstance() const;
		void	BecameActive();					// @004c6920
		void	Execute();						// @004c6934
	protected:
		char	*destroyedImage;				// @0x90  this[0x24]
		int		currentSeekIndex;				// @0x94  this[0x25]  attr idx
		int		minSeekIndex;					// @0x98  this[0x26]  attr idx
		int		maxSeekIndex;					// @0x9C  this[0x27]  attr idx
		int		seekVoltageTable;				// @0xA0  this[0x28]  attr idx
		Entity	*voltageSubsystem;				// @0xA4  this[0x29]
		Subsystem *subsystem;					// @0xA8  this[0x2A]
		Scalar	previousVoltage;				// @0xAC  this[0x2B]  (9999 = redraw)
		Scalar	xScale;							// @0xB0  this[0x2C]  =230.0f
		Scalar	yScale;							// @0xB4  this[0x2D]  =187.0f
		int		destroyedShown;					// @0xB8  this[0x2E]
		Logical	drawCursor;						// @0xBC  this[0x2F]
		// helpers: SetupClip @004c6be4, DrawCursor @004c6c30, DrawTicks @004c6c6c
	};


	//#######################################################################
	// ConfigMapGauge -- the joystick / config-manager (control-mapper) state
	// lamp.  @004c6d80 ctor / @004c6e54 dtor / @004c6ee0 SetColor /
	// @004c6ef4 BecameActive / @004c6f1c Execute.  vtable PTR_FUN_0051a1b8.
	// Owns a base joystick bitmap ("btjoy.pcc") plus four config-state pixmaps
	// (cm_off/cm_other/cm_only/cm_both .pcc) selected from a 4-entry table
	// (DAT_00518eb8) driven by the control-mapper state.  Named "ConfigMap".
	//#######################################################################
	class ConfigMapGauge :
		public GraphicGauge
	{
	public:
		ConfigMapGauge(							// @004c6d80
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int x, int y, Entity *subsystem, const char *identification_string);
		~ConfigMapGauge();						// @004c6e54
		Logical	TestInstance() const;
		void	SetColor(int color);			// @004c6ee0  this[0x25]
		void	BecameActive();					// @004c6ef4
		void	Execute();						// @004c6f1c
	protected:
		Entity	*subsystem;						// @0x90  this[0x24]
		int		color;							// @0x94  this[0x25]
		char	*joystickImage;					// @0x98  this[0x26]  "btjoy.pcc"
		char	*stateImage[4];					// @0x9C  this[0x27..0x2A]
		int		previousState[4];				// @0xAC  this[0x2B..0x2E]
		Logical	dirty;							// @0xBC  this[0x2F]
	};


	//#######################################################################
	// Two small OneOfSeveral subclasses that drive the selected frame from a
	// subsystem value through a file-private GaugeConnection (the same
	// connection classes declared in btl4gaug.cpp).
	//   AnimatedSubsystemLamp  @004c70a4 (vtable 0051a174) -- connection @004c3134
	//   AnimatedSourceLamp     @004c7160 (vtable 0051a130) -- connection @004c31ec
	// Both chain OneOfSeveral::OneOfSeveral (@004c4d88, fromImageStrip=1) and
	// share dtor FUN_004c4e7c.  Used for the cooling-loop / power-source lamps.
	// (Class names best-effort; the gauge is generic and reused with the
	// instance strings "CoolingLoop" and "PowerSource".)
	//#######################################################################
	class AnimatedSubsystemLamp :				// (best-effort)
		public OneOfSeveral
	{
	public:
		AnimatedSubsystemLamp(					// @004c70a4
			GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image, int columns, int rows,
			void *subsystem, const char *identification_string);
		~AnimatedSubsystemLamp();				// @004c7134
	protected:
		int		selected;						// @0xAC  this[0x2B]  (connection dst)
	};

	class AnimatedSourceLamp :					// (best-effort)
		public OneOfSeveral
	{
	public:
		AnimatedSourceLamp(						// @004c7160
			GaugeRate, ModeMask, L4GaugeRenderer *, int,
			int x, int y, const char *image, int columns, int rows,
			void *source, const char *identification_string);
		~AnimatedSourceLamp();					// @004c71f0
	protected:
		int		selected;						// @0xAC  this[0x2B]
	};


	//#######################################################################
	// ScalarBarGauge -- a generator-voltage bar (derives from the MUNGA L4 bar
	// primitive @00472ef0).  Two ctors:
	//   @004c721c (vtable 0051a0e4) adds an "AltId" connection (@004c3288)
	//   @004c72ac (same vtable)     adds a plain GaugeConnectionDirectOf<Scalar>
	//                               (@00474855)
	// Both share dtor FUN_004c733c (chains the bar dtor @00472fb4).  Used with
	// the strings "GeneratorVoltage(slotOf)" / "GeneratorVoltage(scalar)".
	//#######################################################################
	// ScalarBarGauge chains the MUNGA L4 bar primitive @00472ef0 == the engine
	// BarGraphBitMapScalar (WipeGaugeScalar).  Its value slot @0xB4 (this[0x2D])
	// IS the inherited WipeGaugeScalar::currentValue -- the connection writes it,
	// so NO own field is declared (declaring one would shadow / mis-align).
	class ScalarBarGauge :
		public BarGraphBitMapScalar				// @00472ef0 base (WipeGaugeScalar : GraphicGauge)
	{
	public:
		// @004c721c -- the "slotOf" variant: bar body then AddConnection(new
		// GeneratorVoltageConnection @004c3288) feeding currentValue from a
		// resolved voltage source.  (The @004c72ac plain-Scalar variant is unused
		// by the cluster path.)
		ScalarBarGauge(							// @004c721c
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int left, int bottom, int right, int top,
			const char *tile_image, int foreground_color, int background_color,
			WipeGaugeScalar::Direction direction, Scalar min, Scalar max,
			void *voltage_source, const char *identification_string);
		// @004c72ac -- the plain-Scalar variant (a DIRECT Scalar* value source, a
		// GaugeConnectionDirectOf<Scalar> instead of the GeneratorVoltageConnection).
		// GeneratorCluster is its caller.  Disambiguated from the void* overload by
		// the Scalar* first arg (exact match here, std-conversion to void*).
		ScalarBarGauge(							// @004c72ac
			GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
			int left, int bottom, int right, int top,
			const char *tile_image, int foreground_color, int background_color,
			WipeGaugeScalar::Direction direction, Scalar min, Scalar max,
			Scalar *value_source, const char *identification_string);
		~ScalarBarGauge();						// @004c733c
	};


	//#######################################################################
	// GeneratorCluster -- the generator read-out panel.  @004c7368 Make /
	// @004c746c ctor / @004c7778 dtor.  vtable PTR_FUN_0051a0a0.  A GraphicGauge
	// that owns five child gauges, parented to its own graphics port:
	//      VertTwoPartBar         (temperature)    this[0x26]
	//      ScalarBarGauge         (voltage 0..12kV) this[0x27]
	//      BitMapInverseWipe/Leak (coolant leak)    this[0x28]
	//      TwoState x2            (status lamps)    this[0x29],this[0x2A]
	// Reads CurrentTemperature/DegradationTemperature/FailureTemperature/
	// CoolantMassLeakRate/OutputVoltage attribute indices off the subsystem.
	// Make resolves the named subsystem ("GeneratorCluster") via FindSubObject;
	// warns "Subsystem <name> not found".
	//#######################################################################
	class GeneratorCluster :
		public GraphicGauge
	{
	public:
		// gauge wave P2: registered "GeneratorCluster" (engineering buttons 9-12,
		// GeneratorA..D).  Corrected ctor param order == binary FUN_004c746c; only
		// the dtor is overridden (Execute/BecameActive/TestInstance inherited).
		static MethodDescription methodDescription;
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c7368
		GeneratorCluster(						// @004c746c  (BINARY param order)
			ModeMask, L4GaugeRenderer *, int owner_ID, int graphics_port_number,
			int x, int y, Subsystem *subsystem,
			const char *background_image, int extra_color,
			const char *temp_tile, int temp_bg_color, int temp_fill_color,
			const char *voltage_tile, int voltage_fg_color,
			const char *leak_image, int leak_color_b,
			const char *lampA_image, const char *lampB_image,
			int lamp_on_color, int lamp_off_color,
			const char *identification_string);
		~GeneratorCluster();					// @004c7778
		// A container panel MUST override BecameActive + Execute: the engine base
		// Gauge::Execute is Fail("not overridden")->abort (GAUGE.cpp:598), and the
		// default BecameActive self-inactivates.  The panel draws its static
		// background pixmap; the 5 self-registered child gauges draw the dynamic
		// content.  (The decode's "only the dtor is overridden" was wrong: the
		// 1995 base Gauge::Execute was a no-op, the 2007 engine's aborts.)
		void	BecameActive();
		void	Execute();
	protected:
		char	*backgroundImage;				// @0x90  this[0x24]  interned .pcc (pixelMap8Bin AddRef'd)
		int		secondaryColor;					// @0x94  this[0x25]  = leak colorB (stored, unread here)
		GraphicGauge
				*temperatureBar,				// @0x98  this[0x26]  VertTwoPartBar
				*voltageBar,					// @0x9C  this[0x27]  ScalarBarGauge (@004c72ac variant)
				*leakGauge,						// @0xA0  this[0x28]  BitMapInverseWipe
				*lampA,							// @0xA4  this[0x29]  TwoState
				*lampB;							// @0xA8  this[0x2A]  TwoState
		Subsystem *subsystem;					// @0xAC  this[0x2B]
		int		_reserved0xB0;					// @0xB0  this[0x2C]  (trailing pad -> sizeof 0xB4)
	};


	//#######################################################################
	// PrepEngrScreen (config keyword "prepEngr") -- the per-engineering-screen
	// STATIC LABEL overlay.  @004c7b30 Make / @004c7bf0 ctor / @004c7d14 dtor /
	// @004c7e48 BecameActive.  vtable PTR_FUN_0051a06c.
	//
	// A GraphicGaugeBackground (paint-on-activation, NOT an Execute gauge -- the
	// same base/vtable shape as the engine's BackgroundBitmap: only the dtor +
	// BecameActive slots are overridden).  Interns 7 status .pcc's (font + 6
	// labels) and, when its MFD-Eng screen (1..12) activates, paints the labels
	// for the ONE subsystem whose auxScreenNumber == this screen, dispatched by
	// the subsystem's ClassID.  Was a MISLABELED stub (base Gauge, Execute, and
	// mech/screenNumber SWAPPED) with no methodDescription -> "prepEngr" was
	// parse-skipped (12 CFG calls never built).
	//#######################################################################
	class PrepEngrScreen :
		public GraphicGaugeBackground
	{
	public:
		static MethodDescription methodDescription;								// "prepEngr"
		static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);	// @004c7b30
		PrepEngrScreen(							// @004c7bf0
			ModeMask, L4GaugeRenderer *, unsigned int owner_ID,
			int graphics_port_number, Entity *mech, int screen_number,
			const char *img0/*font*/, const char *img1, const char *img2,
			const char *img3, const char *img4, const char *img5,
			const char *img6, const char *identification_string = "PrepEngr");
		~PrepEngrScreen();						// @004c7d14
		void	BecameActive();					// @004c7e48  (the paint slot -- NOT Execute)
	protected:
		int		screenNumber;					// @0x6C  this[0x1B]  (FIX: was mech)
		Entity	*mech;							// @0x70  this[0x1C]  (FIX: was screenNumber)
		char	*statusImage[7];				// @0x74  this[0x1D..0x23]  (interned .pcc names)
		// sizeof == 0x90 (Make alloc); no offset locks (2007 GraphicGaugeBackground
		// base not byte-identical; every read is via named members / safe accessors).
	};


	//#######################################################################
	// SubsystemCluster family -- the big composite panels.  Each is a
	// GraphicGauge that builds a dozen child gauges into one cockpit instrument.
	//
	//   SubsystemCluster      @004c8140  (vtable 0051a020) -- base "engineering"
	//        panel: HorizTwoPartBar + cooling/power loops + generator voltage +
	//        OneOfSeveralInt + OneOfSeveralStates + 2x VertTwoPartBar + LeakGauge
	//        + BackgroundBitmap.  Uses the btXXloop / btXbus / evolt / btecmode /
	//        eleak palette files.  Reads InputVoltage/HeatSink/CurrentTemperature/
	//        DegradationTemperature/FailureTemperature attributes.
	//
	//   HeatSinkCluster       @004c8a6c  (vtable 00519fd4) : SubsystemCluster
	//        adds 4 failure-annunciator TwoStates (btehfail/btepfail/btesfail)
	//        and a NumericDisplayScalar.  Execute @004c8db0 scales this[0x35] by
	//        _DAT_004c8df0 into the numeric read-out.
	//
	//   WeaponCluster         @004c8fc4  (vtable 00519f38) : SubsystemCluster
	//        adds a SegmentArc270 (recharge dial, 0..360) + a ConfigMapGauge.
	//        Make-time warns "WeaponCluster missing <name>".  Reads "PercentDone".
	//        Execute @004c9290 toggles a warning lamp when this[0x36] > _DAT_004c92e0.
	//
	//        EnergyWeaponCluster   @004c93b0 (vtable 00519ee8) : WeaponCluster
	//            adds a SeekVoltageGraph ("EngrGraph", edestryd.pcc) and a
	//            seek-step OneOfSeveralInt (bteseek.pcc, subsys+0x3F0).
	//        BallisticWeaponCluster @004c9558 (vtable 00519e98) : WeaponCluster
	//            adds 2x NumericDisplayInteger (ammo), jam/fire TwoStates
	//            (btejam/btefire), NumericDisplayScalarTwoState, an eject
	//            BitMapInverseWipeScalar (bteejtm) reading subsys+0x3F8, plus a
	//            GraphicsViewRecord erase tracker (this[0x3F]).  Execute @004c9a38
	//            tracks weaponAlarm==5 (Jammed) and the ammo-bin link (+0x43C).
	//#######################################################################
	class SubsystemCluster :
		public GraphicGauge
	{
	public:
		// @004c8140.  Binary param order (rate/mode are hardcoded 0xFFFF/0xFFFFFFFF
		// in the base GraphicGauge ctor; the panel's two bit-plane MODE masks are
		// mfd_mode (MFD-port children) and eng_mode (engineering-port children)).
		SubsystemCluster(						// @004c8140
			ModeMask mfd_mode, L4GaugeRenderer *renderer, int owner_ID,
			int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image,
			const char *label, char **image_names,
			const char *identification_string);
		~SubsystemCluster();					// @004c87dc
		Logical	TestInstance() const;
		void	BecameActive();					// @004c88e4 (shared base Execute trampoline)
		void	Execute();						// @004c88e4
	protected:
		BackgroundBitmap
				*background;					// @0x90  this[0x24]  BackgroundBitmap
		GraphicGauge
				*generatorVoltageBar,			// @0x94  this[0x25]  ScalarBarGauge (evolt)
				*temperatureBar,				// @0x98  this[0x26]  HorizTwoPartBar
				*coolingLoopA,					// @0x9C  this[0x27]  AnimatedSubsystemLamp
				*coolingLoopB,					// @0xA0  this[0x28]
				*powerSourceA,					// @0xA4  this[0x29]
				*powerSourceB,					// @0xA8  this[0x2A]
				*vertBarA,						// @0xAC  this[0x2B]  VertTwoPartBar
				*vertBarB,						// @0xB0  this[0x2C]
				*modeLamp,						// @0xB4  this[0x2D]  OneOfSeveralInt
				*stateLamp,						// @0xB8  this[0x2E]  OneOfSeveralStates
				*leakGauge;						// @0xBC  this[0x2F]  LeakGauge
		Subsystem *subsystem;					// @0xC0  this[0x30]
		// POLARITY CORRECTED (PPC-dial fix, 2026-07-12): the binary's
		// *(subsystem+0x40)==1 means the subsystem FAILED -- it lights the
		// destroyed-X TwoStates (engine TwoState draws bright on NONZERO) and
		// selects the dead-panel look (GetDrawState 1 = black fill).  The old
		// name `operating` had it backwards, inverting every consumer.
		Logical	failedState;					// @0xC4  this[0x31]  1 = subsystem destroyed
		int		previousDrawState;				// @0xC8  this[0x32]  (Execute repaint key)

		// internal helpers (non-virtual; @004c89c4 / @004c8820 / @004c8a28)
		void	DrawPanelFrame(int color);		// @004c89c4
		void	ReleaseChildren();				// @004c8820
		void	SetChildrenEnable(int enable);	// @004c8a28
	public:
		int		GetDrawState();					// @004c8990 (operational-state virtual, vtbl+0x48)
	protected:
	};

	class HeatSinkCluster :						// @004c8a6c
		public SubsystemCluster
	{
	public:
		HeatSinkCluster(						// @004c8a6c
			ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port,
			int x, int y, Subsystem *subsystem, Subsystem *hud, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image, const char *label,
			const char *fail_lamp_image, char **image_names,
			const char *identification_string);
		~HeatSinkCluster();						// @004c8d18
		void	Execute();						// @004c8db0
	protected:
		Subsystem *failSubsystem;				// @0xCC  this[0x33]
		Logical	failFlag;						// @0xD0  this[0x34]
		Scalar	heatLoad;						// @0xD4  this[0x35]
		Scalar	heatLoadScaled;					// @0xD8  this[0x36]
		GraphicGauge
				*heatFailLamp,					// @0xDC  this[0x37]  TwoState
				*hsFailLamp,					// @0xE0  this[0x38]  TwoState (btehfail)
				*powerFailLamp,					// @0xE4  this[0x39]  TwoState (btepfail)
				*structFailLamp,				// @0xE8  this[0x3A]  TwoState (btesfail)
				*heatNumeric;					// @0xEC  this[0x3B]  NumericDisplayScalar
	};

	//
	// MyomerCluster @004c8df4 (vtable 00519f88) : SubsystemCluster -- the myomer
	// (muscle) panel.  Adds a SeekVoltageGraph ("EngrGraph", edestryd.pcc) fed by
	// an InputVoltage GeneratorVoltageConnection (writes seekValue@0x33) + a
	// seek-step OneOfSeveralInt (bteseek.pcc, subsys+0x800).  Execute = base.
	//
	class MyomerCluster :						// @004c8df4
		public SubsystemCluster
	{
	public:
		MyomerCluster(							// @004c8df4
			ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port,
			int x, int y, Subsystem *subsystem, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image, const char *label,
			char **image_names, const char *identification_string);
		~MyomerCluster();						// @004c8f54
	protected:
		Scalar	seekValue;						// @0xCC  this[0x33]  (connection dst)
		GraphicGauge
				*seekGraph,						// @0xD0  this[0x34]  SeekVoltageGraph
				*seekStepLamp;					// @0xD4  this[0x35]  OneOfSeveralInt
	};

	class WeaponCluster :						// @004c8fc4
		public SubsystemCluster
	{
	public:
		WeaponCluster(							// @004c8fc4
			ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port,
			int x, int y, Subsystem *subsystem, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image, const char *label,
			const char *cluster_image, char **image_names,
			const char *identification_string);
		~WeaponCluster();						// @004c91d4
		void	BecameActive();					// @004c9258
		void	Execute();						// @004c9290
		void	DrawWarningLamp(int color);		// @004c932c
	protected:
		char	*clusterImage;					// @0xCC  this[0x33]
		GraphicGauge *rechargeArc;				// @0xD0  this[0x34]  SegmentArc270
		ConfigMapGauge *configMap;				// @0xD4  this[0x35]
		Scalar	percentDone;					// @0xD8  this[0x36]  (connection dst)
		int		warningCenterX;					// @0xDC  this[0x37]
		int		warningCenterY;					// @0xE0  this[0x38]
		int		warningState;					// @0xE4  this[0x39]
		const char *diagWeaponName;				// PORT diagnostic (appended; clusters are plain-new)
	};

	class EnergyWeaponCluster :					// @004c93b0
		public WeaponCluster
	{
	public:
		EnergyWeaponCluster(					// @004c93b0
			ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port,
			int x, int y, Subsystem *subsystem, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image, const char *label,
			const char *cluster_image, char **image_names,
			const char *identification_string);
		~EnergyWeaponCluster();					// @004c94dc
	protected:
		SeekVoltageGraph *seekGraph;			// @0xE8  this[0x3A]
		GraphicGauge	 *seekStepLamp;			// @0xEC  this[0x3B]  OneOfSeveralInt
	};

	class BallisticWeaponCluster :				// @004c9558
		public WeaponCluster
	{
	public:
		BallisticWeaponCluster(					// @004c9558
			ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port,
			int x, int y, Subsystem *subsystem, ModeMask eng_mode,
			const char *eng_port_name, const char *tile_image, const char *label,
			const char *cluster_image, char **image_names,
			const char *font_a, const char *font_b,
			const char *identification_string);
		~BallisticWeaponCluster();				// @004c9940
		void	BecameActive();					// @004c99cc
		void	Execute();						// @004c9a38
		Logical	TestInstance() const;			// @004c9adc
	protected:
		Logical	jammed;							// @0xE8  this[0x3A]
		Logical	firing;							// @0xEC  this[0x3B]
		Logical	reloading;						// @0xF0  this[0x3C]
		int		reloadStartTime;				// @0xF4  this[0x3D]
		Scalar	reloadSeconds;					// @0xF8  this[0x3E]
		GraphicsViewRecord
				*ammoErase;						// @0xFC  this[0x3F]
		GraphicGauge
				*ammoNumeric,					// @0x100 this[0x40]  NumericDisplayScalarTwoState
				*destroyedLamp,					// @0x104 this[0x41]  TwoState
				*jamLamp,						// @0x108 this[0x42]  TwoState (btejam)
				*fireLamp,						// @0x10C this[0x43]  TwoState (btefire)
				*ejectWipe,						// @0x110 this[0x44]  BitMapInverseWipeScalar
				*ammoCountA,					// @0x114 this[0x45]  NumericDisplayInteger
				*ammoCountB;					// @0x118 this[0x46]  NumericDisplayInteger
	};


	//#######################################################################
	// vehicleSubSystems -- the config primitive that builds the engineering-
	// screen (MFD) subsystem cluster panels.  Make @004cbaf0 (methodDescription
	// @0x51c080, 8 typeString params = the 8 status strip bitmaps) is a per-
	// subsystem factory: it walks the mech roster (skipping slot 0), and for each
	// subsystem builds the right cluster (HeatSink/Myomer/Energy/Ballistic) onto
	// one of 12 auxiliary MFD positions selected by subsystem[0x1dc] (the aux-
	// screen position 1..12).  This holder just carries the registered
	// MethodDescription + the static Make dispatcher (there is no instance).
	//#######################################################################
	class VehicleSubSystems
	{
	public:
		static MethodDescription methodDescription;
		static Logical Make(				// @004cbaf0
			int display_port_index, Vector2DOf<int> position,
			Entity *entity, GaugeRenderer *gauge_renderer);
	};

#endif
