//===========================================================================//
// File:	WeaponMover.hpp														
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 09/09/98  JSE  Inital base class based off of Shadowrun/Adept                   
// 09/25/98  BDB  Inital WeaponMover class based off of Vehicle 
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "MW4.hpp"

#include <Adept\Mover.hpp>

namespace Adept {class Effect;}


namespace MechWarrior4
{	
	class Adept::Effect;
	class MWObject;


	void WeaponMoverSecurityCheckStart();
	void WeaponMoverSecurityCheckStop();

	
	//##########################################################################
	//##################    WeaponMover::CreateMessage    ######################
	//##########################################################################

	class WeaponMover__CreateMessage:
		public Adept::Mover__CreateMessage
	{
	public:
		Stuff::Scalar
			damageAmount;
		Stuff::Scalar
			maxDistance;
// MSL 5.03 Min Distance
//		Stuff::Scalar
//			minDistance;
		Adept::ReplicatorID
			inflictingEntityID;
		Stuff::Scalar
			heatAmount;
		Stuff::Scalar 
			splashRadius;
		Stuff::Scalar
			percentageOfDamageToDirectHit;
		Stuff::Scalar
			minPercentageOfDamageToSphereHit;
		Stuff::Scalar
			maxPercentageOfDamageToSphereHit;
		int
			itemID;

		WeaponMover__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const ResourceID& instance_id,
			const Stuff::LinearMatrix4D &creation_matrix,
			Stuff::Scalar age,
			int execution_state,
			int name_id,
			int entity_alignment,
			const Stuff::Motion3D &initial_velocity,
			const Stuff::Motion3D &initial_acceleration,
			Stuff::Scalar damage_amount,
			Stuff::Scalar heat_amount,
			Stuff::Scalar max_distance,
// MSL 5.03 Min Distance
//			Stuff::Scalar min_distance,
			Adept::ReplicatorID inflicting_id,
			Stuff::Scalar splash_radius,
			Stuff::Scalar percentage_damage_direct_hit,
			Stuff::Scalar min_percentage_damage_sphere,
			Stuff::Scalar max_percentage_damage_sphere,
			int item_id
		):
			Adept::Mover__CreateMessage(
				length, 
				priority, 
				message_flags, 
				class_id, 
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment,
				initial_velocity,
				initial_acceleration
			),
				damageAmount(damage_amount),
				maxDistance(max_distance),
// MSL 5.03 Min Distance
//				minDistance(min_distance),
				inflictingEntityID(inflicting_id),
				heatAmount(heat_amount),
				splashRadius(splash_radius),
				percentageOfDamageToDirectHit(percentage_damage_direct_hit),
				minPercentageOfDamageToSphereHit(min_percentage_damage_sphere),
				maxPercentageOfDamageToSphereHit(max_percentage_damage_sphere),
				itemID(item_id)
				{}
	};

	//##########################################################################
	//######################   WeaponMover::GameModel    #######################
	//##########################################################################

	class WeaponMover__GameModel:
		public Adept::Mover__GameModel
	{
	public:
		Adept::ResourceID
			hitEffectMaterialTable;
		Adept::ResourceID
			secondaryHitEffectMaterialTable;
		Adept::ResourceID
			secondaryHitEffectResourceID;
		Adept::ResourceID
			hitEffectResourceID;
		Adept::ResourceID
			damageDecalResourceID;
		Stuff::Scalar
			maxDistance;
// MSL 5.03 Min Distance
//		Stuff::Scalar
//			minDistance;
		Adept::ResourceID
			trailResource;
		bool
			doesPlaceCrater;
		int
			m_craterID;
		Stuff::Scalar
			m_lightAmpFlareOut;		
		

		enum {
			MaxDistanceAttributeID = WeaponMover__GameModel::NextAttributeID,
// MSL 5.03 Min Distance
//			MinDistanceAttributeID,
			TrailResourceAttributeID,
			DoesPlaceCraterAttributeID,
			HitEffectResourceAttributeID,
			SecondaryHitEffectResourceAttributeID,
			DamageDecalResourceAttributeID,
			LightAmpFlareOutAttributeID,
			NextAttributeID
		};

		static bool
			ReadAndVerify(
				WeaponMover__GameModel *model,
				ModelAttributeEntry *attribute_entry, 
				const char *data,
				char **error,
				int error_buffer = 128
			);

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//############################    WeaponMover    ###########################
	//##########################################################################

	//-------------------------------------------------------------------------
	// The following helper classes must always be typedef'd or overriden by an
	// inheritor
	//
	typedef Adept::Mover__ExecutionStateEngine			WeaponMover__ExecutionStateEngine;
	typedef Adept::Mover__ClassData						WeaponMover__ClassData;
	typedef Adept::Mover__Message						WeaponMover__Message;
	
	extern DWORD Executed_WeaponMover_Count;

	//-----------------------  End of inheritance stuff ------------------------

	class WeaponMover:
		public Adept::Mover
	{
		friend class MovementClass;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Adept::Mover BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef WeaponMover__ClassData						ClassData;
		typedef WeaponMover__GameModel						GameModel;
		typedef WeaponMover__Message						Message;
		typedef WeaponMover__ExecutionStateEngine			ExecutionStateEngine;
		typedef WeaponMover__CreateMessage					CreateMessage;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static WeaponMover* 
			Make(
				CreateMessage *message,
				ReplicatorID *base_id
			);
		WeaponMover(
			ClassData *class_data,
			CreateMessage *message,
			ReplicatorID *base_id,
			ElementRenderer::Element *element
		);

		~WeaponMover();

		void
			Reuse(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

		void
			SentenceToDeathRow();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Flag Support
	//
	public:
		enum 
		{
			DefaultFlags = HermitMode
		};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Game Model support
	//
	public:
		const GameModel*
			GetGameModel()
				{return Cast_Pointer(const GameModel*, gameModelResource.GetPointer());}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	public:
		int
			GetExecutionSlot();

		void
			PreCollisionExecute(Stuff::Time till);
		#if defined(LAB_ONLY)
			void
				SyncMatrices(bool update_matrix);
		#endif
		bool
			CollisionHandler(
				Stuff::LinearMatrix4D *new_position,
				Stuff::DynamicArrayOf<CollisionData> *collisions
			);
		void
			PostCollisionExecute(Stuff::Time till);
		virtual void
			PostCollision(Stuff::DynamicArrayOf<CollisionData> *collisions);
		virtual void
			BlowUpIfOffMap();
		void
			CreateMissileTrail();
		char
			GetDamageType();

		void
			CreateHitEffect(
				Normal3D normal,
				Point3D target_point,
				BYTE hit_material
			);
		void
			CreateSecondaryHitEffect(
				Normal3D normal,
				Point3D target_point,
				BYTE hit_material,
				Adept::Entity *entity_hit
			);
		void
			CreateDamageDecal(
			Adept::Entity *hit_entity,
				Normal3D normal,
				Point3D target_point
			);

		Stuff::SlotOf<Adept::Effect*>
			trailEffect;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
      		TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Movement vars and methods
	public:
		Stuff::Point3D 
			startPoint;
		
		Stuff::Scalar
			maxDistance;
	
// MSL 5.03 Min Distance
//		Stuff::Scalar
//			minDistance;
	
		Stuff::Scalar
			damageAmount;

		Stuff::Scalar
			heatAmount;

		Adept::ReplicatorID
			inflictingEntityID;

		MWObject*
			inflictingVehicle;

		int itemID;

// MSL 5.06 Armor Mode
		int m_ArmorMode;

		ChainOf<Entity *>
			splashedEntities;

		int 
			splashSize;

		

		Stuff::Scalar 
			splashRadius;
		Stuff::Scalar
			percentageOfDamageToDirectHit;
		Stuff::Scalar
			minPercentageOfDamageToSphereHit;
		Stuff::Scalar
			maxPercentageOfDamageToSphereHit;


		virtual void DealSplashDamage(const CollisionData *data);
		static void SplashCallBack(Entity *entity, Entity *original_enitiy, const Stuff::Sphere &sphere);
		static void SubSplashCallBack(CollisionVolume *solid, Entity *original_enitiy, const Stuff::Sphere &sphere);



	};
}
