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.

198 lines
5.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "passtime_ballcontroller_homing.h"
  9. #include "passtime_convars.h"
  10. #include "tf_passtime_logic.h"
  11. #include "tf_passtime_ball.h"
  12. #include "tf_weapon_passtime_gun.h"
  13. #include "tf_gamestats.h"
  14. #include "tf_gamerules.h"
  15. #include "tf_player.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. //-----------------------------------------------------------------------------
  19. CPasstimeBallControllerHoming::CPasstimeBallControllerHoming()
  20. : CPasstimeBallController( 1 )
  21. , m_fTargetSpeed( 0 )
  22. , m_bIsHoming( false )
  23. , m_fHomingStrength( 0 )
  24. {}
  25. //-----------------------------------------------------------------------------
  26. CPasstimeBallControllerHoming::~CPasstimeBallControllerHoming()
  27. {
  28. StopHoming();
  29. }
  30. //-----------------------------------------------------------------------------
  31. void CPasstimeBallControllerHoming::StartHoming( CPasstimeBall *pBall, CTFPlayer *pTarget, bool isCharged )
  32. {
  33. Assert( pTarget && pBall );
  34. SetIsEnabled( true );
  35. m_bIsHoming = true;
  36. m_hTarget = pTarget;
  37. m_hBall = pBall;
  38. pBall->VPhysicsGetObject()->EnableGravity( false );
  39. m_fHomingStrength = 0.01f; // totally arbitrary
  40. pBall->SetHomingTarget( pTarget );
  41. if ( tf_passtime_experiment_instapass.GetBool() && (!tf_passtime_experiment_instapass_charge.GetBool() || isCharged) )
  42. {
  43. auto pos = pTarget->EyePosition();
  44. pBall->Teleport( &pos, nullptr, nullptr );
  45. }
  46. }
  47. //-----------------------------------------------------------------------------
  48. void CPasstimeBallControllerHoming::StopHoming()
  49. {
  50. if ( !m_bIsHoming )
  51. return;
  52. CPasstimeBall *pBall = m_hBall.Get();
  53. if ( pBall )
  54. {
  55. if( pBall->VPhysicsGetObject() )
  56. {
  57. pBall->VPhysicsGetObject()->EnableGravity( true );
  58. }
  59. pBall->SetHomingTarget( 0 );
  60. }
  61. m_bIsHoming = false;
  62. m_hTarget = 0;
  63. m_hBall = 0;
  64. }
  65. //-----------------------------------------------------------------------------
  66. void CPasstimeBallControllerHoming::SetTargetSpeed( float f )
  67. {
  68. m_fTargetSpeed = MAX(1.0f, f);
  69. }
  70. //-----------------------------------------------------------------------------
  71. bool CPasstimeBallControllerHoming::IsActive() const
  72. {
  73. return m_bIsHoming;
  74. }
  75. //-----------------------------------------------------------------------------
  76. bool CPasstimeBallControllerHoming::Apply( CPasstimeBall *ball )
  77. {
  78. if ( ball != m_hBall )
  79. return false;
  80. if ( !m_hBall.Get() )
  81. {
  82. StopHoming();
  83. return false;
  84. }
  85. CTFPlayer *pPlayer = m_hTarget.Get();
  86. if( !pPlayer )
  87. {
  88. StopHoming();
  89. return false;
  90. }
  91. HudNotification_t cantPickUpReason;
  92. if ( pPlayer && !g_pPasstimeLogic->BCanPlayerPickUpBall( pPlayer, &cantPickUpReason ) )
  93. {
  94. if ( cantPickUpReason && TFGameRules() )
  95. {
  96. CSingleUserReliableRecipientFilter filter( pPlayer );
  97. TFGameRules()->SendHudNotification( filter, cantPickUpReason );
  98. }
  99. if ( m_bIsHoming )
  100. {
  101. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesFailed;
  102. CTF_GameStats.m_passtimeStats.AddPassTravelDistSample( ball->GetAirtimeDistance() );
  103. StopHoming();
  104. }
  105. return false;
  106. }
  107. Assert( IsActive() && IsEnabled() );
  108. IPhysicsObject *pPhys = ball->VPhysicsGetObject();
  109. Vector ballpos;
  110. pPhys->GetPosition( &ballpos, 0 );
  111. Vector targetvel = pPlayer->EyePosition() - ballpos;
  112. targetvel.NormalizeInPlace();
  113. targetvel *= m_fTargetSpeed;
  114. Vector currentvel;
  115. pPhys->GetVelocity( &currentvel, 0 );
  116. Vector steer = targetvel - currentvel;
  117. pPhys->ApplyForceCenter( steer * m_fHomingStrength );
  118. m_fHomingStrength = clamp(m_fHomingStrength * 1.1f, 0, 1); // totally arbitrary
  119. return true;
  120. }
  121. //-----------------------------------------------------------------------------
  122. void CPasstimeBallControllerHoming::OnBallCollision(
  123. CPasstimeBall *ball, int index, gamevcollisionevent_t *ev )
  124. {
  125. Assert( IsActive() && IsEnabled() );
  126. if ( ball != m_hBall )
  127. return;
  128. if ( m_iMaxBounces <= 0 )
  129. {
  130. if ( m_bIsHoming )
  131. {
  132. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesFailed;
  133. CTF_GameStats.m_passtimeStats.AddPassTravelDistSample( ball->GetAirtimeDistance() );
  134. StopHoming();
  135. }
  136. }
  137. else
  138. --m_iMaxBounces;
  139. }
  140. //-----------------------------------------------------------------------------
  141. void CPasstimeBallControllerHoming::OnBallPickedUp(
  142. CPasstimeBall *ball, CTFPlayer *catcher )
  143. {
  144. Assert( IsActive() && IsEnabled() );
  145. if ( ball == m_hBall )
  146. StopHoming();
  147. }
  148. //-----------------------------------------------------------------------------
  149. void CPasstimeBallControllerHoming::OnBallDamaged( CPasstimeBall *ball )
  150. {
  151. Assert( IsActive() && IsEnabled() );
  152. if ( ball == m_hBall && m_bIsHoming )
  153. {
  154. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesShotDown;
  155. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesFailed;
  156. CTF_GameStats.m_passtimeStats.AddPassTravelDistSample( ball->GetAirtimeDistance() );
  157. StopHoming();
  158. }
  159. }
  160. //-----------------------------------------------------------------------------
  161. void CPasstimeBallControllerHoming::OnBallSpawned( CPasstimeBall *ball )
  162. {
  163. Assert( IsActive() && IsEnabled() );
  164. StopHoming();
  165. }
  166. //-----------------------------------------------------------------------------
  167. void CPasstimeBallControllerHoming::OnDisabled()
  168. {
  169. if ( m_bIsHoming )
  170. {
  171. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesShotDown;
  172. ++CTF_GameStats.m_passtimeStats.summary.nTotalPassesFailed;
  173. CTF_GameStats.m_passtimeStats.AddPassTravelDistSample( m_hBall->GetAirtimeDistance() );
  174. }
  175. StopHoming();
  176. }