111 lines
3.4 KiB
C++
111 lines
3.4 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "tf_passtime_ball.h"
|
|
#include "tf_passtime_logic.h"
|
|
#include "passtime_convars.h"
|
|
#include "passtime_ballcontroller_playerseek.h"
|
|
#include "tf_player.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
namespace {
|
|
const int kPriority = 1; // same as homing, so they stack
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CPasstimeBallControllerPlayerSeek::CPasstimeBallControllerPlayerSeek()
|
|
: CPasstimeBallController( kPriority ) // low priority
|
|
, m_fEnableTime( 0 )
|
|
{}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CPasstimeBallControllerPlayerSeek::Apply( CPasstimeBall *ball )
|
|
{
|
|
if ( gpGlobals->curtime < m_fEnableTime )
|
|
return false;
|
|
return Seek( ball, FindTarget( ball->GetThrower(), ball->GetAbsOrigin() ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CTFPlayer *CPasstimeBallControllerPlayerSeek::FindTarget( CTFPlayer *pIgnorePlayer, const Vector& ballOrigin ) const
|
|
{
|
|
CTFPlayer *pTarget = 0;
|
|
float closestPlayerDist = tf_passtime_ball_seek_range.GetFloat();
|
|
closestPlayerDist *= closestPlayerDist; // avoid some sqrts
|
|
|
|
// Treat this trace exactly like radius damage
|
|
CTraceFilterIgnorePlayers traceFilter( 0, COLLISION_GROUP_PLAYER_MOVEMENT );
|
|
|
|
for ( int i = 1; i <= MAX_PLAYERS; i++ )
|
|
{
|
|
CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( i ) );
|
|
if ( !pPlayer )
|
|
continue; // wat
|
|
|
|
if ( pPlayer == pIgnorePlayer )
|
|
continue;
|
|
|
|
const Vector& eyepos = pPlayer->WorldSpaceCenter();
|
|
const float dist = (eyepos - ballOrigin).LengthSqr();
|
|
if ( dist >= closestPlayerDist )
|
|
continue; // to far away
|
|
|
|
if ( pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) )
|
|
continue; // don't seek any disguised people
|
|
|
|
if ( !g_pPasstimeLogic->BCanPlayerPickUpBall( pPlayer ) )
|
|
continue; // can't pick it up
|
|
|
|
trace_t trace;
|
|
UTIL_TraceLine( ballOrigin, eyepos, MASK_PLAYERSOLID, &traceFilter, &trace );
|
|
if ( trace.fraction != 1 )
|
|
continue; // occluded
|
|
|
|
// chicken dinner
|
|
pTarget = pPlayer;
|
|
closestPlayerDist = dist;
|
|
}
|
|
return pTarget;
|
|
}
|
|
|
|
extern float GetCurrentGravity( void ); // tf_gamerules.h
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CPasstimeBallControllerPlayerSeek::Seek( CPasstimeBall *ball, CTFPlayer *pTarget ) const
|
|
{
|
|
if ( !pTarget )
|
|
return false;
|
|
|
|
// taken from ballcontroller_homing
|
|
IPhysicsObject *pPhys = ball->VPhysicsGetObject();
|
|
Vector ballpos;
|
|
pPhys->GetPosition( &ballpos, 0 );
|
|
|
|
Vector targetvel = pTarget->EyePosition() - ballpos;
|
|
targetvel.NormalizeInPlace();
|
|
targetvel *= pTarget->TeamFortress_CalculateMaxSpeed() *
|
|
tf_passtime_ball_seek_speed_factor.GetFloat();
|
|
|
|
Vector currentvel;
|
|
pPhys->GetVelocity( ¤tvel, 0 );
|
|
Vector steer = targetvel - currentvel;
|
|
pPhys->AddVelocity( &steer, 0 );
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CPasstimeBallControllerPlayerSeek::OnBallSpawned( CPasstimeBall *ball )
|
|
{
|
|
// NOTE: this hack is the only thing that prevents players from picking up
|
|
// balls immediately after they were thrown (including by nearby unrelated
|
|
// players)
|
|
m_fEnableTime = gpGlobals->curtime + 0.25f;
|
|
}
|