//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ====
//
//
//=============================================================================

#include "cbase.h"
#include "entityinput.h"
#include "entityoutput.h"
#include "eventqueue.h"
#include "soundent.h"
#include "logic_rts_mode.h"
#include "player.h"
#include "shared_classnames.h"
#include "hl2_shareddefs.h"
#include "hl2wars/hl2wars_player.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

const int SF_REMOVE_ON_FIRE				= 0x001;	// Relay will remove itself after being triggered.
const int SF_ALLOW_FAST_RETRIGGER		= 0x002;	// Unless set, relay will disable itself until the last output is sent.

LINK_ENTITY_TO_CLASS(logic_rts_mode, CLogicRTSMode);

BEGIN_DATADESC( CLogicRTSMode )

	DEFINE_FIELD(m_bWaitForRefire, FIELD_BOOLEAN),
	DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled"),

	// Inputs
	DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable),
	DEFINE_INPUTFUNC(FIELD_VOID, "EnableRefire", InputEnableRefire),
	DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable),
	DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle),
	DEFINE_INPUTFUNC(FIELD_VOID, "CancelPending", InputCancelPending),

	DEFINE_KEYFIELD( m_iDestinationRTS, FIELD_STRING, "destinationRTS" ),
	DEFINE_KEYFIELD( m_iDestinationFPS, FIELD_STRING, "destinationFPS" ),

	DEFINE_KEYFIELD( m_iTeamRTS, FIELD_INTEGER, "teamrts" ),
	DEFINE_FIELD(m_bHasSuit, FIELD_BOOLEAN),

	// Outputs
	//DEFINE_OUTPUT(m_OnTrigger, "OnTrigger"),
	DEFINE_OUTPUT(m_OnSpawn, "OnSpawn"),

END_DATADESC()



//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CLogicRTSMode::CLogicRTSMode(void)
{
}


//------------------------------------------------------------------------------
// Kickstarts a think if we have OnSpawn connections.
//------------------------------------------------------------------------------
void CLogicRTSMode::Activate()
{
	BaseClass::Activate();
	
	if ( m_OnSpawn.NumberOfElements() > 0)
	{
		SetNextThink( gpGlobals->curtime + 0.01 );
	}
}


//-----------------------------------------------------------------------------
// If we have OnSpawn connections, this is called shortly after spawning to
// fire the OnSpawn output.
//-----------------------------------------------------------------------------
void CLogicRTSMode::Think()
{
	// Fire an output when we spawn. This is used for self-starting an entity
	// template -- since the logic_relay is inside the template, it gets all the
	// name and I/O connection fixup, so can target other entities in the template.
	m_OnSpawn.FireOutput( this, this );

	// We only get here if we had OnSpawn connections, so this is safe.
	if ( m_spawnflags & SF_REMOVE_ON_FIRE )
	{
		UTIL_Remove(this);
	}
}


//------------------------------------------------------------------------------
// Purpose: Turns on the relay, allowing it to fire outputs.
//------------------------------------------------------------------------------
void CLogicRTSMode::InputEnable( inputdata_t &inputdata )
{
	m_bDisabled = false;

	// get the player
	CHL2Wars_Player *pPlayer = NULL;
	if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() )
	{
		pPlayer = (CHL2Wars_Player *)inputdata.pActivator;
	}

	if( !pPlayer )
		return;
	
	pPlayer->SetTeamRTSID( m_iTeamRTS );
	// equip rts suit = init the rts hud with panel
	pPlayer->SetRTSMode( true );  

	// teleport to the rts destination
	TeleportFPSRTS(m_iDestinationRTS, pPlayer);
}

//------------------------------------------------------------------------------
// Purpose: Enables us to fire again. This input is only posted from our Trigger
//			function to prevent rapid refire.
//------------------------------------------------------------------------------
void CLogicRTSMode::InputEnableRefire( inputdata_t &inputdata )
{ 
	m_bWaitForRefire = false;
}


//------------------------------------------------------------------------------
// Purpose: Cancels any I/O events in the queue that were fired by us.
//------------------------------------------------------------------------------
void CLogicRTSMode::InputCancelPending( inputdata_t &inputdata )
{ 
	g_EventQueue.CancelEvents( this );

	// Stop waiting; allow another Trigger.
	m_bWaitForRefire = false;
}


//------------------------------------------------------------------------------
// Purpose: Turns off the relay, preventing it from firing outputs.
//------------------------------------------------------------------------------
void CLogicRTSMode::InputDisable( inputdata_t &inputdata )
{ 
	m_bDisabled = true;

	// get player
	CHL2Wars_Player *pPlayer = NULL;
	if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() )
	{
		pPlayer = (CHL2Wars_Player *)inputdata.pActivator;
	}
	if( !pPlayer )
		return;
		
	// become a mortal person again.
	pPlayer->SetRTSMode( false );    

	TeleportFPSRTS(m_iDestinationFPS, pPlayer);
}


//------------------------------------------------------------------------------
// Purpose: Toggles the enabled/disabled state of the relay.
//------------------------------------------------------------------------------
void CLogicRTSMode::InputToggle( inputdata_t &inputdata )
{ 
	m_bDisabled = !m_bDisabled;

	if( m_bDisabled )
		InputDisable( inputdata );
	else
        InputEnable( inputdata );
}

//------------------------------------------------------------------------------
// Purpose: Teleport the player to the landmark, rts or fps
//------------------------------------------------------------------------------
void CLogicRTSMode::TeleportFPSRTS( string_t destination, CBasePlayer *pPlayer )
{ 
	//\\ teleport to the RTS/FPS destination //
    CBaseEntity	*pentTarget = NULL;

	// The activator and caller are the same
	pentTarget = gEntList.FindEntityByName( pentTarget, destination, NULL, pPlayer, pPlayer );
	if (!pentTarget)
	{
	   return;
	}

	pPlayer->SetGroundEntity( NULL );
	
	Vector tmp = pentTarget->GetAbsOrigin();

	// make origin adjustments in case the teleportee is a player. (origin in center, not at feet)
	tmp.z -= pPlayer->WorldAlignMins().z;

	//
	// Only modify the toucher's angles and zero their velocity if no landmark was specified.
	//
	const QAngle *pAngles = NULL;
	Vector *pVelocity = NULL;

#ifdef HL1_DLL
	Vector vecZero(0,0,0);		
#endif

	pAngles = &pentTarget->GetAbsAngles();

#ifdef HL1_DLL
	pVelocity = &vecZero;
#else
	pVelocity = NULL;	//BUGBUG - This does not set the player's velocity to zero!!!
#endif

	pPlayer->Teleport( &tmp, pAngles, pVelocity );
}

