summaryrefslogtreecommitdiff
path: root/game/server/tf/player_vs_environment/archer_proxy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf/player_vs_environment/archer_proxy.cpp')
-rw-r--r--game/server/tf/player_vs_environment/archer_proxy.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/game/server/tf/player_vs_environment/archer_proxy.cpp b/game/server/tf/player_vs_environment/archer_proxy.cpp
new file mode 100644
index 0000000..0125d12
--- /dev/null
+++ b/game/server/tf/player_vs_environment/archer_proxy.cpp
@@ -0,0 +1,188 @@
+//========= 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 );
+ }
+}