#include "rp.h"
#pragma hdrstop

#include "blocker.h"
#include "..\munga\dropzone.h"
#include "vtv.h"
#include "..\munga\hostmgr.h"
#include "..\munga\app.h"
#include "scorzone.h"
#include "..\munga\nttmgr.h"

//#############################################################################
//###############################    Blocker     ##############################
//#############################################################################

//#############################################################################
// Shared Data Support
//
Derivation* Blocker::GetClassDerivations()
{	static Derivation classDerivations(Crusher::GetClassDerivations(), "Blocker");
	return &classDerivations;
}


Blocker::SharedData
	Blocker::DefaultData(
		Blocker::GetClassDerivations(),
		Blocker::MessageHandlers,
		Blocker::GetAttributeIndex(),
		Blocker::StateCount,
		(Blocker::MakeHandler)Blocker::Make
	);

const Receiver::HandlerEntry
	Blocker::MessageHandlerEntries[]=
{
	MESSAGE_ENTRY(Blocker, Score),
	MESSAGE_ENTRY(Blocker, DropZoneReply)
};

Receiver::MessageHandlerSet
	Blocker::MessageHandlers(
		ELEMENTS(Blocker::MessageHandlerEntries),
		Blocker::MessageHandlerEntries,
		Crusher::GetMessageHandlers()
	);

//#############################################################################
// Message Support
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void Blocker::DropZoneReplyMessageHandler(
		DropZone::ReplyMessage *message
	)
{
	Check(this);
	Check(message);

	if (!playerVehicle)
	{
		CreatePlayerVehicle(message->dropZoneLocation);
		InitializePlayerLink();
		SetPerformance(&Blocker::PlayerSimulation);
		AlwaysExecute();
		deathCount = 0;
	}
	else if (deathCount == message->deathCount)
	{
		if (GetSimulationState() == MissionEndingState)
		{
			Check_Fpu();
			return;
		}
		if (GetSimulationState() != DropZoneAcquiredState)
		{
			ResetAfterDeath(message);
			return;
		}
	}
	else
	{
		return;
	}
	DeleteAllOffensivePlayers();
	ForceUpdate();
	SetSimulationState(VehicleTranslocatedState);
	VTV *vtv = (VTV*)playerVehicle;
	Check(vtv);
	vtv->Reset(message->dropZoneLocation, True);
	if (goalEntity)
	{
		Check(goalEntity);
		PointVTVTowardGoal();
		vtv->ForceUpdate();
	}
	Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Blocker::AddOffensivePlayer(OffensivePlayer &offensive_player)
{
	Check(this);
	Check(offensive_player.offensivePlayer);
	RPPlayer *rp_player = offensive_player.offensivePlayer;
	//
	//---------------------------------------------
	// Death Points awarded if ....
	//  This Blocker gets hit by a runner
	// from the other team with collision Damage!
	//---------------------------------------------
	//
	if ( (rp_player->playerType == RunnerPlayerType) &&
			(teamID != rp_player->teamID) &&
			(offensive_player.damageType == Damage::CollisionDamageType)
		)
	{
		offensive_player.deathBonus = 500.0f;
	}
	else
	{
		offensive_player.deathBonus = 0.0f;
	}
	offensivePlayerList.AddValue(
		&offensive_player,
		offensive_player.damageType
	);
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Blocker::ScoreMessageHandler(ScoreMessage *message)
{
	Check(this);
	Check(message);
	Check(application);
	RPPlayer::ScoreMessageHandler(message);
	HostManager *host = application->GetHostManager();
	Check(host);
	RPPlayer *rp_player = (RPPlayer*)
			host->GetEntityPointer(message->pointSender);
	if (!rp_player)
	{
		Check_Fpu();
		return;
	}
	Check(rp_player);
	if  (	((rp_player->playerType == CrusherPlayerType) || (rp_player->playerType == RunnerPlayerType)) &&
					(rp_player->teamID != teamID)
				)
	{
		ScoreMessage score_message(
				Blocker::ScoreMessageID,
				sizeof(Blocker::ScoreMessage),
				CrusherScorePointType,
				message->scoreAward*1.5f,
				GetEntityID()
			);
		if(teamRunner)
		{
			Check(teamRunner);
			teamRunner->Dispatch(&score_message);
		}
	}

	//
	// HACK - ECH 7/6/95 - Allow the player vehicle to respond to score
	// messages, allows attribute system to be used for scoring
	//
	Check(playerVehicle);
	playerVehicle->RespondToScoreMessage(message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Blocker::PlayerSimulation(Scalar time_slice)
{
	Check(this);
	//
	//------------------------------------------------------------------------
	// Service the status message queue
	//------------------------------------------------------------------------
	//
	StatusMessageUpdate(time_slice);

	//
	//------------------------------------------------
	// Only one team runner only have to do this once
	//-------------------------------------------------
	//
	Player::PlayerSimulation(time_slice);
	if (!teamRunner)
	{
		InitTeamRunner();
	}
	if (teamRunner)
	{
		Entity *our_vehicle = GetPlayerVehicle();
		Check(our_vehicle);
		if (!goalEntity)
		{
			goalEntity = teamRunner->GetPlayerVehicle();
			if (goalEntity)
			{
				PointVTVTowardGoal();
				our_vehicle->ForceUpdate();
			}
		}

		//
		//----------------------------------------------------------------------
		// Otherwise, if we aren't running yet, make sure that we are pointed in
		// the correct direction - HACK
		//----------------------------------------------------------------------
		//
		else if (
			application->GetApplicationState() < Application::RunningMission
		)
		{
			Scalar alignment = our_vehicle->localToWorld(2,2);
			PointVTVTowardGoal();
			if (alignment * goalEntity->localToWorld(2,2) < 0.0f)
			{
				our_vehicle->ForceUpdate();
			}
		}
	}
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Blocker::Blocker(
	MakeMessage *creation_message,
	SharedData	&shared_data
)
: Crusher(creation_message, shared_data)
{
	StatusMessage
		*message = new StatusMessage(NULL,RPStatusMessage::BlockerMessage,1e10);
	Register_Object(message);
	AddStatusMessage(message);
}

Blocker::~Blocker()
{
	Check(this);
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Blocker*
	Blocker::Make(MakeMessage *creation_message)
{
	Check_Fpu();
	return new Blocker(creation_message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	Blocker::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}
