141 lines
4.6 KiB
C++
141 lines
4.6 KiB
C++
// 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
|