//===========================================================================//
// File:	mechmppr.hpp                                                        //
// Project: BattleTech           Brick: Entity Manager                        //
// Contents: Mech controls mapper -- maps pilot control inputs and view       //
//           selection onto the Mech's motion / torso / eyepoint demands      //
//---------------------------------------------------------------------------//
//   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, cluster
// @004afbe0-@004b08c0) cross-referenced against the Red Planet sibling
// RP\VTVMPPR.cpp / VTVMPPR.h (VTVControlsMapper) -- same engine, same
// mapper pattern.  The class name "MechControlsMapper" is recovered verbatim
// from the Derivation name string @0050f173.  Attribute and message names are
// recovered from the class string pool @0050f180-@0050f367 and the attribute
// table @0050efd0; the configuration / event-mapping stub strings come from
// @0050f370-@0050f44a.
//
// Field offsets in comments are the byte offsets observed in the decompiled
// object (e.g. "@0x114" == this[0x45]).  Names follow VTVControlsMapper where
// the role is identical; Mech-specific members (torso, pilot array) are named
// from the attribute table and flagged best-effort where uncertain.
//
// This is the BattleTech analog of Red Planet's VTVControlsMapper.  Like that
// class it is the active "Performance" of the master, dynamic Mech: each
// simulation frame InterpretControls() reads the raw stick/throttle/pedals and
// the look/torso buttons and produces speedDemand / turnDemand plus the torso
// and eyepoint pose used by the locomotion and view code.
//

#if !defined(MECHMPPR_HPP)
#	define MECHMPPR_HPP

#if !defined(SUBSYSTM_HPP)
#	include <subsystm.hpp>
#endif
#if !defined(CONTROLS_HPP)
#	include <controls.hpp>		// ControlsButton, ControlsJoystick
#endif

//#####################    Forward Class Declarations  #######################
class Mech;
class Pilot;

