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.

263 lines
7.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "tempent.h"
  9. #include "c_tf_passtime_logic.h"
  10. #include "tf_hud_passtime_reticle.h"
  11. #include "passtime_convars.h"
  12. #include "passtime_game_events.h"
  13. #include "tf_shareddefs.h"
  14. #include "tf_classdata.h"
  15. #include "c_tf_player.h"
  16. #include "c_func_passtime_goal.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. void C_TFPasstimeLogic::PostDataUpdate( DataUpdateType_t updateType )
  20. {
  21. BaseClass::PostDataUpdate( updateType );
  22. if ( updateType == DATA_UPDATE_CREATED )
  23. {
  24. SetNextClientThink( CLIENT_THINK_ALWAYS );
  25. m_pBallReticle = new C_PasstimeBallReticle();
  26. m_pPassReticle = new C_PasstimePassReticle();
  27. for( auto *pGoal : C_FuncPasstimeGoal::GetAutoList() )
  28. {
  29. m_pGoalReticles.AddToTail( new C_PasstimeGoalReticle(
  30. static_cast<C_FuncPasstimeGoal*>( pGoal ) ) );
  31. }
  32. }
  33. }
  34. //-----------------------------------------------------------------------------
  35. C_TFPasstimeLogic* g_pPasstimeLogic;
  36. extern ConVar hud_fastswitch;
  37. //-----------------------------------------------------------------------------
  38. IMPLEMENT_CLIENTCLASS_DT( C_TFPasstimeLogic, DT_TFPasstimeLogic, CTFPasstimeLogic )
  39. RecvPropEHandle( RECVINFO( m_hBall ) ),
  40. RecvPropArray( RecvPropVector( RECVINFO( m_trackPoints[0] ) ), m_trackPoints ),
  41. RecvPropInt( RECVINFO( m_iNumSections ) ),
  42. RecvPropInt( RECVINFO( m_iCurrentSection ) ),
  43. RecvPropFloat( RECVINFO( m_flMaxPassRange ) ),
  44. RecvPropInt( RECVINFO( m_iBallPower ), 8 ),
  45. RecvPropFloat( RECVINFO( m_flPackSpeed ) ),
  46. RecvPropArray3( RECVINFO_ARRAY( m_bPlayerIsPackMember ), RecvPropInt( RECVINFO( m_bPlayerIsPackMember[0] ) ) ),
  47. END_RECV_TABLE()
  48. LINK_ENTITY_TO_CLASS( passtime_logic, C_TFPasstimeLogic );
  49. //-----------------------------------------------------------------------------
  50. C_TFPasstimeLogic::C_TFPasstimeLogic()
  51. {
  52. m_pBallReticle = nullptr;
  53. m_pPassReticle = nullptr;
  54. memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) );
  55. memset( m_bPlayerIsPackMember, 0, sizeof( m_bPlayerIsPackMember ) );
  56. for( int i = 0; i < m_trackPoints.Count(); ++i )
  57. {
  58. m_trackPoints.GetForModify(i).Zero();
  59. }
  60. g_pPasstimeLogic = this;
  61. }
  62. //-----------------------------------------------------------------------------
  63. C_TFPasstimeLogic::~C_TFPasstimeLogic()
  64. {
  65. delete m_pBallReticle;
  66. m_pGoalReticles.PurgeAndDeleteElements();
  67. delete m_pPassReticle;
  68. // Don't set g_pPasstimeLogic to null here because sometimes this destructor
  69. // happens after the contructor of the new object
  70. // FIXME: what's the right way to do this?
  71. }
  72. //-----------------------------------------------------------------------------
  73. void C_TFPasstimeLogic::Spawn()
  74. {
  75. }
  76. //-----------------------------------------------------------------------------
  77. void C_TFPasstimeLogic::ClientThink()
  78. {
  79. BaseClass::ClientThink();
  80. SetNextClientThink( CLIENT_THINK_ALWAYS );
  81. m_pBallReticle->OnClientThink();
  82. for ( auto *pGoal : m_pGoalReticles )
  83. {
  84. pGoal->OnClientThink();
  85. }
  86. m_pPassReticle->OnClientThink();
  87. UpdateBeams();
  88. }
  89. //-----------------------------------------------------------------------------
  90. void C_TFPasstimeLogic::DestroyBeams( C_PasstimeBall *pBall )
  91. {
  92. for ( CNewParticleEffect *pBeam : m_apPackBeams )
  93. {
  94. if ( pBeam )
  95. {
  96. pBall->ParticleProp()->StopEmission( pBeam );
  97. }
  98. }
  99. memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) );
  100. }
  101. //-----------------------------------------------------------------------------
  102. void C_TFPasstimeLogic::DestroyBeam( int i, C_PasstimeBall *pBall )
  103. {
  104. CNewParticleEffect *pBeam = m_apPackBeams[i];
  105. if ( pBeam )
  106. {
  107. pBall->ParticleProp()->StopEmissionAndDestroyImmediately( pBeam );
  108. m_apPackBeams[i] = nullptr;
  109. }
  110. }
  111. //-----------------------------------------------------------------------------
  112. void C_TFPasstimeLogic::UpdateBeams()
  113. {
  114. C_PasstimeBall *pBall = GetBall();
  115. if ( !pBall )
  116. {
  117. return;
  118. }
  119. C_TFPlayer *pCarrier = pBall->GetCarrier();
  120. if ( !pCarrier )
  121. {
  122. DestroyBeams( pBall );
  123. return;
  124. }
  125. const char *pEffectName = "passtime_beam";
  126. CParticleProperty *pParticles = pBall->ParticleProp();
  127. for ( int i = 1; i <= MAX_PLAYERS; ++i )
  128. {
  129. if ( !m_bPlayerIsPackMember[i] )
  130. {
  131. DestroyBeam( i, pBall );
  132. continue;
  133. }
  134. CTFPlayer *pPlayer = (CTFPlayer*) UTIL_PlayerByIndex( i );
  135. if ( !pPlayer || ( pPlayer == pCarrier ) || !pPlayer->IsAlive() )
  136. {
  137. DestroyBeam( i, pBall );
  138. continue;
  139. }
  140. if ( !m_apPackBeams[i] )
  141. {
  142. CNewParticleEffect *pBeam = pParticles->Create( pEffectName, PATTACH_ABSORIGIN_FOLLOW );
  143. pParticles->AddControlPoint( pBeam, 1, pPlayer, PATTACH_ABSORIGIN_FOLLOW, 0, Vector(0,0,16) );
  144. m_apPackBeams[i] = pBeam;
  145. }
  146. }
  147. }
  148. //-----------------------------------------------------------------------------
  149. void C_TFPasstimeLogic::GetTrackPoints( Vector (&points)[16] )
  150. {
  151. memcpy( points, m_trackPoints.Base(), sizeof(points) );
  152. }
  153. //-----------------------------------------------------------------------------
  154. bool C_TFPasstimeLogic::GetImportantEntities( C_PasstimeBall **ppBall, C_TFPlayer **ppCarrier, C_TFPlayer **ppHomingTarget ) const
  155. {
  156. C_PasstimeBall *pBall = GetBall();
  157. if ( !pBall )
  158. {
  159. return false;
  160. }
  161. if ( ppBall )
  162. {
  163. *ppBall = pBall;
  164. }
  165. if ( ppCarrier )
  166. {
  167. *ppCarrier = pBall->GetCarrier();
  168. }
  169. if ( ppHomingTarget )
  170. {
  171. *ppHomingTarget = ToTFPlayer( pBall->GetHomingTarget() );
  172. }
  173. return true;
  174. }
  175. //-----------------------------------------------------------------------------
  176. bool C_TFPasstimeLogic::GetBallReticleTarget( C_BaseEntity **ppEnt, bool *bHomingActive ) const
  177. {
  178. Assert( ppEnt );
  179. if ( !ppEnt )
  180. {
  181. return false;
  182. }
  183. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  184. if ( !pLocalPlayer )
  185. {
  186. return false;
  187. }
  188. C_PasstimeBall *pBall = 0;
  189. C_TFPlayer *pCarrier = 0, *pHomingTarget = 0;
  190. if ( !GetImportantEntities( &pBall, &pCarrier, &pHomingTarget ) )
  191. {
  192. return false;
  193. }
  194. C_BaseEntity *pEnt = pCarrier ? pCarrier : (C_BaseEntity*)pBall;
  195. if ( !pEnt
  196. || (pEnt == pLocalPlayer)
  197. || (pEnt->GetEffects() & EF_NODRAW)
  198. || ((pEnt->GetTeamNumber() != TEAM_UNASSIGNED)
  199. && (pEnt->GetTeamNumber() != pLocalPlayer->GetTeamNumber()))
  200. || (pLocalPlayer->IsObserver() && (GetSpectatorMode() != OBS_MODE_ROAMING) && (GetSpectatorTarget() == pEnt->index)) )
  201. {
  202. return false;
  203. }
  204. *ppEnt = pEnt;
  205. if ( bHomingActive )
  206. {
  207. *bHomingActive = pHomingTarget != 0;
  208. }
  209. return true;
  210. }
  211. //-----------------------------------------------------------------------------
  212. bool C_TFPasstimeLogic::BCanPlayerPickUpBall( C_TFPlayer *pPlayer ) const
  213. {
  214. return pPlayer
  215. && pPlayer->IsAllowedToPickUpFlag()
  216. && pPlayer->IsAlive() // NOTE: it's possible to be alive and dead at the same time
  217. && !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE )
  218. && !pPlayer->m_Shared.InCond( TF_COND_PHASE )
  219. && !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF )
  220. && !pPlayer->m_Shared.InCond( TF_COND_SELECTED_TO_TELEPORT )
  221. && !pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK )
  222. && !pPlayer->m_Shared.InCond( TF_COND_TAUNTING )
  223. && !pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE )
  224. && !pPlayer->m_Shared.IsControlStunned()
  225. && !pPlayer->m_Shared.IsStealthed()
  226. && !pPlayer->m_Shared.IsCarryingObject();
  227. }