//===========================================================================//
// File: Entity.hpp                                                          //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 11/29/94  JMA  Initial coding.                                            //
// 08/25/97  JMA  Infrastructure changes												  //
// 08/25/97  ECH	Infrastructure changes												  //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-97, Virtual World Entertainment, Inc.                  //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "Adept.hpp"
#include "Replicator.hpp"
#include "ExecutionState.hpp"
#include "Event.hpp"
#include "NameTable.hpp"
#include "RendererManager.hpp"
#include <ElementRenderer\Element.hpp>

namespace Adept {

	class RendererComponentWeb;
	class Renderer;
	class AttributeEntry;
	class AttributeTable;
	class ModelAttributeEntry;
	class CollisionVolume;
	class DamageObject;

	class Entity;
	class Entity__ClassData;
	class Entity__GameModel;
	class Entity__BecomeInterestingMessage;
	class Entity__CreateMessage;
	class Entity__TakeDamageMessage;
	class Entity__UpdateMessage;

	//##########################################################################
	//##################    Entity::CreateMessage    ###########################
	//##########################################################################

	class Entity__CreateMessage:
		public Replicator__CreateMessage
	{
	public:

#if NSWIZZLE
		ResourceID
			dataListID;
		Stuff::LinearMatrix4D
			localToParent;
		Entity__ExecutionStateEngine::FactoryRequest
			executionState;
		ObjectID
			nameID;
		Stuff::Scalar
			initialAge;
		int
			alignment;
#else
		Stuff::LinearMatrix4D
			localToParent;
		Entity__ExecutionStateEngine::FactoryRequest
			executionState;
		Stuff::Scalar
			initialAge;
		ResourceID
			dataListID;
		int
			alignment;
		ObjectID
			nameID;
#endif

		Entity__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const ResourceID& data_list_id,
			const Stuff::LinearMatrix4D &local_to_parent,
			Stuff::Scalar age,
			int execution_state,
			ObjectID name_id,
			int entity_alignment
		):
			Replicator__CreateMessage(
				length, 
				priority, 
				message_flags, 
				class_id,
				replicator_flags
			),
			dataListID(data_list_id),
			localToParent(local_to_parent),
			initialAge(age),
			executionState(execution_state),
			nameID(name_id),
			alignment(entity_alignment)
				{}

		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//######################    Entity::GameModel    ###########################
	//##########################################################################

	class Entity__GameModel
	{
	public:

#if NSWIZZLE
		Stuff::RegisteredClass::ClassID
			classID;

		ResourceID
			elementResourceID,
			obbStreamResourceID;
		unsigned
			defaultFlags;

		static void
			GetEffectResourceID(ResourceID *return_id, const ResourceID& effect_stream, BYTE index);
		void
			TestInstance() const
				{}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	public:
		typedef int
			AttributeID;
		typedef int 
			Entity__GameModel::*AttributePointer;
		bool
			collider,
			canBeWalkedOn,
			canBeShot,
			waterSurface,
			OBBCollides;
		int
			walkThru;
#else
		bool
			collider,
			canBeWalkedOn,
			canBeShot,
			waterSurface,
			OBBCollides;
		int
			walkThru;
		Stuff::RegisteredClass::ClassID
			classID;

		ResourceID
			obbStreamResourceID,
			elementResourceID;
		unsigned
			defaultFlags;

		static void
			GetEffectResourceID(ResourceID *return_id, const ResourceID& effect_stream, BYTE index);
		void
			TestInstance() const
				{}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	public:
		typedef int
			AttributeID;
		typedef int 
			Entity__GameModel::*AttributePointer;
#endif

		enum 
		{
			AnyAttributeID = 0,
			ColliderAttributeID,
			CanBeWalkedOnAttributeID,
			CanBeShotAttributeID,
			WaterSurfaceAttributeID,
			OBBCollidesAttributeID,
			NextAttributeID
		};

		enum
		{
			MaxStringLength = 256
		};

//		enum
//		{
//			NothingCanWalkThru =0,
//			HeavyCanWalkThru,
//			MediumCanWalkThru,
//			AnythingCanWalkThru
//		}

		static int 
			WalkThruTextToAscii(const char *string);

		ModelAttributeEntry*
			GetAttributeEntry(AttributeID attribute_ID);
		ModelAttributeEntry*
			GetAttributeEntry(const char *attribute_name);

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

