You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.6 KiB
188 lines
4.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
#include "cbase.h" |
|
|
|
#include "tf_player.h" |
|
#include "tf_projectile_arrow.h" |
|
#include "tf_weapon_grenade_pipebomb.h" |
|
#include "archer_proxy.h" |
|
|
|
LINK_ENTITY_TO_CLASS( archer_proxy, CTFArcherProxy ); |
|
|
|
|
|
ConVar tf_archer_proxy_fire_rate( "tf_archer_proxy_fire_rate", "1", FCVAR_CHEAT ); |
|
|
|
|
|
//-------------------------------------------------------------------------------------- |
|
void CTFArcherProxy::Precache( void ) |
|
{ |
|
// don't need to precache, since player does this for us |
|
BaseClass::Precache(); |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------- |
|
void CTFArcherProxy::Spawn( void ) |
|
{ |
|
BaseClass::Spawn(); |
|
|
|
SetThink( &CTFArcherProxy::Update ); |
|
SetNextThink( gpGlobals->curtime + RandomFloat( 0.1, 1.0f ) * tf_archer_proxy_fire_rate.GetFloat() ); |
|
|
|
m_state = HIDDEN; |
|
m_timer.Invalidate(); |
|
AddEffects( EF_NODRAW ); |
|
m_homePos = GetAbsOrigin(); |
|
|
|
SetModel( "models/weapons/w_models/w_arrow.mdl" ); |
|
} |
|
|
|
|
|
//--------------------------------------------------------------------------------------------- |
|
CTFPlayer *CTFArcherProxy::SelectTarget( void ) |
|
{ |
|
// collect everyone |
|
CUtlVector< CTFPlayer * > playerVector; |
|
CollectPlayers( &playerVector, TF_TEAM_RED, COLLECT_ONLY_LIVING_PLAYERS ); |
|
CollectPlayers( &playerVector, TF_TEAM_BLUE, COLLECT_ONLY_LIVING_PLAYERS, APPEND_PLAYERS ); |
|
|
|
CTFPlayer *newVictim = NULL; |
|
float victimRangeSq = FLT_MAX; |
|
trace_t result; |
|
|
|
for( int i=0; i<playerVector.Count(); ++i ) |
|
{ |
|
float rangeSq = ( playerVector[i]->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); |
|
if ( rangeSq < victimRangeSq ) |
|
{ |
|
UTIL_TraceLine( GetAbsOrigin(), playerVector[i]->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_DEBRIS, &result ); |
|
|
|
if ( !result.DidHit() ) |
|
{ |
|
newVictim = playerVector[i]; |
|
victimRangeSq = rangeSq; |
|
} |
|
} |
|
} |
|
|
|
return newVictim; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------- |
|
void CTFArcherProxy::Update( void ) |
|
{ |
|
SetNextThink( gpGlobals->curtime ); |
|
|
|
switch( m_state ) |
|
{ |
|
case HIDDEN: |
|
m_state = EMERGE; |
|
RemoveEffects( EF_NODRAW ); |
|
m_timer.Start( 1.0f ); |
|
break; |
|
|
|
case EMERGE: |
|
m_state = AIM_AND_FIRE; |
|
m_timer.Start( 1.0f ); |
|
break; |
|
|
|
case AIM_AND_FIRE: |
|
{ |
|
CTFPlayer *target = SelectTarget(); |
|
if ( target ) |
|
{ |
|
Vector to = target->GetAbsOrigin() - GetAbsOrigin(); |
|
QAngle angles; |
|
VectorAngles( to, angles ); |
|
|
|
SetAbsAngles( angles ); |
|
|
|
if ( m_timer.IsElapsed() ) |
|
{ |
|
ShootArrowAt( target ); |
|
// ShootGrenadeAt( target ); |
|
|
|
m_state = HIDE; |
|
m_timer.Start( 1.0f ); |
|
} |
|
} |
|
break; |
|
} |
|
|
|
case HIDE: |
|
if ( m_timer.IsElapsed() ) |
|
{ |
|
m_state = HIDDEN; |
|
AddEffects( EF_NODRAW ); |
|
m_timer.Start( 1.0f ); |
|
} |
|
break; |
|
} |
|
|
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------- |
|
void CTFArcherProxy::ShootArrowAt( CBaseEntity *target ) |
|
{ |
|
if ( !target ) |
|
{ |
|
return; |
|
} |
|
|
|
Vector to = target->EyePosition() - GetAbsOrigin(); |
|
to.NormalizeInPlace(); |
|
|
|
QAngle angles; |
|
VectorAngles( to, angles ); |
|
|
|
const float arrowSpeed = 2600.0f; |
|
const float arrowGravity = 0.1f; |
|
CTFProjectile_Arrow *arrow = CTFProjectile_Arrow::Create( GetAbsOrigin() + 20.0f * to, angles, arrowSpeed, arrowGravity, TF_PROJECTILE_ARROW, this, this ); |
|
if ( arrow ) |
|
{ |
|
arrow->SetLauncher( this ); |
|
arrow->SetCritical( false ); |
|
arrow->SetDamage( 100.0f ); |
|
|
|
EmitSound( "Weapon_CompoundBow.Single" ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------- |
|
void CTFArcherProxy::ShootGrenadeAt( CBaseEntity *target ) |
|
{ |
|
if ( !target ) |
|
{ |
|
return; |
|
} |
|
|
|
Vector to = target->EyePosition() - GetAbsOrigin(); |
|
to.NormalizeInPlace(); |
|
|
|
QAngle angles; |
|
VectorAngles( to, angles ); |
|
|
|
|
|
float launchSpeed = 1000.0f; |
|
Vector velocity = ( to * launchSpeed ) + ( Vector( 0, 0, 1.0f ) * 200.0f ); |
|
AngularImpulse angVelocity = AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ); |
|
|
|
CTFGrenadePipebombProjectile *grenade = static_cast< CTFGrenadePipebombProjectile * >( CBaseEntity::CreateNoSpawn( "tf_projectile_pipe", GetAbsOrigin(), angles, NULL ) ); |
|
if ( grenade ) |
|
{ |
|
// Set the pipebomb mode before calling spawn, so the model & associated vphysics get setup properly |
|
grenade->SetPipebombMode(); |
|
DispatchSpawn( grenade ); |
|
|
|
const int damage = 100; |
|
const float radius = 100.0f; |
|
|
|
grenade->InitGrenade( velocity, angVelocity, NULL, damage, radius ); |
|
grenade->m_flFullDamage = grenade->GetDamage(); |
|
grenade->ApplyLocalAngularVelocityImpulse( angVelocity ); |
|
grenade->SetCritical( false ); |
|
grenade->SetLauncher( this ); |
|
} |
|
}
|
|
|