//============================================================================//
// File:	projtile.hpp                                                         //
// Project: BattleTech																			//
// Contents: In-flight projectile entity base (position/velocity/lifetime/      //
//			collision); parent of Missile.                                       //
//----------------------------------------------------------------------------//
//   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
// @004be1bc-@004be3b4 in part_013.c).  NO surviving header exists for this base
// -- only the test fragment PROJTILE.TCP (Projectile::TestClass).  The class
// declaration is INFERRED from:
//   * the decompiled ctor @004be1bc, dtor @004be358 and allocator @004be384
//   * the derived Missile (missile.hpp/cpp), whose integrator @004bef78 reads
//     these base fields (position @0x100, velocity @0x1DC, segment/world @0x300)
//   * PROJTILE.TCP (Projectile::TestClass -- note: takes NO argument)
// Member names past the Entity base are best-effort and flagged.
//
// Inheritance chain established from the decomp:
//      Entity (FUN_004234f0 base ctor) -> Projectile (vtable @00512a5c, 0x340)
//             -> Missile               (vtable @00512f2c, 0x368)
// The ctor stamps vtable PTR_FUN_00512a5c, registers the projectile into the
// owning world-segment table, snapshots the launch kinematics out of the spawn
// descriptor, and installs one of two Performance variants (authoritative vs
// network-ghost) selected by the entity flags (this+0x28 & 0xC == 4).
//
// Object byte offsets (this is an int* in the decomp, word index in parens).
// Everything below +0x300 is the Entity base (transform @0x100, velocity @0x1DC,
// thrust-velocity @0x1E8, born/spawn ticks @0x10/@0x14, status flags @0x18).
//

#if !defined (PROJTILE_HPP)
#	define	PROJTILE_HPP

#	if !defined(ENTITY_HPP)
#		include <entity.hpp>		// Projectile : Entity
#	endif

#	if !defined(POINT3D_HPP)
#		include <point3d.hpp>
#	endif

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

//###########################################################################
//#########################     CLASS -- Projectile   #######################
//###########################################################################
//
//	(vtable @00512a5c, ctor @004be1bc, dtor @004be358, allocator @004be384.)
//
	class Projectile:
		public Entity
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	public:
		static Derivation ClassDerivations;		// IsDerivedFrom tag 0x512980
		static Receiver::MessageHandlerSet MessageHandlers;
		static AttributeIndexSet AttributeIndex;
		static SharedData DefaultData;			// resolved as &DAT_005129b0

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

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

		// The default per-frame integrate-and-collide pass.  Installed by the
		// ctor as the active Performance: PTR_LAB_005129e8 when authoritative
		// (flags & 0xC == 4), PTR_LAB_005129f4 for a network ghost.  Missile
		// supplies its own override (Missile::MoveAndCollide @004bef78).
		void
			MoveAndCollide(Scalar time_slice);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// 	TestClass Support  (PROJTILE.TCP)
	//
	public:
		static Logical
			TestClass();						// PROJTILE.TCP: returns True
		Logical
			TestInstance() const;				// @004be3b4

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:
		Projectile(								// @004be1bc
			int				owner,				// spawning weapon / streamed-entity ctx
			const char		*spawn_descriptor	// launch descriptor record
		);
		~Projectile();							// @004be358

		// @004be384 -- allocate (0x340 bytes) and construct with &DAT_005129b0.
		static Projectile *
			New(int spawn_context);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Model / animation update binding (Entity sub-object)
	//
	//	this[0x94..0x97] = a bound member-function ("model update" callback,
	//	PTR_FUN_005129dc) invoked each frame; 0x250 is its context pointer.
	//
	protected:
		void			*modelUpdateContext;	// @0x250 (word 0x94)

		// hosted-subsystem roster (used by Missile; Projectile-level per the decomp)
		int				subsystemCount;			// @0x124 (word 0x49)
		Subsystem	  **subsystems;				// @0x128 (word 0x4a)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Recovered internal helpers (engine-internal artifacts in the decomp;
	// declared here so the recovered ctor / integrator compile.  Bodies are
	// reconstructed structurally -- the world/segment/motion plumbing lives in
	// the Entity engine layer).
	//
	protected:
		void	InitSegmentLink(void *link);				// FUN_0041db7c
		void	SetStatusLevel(int level);					// FUN_0041bbd8 (status alarm)
		void   *ResolveWorld(void *app_context);			// owning world / segment system
		void   *ResolveMotionSource(void *app_context);		// FUN_00433ed4
		void	BindModelUpdate(void *callback);			// bind model-update member fn
		void	IntegrateMotion();							// FUN_00421b2c
		void	AdvanceModel(Scalar time_slice);			// FUN_00421bac
		Entity *CollisionQuery(Scalar time_slice);			// FUN_0042291c
		void	Retire();									// FUN_0042061c

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Projectile-specific data appended past the Entity base (offsets best-effort).
	//
	protected:
		void		*world;				// @0x300 (word 0xC0) owning world / segment system
		Segment		*currentSegment;	// @0x304 (word 0xC1) segment node for this cell
		int			segmentIndex;		// @0x308 (word 0xC2) descriptor +0x84
		int			sourceEntity;		// @0x30C (word 0xC3) descriptor +0x88 (firing entity)
		int			sourceWeapon;		// @0x310 (word 0xC4) descriptor +0x8C (firing weapon)
		Point3D		launchPosition;		// @0x314 (word 0xC5) descriptor +0x90
		Vector3D	launchVelocity;		// @0x320 (word 0xC8) descriptor +0x9C
		Vector3D	aimDirection;		// @0x32C (word 0xCB) descriptor +0xA8
		int			modelIndex;			// @0x338 (word 0xCE) descriptor +0xB4 (tracer/LOD model)
		int			damageRecord;		// @0x33C (word 0xCF) descriptor +0xB8 (damage/team id)
	};
#endif
