//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:			The Infiltrator's Weapon
//
// $NoKeywords: $
//=============================================================================

#include "cbase.h"
#include "tf_player.h"
#include "tf_defines.h"
#include "in_buttons.h"
#include "weapon_infiltrator.h"
#include "gamerules.h"
#include "ammodef.h"

#define INFILTRATOR_STAB_RANGE 64.0f

// Damage CVars
ConVar	weapon_infiltrator_damage( "weapon_infiltrator_damage","0", FCVAR_NONE, "Infiltrator backstab damage" );
ConVar	weapon_infiltrator_range( "weapon_infiltrator_range","0", FCVAR_NONE, "Infiltrator backstab range" );

//=====================================================================================================
// INFILTRATOR WEAPON
//=====================================================================================================
IMPLEMENT_SERVERCLASS_ST(CWeaponInfiltrator, DT_WeaponInfiltrator)
END_SEND_TABLE()

LINK_ENTITY_TO_CLASS( weapon_infiltrator, CWeaponInfiltrator );
PRECACHE_WEAPON_REGISTER(weapon_infiltrator);

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CWeaponInfiltrator::CWeaponInfiltrator( void )
{
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponInfiltrator::Precache( void )
{
	BaseClass::Precache();
}

//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CWeaponInfiltrator::ComputeEMPFireState( void )
{
	if (IsOwnerEMPed())
	{
		// FIXME: Need a sound
		//UTIL_EmitSound( pPlayer->pev, CHAN_WEAPON, g_pszEMPGatlingFizzle, 1.0, ATTN_NORM );
		return false;
	}
	return true;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CWeaponInfiltrator::Deploy( void )
{
	// Play a shing! sound
	WeaponSound( SPECIAL1 );
	return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponInfiltrator::PrimaryAttack( void )
{
	CBaseTFPlayer *pTarget = GetAssassinationTarget();
	if ( pTarget == NULL )
		return;
	
	WeaponSound( SINGLE );
	PlayAttackAnimation( ACT_VM_PRIMARYATTACK );
	m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration( m_nSequence ) * 0.5;

	// Instant kill
	pTarget->TakeDamage( CTakeDamageInfo( this, GetOwner(), 500.0f, DMG_SLASH ) );
	// Gag until respawn
	pTarget->SetGagged( true );

	CheckRemoveDisguise();
}

//-----------------------------------------------------------------------------
// Purpose: Overloaded to handle the hold-down healing
//-----------------------------------------------------------------------------
void CWeaponInfiltrator::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// Stab 'em
	if (( pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
	{
		PrimaryAttack();
	}

	WeaponIdle();
}

//-----------------------------------------------------------------------------
// Purpose: See if there's an assassination target in front of the player.
// Output : Returns true if a target's found.
//-----------------------------------------------------------------------------
CBaseTFPlayer *CWeaponInfiltrator::GetAssassinationTarget( void )
{
	if ( !ComputeEMPFireState() )
		return NULL;

	CBaseTFPlayer *pPlayer = static_cast< CBaseTFPlayer * >( GetOwner() );
	if ( !pPlayer )
		return NULL;

	trace_t tr;
	Vector vecForward;
	pPlayer->EyeVectors( &vecForward );
	Vector vecOrigin = pPlayer->EyePosition();
	UTIL_TraceLine( vecOrigin, vecOrigin + INFILTRATOR_STAB_RANGE * vecForward, MASK_SHOT, pPlayer, GetCollisionGroup(), &tr );
	if ( tr.fraction == 1.0f || !tr.m_pEnt )
		return NULL;
	CBaseEntity *pEntity = tr.m_pEnt;
	if ( !pEntity || !pEntity->IsPlayer() )
		return NULL;
	if ( !pEntity->IsPlayer() )
		return NULL;

	// Don't target friendlies
	if ( pEntity->InSameTeam( pPlayer ) )
		return NULL;

	// See if the player is facing the right direction
	Vector fwd1, fwd2;
	AngleVectors( pPlayer->GetAbsAngles(), &fwd1, NULL, NULL );
	AngleVectors( pEntity->GetAbsAngles(), &fwd2, NULL, NULL );

	float dot = fwd1.Dot( fwd2 );
	if ( dot <= 0.0f )
		return NULL;

	return (CBaseTFPlayer*)pEntity;
}