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.
157 lines
3.9 KiB
157 lines
3.9 KiB
5 years ago
|
// SharedFunctorUtils.h
|
||
|
// Useful functors for client and server
|
||
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* NOTE: The functors in this file should ideally be game-independant,
|
||
|
* and work for any Source based game
|
||
|
*/
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
#ifndef _SHARED_FUNCTOR_UTILS_H_
|
||
|
#define _SHARED_FUNCTOR_UTILS_H_
|
||
|
|
||
|
#include "debugoverlay_shared.h"
|
||
|
#include "vprof.h"
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Finds visible player on given team that we are pointing at.
|
||
|
* "team" can be TEAM_ANY
|
||
|
* Use with ForEachPlayer()
|
||
|
*/
|
||
|
template < class PlayerType >
|
||
|
class TargetScan
|
||
|
{
|
||
|
public:
|
||
|
TargetScan( PlayerType *me, int team, float aimTolerance = 0.01f, float maxRange = 2000.0f, float closestPointTestDistance = 50.0f, bool debug = false )
|
||
|
{
|
||
|
m_me = me;
|
||
|
AngleVectors( m_me->EyeAngles(), &m_viewForward );
|
||
|
m_team = team;
|
||
|
m_closeDot = 1.0f - aimTolerance;
|
||
|
m_bestDot = m_closeDot;
|
||
|
m_maxRange = maxRange;
|
||
|
m_target = NULL;
|
||
|
m_closestPointTestDistance = closestPointTestDistance;
|
||
|
m_debug = debug;
|
||
|
}
|
||
|
|
||
|
|
||
|
virtual bool operator() ( PlayerType *them )
|
||
|
{
|
||
|
VPROF( "TargetScan()" );
|
||
|
if ( them != m_me &&
|
||
|
them->IsAlive() &&
|
||
|
(m_team == TEAM_ANY || them->GetTeamNumber() == m_team) &&
|
||
|
IsPotentialTarget( them ) )
|
||
|
{
|
||
|
// move the start point out for determining closestPos, to help with close-in checks (healing, etc)
|
||
|
Vector closestPos;
|
||
|
Vector start = m_me->EyePosition();
|
||
|
Vector end = start + m_viewForward * m_closestPointTestDistance;
|
||
|
Vector testPos;
|
||
|
CalcClosestPointOnLineSegment( them->WorldSpaceCenter(), start, end, testPos );
|
||
|
|
||
|
start = them->GetAbsOrigin();
|
||
|
end = start;
|
||
|
end.z += them->CollisionProp()->OBBMaxs().z;
|
||
|
CalcClosestPointOnLineSegment( testPos, start, end, closestPos );
|
||
|
if ( m_debug )
|
||
|
{
|
||
|
NDebugOverlay::Cross3D( closestPos, 1, 255, 255, 255, true, -1.0f );
|
||
|
NDebugOverlay::Line( end, start, 255, 0, 0, true, -1.0f );
|
||
|
}
|
||
|
|
||
|
Vector to = closestPos - m_me->EyePosition();
|
||
|
to.NormalizeInPlace();
|
||
|
|
||
|
Vector meRangePoint, themRangePoint;
|
||
|
m_me->CollisionProp()->CalcNearestPoint( closestPos, &meRangePoint );
|
||
|
them->CollisionProp()->CalcNearestPoint( meRangePoint, &themRangePoint );
|
||
|
float range = meRangePoint.DistTo( themRangePoint );
|
||
|
|
||
|
if ( range > m_maxRange )
|
||
|
{
|
||
|
// too far away
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
float dot = ViewDot( to );
|
||
|
if ( dot > m_closeDot )
|
||
|
{
|
||
|
// target is within angle cone, check visibility
|
||
|
if ( IsTargetVisible( them ) )
|
||
|
{
|
||
|
if ( dot >= m_bestDot )
|
||
|
{
|
||
|
m_target = them;
|
||
|
m_bestDot = dot;
|
||
|
}
|
||
|
|
||
|
m_allTargets.AddToTail( them );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
PlayerType *GetTarget( void ) const
|
||
|
{
|
||
|
return m_target;
|
||
|
}
|
||
|
|
||
|
const CUtlVector< PlayerType * > &GetAllTargets( void ) const
|
||
|
{
|
||
|
return m_allTargets;
|
||
|
}
|
||
|
|
||
|
float GetTargetDot( void ) const
|
||
|
{
|
||
|
return m_bestDot;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
/**
|
||
|
* Is the point in our FOV?
|
||
|
*/
|
||
|
virtual float ViewDot( const Vector &dir ) const
|
||
|
{
|
||
|
return DotProduct( m_viewForward, dir );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is the given actor a visible target?
|
||
|
*/
|
||
|
virtual bool IsTargetVisible( PlayerType *them ) const
|
||
|
{
|
||
|
// The default check is a straight-up IsAbleToSee
|
||
|
return m_me->IsAbleToSee( them, CBaseCombatCharacter::DISREGARD_FOV ); // already have a dot product checking FOV
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is the given player a possible target at all?
|
||
|
*/
|
||
|
virtual bool IsPotentialTarget( PlayerType *them ) const
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
PlayerType *m_me;
|
||
|
Vector m_viewForward;
|
||
|
int m_team;
|
||
|
|
||
|
float m_closeDot;
|
||
|
float m_bestDot;
|
||
|
float m_maxRange;
|
||
|
float m_closestPointTestDistance;
|
||
|
bool m_debug;
|
||
|
|
||
|
PlayerType *m_target;
|
||
|
CUtlVector< PlayerType * > m_allTargets;
|
||
|
};
|
||
|
|
||
|
|
||
|
#endif
|