//===========================================================================//
// File:     exptbl.hpp                                                      //
// Title:    Declaration of ExplosionTable, ExplosionTableEntry              //
// Project:  BattleTech                                                      //
// Purpose:  A Structure To hold Explosion Information for An entity 		  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 11/23/95  JM	Initial Coding                                             //
//===========================================================================//

#if !defined (EXPTBL_HPP)
#	define EXPTBL_HPP

#	if !defined (PLUG_HPP)
#		include <plug.hpp>
#	endif

#	if !defined (TABLE_HPP)
#		include <table.hpp>
#	endif

#	if !defined (RESOURCE_HPP)
#		include <resource.hpp>
#	endif

#	if !defined(ENTITYID_HPP)
#		include <entityid.hpp>
#	endif

#	if !defined(CMPNNT_HPP)
#		include <cmpnnt.hpp>
#	endif

	class Entity;
	class NotationFile;
	class Point3D;

	//##############################################################################
	//######################   Class ExplosionTableEntry    ########################
	//##############################################################################

	class ExplosionTableEntry : public Plug
	{

		protected:

			Scalar
				damageLevel;

			Enumeration
				graphicState;

			ResourceDescription::ResourceID
				explosionResourceID;

			Scalar
				timeDelay;

		public:

			ExplosionTableEntry(MemoryStream *exp_stream);
			~ExplosionTableEntry();

			static Logical
				CreateStreamedExplosion(
					ResourceFile	*resource_file,
					CString			exp_file_name,
					NotationFile 	*exp_file,
					CString        exp_page_name,
					MemoryStream	*explosion_stream
				);

			ResourceDescription::ResourceID
				GetExplosionResourceID() const
			{Check(this); return explosionResourceID;}

			Scalar
				GetDamageLevel() const
			{Check(this); return damageLevel;}

			Enumeration
				GetGraphicState() const
			{Check(this); return graphicState;}

			Scalar
				GetTimeDelay() const
			{Check(this); return timeDelay;}

			void
				CreateExplosion(
					const EntityID	&entity_hit_ID,
					const EntityID	&creating_entity_ID,
					const Point3D	&explode_position
				);
	};

	//##############################################################################
	//########################   Class ExplosionTable    ###########################
	//##############################################################################

	// (Although sharing instance not fully implemented yet!)
	// Note: Explosion tables specifically do not hold any references to any
	// specific damage Zone as you will most likely be sharing instances of
	// explosion tables across entity's, subsystem's, etc..
	//
	class ExplosionTable : public TableOf<ExplosionTableEntry*, int>
	{
		protected:

			typedef
				TableIteratorOf<ExplosionTableEntry*, int>
					ExplosionTableIterator;

		public:

			ExplosionTable(MemoryStream *exp_stream);
			~ExplosionTable();

			ExplosionTableEntry*
				SelectDamageLevelEntry(Scalar damage_level);

			ExplosionTableEntry*
				SelectGraphicStateEntry(Enumeration graphic_state);

			void
				DamageExplosion(
					const EntityID	&entity_hit_ID,
					const EntityID	&creating_entity_ID,
					Scalar damage_level,
					const Point3D &explode_position
				)
			{
				Check(this);
				ExplosionTableEntry *exp_entry = SelectDamageLevelEntry(damage_level);
				if (exp_entry)
				{
					CreateExplosion(
						exp_entry,
						entity_hit_ID,
						creating_entity_ID,
						explode_position
					);
				}
				#if DEBUG_LEVEL>0
				else
				{
					Tell("DamageLevel = ");
					Tell(damage_level);
					Warn("not valid for ExplosionTable, no Explosion being created !\n");
				}
				#endif
			}

			void
				CreateExplosion(
					ExplosionTableEntry	*explosion_entry,
					const EntityID	&entity_hit_ID,
					const EntityID	&creating_entity_ID,
					Point3D	explode_position	// world coordinates
				);

			void
				GraphicStateExplosion(
					const EntityID &entity_hit_ID,
					const EntityID &creating_entity_ID,
					const Point3D &explode_position,
					Enumeration	graphic_state
				)
			{
				Check(this);
				ExplosionTableEntry *exp_entry = SelectGraphicStateEntry(graphic_state);
				if (exp_entry)
				{
					CreateExplosion(
						exp_entry,
						entity_hit_ID,
						creating_entity_ID,
						explode_position
					);
				}
				#if DEBUG_LEVEL>0
				else
				{
					Tell("DamageZone::GraphicState = ");
					Tell(graphic_state);
					Warn("not valid for ExplosionTable, no Explosion being created !\n");
				}
				#endif
			}

			Logical
				CrossedDamageLevelThreshold(Scalar old_value, Scalar new_value);

			static Logical
				CreateStreamedExplosionTable(
					ResourceFile	*resource_file,
					CString			model_name,
					NotationFile	*exp_file,
					CString			exp_filename,
					MemoryStream	*explosion_stream
				);
	};
	
	//##########################################################################
	//######################    EntityEffectWatcher    #########################
	//##########################################################################

	class EntityEffectWatcher :
		public Component
	{
		protected:

			Scalar
				*oldDamageLevel;

			Entity
				*entityWatched;

		public:

			EntityEffectWatcher(
				Entity 	*entity_watched
			);

			~EntityEffectWatcher();


			Logical
				TestInstance() const;

         void
				Execute();

	};
#endif
