This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
nekohook/modules/source2013/sdk/game/shared/SharedFunctorUtils.h
2020-08-04 13:13:01 -04:00

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