//###########################################################################
//#########################   MechControlsMapper   ##########################
//###########################################################################
//
//	Primary vtable @0050f45c (slot 0 = scalar-deleting destructor @004b044c;
//	slots 1-13 inherited from Subsystem; slots 18/19 -- vtable+0x48/+0x4c --
//	are the NotifyOf* hooks below).  A secondary "controls mapper /
//	configurator" interface vtable @0050f498 supplies the EnterConfiguration /
//	ExitConfiguration / event-mapping stubs (all "not overridden" by default).
//
	class MechControlsMapper:
		public Subsystem
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	public:
		// WinTesla engine refactored the static derivation/handler/attribute
		// objects behind Get* accessors (avoids static-init ordering bugs).
		static Derivation	*GetClassDerivations();	// @0050ee10
		static SharedData	DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Messaging Support
	//
	//	Message IDs and handler names recovered from the message table
	//	@0050ee40 (string pool @0050f180).  IDs 3..0x13 (the auxiliary-equipment
	//	and zoom buttons) are routed through the shared ConfigureMappable
	//	handler @004afbc4; the last three drive dedicated handlers.
	//
	public:
		enum {
			Aux1QuadMessageID = Subsystem::NextMessageID,	// 3
			Aux1Eng1MessageID, Aux1Eng2MessageID,
			Aux1Eng3MessageID, Aux1Eng4MessageID,
			Aux2QuadMessageID,
			Aux2Eng1MessageID, Aux2Eng2MessageID,
			Aux2Eng3MessageID, Aux2Eng4MessageID,
			Aux3QuadMessageID,
			Aux3Eng1MessageID, Aux3Eng2MessageID,
			Aux3Eng3MessageID, Aux3Eng4MessageID,
			ZoomInMessageID,					// 0x12
			ZoomOutMessageID,					// 0x13
			CycleControlModeMessageID,			// 0x14
			CycleDisplayModeMessageID,			// 0x15
			ToggleVoiceAssistMessageID,			// 0x16
			NextMessageID
		};

		void
			ConfigureMappableMessageHandler(	// @004afbc4  (shared)
				ReceiverDataMessageOf<ControlsButton> *message
			);
		void
			CycleControlModeMessageHandler(		// @004afbe0
				ReceiverDataMessageOf<ControlsButton> *message
			);
		void
			CycleDisplayModeMessageHandler(		// @004afcac
				ReceiverDataMessageOf<ControlsButton> *message
			);
		void
			ToggleVoiceAssistMessageHandler(	// @004afce8
				ReceiverDataMessageOf<ControlsButton> *message
			);

	private:
		static const HandlerEntry MessageHandlerEntries[];	// @0050ee40
	protected:
		static MessageHandlerSet& GetMessageHandlers();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	//	Attribute IDs / names / member offsets recovered from the attribute
	//	table @0050efd0.  (The recorded member offsets carry the engine's
	//	low-bit "scalar" tag, e.g. 0x115 -> &stickPosition @0x114.)
	//
	public:
		enum {
			StickPositionAttributeID = Subsystem::NextAttributeID,	// 3
			ThrottlePositionAttributeID,			// 4
			PedalsPositionAttributeID,				// 5
			ReverseThrustAttributeID,				// 6
			SpeedDemandAttributeID,					// 7
			TurnDemandAttributeID,					// 8
			LookForwardAttributeID,					// 9
			LookLeftAttributeID,					// 0xa
			LookRightAttributeID,					// 0xb
			LookBehindAttributeID,					// 0xc
			LookDownAttributeID,					// 0xd
			TorsoUpAttributeID,						// 0xe
			TorsoDownAttributeID,					// 0xf
			TorsoLeftAttributeID,					// 0x10
			TorsoRightAttributeID,					// 0x11
			TorsoCenterAttributeID,					// 0x12
			ControlModeAttributeID,					// 0x13
			DisplayModeAttributeID,					// 0x14
			PilotArrayPageAttributeID,				// 0x15
			PilotArrayAttributeID,					// 0x16
			NextAttributeID
		};
	private:
		static const IndexEntry AttributePointers[];	// @0050efd0
	protected:
		static AttributeIndexSet& GetAttributeIndex();

	//
	// Published attributes.
	//
	public:
		ControlsJoystick	stickPosition;		// @0x114  (x @0x114, y @0x118)
		Scalar				throttlePosition;	// @0x11C
		Scalar				pedalsPosition;		// @0x120
		ControlsButton		reverseThrust;		// @0x124
		Scalar				speedDemand;		// @0x128  (output)
		Scalar				turnDemand;			// @0x12C  (output)
		ControlsButton		lookForward;		// @0x130
		ControlsButton		lookLeft;			// @0x134
		ControlsButton		lookRight;			// @0x138
		ControlsButton		lookBehind;			// @0x13C
		ControlsButton		lookDown;			// @0x140
		ControlsButton		torsoUp;			// @0x144
		ControlsButton		torsoDown;			// @0x148
		ControlsButton		torsoLeft;			// @0x14C
		ControlsButton		torsoRight;			// @0x150
		ControlsButton		torsoCenter;		// @0x154

		int					pilotArrayPage;		// @0x158  (which "page" of pilots)
		Pilot				*pilotArray[1];		// @0x15C  [0]=local; [1..] remote
											// (variable length; pilotCount entries)

		enum ControlMode {
			BasicMode	 = 0,
			StandardMode = 1,
			VeteranMode	 = 2
		}					controlMode;		// @0x190
		int					displayMode;		// @0x194  (0..2, cycles)

		int					lookState;			// @0x198  eyepoint look selection
		int					previousLookState;	// @0x19C

	protected:
		Logical				pilotArrayBuilt;	// @0x184  built-once flag
		int					*pilotIDs;			// @0x188  parallel id table
		int					pilotCount;			// @0x18C

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Model Support
	//
	public:
		typedef void
			(MechControlsMapper::*Performance)(Scalar time_slice);

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

		// The active master-Mech performance (vtable default @0050f120).
		void
			InterpretControls(Scalar time_slice);	// @004afd10

		// Owner accessor -- the mapper's owning entity is always a Mech.
		// (Subsystem::GetEntity() returns the generic Entity*; the decomp
		// pseudo-C used the owner pointer directly.)
		Mech*
			GetMech();

	//
	// Look / torso eyepoint selection.
	//
	public:
		enum LookState {
			LookNone		= 0,
			LookLeftState	= 1,
			LookRightState	= 2,
			LookBehindState	= 3,
			LookDownState	= 4
		};

	//
	// Pilot-array (other-player roster) management.  Built lazily on first
	// use from the "Players" group of the application object (@0050f44b).
	//
	public:
		void
			BuildPilotArray();					// @004b0600
		Pilot *
			GetPilot(int index);				// @004b0898
		void
			ChooseNearestPilot(int self_id);	// @004b04d8
		void
			ChooseDefaultPilot();				// @004b07f0
		void
			UpdateCurrentPilot(int page);		// @004b049c
	protected:
		void
			FillPilotArray();					// @004b06cc

	//
	// Configuration / event-mapping interface (the secondary vtable @0050f498).
	// Platform-specific derived mappers override these; the base mapper traps
	// any unrouted call.
	//
	public:
		virtual void
			EnterConfiguration(
				ControlsButton	*destination,
				Receiver		*receiver,
				Receiver::MessageID	activation_message_id,
				Receiver::MessageID	configuration_message_id
			);
		virtual void
			ExitConfiguration();				// @004b029c
		virtual void
			CreateTemporaryEventMappings(		// @004b02b8
				Receiver			*receiver,
				Receiver::MessageID	config_message_id
			);
		virtual void
			AddOrErase(							// @004b02d4
				unsigned int		button_ID,
				ControlsButton		*destination
			);

		virtual void
			NotifyOfControlModeChange(int new_mode);	// @004b048c (vtable+0x48)
		virtual void
			NotifyOfDisplayModeChange(int new_mode);	// @004b0494 (vtable+0x4c)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:
		MechControlsMapper(						// @004b02f0
			Mech				*owner,
			int					subsystem_ID,
			SubsystemResource	*subsystem_resource,
			SharedData			&shared_data = DefaultData
		);
		~MechControlsMapper();					// @004b044c

		Logical
			TestInstance() const;				// @004b08c0
	};

#endif
