Team Fortress 2 Source Code as on 22/4/2020
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.

156 lines
3.9 KiB

  1. // SharedFunctorUtils.h
  2. // Useful functors for client and server
  3. //========= Copyright Valve Corporation, All rights reserved. ============//
  4. //--------------------------------------------------------------------------------------------------------
  5. /**
  6. * NOTE: The functors in this file should ideally be game-independant,
  7. * and work for any Source based game
  8. */
  9. //--------------------------------------------------------------------------------------------------------
  10. #ifndef _SHARED_FUNCTOR_UTILS_H_
  11. #define _SHARED_FUNCTOR_UTILS_H_
  12. #include "debugoverlay_shared.h"
  13. #include "vprof.h"
  14. //--------------------------------------------------------------------------------------------------------
  15. /**
  16. * Finds visible player on given team that we are pointing at.
  17. * "team" can be TEAM_ANY
  18. * Use with ForEachPlayer()
  19. */
  20. template < class PlayerType >
  21. class TargetScan
  22. {
  23. public:
  24. TargetScan( PlayerType *me, int team, float aimTolerance = 0.01f, float maxRange = 2000.0f, float closestPointTestDistance = 50.0f, bool debug = false )
  25. {
  26. m_me = me;
  27. AngleVectors( m_me->EyeAngles(), &m_viewForward );
  28. m_team = team;
  29. m_closeDot = 1.0f - aimTolerance;
  30. m_bestDot = m_closeDot;
  31. m_maxRange = maxRange;
  32. m_target = NULL;
  33. m_closestPointTestDistance = closestPointTestDistance;
  34. m_debug = debug;
  35. }
  36. virtual bool operator() ( PlayerType *them )
  37. {
  38. VPROF( "TargetScan()" );
  39. if ( them != m_me &&
  40. them->IsAlive() &&
  41. (m_team == TEAM_ANY || them->GetTeamNumber() == m_team) &&
  42. IsPotentialTarget( them ) )
  43. {
  44. // move the start point out for determining closestPos, to help with close-in checks (healing, etc)
  45. Vector closestPos;
  46. Vector start = m_me->EyePosition();
  47. Vector end = start + m_viewForward * m_closestPointTestDistance;
  48. Vector testPos;
  49. CalcClosestPointOnLineSegment( them->WorldSpaceCenter(), start, end, testPos );
  50. start = them->GetAbsOrigin();
  51. end = start;
  52. end.z += them->CollisionProp()->OBBMaxs().z;
  53. CalcClosestPointOnLineSegment( testPos, start, end, closestPos );
  54. if ( m_debug )
  55. {
  56. NDebugOverlay::Cross3D( closestPos, 1, 255, 255, 255, true, -1.0f );
  57. NDebugOverlay::Line( end, start, 255, 0, 0, true, -1.0f );
  58. }
  59. Vector to = closestPos - m_me->EyePosition();
  60. to.NormalizeInPlace();
  61. Vector meRangePoint, themRangePoint;
  62. m_me->CollisionProp()->CalcNearestPoint( closestPos, &meRangePoint );
  63. them->CollisionProp()->CalcNearestPoint( meRangePoint, &themRangePoint );
  64. float range = meRangePoint.DistTo( themRangePoint );
  65. if ( range > m_maxRange )
  66. {
  67. // too far away
  68. return true;
  69. }
  70. float dot = ViewDot( to );
  71. if ( dot > m_closeDot )
  72. {
  73. // target is within angle cone, check visibility
  74. if ( IsTargetVisible( them ) )
  75. {
  76. if ( dot >= m_bestDot )
  77. {
  78. m_target = them;
  79. m_bestDot = dot;
  80. }
  81. m_allTargets.AddToTail( them );
  82. }
  83. }
  84. }
  85. return true;
  86. }
  87. PlayerType *GetTarget( void ) const
  88. {
  89. return m_target;
  90. }
  91. const CUtlVector< PlayerType * > &GetAllTargets( void ) const
  92. {
  93. return m_allTargets;
  94. }
  95. float GetTargetDot( void ) const
  96. {
  97. return m_bestDot;
  98. }
  99. protected:
  100. /**
  101. * Is the point in our FOV?
  102. */
  103. virtual float ViewDot( const Vector &dir ) const
  104. {
  105. return DotProduct( m_viewForward, dir );
  106. }
  107. /**
  108. * Is the given actor a visible target?
  109. */
  110. virtual bool IsTargetVisible( PlayerType *them ) const
  111. {
  112. // The default check is a straight-up IsAbleToSee
  113. return m_me->IsAbleToSee( them, CBaseCombatCharacter::DISREGARD_FOV ); // already have a dot product checking FOV
  114. }
  115. /**
  116. * Is the given player a possible target at all?
  117. */
  118. virtual bool IsPotentialTarget( PlayerType *them ) const
  119. {
  120. return true;
  121. }
  122. PlayerType *m_me;
  123. Vector m_viewForward;
  124. int m_team;
  125. float m_closeDot;
  126. float m_bestDot;
  127. float m_maxRange;
  128. float m_closestPointTestDistance;
  129. bool m_debug;
  130. PlayerType *m_target;
  131. CUtlVector< PlayerType * > m_allTargets;
  132. };
  133. #endif