		static void
			WriteToText(
				Entity__GameModel *model,
				ModelAttributeEntry *attribute_entry,
				char **text_string
			);

		static void
			SaveGameModel(
				Entity__GameModel *model,
				Stuff::NotationFile *data_file
			);

		typedef bool
			(*ReadAndVerifier)(
				Entity__GameModel *model,
				ModelAttributeEntry *attribute_entry, 
				const char *data,
				char **error,
				int error_buffer = 128
			);
		typedef void
			(*ModelWrite)(
					Entity__GameModel *model,
				ModelAttributeEntry *attribute_entry,
				char **text_string
			);
		typedef void
			(*ModelSave)(
				Entity__GameModel *model,
				Stuff::NotationFile *data_file
			);


		class Script
		{
		public:
			Script(
				Stuff::MemoryStream *model_stream,
				Stuff::NotationFile *model_file,
				Entity__ClassData *model_class_data
			):
				modelStream(model_stream),
				modelFile(model_file),
				modelClassData(model_class_data)
					{}
				
			void
				TestInstance() const
					{}

			Stuff::MemoryStream
				*modelStream;
			Stuff::NotationFile
				*modelFile;
			Entity__ClassData
				*modelClassData;
		};

		typedef void
			(*Factory)(Script *script);
		static void
			ConstructGameModel(Script *script);
		static void
			ConstructOBBStream(Script *script);
	};

	//##########################################################################
	//###########################    Entity    #################################
	//##########################################################################

	typedef Replicator__Message Entity__Message;
	typedef Replicator__DestroyMessage Entity__DestroyMessage;
	class Entity__CollisionQuery;
	class Entity__CollisionData;

