//===========================================================================//
// File:	Armor.hpp														 //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/19/01  MSL  Added StandardArmor                                        //
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "MW4.hpp"
#include "Subsystem.hpp"

#include <Adept\DamageObject.hpp>

namespace MechWarrior4
{
	class Mech;

	//##########################################################################
	//##################    Armor::CreateMessage    ############################
	//##########################################################################

	class Armor__CreateMessage:
		public Subsystem__CreateMessage
	{
	public:
		typedef Subsystem__CreateMessage BaseClass;
	
		Stuff::Scalar
			m_leftLegArmor,
			m_rightLegArmor,
			m_leftArmArmor,
			m_rightArmArmor,
			m_leftFrontTorsoArmor,
			m_rightFrontTorsoArmor,
			m_centerFrontTorsoArmor,
			m_centerRearTorsoArmor,
			m_headArmor;
		int
			m_armorType,
			m_internalType;
			
		Armor__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,
			int subsystem_index,
			BYTE location_id,
			int critical_hits,
			Stuff::Scalar left_leg,
			Stuff::Scalar right_leg,
			Stuff::Scalar left_arm,
			Stuff::Scalar right_arm,
			Stuff::Scalar left_front,
			Stuff::Scalar right_front,
			Stuff::Scalar center_front,
			Stuff::Scalar center_rear,
			Stuff::Scalar head,
			int armor_type,
			int internal_type
		):
			Subsystem__CreateMessage(
				length, 
				priority, 
				message_flags, 
				class_id, 
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment,
				subsystem_index,
				location_id,
				critical_hits
			),
				m_leftLegArmor(left_leg),
				m_rightLegArmor(right_leg),
				m_leftArmArmor(left_arm),
				m_rightArmArmor(right_arm),
				m_leftFrontTorsoArmor(left_front),
				m_rightFrontTorsoArmor(right_front),
				m_centerFrontTorsoArmor(center_front),
				m_centerRearTorsoArmor(center_rear),
				m_headArmor(head),
				m_armorType(armor_type),
				m_internalType(internal_type)
			{
			}
			

		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//###########################   Weapon GameModel    ########################
	//##########################################################################

	class Armor__GameModel;

	typedef Subsystem__ClassData							Armor__ClassData;
	typedef Subsystem__Message								Armor__Message;
	typedef Subsystem__ExecutionStateEngine					Armor__ExecutionStateEngine;
	
	class Armor__GameModel:
		public Subsystem::GameModel
	{
	public:
		typedef Subsystem::GameModel BaseClass;

		Stuff::Scalar
			m_armDistributive,
			m_legDistributive,
			m_sideFrontDistributive,
			m_centerFrontDistributive,
			m_sideRearDistributive,
			m_centerRearDistributive;

		int
// MSL 5.00 Armor
			m_pointsPerStandardTon,
			m_pointsPerFerroTon,
			m_pointsPerReflectiveTon,
			m_pointsPerReactiveTon,
			m_pointsPerSolarianTon;

		enum {
			ArmDistributiveAttributeID = Subsystem__GameModel::NextAttributeID,
			LegDistributiveAttributeID,
			SideFrontDistributiveAttributeID,
			CenterFrontDistributiveAttributeID,
			CenterRearDistributiveAttributeID,
// MSL 5.00 Armor
			PointsPerStandardTonAttributeID,
			PointsPerFerroTonAttributeID,
			PointsPerReflectiveTonAttributeID,
			PointsPerReactiveTonAttributeID,
			PointsPerSolarianTonAttributeID,
			NextAttributeID
		};

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


		static void
			ConstructGameModel(Script *script);

		//This is used for Debugging purposes and can eventually be removed
		//when desgin is done tweaking armor paramters
		Stuff::Scalar
			m_totalArmorDistribution;
	};

	//##########################################################################
	//###########################   Armor   ####################################
	//##########################################################################
	class Armor:
		public Subsystem
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Subsystem BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef Armor__ClassData							ClassData;
		typedef Armor__GameModel							GameModel;
		typedef Armor__Message								Message;
		typedef Armor__ExecutionStateEngine					ExecutionStateEngine;
		typedef Armor__CreateMessage						CreateMessage;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static Armor* 
			Make(
				CreateMessage *message,
				ReplicatorID *base_id
			);
		
		Adept::Replicator::CreateMessage*
			SaveMakeMessage(Stuff::MemoryStream *stream, Adept::ResourceFile *res_file);

		void
			SaveInstanceText(Stuff::Page *page);

		static void
			CreateStream(
				Adept::ResourceID data_list,
				Stuff::MemoryStream *stream
			);

	protected:
		Armor(
			ClassData *class_data,
			CreateMessage *message,
			ReplicatorID *base_id,
			ElementRenderer::Element *element
		);

		~Armor();

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

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		void 
			InitializeDamageObjectsWithArmor();
		bool
			ConnectSubsystem();

		enum{
// MSL 5.00 Armor
//			FerroFiberusArmor = 0,
			StandardArmor = 0,
			FerroFiberusArmor,
			ReactiveArmor,
			ReflectiveArmor,
			SolarianArmor
		};

		int
			m_armorMultiplier;

		static const char*
			ArmorTypeAsciiToText(int armor_type);
		static int
			ArmorTypeTextToAscii(const char *armor_type_string);

		enum{
			StandardInternal = 0,
			EndoSteelInternal
		};

		static const char*
			InternalTypeAsciiToText(int internal_type);
		static int
			InternalTypeTextToAscii(const char *internal_type_string);

		int
			GetTotalArmor()
				{Check_Object(this); return (int)m_totalArmor;}
		Stuff::Scalar
			GetTotalTonage()
				{Check_Object(this); return m_totalTonage;}
		Stuff::Scalar
			GetArmorValue(int index)
				{Check_Object(this); return m_armorZoneValues[index];}
		int
			GetArmorType()
				{Check_Object(this); return m_armorType;}
		int
			GetInternalType()
				{Check_Object(this); return m_internalType;}
		int
			SetArmorType(int new_type);

	protected:
		Stuff::Scalar
			m_armorZoneValues[Adept::DamageObject::HeadArmorZone + 1];

		int
			m_armorType,
			m_internalType;
		Stuff::Scalar 
			m_totalArmor,
			m_totalTonage;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Mech Lab support
	//
	public:
		bool 
			ApplyDistributiveArmor();
		bool
			ApplyZoneBasedArmor(int armor_zone, Stuff::Scalar armor_amount);
		bool
			SetZoneBasedArmor(int armor_zone, Stuff::Scalar armor_amount);

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


