
#include "MW4Headers.hpp"

#include "BeamEntity.hpp"
#include <Adept\EntityClassData.hpp>
#include "MWPlayer.hpp"
#include "VehicleInterface.hpp"
#include <Adept\Effect.hpp>
#include <Adept\Map.hpp>
#include "MWMover.hpp"
#include "MWObject.hpp"
#include <Adept\NameTable.hpp>
#include "Decal.hpp"
#include "MWDamageObject.hpp"
#include <Adept\CollisionGrid.hpp>
#include <Adept\VideoRenderer.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Site.hpp>
#include "mwmission.hpp"
#include "bucket.hpp"
#include "MWApplication.hpp"

//#############################################################################
//###############################    BeamEntity    ############################
//#############################################################################

BeamEntity::ClassData*
	BeamEntity::DefaultData = NULL;

DWORD MechWarrior4::Executed_Beam_Count = 0;

#define HUNT_ADD_EFFECT_BUG

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			BeamEntityClassID,
			"MechWarrior4::BeamEntity",
			BaseClass::DefaultData,
			0, NULL,
			(Entity::Factory)Make,
			NULL,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			NULL,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);

	CUSTOM_DIRECT_ATTRIBUTE(
		BeamEntity,
		BeamDistance,
		beamDistanceAttribute,
		Scalar,
		ScalarClassID
	);

	CUSTOM_DIRECT_ATTRIBUTE(
		BeamEntity,
		TargetPoint,
		targetPoint,
		Point3D,
		Point3DClassID
	);

	CUSTOM_DIRECT_ATTRIBUTE(
		BeamEntity,
		BeamHitSFX,
		beamHitSFX,
		int,
		IntClassID
	);

	CUSTOM_DIRECT_ATTRIBUTE(
		BeamEntity,
		BeamStatus,
		beamStatus,
		bool,
		BoolClassID
	);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		BeamEntity__GameModel,
		HitEffectResource,
		hitEffectResourceID,
		ResourceID
	);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		BeamEntity__GameModel,
		DamageDecalResource,
		damageDecalResourceID,
		ResourceID
	);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BeamEntity*
	BeamEntity::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	gos_PushCurrentHeap(Heap);
	Check_Object(EntityManager::GetInstance());
	BeamEntity *new_entity;
	Entity *entity = EntityManager::GetInstance()->RequestFromArmory(message->dataListID);
	if (entity)
	{
		new_entity = Cast_Object(BeamEntity*, entity);
		new_entity->Reuse(message, base_id);
	}
	else
		new_entity = new BeamEntity(DefaultData, message, base_id, NULL);
	gos_PopCurrentHeap();
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BeamEntity::BeamEntity(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	Entity(class_data, message, base_id, element),
	siteEntity(NULL),
	targetEntity(NULL)
{
	Check_Pointer(this);
	Check_Object(message);
	Check_Object(Connection::Local);

	inflictingEntityID = message->inflictingEntityID;

	if (MWApplication::GetInstance()->networkingFlag == true)
	{
		MWMission *mission;
		Check_Object (MWMission::GetInstance());
		mission = Cast_Object (MWMission *,MWMission::GetInstance());
		mission->m_BucketManager->NotifyAction (CBucketManager::SHOTS_FIRED,inflictingEntityID,1);
	}

	// find the entity and connect to it
	Check_Object(Network::GetInstance());
	Connection	*connection = Network::GetInstance()->GetConnection(inflictingEntityID.connectionID);
	Check_Object(connection);

	Replicator *replicator;
	replicator = connection->FindReplicator(inflictingEntityID);

	Verify(replicator->IsDerivedFrom(MWObject::DefaultData));
	inflictingVehicle = Cast_Object(MWObject *, replicator);

	Site *site = inflictingVehicle->m_sites.Find(message->siteName);
	Check_Object(site);

	siteEntity.Add(site);
	targetOffset = Stuff::Point3D::Identity;
	if(message->targetID != ReplicatorID::Null)
	{

		Check_Object(Network::GetInstance());
		Connection	*connection = Network::GetInstance()->GetConnection(message->targetID.connectionID);
		if (connection)
		{
			Check_Object(connection);

			Replicator *rep = connection->FindReplicator(message->targetID);

			if (rep)
			{
				targetEntity.Add(Cast_Object(
					Entity*,
					rep
				));

			//
			// If we have an entity we are locked on then targetPoint is the offset from the object itself
			// we save this to use later in the raycast testing against where the object is now.
			//
				//
				// Make targetOffset the difference from the target entity to the point
				// 
				targetOffset.MultiplyByInverse(message->targetPoint, targetEntity.GetCurrent()->GetLocalToWorld());
			}
		}


	}
	
	targetPoint = message->targetPoint;
	targetNormal = message->targetNormal;
	damageAmount = message->damageAmount;
	targetMaterial = message->targetMaterial;
	heatAmount = message->heatAmount;
	maxDistance = message->maxDistance;
// MSL 5.03 Min Distance
//	minDistance = message->minDistance;

	itemID = message->itemID;

	Check_Object(siteEntity.GetCurrent());
	beamHitSFX = 0;
	CommonConstructor();

	lastParameterization = gos_GetElapsedTime();
//	firstFrame = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BeamEntity::~BeamEntity()
{
	DESTRUCTOR("BeamEntity");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::Reuse(
		const CreateMessage *message,
		ReplicatorID *base_id
	)
{
	Check_Object(this);
	BaseClass::Reuse(message, base_id);

	Check_Pointer(this);
	Check_Object(message);
	Check_Object(Connection::Local);

	// find the entity and connect to it
	inflictingEntityID = message->inflictingEntityID;

	// find the entity and connect to it
	Check_Object(Network::GetInstance());
	Connection	*connection = Network::GetInstance()->GetConnection(inflictingEntityID.connectionID);
	Check_Object(connection);

	Replicator *replicator;
	replicator = connection->FindReplicator(inflictingEntityID);

	Verify(replicator->IsDerivedFrom(MWObject::DefaultData));
	inflictingVehicle = Cast_Object(MWObject *, replicator);

	Site *site = inflictingVehicle->m_sites.Find(message->siteName);
	Check_Object(site);

	siteEntity.Remove();
	siteEntity.Add(site);
	targetOffset = Stuff::Point3D::Identity;

		if(message->targetID != ReplicatorID::Null)
	{

		Check_Object(Network::GetInstance());
		Connection	*connection = Network::GetInstance()->GetConnection(message->targetID.connectionID);
		if (connection)
		{
			Check_Object(connection);

			Replicator *rep = connection->FindReplicator(message->targetID);

			if (rep)
			{
				targetEntity.Add(Cast_Object(
					Entity*,
					rep
				));

			//
			// If we have an entity we are locked on then targetPoint is the offset from the object itself
			// we save this to use later in the raycast testing against where the object is now.
			//
				//
				// Make targetOffset the difference from the target entity to the point
				// 
				targetOffset.MultiplyByInverse(message->targetPoint, targetEntity.GetCurrent()->GetLocalToWorld());
			}
		}

	}

	targetPoint = message->targetPoint;
	targetNormal = message->targetNormal;
	damageAmount = message->damageAmount;
	targetMaterial = message->targetMaterial;
	heatAmount = message->heatAmount;
	maxDistance = message->maxDistance;
// MSL 5.03 Min Distance
//	minDistance = message->minDistance;

	Check_Object(siteEntity.GetCurrent());
	beamHitSFX = 0;
	CommonConstructor();

	lastParameterization = gos_GetElapsedTime();
//	firstFrame = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::CommonConstructor()
{
	Check_Pointer(this);
	
	rayCastDone = false;
	lastParameterization = gos_GetElapsedTime();

	if (siteEntity.GetCurrent())
	{
 		ReplicatorID beam_hit_entity_id;
		beam_hit_entity_id = MoveBeam();
		//We want to make sure that what we are hitting now is what we thought we should hit..if not then no damage
		if(targetEntity.GetCurrent())
		{
			//
			// The hit effect will hang in empty space if we destroy something when we hit it. We should leave the destruction
			// effect only in this case.
			// This doesn't fix all cases since it could be destroyed as a result of another weapon
			// this frame, and our hit effect will still be around.
			//
			
			//only damage if we are really hitting (nothing was in our way)
			if(beam_hit_entity_id != ReplicatorID::Null)
				InflictDamage(beam_hit_entity_id);

			//
			// Don't do hit effect under water unless we hit something
			//

			Check_Object (Map::GetInstance());
			const Adept::Map__GameModel *mapModel = Map::GetInstance()->GetGameModel();
			Check_Object(mapModel);

		//	if (!targetEntity.GetCurrent()->IsDestroyed())
		//	{
				if (targetPoint.y >= ((mapModel->m_waterLevel) -.001f) ||
						!targetEntity.GetCurrent()->IsDerivedFrom(Map::DefaultData))
				{
					CreateHitEffect();
					PlaceDamageDecal();
				}
		//	}
		}
//		else
	//	{
		//		MoveBeam();
//		}
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::PostCollisionExecute(Time till)
{
	Check_Pointer(this);

	Set_Statistic(Executed_Beam_Count, Executed_Beam_Count+1);
	POSTCOLLISION_LOGIC("Beam");

#if 0

	// NO LONGER SUPPORTED!!!!!!!!!!!!!

	if(GetTimeParameter(till) >= 0.5)
	{
		//
		//------------------------------
		//We need to update our position
		//------------------------------
		//
		Check_Object(siteEntity);
		MWObject *mw_object = siteEntity->GetParentVehicle();
		Check_Object(mw_object);
		mw_object->targetQuery->line->FindEnd(&targetPoint);
		targetEntity = mw_object->targetQuery->raySource;
	
		lastParameterization = gos_GetElapsedTime();

		MoveBeam();

		if(targetEntity)
		{
			CreateHitEffect();
			PlaceDamageDecal();
			InflictDamage();
		}
	}
	else

#endif

#if 0
	if(firstFrame)
	{
		firstFrame = false;
		RendererComponentWeb *video_web = GetComponentWeb(VideoRenderer::Instance);
		if(video_web)
		{
			Check_Object(video_web);
			video_web->SendCommand(Renderer::StartEffectCommandID);
		}
	}
#endif
	MoveBeam();

	SyncMatrices(true);
	BaseClass::PostCollisionExecute(till);

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ReplicatorID
	BeamEntity::MoveBeam()
{
	Check_Object(this);

	ReplicatorID hit_entity_id = ReplicatorID::Null;

	// if we haven't lost our master...
	if (siteEntity.GetCurrent() == NULL)
		return hit_entity_id;

	Check_Object(siteEntity.GetCurrent());

	Point3D new_translation;
	new_translation = siteEntity.GetCurrent()->GetLocalToWorld();

	if (!rayCastDone && targetEntity.GetCurrent())
	{
		Stuff::LinearMatrix4D tempLtW;
//		Stuff::LinearMatrix4D ltw = Stuff::LinearMatrix4D::Identity;
//		ltw.BuildTranslation(targetOffset);
		tempLtW = targetEntity.GetCurrent()->GetLocalToWorld();
		targetPoint.Multiply(targetOffset, tempLtW);
		hit_entity_id = targetEntity.GetCurrent()->GetReplicatorID();
	}

	Line3D target_line_copy;
	Vector3D target_vector;
	target_vector.Subtract(targetPoint, new_translation);

	Scalar beam_length = target_vector.GetLength();
	beamDistanceAttribute = beam_length;

	if(!rayCastDone)
	{
		rayCastDone = true;
		Line3D target_line;
		Normal3D target_normal;
		
		target_line.SetOrigin(new_translation);
		target_line.SetDirection(target_vector);
		target_line.m_length = maxDistance;


		Entity::CollisionQuery target_query(&target_line, &target_normal, (Entity::WalkerMask), inflictingVehicle);
		Adept::Entity *entity_hit;
		Check_Object(CollisionGrid::Instance);
		entity_hit = CollisionGrid::Instance->ProjectLine(&target_query);

		target_line_copy = *(target_query.m_line);
		//
		// If we don't hit anything with the cast, then we just leave the target point where it was last frame
		//
		//		Not doing this check can cause a crash. If the beam goes through the "hit" object and the beam is pointed
		//    towards the end of the world, the m_line is extending off the map, and fails the FindZone() call.
		//
		if (entity_hit)
		{
			target_query.m_line->FindEnd(&targetPoint);
			hit_entity_id = entity_hit->GetReplicatorID();
			targetEntity.Remove();
			targetEntity.Add(entity_hit);
		}
	
		PlayWaterEffectIfNecessary(target_line_copy);
	}
	
	LinearMatrix4D new_position = LinearMatrix4D::Identity;
	new_position.BuildTranslation(new_translation);

	ElementRenderer::Element *element = GetElement();
	Check_Object(element);
	element->SetLocalToParent(new_position);
	NeedMatrixSync();

	return hit_entity_id;


#if 0
	LinearMatrix4D new_position;
	Point3D new_translation;

	new_translation = siteEntity->GetLocalToWorld();
	new_position.BuildTranslation(new_translation);

	Vector3D target_vector;
	target_vector.Subtract(targetPoint, new_translation);
	Scalar beam_length = target_vector.GetLength();

	if(beam_length > maxDistance)
	{
		//
		//----------
		//Scale Beam
		//----------
		//
		Scalar scale;
		scale = maxDistance / beam_length;
		target_vector *= scale;
	}

	YawPitchRange new_rotation;
	new_rotation = target_vector;
	YawPitchRoll new_yaw_pitch_roll = YawPitchRoll::Identity;
	new_yaw_pitch_roll.yaw = new_rotation.yaw;
	new_yaw_pitch_roll.pitch = new_rotation.pitch;
	beamDistanceAttribute = new_rotation.range;
	new_position.BuildRotation(new_yaw_pitch_roll);

	ElementRenderer::Element *element = GetElement();
	Check_Object(element);
	element->SetLocalToParent(new_position);
	NeedMatrixSync();
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void
	BeamEntity::PlayWaterEffectIfNecessary(Line3D target_Line)
{
	const GameModel * model = GetGameModel();
	Check_Object(model);
	Check_Object (Map::GetInstance());
	const Adept::Map__GameModel *mapModel = Map::GetInstance()->GetGameModel();
	Check_Object(mapModel);

  //
	// Because of certain assumptions at the lower level if you put in watersurface
	// then you end up trying to collision when you get added to the zone, and that's
	// a bad thing if you don't have a collision volume
	//

//	if (model->waterSurface)
//	{
		Stuff::Scalar product;
		Plane water_Level;
		water_Level.normal.x = 0.0f;
		water_Level.normal.y = 1.0f;
		water_Level.normal.z = 0.0f;
		water_Level.offset = mapModel->m_waterLevel;

		Stuff::Scalar to_water = target_Line.GetDistanceTo(water_Level, &product);
		if (product<0.0f && to_water>=0.0f && to_water<=target_Line.m_length)
		{
			Line3D target_LineWaterIntersection;
			target_LineWaterIntersection = target_Line;

			target_LineWaterIntersection.m_length = to_water;

			Point3D point_in_world;
			target_LineWaterIntersection.FindEnd(&point_in_world);

			//
			// Make sure we didn't hit a plane off the map
			//
			if (Map::GetInstance()->FindZone(point_in_world) != -1)
			{

				ResourceID hit_effect_resource_id = ResourceID::Null;

				if(model->hitEffectMaterialTable != ResourceID::Null)
				{
					Entity__GameModel::GetEffectResourceID(&hit_effect_resource_id,
						model->hitEffectMaterialTable, WaterMaterial
					);
				}
			//	else
			//{
			//		hit_effect_resource_id = model->hitEffectResourceID;
			//	}

				if(hit_effect_resource_id != ResourceID::Null)
				{
					Resource hit_effect_resource(hit_effect_resource_id);
					Verify(hit_effect_resource.DoesResourceExist());

					ClassID class_ID;
					class_ID = GetClassIDFromDataListID(hit_effect_resource_id);
					Verify(class_ID != NullClassID);

					LinearMatrix4D effect_position = LinearMatrix4D::Identity;
					effect_position.AlignLocalAxisToWorldVector(water_Level.normal, Y_Axis, X_Axis, Z_Axis);
					effect_position.BuildTranslation(point_in_world);

					Effect::CreateMessage effect_create_message(
						sizeof(Effect::CreateMessage),
						DefaultEventPriority,
						CreateMessage::DefaultFlags,
						class_ID,
						Effect::DefaultFlags,
						hit_effect_resource_id,
						effect_position,
						0.0f,
						ExecutionStateEngine::AlwaysExecuteState,
						NameTable::NullObjectID,
						Entity::DefaultAlignment
					);
					MemoryStream stream(&effect_create_message, effect_create_message.messageLength);

					Entity *entity;
					ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
					entity = CreateEntity(&stream, &beam_id, false);

			#ifdef HUNT_ADD_EFFECT_BUG
				
					if (entity == NULL)
					{
						STOP(("FAILED CREATE ENTITY BEAM"));
					}

			#endif

					Check_Object(entity);
					Check_Object(Map::GetInstance());
					Map::GetInstance()->AddChild(entity);
					entity->SyncMatrices(true);

					// play SFX
					beamHitSFX = 1;
				}
			}




		}
		
//	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::CreateHitEffect()
{
	Check_Object(this);
	
	const GameModel *model = GetGameModel();
	Check_Object(model);

	ResourceID hit_effect_resource_id = ResourceID::Null;

	if((model->hitEffectMaterialTable != ResourceID::Null) &&
		(targetMaterial >= 0) && (targetMaterial < MaterialCount))
	{
		Entity__GameModel::GetEffectResourceID(&hit_effect_resource_id,
			model->hitEffectMaterialTable, targetMaterial
		);
	}
	else
	{
		hit_effect_resource_id = model->hitEffectResourceID;
	}

	if(hit_effect_resource_id != ResourceID::Null)
	{
		Resource hit_effect_resource(hit_effect_resource_id);
		Verify(hit_effect_resource.DoesResourceExist());

		ClassID class_ID;
		class_ID = GetClassIDFromDataListID(hit_effect_resource_id);
		Verify(class_ID != NullClassID);

		LinearMatrix4D effect_position = LinearMatrix4D::Identity;
		effect_position.AlignLocalAxisToWorldVector(targetNormal, Y_Axis, X_Axis, Z_Axis);
		effect_position.BuildTranslation(targetPoint);

		Effect::CreateMessage effect_create_message(
			sizeof(Effect::CreateMessage),
			DefaultEventPriority,
			CreateMessage::DefaultFlags,
			class_ID,
			Effect::DefaultFlags,
			hit_effect_resource_id,
			effect_position,
			0.0f,
			ExecutionStateEngine::AlwaysExecuteState,
			NameTable::NullObjectID,
			Entity::DefaultAlignment
		);
		MemoryStream stream(&effect_create_message, effect_create_message.messageLength);

		Entity *entity;
		ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
		entity = CreateEntity(&stream, &beam_id, false);

#ifdef HUNT_ADD_EFFECT_BUG
	
		if (entity == NULL)
		{
			STOP(("FAILED CREATE ENTITY BEAM"));
		}

#endif

		Check_Object(entity);
		Check_Object(Map::GetInstance());
		Map::GetInstance()->AddChild(entity);
		entity->SyncMatrices(true);

		// play SFX
		beamHitSFX = 1;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::PlaceDamageDecal()
{
	Check_Object(this);
	
	const GameModel *model = GetGameModel();
	Check_Object(model);
	if (model->damageDecalResourceID != ResourceID::Null)
	{
		Resource damage_effect_resource(model->damageDecalResourceID);
		Verify(damage_effect_resource.DoesResourceExist());
		ClassID class_ID;
		class_ID = GetClassIDFromDataListID(model->damageDecalResourceID);
		Verify(class_ID != NullClassID);

		LinearMatrix4D effect_position = LinearMatrix4D::Identity;
		effect_position.AlignLocalAxisToWorldVector(targetNormal, Y_Axis, X_Axis, Z_Axis);
		effect_position.BuildTranslation(targetPoint);

		Decal::CreateMessage decal_create_message(
			sizeof(Effect::CreateMessage),
			DefaultEventPriority,
			CreateMessage::DefaultFlags,
			class_ID,
			Decal::DefaultFlags,
			model->damageDecalResourceID,
			effect_position,
			0.0f,
			ExecutionStateEngine::NeverExecuteState,
			NameTable::NullObjectID,
			Entity::DefaultAlignment
		);
		MemoryStream stream(&decal_create_message, decal_create_message.messageLength);

		Entity *entity;
		ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID();
		entity = CreateEntity(&stream, &beam_id, false);
		Check_Object(entity);
		Check_Object(targetEntity.GetCurrent());
		targetEntity.GetCurrent()->AddChild(entity);
		entity->SyncMatrices(true);
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::InflictDamage(ReplicatorID damaged_entity)
{
	Check_Object(this);
	Check_Object(targetEntity.GetCurrent());
	Check_Object(siteEntity.GetCurrent());

// MSL 5.06 Armor Mode
	MWApplication *m_App;
	m_App = MWApplication::GetInstance ();
	m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn;

	Entity::TakeDamageMessage damage_message(
		//targetEntity.GetCurrent()->GetReplicatorID(),
		damaged_entity,
		inflictingEntityID,
		damageAmount,
		m_ArmorMode,
		BeamDamageType,
		targetNormal,
		targetPoint,
		heatAmount,
		false,
		itemID
	);
	
	targetEntity.GetCurrent()->Receive(&damage_message);

	//targetEntity->Dispatch(&damage_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	BeamEntity::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

