//============================================================================//
// File:	missile.hpp                                                          //
// Project: BattleTech																			//
// Contents: A guided self-propelled projectile entity that hosts a Seeker     //
//			and a MissileThruster subsystem.                                     //
//----------------------------------------------------------------------------//
//   Date    Who  Modification                                                //
// --------  ---  ------------------------------------------------------------//
// 04/13/95  JM  Initial coding.                                              //
//----------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved  //
//                   	PROPRIETARY AND CONFIDENTIAL                          //
//============================================================================//
//
// RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, module cluster
// @004bef4c-@004bf8bc in part_013.c).  NO surviving header exists for this
// class -- only the test fragments MISSILE.TCP and PROJTILE.TCP.  The
// declaration below is therefore INFERRED from:
//   * the decompiled ctor @004bf5b4 and integrator @004bef78
//   * MISSILE.TCP (Missile::TestClass: GetSubsystem(MissileThrusterSubsystem /
//     SeekerSubsystem), MoveAndCollide, gun->currentProjectile)
//   * the surviving SEEKER.HPP / MISTHRST.HPP that name its two subsystems
//   * the sibling Projectile base (PROJTILE.TCP: Projectile::TestClass)
// Member names past the Projectile base are best-effort and flagged.
//
// Inheritance chain established from the decomp:
//      Entity -> Projectile (ctor @004be1bc, vtable @00512a5c, sizeof 0x340)
//             -> Missile     (ctor @004bf5b4, vtable @00512f2c, sizeof 0x368)
// The Missile ctor chains Projectile::Projectile (@004be1bc) and then builds a
// 2-entry subsystem roster: slot 0 = Seeker ("Seeker"), slot 1 =
// MissileThruster ("MissleThruster", spelled as in the shipped string table
// @00512e25).  Spawned by the launcher as streamed-entity ClassID 0xBD0.
//

#if !defined (MISSILE_HPP)
#	define	MISSILE_HPP

#	if !defined(PROJTILE_HPP)
#		include <projtile.hpp>		// Projectile : Entity base
#	endif

//######################### Forward Class Declarations ########################
	class Mech;
	class Seeker;
	class MissileThruster;

//###########################################################################
//#########################     CLASS -- Missile    #########################
//###########################################################################
//
//	(vtable @00512f2c, ctor @004bf5b4, dtor @004bf890, allocator @004bf8bc.)
//
	class Missile:
		public Projectile
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	public:
		static Derivation ClassDerivations;
		static Receiver::MessageHandlerSet MessageHandlers;
		static AttributeIndexSet AttributeIndex;
		static SharedData DefaultData;

		// Entity factory hook (Entity::SharedData requires a MakeHandler).
		static Entity *Make(MakeMessage *creation_message);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Subsystem roster
	//
	//	The two hosted subsystem IDs, used by GetSubsystem() in MISSILE.TCP.
	//	Build order in the ctor (@004bf5b4): Seeker first, MissileThruster
	//	second.
	//
	public:
		enum {
			SeekerSubsystem			= 0,
			MissileThrusterSubsystem	= 1,
			SubsystemCount				= 2		// this[0x49] == 2  (@0x124)
		};

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

		// @004bef78 -- the per-frame integrate-guidance-and-collide pass.
		// Ages the missile (this+0x35c), asks the Seeker for the lead point,
		// applies the MissileThruster acceleration toward it, integrates
		// position/velocity, runs the world collision query (FUN_0042291c) and,
		// on impact, spawns the explosion/Damage entity (FUN_004be078) before
		// retiring itself.
		void
			MoveAndCollide(Scalar time_slice);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Update record (network)
	//
	protected:
		void
			WriteUpdateRecord(						// vtable slot 7, @004bef4c
				UpdateRecord	*message,
				int				update_model);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// 	TestClass Support  (MISSILE.TCP)
	//
	public:
		static Logical
			TestClass(Mech &);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:
		Missile(									// @004bf5b4
			int				owner,				// spawning launcher / streamed-entity ctx
			const char		*spawn_descriptor	// &DAT_00512d48 default record
		);
		~Missile();									// @004bf890

		// @004bf8bc -- allocate (0x368 bytes) and construct.
		static Missile *
			New(int spawn_context);

		Logical
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local data appended past the Projectile base (offsets best-effort).
	//
	protected:
		Scalar		lifetime;			// @0x340 this[0xd0]  max time-of-flight (model +0x44)
		Scalar		ageFraction;		// @0x344 this[0xd1]  age/lifetime, clamped to 1.0
		Scalar		thrustScale;		// @0x348 this[0xd2]  sqrt(model+0x48 / mass)
		void		*targetConnection;	// @0x34c this[0xd3]  resolved target/launcher link
		Vector3D	targetOffset;		// @0x350 this[0xd4..0xd6] aim offset handed to the Seeker
		Scalar		age;				// @0x35c this[0xd7]  accumulated time-of-flight
		void		*explosionModel;	// @0x360 this[0xd8]  detonation model (model +?)
		int			detonationFlag;		// @0x364 this[0xd9]  proximity/contact detonation mode

		// --- Entity-motion working fields (reconstruction; the shipped binary
		//     keeps these in the Entity transform/motion block). ---
		Scalar		mass;				// missile mass (model)
		Vector3D	velocity;			// @0x1dc linear velocity
		Vector3D	thrustVelocity;		// @0x1e8 thrust-contributed velocity
		Scalar		thrustImpulse;		// @0x1d0 thrust impulse scale
		Vector3D	thrusterAxis;		// @0x234 thruster acceleration axis

		// --- small proxy types for the recovered model/thruster reads ---
		struct ModelRecord {
			Scalar	maxTimeOfFlight;	// model +0x44
			Scalar	thrust;				// model +0x48
			int		detonationMode;		// model +0x50
		};
		struct ThrusterState {
			Scalar	acceleration;
		};

		// --- recovered helpers (engine/model plumbing rendered as artifacts) ---
		void		GetForward(Vector3D &out);				// FUN_0040d150
		void	   *ResolveTargetConnection(int owner);		// resolved target/launcher link
		Vector3D	LaunchAimOffset(int owner);				// launch aim offset
		const ModelRecord *ResolveModel();					// FUN_00407064 chain
		void		SpawnDetonation(Entity *hit);			// FUN_004be078 (ClassID 0x5C)

		// subsystem roster (Projectile base fields, shown for clarity)
		// int		subsystemCount;		// @0x124 this[0x49] == 2
		// Subsystem **subsystems;		// @0x128 this[0x4a] -> {Seeker, MissileThruster}
	};
#endif