	class Entity:
		public Replicator
	{
		friend class Entity__ExecutionStateEngine;
		friend class Entity__ExecutingChildEntityIterator;
		friend class EntityManager;
		friend class Map;
		friend class CollisionGrid;
		friend class Zone;
		friend class CollisionVolume;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Inheritance support
	//
	public:
		typedef Entity__ClassData					ClassData;
		typedef Entity__GameModel					GameModel;
		typedef Entity__CreateMessage				CreateMessage;
		typedef Entity__Message						Message;
		typedef Entity__DestroyMessage				DestroyMessage;
		typedef Entity__UpdateMessage				UpdateMessage;
		typedef Entity__ExecutionStateEngine		ExecutionStateEngine;
		typedef Entity__CollisionQuery				CollisionQuery;
		typedef Entity__CollisionData				CollisionData;
		typedef Entity__TakeDamageMessage			TakeDamageMessage;
		typedef Entity__BecomeInterestingMessage	BecomeInterestingMessage;
		typedef Replicator BaseClass;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
		ClassData*
			GetClassData();
		static ClassData
			*DefaultData;

		static HGOSHEAP
			s_Heap,
			s_CollisionHeap;
		static int
			s_EntitiesSynced;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef Entity*
			(*Factory)(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

		static Entity* 
			Make(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

		Replicator::CreateMessage*
			SaveMakeMessage(Stuff::MemoryStream *stream, ResourceFile *res_file);

		virtual void
			SaveInstanceText(Stuff::Page *page);

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

		virtual void
			SentenceToDeathRow();

		static Entity*
			CreateEntity(
				Stuff::MemoryStream *stream,
				ReplicatorID *base_id,
				bool use_armory=true
			);

		void
			Destroy()				//Never Call this unless you really need to
				{Check_Object(this); delete this;}
			

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Message Support
	//
	public:
		enum {
			UpdateMessageID = Replicator::NextMessageID,
			TakeDamageMessageID,
			BecomeInterestingMessageID,
			NextMessageID
		};

		void
			DestroyMessageHandler(const DestroyMessage *message);
		void
			UpdateMessageHandler(const UpdateMessage *message);
		void
			TakeDamageMessageHandler(const TakeDamageMessage *message);
		void
			BecomeInterestingMessageHandler(const BecomeInterestingMessage *message);

		void
			RequestUpdate(int update_flags);
		virtual UpdateMessage*
			ConstructUpdate(Stuff::MemoryStream *stream);

	protected:
		static const MessageEntry
			MessageEntries[];
		int
			updateFlags;
		Stuff::SlotOf<AbstractEvent*>
			m_pendingInterestMessage;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Flag Support
	//
	public:
		enum 
		{
			PropTypeFlagBit = Replicator::NextFlagBit,
			DirtyMatrixFlagBit = PropTypeFlagBit+2,
			PostCollisionFlagBit,
			InterestLevelFlagBit,
			DirtyZoneFlagBit = InterestLevelFlagBit+2,
			TileBoundFlagBit,
			ColliderFlagBit,
			CanBeWalkedOnFlagBit,
			CanBeShotFlagBit,
			WaterSurfaceFlagBit,
			OBBCollidesFlagBit,
			EditorIsMovingFlagBit,
			WalkThruBit,
			DestroyedFlagBit = WalkThruBit+2,
			ReusableFlagBit,
			DamageDecalFlagBit,
			TriedToMoveOffMapThisFrameFlagBit,
			NextFlagBit
		};

		enum InterestLevel
		{
			DormantInterestLevel	= 0,
			SimulationInterestLevel	= 1<<InterestLevelFlagBit,
			RenderingInterestLevel	= 2<<InterestLevelFlagBit
		};

		enum PropType {
			PlayerPropType			= 0,
			MissionPropType			= 1<<PropTypeFlagBit,
			ArmoryPropType			= 2<<PropTypeFlagBit,
			MapPropType				= 3<<PropTypeFlagBit
		};

		enum WalkThruType {
			NothingCanWalkThruType	= 0,
			HeavyCanWalkThruType	= 1<<WalkThruBit,
			MediumCanWalkThruType	= 2<<WalkThruBit,
			AnythingCanWalkThruType = 3<<WalkThruBit
		};

		enum CollisionMask
		{
			CanBeWalkedOnFlag	= 1<<CanBeWalkedOnFlagBit,
			CanBeShotFlag		= 1<<CanBeShotFlagBit,
			WaterSurfaceFlag	= 1<<WaterSurfaceFlagBit,
			EditorIsMovingFlag	= 1<<EditorIsMovingFlagBit,
			OBBCollidesFlag		= 1<<OBBCollidesFlagBit,

			NeverCollidesMask	= 0,
			WalkerMask			= CanBeWalkedOnFlag|CanBeShotFlag,
			FloaterMask			= CanBeWalkedOnFlag|WaterSurfaceFlag,
			AlwaysCollidesMask	= FloaterMask|WalkerMask|OBBCollidesFlag,
			AllCollisionsMask	= AlwaysCollidesMask|EditorIsMovingFlag
		};

		enum 
		{
			PropTypeMask			= 3<<PropTypeFlagBit,
			DirtyMatrixFlag			= 1<<DirtyMatrixFlagBit,
			PostCollisionFlag		= 1<<PostCollisionFlagBit,
			InterestLevelMask		= 3<<InterestLevelFlagBit,
			DirtyZoneFlag			= 1<<DirtyZoneFlagBit,
			ColliderFlag			= 1<<ColliderFlagBit,
			TileBoundFlag			= 1<<TileBoundFlagBit,

			WalkThruMask			= 3<<WalkThruBit,
			GameModelMask			= ColliderFlag|AlwaysCollidesMask|WalkThruMask,
			DestroyedFlag			= 1<<DestroyedFlagBit,

			ReusableFlag			= 1<<ReusableFlagBit,
			DamageDecalFlag			= 1<<DamageDecalFlagBit,

			TriedToMoveOffMapThisFrameFlag = 1 <<TriedToMoveOffMapThisFrameFlagBit,
			DefaultFlags			= 0
		};

		void
			SetPropType(PropType type)
				{Check_Object(this); replicatorFlags &= ~PropTypeMask; replicatorFlags |= type;}
		PropType
			GetPropType()
				{Check_Object(this); return static_cast<PropType>(replicatorFlags&PropTypeMask);}

		void
			NeedMatrixSync()
				{Check_Object(this); replicatorFlags |= DirtyMatrixFlag;}
		void
			ClearNeedMatrixSync()
				{
					Check_Object(this); Check_Object(entityElement);
					replicatorFlags &= ~DirtyMatrixFlag;
				}
		bool
			IsMatrixDirty()
				{Check_Object(this); return (replicatorFlags&DirtyMatrixFlag) != 0;}

		void
			UsePostCollision()
				{Check_Object(this); replicatorFlags |= PostCollisionFlag;}
		void
			IgnorePostCollision()
				{Check_Object(this); Verify(!newCollisions); replicatorFlags &= ~PostCollisionFlag;}
		bool
			IsUsingPostCollision()
				{Check_Object(this); return (replicatorFlags&PostCollisionFlag) != 0;}

		InterestLevel
			GetInterestLevel()
				{Check_Object(this); return static_cast<InterestLevel>(replicatorFlags&InterestLevelMask);}
		void
			SetInterestMask(InterestLevel type)
				{Check_Object(this); replicatorFlags &= ~InterestLevelMask; replicatorFlags |= type;}
		void
			SetInterestLevel(InterestLevel type);

		bool
			IsACollider()
				{Check_Object(this); return (replicatorFlags & ColliderFlag) != 0;}

		bool
			IsZoneDirty()
				{Check_Object(this); return (replicatorFlags&DirtyZoneFlag) != 0;}

		void
			BindToZone();
		void
			BindToTile();
		bool
			IsTileBound()
				{Check_Object(this); return (replicatorFlags & TileBoundFlag) != 0;}

		CollisionMask
			GetCollisionMask()
				{Check_Object(this); return static_cast<CollisionMask>(replicatorFlags & AllCollisionsMask);}
		virtual void
			SetCollisionMask(CollisionMask mask);
		bool
			CouldCollideWith(int mask)
				{Check_Object(this); return (replicatorFlags & mask & AllCollisionsMask) != 0;}
		bool
			CanBeWalkedOn()
				{Check_Object(this); return (replicatorFlags & CanBeWalkedOnFlag) != 0;}
		bool
			CanBeShot()
				{Check_Object(this); return (replicatorFlags & CanBeShotFlag) != 0;}
		bool
			IsWaterSurface()
				{Check_Object(this); return (replicatorFlags & WaterSurfaceFlag) != 0;}
		bool
			CanOBBCollide()
				{Check_Object(this); return (replicatorFlags & OBBCollidesFlag) != 0;}

		void
			SetWalkThruType(WalkThruType type)
				{Check_Object(this); replicatorFlags &= ~WalkThruMask; replicatorFlags |= type;}
		WalkThruType
			GetWalkThruType()
				{Check_Object(this); return static_cast<WalkThruType>(replicatorFlags&WalkThruMask);}


		bool
			IsDestroyed()
				{Check_Object(this); return (replicatorFlags & DestroyedFlag) !=0;}
		void
			SetDestroyedFlag(int damage_mode);
		void
			ClearDestroyedFlag();
		bool 
			HasTriedToMoveOffMapThisFrameFlag()
			{Check_Object(this); return (replicatorFlags & TriedToMoveOffMapThisFrameFlag) != 0;}
		void
			SetTriedToMoveOffMapThisFrameFlag();
		void
			ClearTriedToMoveOffMapThisFrameFlag();

		bool
			HasPlacedDamageDecal()
				{Check_Object(this); return (replicatorFlags & DamageDecalFlag) !=0;}
		void
			SetDamageDecalFlag()
				{Check_Object(this); replicatorFlags |= DamageDecalFlag;}
		void
			ClearDamageDecalFlag()
				{Check_Object(this); replicatorFlags &= ~DamageDecalFlag;}

		bool
			IsReusable()
				{Check_Object(this); return (replicatorFlags & ReusableFlag) != 0;}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	public:
		typedef int
			AttributeID;
		typedef int 
			Entity::*AttributePointer;

		Stuff::Scalar 
			lightIntensity;

		enum 
		{
			AnyAttributeID = 0,
			ExecutionStateAttributeID,
			LocalToWorldAttributeID,
			IsDestroyedAttributeID,
			VisualRepresentationAttributeID,
			LightIntensityAttributeID, 
			NextAttributeID
		};

		AttributeEntry*
			GetAttributeEntry(AttributeID attribute_ID);
		AttributeEntry*
			GetAttributeEntry(const char *attribute_name);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Resource Support
	//
	public:
		const GameModel*
			GetGameModel()
				{Check_Object(this); return Cast_Pointer(GameModel*, gameModelResource.GetPointer());}
		static void
			GetGameModelResourceFromDataListID(
				Resource *resource,
				const ResourceID &data_list
			);
		static ClassID
			GetClassIDFromDataListID(const ResourceID &data_list);

		const ResourceID&
			GetDataListResourceID()
				{Check_Object(this); return dataListResource.GetResourceID();}

		const char*
			GetModelName()
				{Check_Object(this); return dataListResource.GetName();}

		const char*
			GetGameModelResourceName()
				{Check_Object(this); return (gameModelResource.GetName());}

		Resource*
			GetDataListResource()
				{Check_Object(this); return (&dataListResource);}

		Resource*
			GetGameModelResource()
				{Check_Object(this); return (&gameModelResource);}

		const ResourceID&
			GetGameModelResourceID()
				{Check_Object(this); return gameModelResource.GetResourceID();}

		virtual char *
			GetObjectName()
				{Check_Object(this); return (char *)" ";}

		Stuff::MString
			instanceName;
		ObjectID
			objectID;

	protected:
		Resource
			dataListResource,
			gameModelResource;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Ownership 
	//
	public:
		Entity*
			GetParentEntity()
				{Check_Object(this); return parentEntity;}

		virtual void
			AddChild(Entity *entity);
		virtual void
			RemoveChild(Entity *entity);

		const Stuff::LinearMatrix4D&
			GetLocalToWorld()
				{
					Check_Object(this); Check_Object(entityElement);
					return entityElement->GetLocalToWorld();
				}
		const Stuff::LinearMatrix4D&
			GetLocalToParent()
				{
					Check_Object(this); Check_Object(entityElement);
					return entityElement->GetLocalToParent();
				}

		void
			SetNewLocalToParent(const Stuff::LinearMatrix4D &new_local_to_world);

		//
		// Only use this member for creating iterators in editors, etc.
		// DO NOT use this directly in the game
		//
		Stuff::ChainOf<Entity*>
			childEntityChain;

	protected:
		void
			DeleteChildEntities();

		virtual void
			ChildPreCollisionChanged(Entity *entity);

		Entity
			*parentEntity;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Renderer Support
	//
	public:
		RendererComponentWeb*
			GetComponentWeb(unsigned renderer_id)
				{
					Check_Object(this);
					return componentWebs[renderer_id];
				}
		void
			SetComponentWeb(
				unsigned renderer_id,
				RendererComponentWeb *web
			);

		bool
			m_doesNeedToUpdateWebs;
		void
			ExecuteComponentWebs();
		void
			ExecuteChildComponentWebs();

		virtual void
			BecomeInteresting(bool render_me);
		virtual void
			BecomeUninteresting();

		const ResourceID&
			GetRendererDataResourceID(int renderer_type);

		ElementRenderer::Element*
			GetElement()
				{Check_Object(this); return entityElement;}

	protected:
		RendererComponentWeb*
			componentWebs[RendererManager::RendererTypeCount];
		ElementRenderer::Element
			*entityElement;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	public:
		bool isPlayerVehicle;

		virtual int
			GetExecutionSlot();

		virtual void
			PreCollisionExecute(Stuff::Time till);
		virtual bool
			CollisionHandler(
				Stuff::LinearMatrix4D *new_position,
				Stuff::DynamicArrayOf<CollisionData> *collisions
			);
		virtual void
			SyncMatrices(bool update_matrix);
		virtual void
			SyncMatricesFirstLevelOnly(bool update_matrix);

		virtual void
			PostCollisionExecute(Stuff::Time till);

		virtual int
			GetTableArray()
				{Check_Object(this); return NameTable::CulturalArray;}

		ExecutionStateEngine
			*executionState;

		virtual void
			PlaceOnEntity(
				Stuff::LinearMatrix4D *position,
				Stuff::Motion3D *velocity,
				const Stuff::LinearMatrix4D &initial_offset,
				const Stuff::Motion3D &initial_velocity
			);

		void
			FollowAndBillBoard(
				Stuff::LinearMatrix4D *position,
				Stuff::UnitVector3D *direction
			);

		Stuff::Scalar
			GetTimeParameter(Stuff::Time till)
				{
					Stuff::Scalar slice = static_cast<Stuff::Scalar>(till - lastParameterization);
					return slice;
				}

		Stuff::Scalar
			GetTimeSlice(Stuff::Time till)
				{
					Stuff::Scalar slice = static_cast<Stuff::Scalar>(till - lastExecuted);
					return slice;
				}

		CollisionVolume*
			GetSolidVolume()
				{Check_Object(this); return solidVolume;}
		CollisionVolume*
			GetHierarchicalVolume()
				{Check_Object(this); return hierarchicalVolume;}

		Entity*
			ProjectLine(
				Stuff::Line3D *line,
				CollisionMask mask,
				Stuff::Point3D *target_offset,
				Stuff::Normal3D *normal
			);

		virtual bool
			IsWithin(
				Entity *target,
				Stuff::Scalar distance,
				bool ignorey = false
			);

		Stuff::Scalar
			GetDistanceFrom(Entity *target);

		Stuff::Scalar
			GetDistanceSquaredFrom(Entity *target, bool ignore_y = false);


		Stuff::Time
			lastExecuted,
			lastParameterization;

		Stuff::LinearMatrix4D
			initialLocalToParent;

		enum{
			DefaultAlignment = 0,
			Player,
			Enemy,
			Team1,
			Team2,
			Team3,
			Team4,
			LastAlignment
		};

		virtual int
			GetAlignment() const
				{ return (alignment);	}
		
		void
			SetAlignment(int _alignment)
				{ alignment = _alignment; }

		int
			GetRelativeAlignment(int object_alignment) const
		{
			if (object_alignment == DefaultAlignment)
			{
				return (DefaultAlignment);
			}

			int align = GetAlignment();

			if (align == DefaultAlignment)
			{
				return (DefaultAlignment);
			}

			if (align != object_alignment)
			{
				return (Enemy);
			}

			return (Player);
		}

		static const char *
			AlignmentAsciiToText(int alignment);
		static int
			AlignmentTextToAscii(const char *alignment);

		void SetPlayerVehicle()
		{
			isPlayerVehicle = true;
		}

		bool IsPlayerVehicle()
		{
			return isPlayerVehicle;
		}

		//These are for sensor speed in lookups.  I makes us not have
		//to drill down into entity class structure to check if they can
		//be sensed by sensors.  This is not good practice.  I suck.
		virtual int
			GetSensorMode()
				{return -1;}
		virtual bool
			DoesHaveECM()
				{return false;}
		//
		// NOTE! DO NOT CALL THESE DIRECTLY.  THEY ARE FOR STATE ENGINES!
		//

		virtual void
			EnterNeverExecuteState();
		virtual void
			LeaveNeverExecuteState();

		bool IsMultiTile()
			{Check_Object(this); return minTileRow!=maxTileRow || minTileColumn!=maxTileColumn;}
		bool IsMultiZone()
			{Check_Object(this); return (minTileRow&~7)!=(maxTileRow&~7) || (minTileColumn&~7)!=(maxTileColumn&~7);}

		BYTE GetMinTileRow()
			{Check_Object(this); return minTileRow;}
		BYTE GetMinTileCol()
			{Check_Object(this); return minTileColumn;}
		BYTE GetMaxTileRow()
			{Check_Object(this); return maxTileRow;}
		BYTE GetMaxTileCol()
			{Check_Object(this); return maxTileColumn;}

		void
			RemoveCollision();

		virtual bool IsNeverExecuteState();

		virtual bool				// TEMPORARY until Fang fixes the SlidingShapeComponent NonCom bug -- PAULTOZ
			IsNonCom() const
				{	return (false);	}

	protected:
		CollisionVolume
			*solidVolume,
			*hierarchicalVolume;
		Stuff::DynamicArrayOf<CollisionData>
			*oldCollisions,
			*newCollisions;
		Entity
			*nextPreExecution;

		BYTE
			minTileRow,
			maxTileRow,
			minTileColumn,
			maxTileColumn;

		Entity
			*dontHit;

		int
			alignment;
		bool
			collisionAllowed;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Damage support
	//
	public:

		enum{
			PrestineState = 0,
			DestroyedState,
			PrestineInternalState,
			DestroyedInternalState, 
			PrestineNoneState=0xe,
			DestroyedNoneState=0xf,
			PrestineBothState=0x20,
			DestroyedBothState=0x31
		};

		virtual void
			SetDamageObject(DamageObject *damage_object);
		virtual void
			ReactToHit(const TakeDamageMessage *message,DamageObject *partHit)
				{};
		virtual void
			ReactToInternalDamage(int damage_mode)
				{};
		virtual void
			ReactToDestruction(int damage_mode,int damage_type);
		virtual void
			ReactToDamageTaken(Stuff::Scalar damage_taken, const Adept::ReplicatorID& inflicting_entity, int weaponID, int damageType)
				{};
		virtual bool
			FriendlyFire(const TakeDamageMessage *message);

		void
			NotifyWhoHitMe(const ReplicatorID& inflicting_id, int weap_id)
				{Check_Object(this); m_whoShotMeLast = inflicting_id; m_weaponShotMeLast = weap_id;}

		virtual void
			TakeSplashDamage(Adept::Entity__TakeDamageMessage *message){};

		void
			SetDestroyedRepresentation();
		void
			SetInternalRepresentation();
		void
			SetBothRepresentation();
		void
			SetExternalRepresentation();
		void
			SetNoneRepresentation();

		void
			DestroyChildren(int damage_mode);
		virtual void
			DestroyDamageObjects(){};

		//This is used to have a pointer to the death entity of the object if it is destroyed.
		Stuff::SlotOf<Entity *>
			m_deathEntity;

		void
			ApplyVisualDamage(const TakeDamageMessage *message, int armor_zone);

		virtual bool
			IsDestroyable();

		DamageObject
			*damageObject;
		int
			isDestroyed;
		int
			visualRepresentation;
		ReplicatorID
			m_whoShotMeLast;
		int
			m_weaponShotMeLast;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network Damage support
	//
		int
			damageBit;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test support
	//
	public:
		void
			TestInstance();
	};
	
	//##########################################################################
	//############    Entity::TakeDamageMessage     ############################
	//##########################################################################

	class Entity__TakeDamageMessage:
		public Entity__Message
	{
	public:
		Stuff::Scalar amountOfDamage;
		int amountOfModifier;
		ReplicatorID inflictingEntityID;
		char typeOfDamage;
		Stuff::Normal3D normal;
		Stuff::Point3D hitOffset;
		Stuff::Scalar amountOfHeat;
		bool quickDamage;
		int weaponID;

	public:
		enum {DefaultWeaponType=-1};

		Entity__TakeDamageMessage(
			const ReplicatorID &receiving_entity_id,
			const ReplicatorID &inflicting_entity_id,
			Stuff::Scalar damage_amount,
			int damage_modifier,
			char type_of_damage,
			const Stuff::Normal3D& hit_normal,
			const Stuff::Point3D& hit_offset,
			Stuff::Scalar heat_amount,
			bool quick_damage,
			int weapon_id
		):
			Entity__Message(
				Entity::TakeDamageMessageID, 
				sizeof(*this),
				Adept::DefaultEventPriority, 
				DefaultFlags,
				receiving_entity_id
			)
				 , normal(hit_normal)
				 , hitOffset(hit_offset)
				{
					inflictingEntityID = inflicting_entity_id;
					amountOfDamage = damage_amount;
					amountOfModifier = damage_modifier;
					typeOfDamage = type_of_damage;
					amountOfHeat = heat_amount;
					quickDamage = quick_damage;
					weaponID = weapon_id;
				}
	};

	//##########################################################################
	//############    Entity::UpdateMessage     ################################
	//##########################################################################

	class Entity__UpdateMessage:
		public Entity__Message
	{
	public:
		Stuff::LinearMatrix4D
			localToParent;

		Entity__UpdateMessage(
			const ReplicatorID &replicator_id,
			const Stuff::LinearMatrix4D& local_to_parent
		):
			Entity__Message(
				Entity::UpdateMessageID, 
				sizeof(*this),
				Adept::DefaultEventPriority, 
				DefaultFlags,
				replicator_id
			),
			localToParent(local_to_parent)
				{}
	};

	//##########################################################################
	//########    Entity::BecomeInterestingMessage     #########################
	//##########################################################################

	class Entity__BecomeInterestingMessage:
		public Entity__Message
	{
	public:
		bool m_render;

		Entity__BecomeInterestingMessage(
			const ReplicatorID &replicator_id,
			bool render
		):
			Entity__Message(
				Entity::BecomeInterestingMessageID, 
				sizeof(*this),
				Adept::DefaultEventPriority, 
				DefaultFlags,
				replicator_id
			),
			m_render(render)
				{}
	};

	//##########################################################################
	//#######################    Attribute Macros     ##########################
	//##########################################################################

	//
	// class name, attribute name, attribute, type
	//
	#define DIRECT_ATTRIBUTE(c,n,a,t)\
		{\
			AttributeEntry *attribute_entry;\
			attribute_entry = new DirectAttributeEntryOf<t, t##ClassID>(\
				c::n##AttributeID,\
				#n,\
				reinterpret_cast<Entity::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->attributeTable.AddAttributeEntry(attribute_entry);\
		}

	//
	// class name, attribute name, attribute, type, class id
	//
	#define CUSTOM_DIRECT_ATTRIBUTE(c,n,a,t,id)\
		{\
			AttributeEntry *attribute_entry;\
			attribute_entry = new DirectAttributeEntryOf<t, id>(\
				c::n##AttributeID,\
				#n,\
				reinterpret_cast<Entity::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->attributeTable.AddAttributeEntry(attribute_entry);\
		}

	//
	// class name, attribute name, attribute, type
	//
	#define INDIRECT_ATTRIBUTE(c,n,a,t)\
		{\
			AttributeEntry *attribute_entry;\
			attribute_entry = new IndirectAttributeEntryOf<t, t##ClassID>(\
				c::n##AttributeID,\
				#n,\
				reinterpret_cast<Entity::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->attributeTable.AddAttributeEntry(attribute_entry);\
		}

	//
	// class name, attribute name, attribute, type
	//
	#define DIRECT_STATE_ATTRIBUTE(c,n,a,t)\
		{\
			AttributeEntry *attribute_entry;\
			attribute_entry = new DirectStateAttributeEntry(\
				c::n##AttributeID,\
				#n,\
				t##ClassID,\
				reinterpret_cast<Entity::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->attributeTable.AddAttributeEntry(attribute_entry);\
		}

	//
	// class name, attribute name, attribute, type
	//
	#define INDIRECT_STATE_ATTRIBUTE(c,n,a,t)\
		{\
			AttributeEntry *attribute_entry;\
			attribute_entry = new IndirectStateAttributeEntry(\
				c::n##AttributeID,\
				#n,\
				t##ClassID,\
				reinterpret_cast<Entity::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->attributeTable.AddAttributeEntry(attribute_entry);\
		}

	//##########################################################################
	//##################    Game Model Attribute Macros     ####################
	//##########################################################################

	//
	// class name, attribute name, attribute, type
	//
	#define DIRECT_GAME_MODEL_ATTRIBUTE(c,n,a,t)\
		{\
			ModelAttributeEntry *attribute_entry;\
			attribute_entry = new DirectModelAttributeEntryOf<t, t##ClassID>(\
				c::n##AttributeID,\
				#n,\
				reinterpret_cast<Entity__GameModel::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->gameModelAttributeTable.AddAttributeEntry(attribute_entry);\
		}

	//
	// class name, attribute name, attribute, type, class id
	//
	#define CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(c,n,a,t,id)\
		{\
			ModelAttributeEntry *attribute_entry;\
			attribute_entry = new DirectModelAttributeEntryOf<t, id>(\
				c::n##AttributeID,\
				#n,\
				reinterpret_cast<Entity__GameModel::AttributePointer>(\
					reinterpret_cast<int c::*>(&c::a)\
				)\
			);\
			Register_Object(attribute_entry);\
			Check_Object(DefaultData);\
			DefaultData->gameModelAttributeTable.AddAttributeEntry(attribute_entry);\
		}

	//##########################################################################
	//###########################    Entity    #################################
	//##########################################################################

	class Entity__CollisionQuery:
		public ElementRenderer::CollisionQuery
	{
	public:
		Entity
			*m_raySource;
		Entity::CollisionMask
			m_collisionMask;

		Entity__CollisionQuery(
			Stuff::Line3D *l,
			Stuff::Normal3D *n,
			Entity::CollisionMask m,
			Entity *source
		):
			ElementRenderer::CollisionQuery(l, n),
			m_raySource(source),
			m_collisionMask(m)
				{}
	};

	class Entity__CollisionData
		#if defined(_ARMOR)
			: public Stuff::Signature
		#endif
	{
	public:
		CollisionVolume
			*m_volume,
			*m_otherVolume;
		Entity
			*m_otherEntity;
		Stuff::Point3D m_worldIntersectionPoint;
		Stuff::Normal3D m_normal;
		Stuff::Normal3D m_otherNormal;
		Stuff::Scalar m_timeSlice;
		BYTE
			m_material;

		void
			TestInstance() const
				{}
	};

}


