//============================================================================//
// File:	mislanch.hpp                                                          //
// Project: BattleTech																			//
// Contents: Weapon Which Launches a missile                                   //
//			Derived From Projectile Weapon                                       //
//----------------------------------------------------------------------------//
//   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
// @004bcff0-@004bd08c in part_013.c) cross-referenced HEAVILY against the
// SURVIVING MISLANCH.HPP and the reconstructed mechweap.hpp base.  The class
// declaration below is the surviving header; the only additions are the byte
// offsets observed in the decompiled object (see mislanch.cpp for @ADDRs).
//
// Inheritance chain established from the decomp:
//      MechWeapon (mechweap.cpp, vtable @00511d2c)
//        -> ProjectileWeapon (ctor @004bc3fc, vtable @0051242c)   ammo/jam/tracer
//             -> MissileLauncher (ctor @004bcff0, vtable @00512570)
//
// The MissileLauncher ctor (@004bcff0) chains ProjectileWeapon::ProjectileWeapon
// (@004bc3fc), installs PTR_FUN_00512570, then reads the two launcher-specific
// resource fields MissileCount (+0x1d0) and MuzzleVelocity (+0x1d4, Vector3D)
// and divides the configured damage by missileCount (per-missile damage).
//

#if !defined (MISLANCH_HPP)
#	define	MISLANCH_HPP

#	if !defined(PROJWEAP_HPP)
#		include <projweap.hpp>
#	endif


class Missile;

//#################   MissileLauncher  SubsystemResource    ###################
//
// Extends the ProjectileWeapon resource.  Parsed by CreateStreamedSubsystem
// @004bd08c (which chains ProjectileWeapon::CreateStreamedSubsystem @004bc7cc).
// Record offsets are relative to the streamed subsystem record:
//      +0x1d0  "MissileCount"    int
//      +0x1d4  "MuzzleVelocity"  Vector3D (3 floats)
//
	struct MissileLauncher__SubsystemResource:
		public ProjectileWeapon::SubsystemResource
	{
		int missileCount;			// +0x1d0  "MissileCount"

		Vector3D
      	muzzleVelocity;			// +0x1d4  "MuzzleVelocity"
	};


//###########################################################################
//#################     CLASS -- MissileLauncher    ##########################
//###########################################################################
//
//	(vtable @00512570, ctor @004bcff0, dtor @004bd060.)
//
	class MissileLauncher:
		public ProjectileWeapon
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Messaging Support
	//

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	public:
		static Derivation ClassDerivations;
		static Receiver::MessageHandlerSet MessageHandlers;
		static AttributeIndexSet AttributeIndex;
		static SharedData DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//

   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Damage Support
	//
	public:
		void TakeDamage(Damage &damage);		// inherits MechWeapon::TakeDamage (vtable slot 6, @004b964c)
		void DeathReset(Logical full_reset);	// best-effort -- chains ProjectileWeapon reset @004bbaf8

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Model Support
	//
	public:

		typedef void
			(MissileLauncher::*Performance)(Scalar time_slice);

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


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:

		typedef	MissileLauncher__SubsystemResource SubsystemResource;
		MissileLauncher(									// @004bcff0
			Mech	*owner,
			int subsystem_ID,
			SubsystemResource	*subsystem_resource,
         SharedData &default_data = DefaultData
		);
		~MissileLauncher();									// @004bd060

		Logical
			TestInstance() const;

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


// local stuff
	protected:

		// @004bcc60 (ProjectileWeapon spawn path) -- builds the streamed-entity
		// spawn descriptor for a Missile (entity ClassID 0xBD0), seeds it with
		// muzzleVelocity + the per-missile Damage, and hands it to the entity
		// manager.  Invoked missileCount times per trigger pull.
		void
			FireWeapon();

		// The ONLY own field: missileCount@0x448 (ctor param_1[0x112]).  The former
		// salvoCount@0x3d4 was a SHADOW of the inherited MechWeapon damageData.burstCount
		// (@0x3A8+0x2C), and muzzleVelocity@0x410 an ALIAS of the inherited ProjectileWeapon
		// launchVelocity -- both re-declared as own members put them at wrong (appended)
		// offsets; removed.  Object ends 0x44C.
		int		missileCount;	// @0x448 (this[0x112]) -- how many missiles per salvo (LAST field)

		friend struct MissileLauncherLayoutCheck;
	};

	struct MissileLauncherLayoutCheck {
		static_assert(offsetof(MissileLauncher, missileCount) == 0x448, "MissileLauncher::missileCount @0x448 (ProjectileWeapon must end 0x448)");
		static_assert(sizeof(MissileLauncher)                 == 0x44C, "sizeof(MissileLauncher) 0x44C (== factory alloc)");
	};
#endif
