Counter Strike : Global Offensive Source Code
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.

406 lines
14 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: An entity that networks the state of the game's objectives.
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "c_team_objectiveresource.h"
  8. #include "igameevents.h"
  9. #include "teamplayroundbased_gamerules.h"
  10. #include "c_baseplayer.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. #define RESOURCE_THINK_TIME 0.1
  14. extern ConVar mp_capstyle;
  15. extern ConVar mp_capdeteriorate_time;
  16. //-----------------------------------------------------------------------------
  17. // Purpose: Owner recv proxy
  18. //-----------------------------------------------------------------------------
  19. void RecvProxy_Owner( const CRecvProxyData *pData, void *pStruct, void *pOut )
  20. {
  21. // hacks? Not sure how else to get the index of the integer that is
  22. // being transmitted.
  23. int index = pData->m_pRecvProp->GetOffset() / sizeof(int);
  24. ObjectiveResource()->SetOwningTeam( index, pData->m_Value.m_Int );
  25. }
  26. //-----------------------------------------------------------------------------
  27. // Purpose: capper recv proxy
  28. //-----------------------------------------------------------------------------
  29. void RecvProxy_CappingTeam( const CRecvProxyData *pData, void *pStruct, void *pOut )
  30. {
  31. int index = pData->m_pRecvProp->GetOffset() / sizeof(int);
  32. ObjectiveResource()->SetCappingTeam( index, pData->m_Value.m_Int );
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Purpose:
  36. //-----------------------------------------------------------------------------
  37. void RecvProxy_CapLayout( const CRecvProxyData *pData, void *pStruct, void *pOut )
  38. {
  39. ObjectiveResource()->SetCapLayout( pData->m_Value.m_pString );
  40. }
  41. IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_BaseTeamObjectiveResource, DT_BaseTeamObjectiveResource, CBaseTeamObjectiveResource)
  42. RecvPropInt( RECVINFO(m_iTimerToShowInHUD) ),
  43. RecvPropInt( RECVINFO(m_iStopWatchTimer) ),
  44. RecvPropInt( RECVINFO(m_iNumControlPoints) ),
  45. RecvPropBool( RECVINFO(m_bPlayingMiniRounds) ),
  46. RecvPropBool( RECVINFO(m_bControlPointsReset) ),
  47. RecvPropInt( RECVINFO(m_iUpdateCapHudParity) ),
  48. RecvPropArray( RecvPropVector(RECVINFO(m_vCPPositions[0])), m_vCPPositions),
  49. RecvPropArray3( RECVINFO_ARRAY(m_bCPIsVisible), RecvPropInt( RECVINFO(m_bCPIsVisible[0]) ) ),
  50. RecvPropArray3( RECVINFO_ARRAY(m_flLazyCapPerc), RecvPropFloat( RECVINFO(m_flLazyCapPerc[0]) ) ),
  51. RecvPropArray3( RECVINFO_ARRAY(m_iTeamIcons), RecvPropInt( RECVINFO(m_iTeamIcons[0]) ) ),
  52. RecvPropArray3( RECVINFO_ARRAY(m_iTeamOverlays), RecvPropInt( RECVINFO(m_iTeamOverlays[0]) ) ),
  53. RecvPropArray3( RECVINFO_ARRAY(m_iTeamReqCappers), RecvPropInt( RECVINFO(m_iTeamReqCappers[0]) ) ),
  54. RecvPropArray3( RECVINFO_ARRAY(m_flTeamCapTime), RecvPropTime( RECVINFO(m_flTeamCapTime[0]) ) ),
  55. RecvPropArray3( RECVINFO_ARRAY(m_iPreviousPoints), RecvPropInt( RECVINFO(m_iPreviousPoints[0]) ) ),
  56. RecvPropArray3( RECVINFO_ARRAY(m_bTeamCanCap), RecvPropBool( RECVINFO(m_bTeamCanCap[0]) ) ),
  57. RecvPropArray3( RECVINFO_ARRAY(m_iTeamBaseIcons), RecvPropInt( RECVINFO(m_iTeamBaseIcons[0]) ) ),
  58. RecvPropArray3( RECVINFO_ARRAY(m_iBaseControlPoints), RecvPropInt( RECVINFO(m_iBaseControlPoints[0]) ) ),
  59. RecvPropArray3( RECVINFO_ARRAY(m_bInMiniRound), RecvPropBool( RECVINFO(m_bInMiniRound[0]) ) ),
  60. RecvPropArray3( RECVINFO_ARRAY(m_iWarnOnCap), RecvPropInt( RECVINFO(m_iWarnOnCap[0]) ) ),
  61. RecvPropArray( RecvPropString( RECVINFO( m_iszWarnSound[0]) ), m_iszWarnSound ),
  62. RecvPropArray3( RECVINFO_ARRAY(m_flPathDistance), RecvPropFloat( RECVINFO(m_flPathDistance[0]) ) ),
  63. // state variables
  64. RecvPropArray3( RECVINFO_ARRAY(m_iNumTeamMembers), RecvPropInt( RECVINFO(m_iNumTeamMembers[0]) ) ),
  65. RecvPropArray3( RECVINFO_ARRAY(m_iCappingTeam), RecvPropInt( RECVINFO(m_iCappingTeam[0]), 0, RecvProxy_CappingTeam ) ),
  66. RecvPropArray3( RECVINFO_ARRAY(m_iTeamInZone), RecvPropInt( RECVINFO(m_iTeamInZone[0]) ) ),
  67. RecvPropArray3( RECVINFO_ARRAY(m_bBlocked), RecvPropInt( RECVINFO(m_bBlocked[0]) ) ),
  68. RecvPropArray3( RECVINFO_ARRAY(m_iOwner), RecvPropInt( RECVINFO(m_iOwner[0]), 0, RecvProxy_Owner ) ),
  69. RecvPropString( RECVINFO(m_pszCapLayoutInHUD), 0, RecvProxy_CapLayout ),
  70. END_RECV_TABLE()
  71. C_BaseTeamObjectiveResource *g_pObjectiveResource = NULL;
  72. //-----------------------------------------------------------------------------
  73. // Purpose:
  74. //-----------------------------------------------------------------------------
  75. C_BaseTeamObjectiveResource::C_BaseTeamObjectiveResource()
  76. {
  77. m_iNumControlPoints = 0;
  78. m_iPrevNumControlPoints = 0;
  79. m_pszCapLayoutInHUD[0] = 0;
  80. m_iUpdateCapHudParity = 0;
  81. m_bControlPointsReset = false;
  82. for ( int i=0; i < MAX_CONTROL_POINTS; i++ )
  83. {
  84. m_flCapTimeLeft[i] = 0;
  85. m_flCapLastThinkTime[i] = 0;
  86. m_flLastCapWarningTime[i] = 0;
  87. m_bWarnedOnFinalCap[i] = false; // have we warned
  88. m_iWarnOnCap[i] = CP_WARN_NORMAL; // should we warn
  89. m_iszWarnSound[i][0] = 0; // what sound should be played
  90. m_flLazyCapPerc[i] = 0.0;
  91. for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ )
  92. {
  93. int iTeamIndex = TEAM_ARRAY( i, team );
  94. m_iTeamIcons[ iTeamIndex ] = 0;
  95. m_iTeamOverlays[ iTeamIndex ] = 0;
  96. m_iTeamReqCappers[ iTeamIndex ] = 0;
  97. m_flTeamCapTime[ iTeamIndex ] = 0.0f;
  98. m_iNumTeamMembers[ iTeamIndex ] = 0;
  99. for ( int ipoint = 0; ipoint < MAX_PREVIOUS_POINTS; ipoint++ )
  100. {
  101. int iIntIndex = ipoint + (i * MAX_PREVIOUS_POINTS) + (team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS);
  102. m_iPreviousPoints[ iIntIndex ] = -1;
  103. }
  104. }
  105. }
  106. for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ )
  107. {
  108. m_iTeamBaseIcons[team] = 0;
  109. }
  110. g_pObjectiveResource = this;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose:
  114. //-----------------------------------------------------------------------------
  115. C_BaseTeamObjectiveResource::~C_BaseTeamObjectiveResource()
  116. {
  117. g_pObjectiveResource = NULL;
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose:
  121. //-----------------------------------------------------------------------------
  122. void C_BaseTeamObjectiveResource::OnPreDataChanged( DataUpdateType_t updateType )
  123. {
  124. BaseClass::OnPreDataChanged( updateType );
  125. m_iPrevNumControlPoints = m_iNumControlPoints;
  126. m_iOldUpdateCapHudParity = m_iUpdateCapHudParity;
  127. m_bOldControlPointsReset = m_bControlPointsReset;
  128. memcpy( m_flOldLazyCapPerc, m_flLazyCapPerc, sizeof(float)*m_iNumControlPoints );
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose:
  132. //-----------------------------------------------------------------------------
  133. void C_BaseTeamObjectiveResource::OnDataChanged( DataUpdateType_t updateType )
  134. {
  135. BaseClass::OnDataChanged( updateType );
  136. if ( m_bOldControlPointsReset != m_bControlPointsReset || m_iNumControlPoints != m_iPrevNumControlPoints )
  137. {
  138. // Tell everyone we know how many control points we have
  139. IGameEvent *event = gameeventmanager->CreateEvent( "controlpoint_initialized" );
  140. if ( event )
  141. {
  142. gameeventmanager->FireEventClientSide( event );
  143. }
  144. }
  145. if ( m_iUpdateCapHudParity != m_iOldUpdateCapHudParity )
  146. {
  147. UpdateControlPoint( "controlpoint_updateimages" );
  148. }
  149. for ( int i = 0; i < m_iNumControlPoints; i++ )
  150. {
  151. if ( m_flOldLazyCapPerc[i] != m_flLazyCapPerc[i] )
  152. {
  153. m_flCapTimeLeft[i] = m_flLazyCapPerc[i] * m_flTeamCapTime[ TEAM_ARRAY(i,m_iCappingTeam[i]) ];
  154. }
  155. }
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose:
  159. //-----------------------------------------------------------------------------
  160. void C_BaseTeamObjectiveResource::UpdateControlPoint( const char *pszEvent, int index )
  161. {
  162. IGameEvent *event = gameeventmanager->CreateEvent( pszEvent );
  163. if ( event )
  164. {
  165. event->SetInt( "index", index );
  166. gameeventmanager->FireEventClientSide( event );
  167. }
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. float C_BaseTeamObjectiveResource::GetCPCapPercentage( int index )
  173. {
  174. Assert( 0 <= index && index <= m_iNumControlPoints );
  175. float flCapLength = m_flTeamCapTime[ TEAM_ARRAY(index,m_iCappingTeam[index]) ];
  176. if( flCapLength <= 0 )
  177. return 0.0f;
  178. float flElapsedTime = flCapLength - m_flCapTimeLeft[index];
  179. if( flElapsedTime > flCapLength )
  180. return 1.0f;
  181. return ( flElapsedTime / flCapLength );
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose:
  185. //-----------------------------------------------------------------------------
  186. int C_BaseTeamObjectiveResource::GetNumControlPointsOwned( void )
  187. {
  188. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  189. if ( !pPlayer )
  190. return 0;
  191. int iTeam = pPlayer->GetTeamNumber();
  192. int nOwned = 0;
  193. for ( int i = 0; i < GetNumControlPoints(); ++i )
  194. {
  195. if ( GetOwningTeam( i ) == iTeam )
  196. {
  197. ++nOwned;
  198. }
  199. }
  200. return nOwned;
  201. }
  202. //-----------------------------------------------------------------------------
  203. // Purpose:
  204. // team -
  205. //-----------------------------------------------------------------------------
  206. void C_BaseTeamObjectiveResource::SetOwningTeam( int index, int team )
  207. {
  208. if ( team == m_iCappingTeam[index] )
  209. {
  210. // successful cap, reset things
  211. m_iCappingTeam[index] = TEAM_UNASSIGNED;
  212. m_flCapTimeLeft[index] = 0.0f;
  213. m_flCapLastThinkTime[index] = 0;
  214. }
  215. m_iOwner[index] = team;
  216. UpdateControlPoint( "controlpoint_updateowner", index );
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. //-----------------------------------------------------------------------------
  221. void C_BaseTeamObjectiveResource::SetCappingTeam( int index, int team )
  222. {
  223. if ( team != GetOwningTeam( index ) && ( team > LAST_SHARED_TEAM ) )
  224. {
  225. m_flCapTimeLeft[index] = m_flTeamCapTime[ TEAM_ARRAY(index,team) ];
  226. }
  227. else
  228. {
  229. m_flCapTimeLeft[index] = 0.0;
  230. }
  231. m_iCappingTeam[index] = team;
  232. m_bWarnedOnFinalCap[index] = false;
  233. m_flCapLastThinkTime[index] = gpGlobals->curtime;
  234. SetNextClientThink( gpGlobals->curtime + RESOURCE_THINK_TIME );
  235. UpdateControlPoint( "controlpoint_updatecapping", index );
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Purpose:
  239. //-----------------------------------------------------------------------------
  240. void C_BaseTeamObjectiveResource::SetCapLayout( const char *pszLayout )
  241. {
  242. Q_strncpy( m_pszCapLayoutInHUD, pszLayout, MAX_CAPLAYOUT_LENGTH );
  243. UpdateControlPoint( "controlpoint_updatelayout" );
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose:
  247. //-----------------------------------------------------------------------------
  248. bool C_BaseTeamObjectiveResource::CapIsBlocked( int index )
  249. {
  250. Assert( 0 <= index && index <= m_iNumControlPoints );
  251. if ( m_flCapTimeLeft[index] )
  252. {
  253. // Blocked caps have capping teams & cap times, but no players on the point
  254. if ( GetNumPlayersInArea( index, m_iCappingTeam[index] ) == 0 )
  255. return true;
  256. }
  257. return false;
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose:
  261. //-----------------------------------------------------------------------------
  262. void C_BaseTeamObjectiveResource::ClientThink()
  263. {
  264. BaseClass::ClientThink();
  265. for ( int i = 0; i < MAX_CONTROL_POINTS; i++ )
  266. {
  267. if ( m_flCapTimeLeft[i] )
  268. {
  269. if ( !IsCPBlocked(i) )
  270. {
  271. bool bDeteriorateNormally = true;
  272. // Make sure there is only 1 team on the cap
  273. int iPlayersCapping = GetNumPlayersInArea( i, GetTeamInZone(i) );
  274. if ( iPlayersCapping > 0 )
  275. {
  276. float flReduction = gpGlobals->curtime - m_flCapLastThinkTime[i];
  277. if ( mp_capstyle.GetInt() == 1 )
  278. {
  279. // Diminishing returns for successive players.
  280. for ( int iPlayer = 1; iPlayer < iPlayersCapping; iPlayer++ )
  281. {
  282. flReduction += ((gpGlobals->curtime - m_flCapLastThinkTime[i]) / (float)(iPlayer+1));
  283. }
  284. }
  285. if ( GetTeamInZone(i) == m_iCappingTeam[i] )
  286. {
  287. bDeteriorateNormally = false;
  288. m_flCapTimeLeft[i] -= flReduction;
  289. if ( !m_bWarnedOnFinalCap[i] )
  290. {
  291. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  292. {
  293. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  294. // If this the local player's team, warn him
  295. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  296. if ( pPlayer )
  297. {
  298. if ( m_iCappingTeam[i] != TEAM_UNASSIGNED &&
  299. pPlayer->GetTeamNumber() != m_iCappingTeam[i] &&
  300. GetCapWarningLevel( i ) == CP_WARN_FINALCAP )
  301. {
  302. // Prevent spam
  303. if ( gpGlobals->curtime > ( m_flLastCapWarningTime[i] + 5 ) )
  304. {
  305. pPlayer->EmitSound( GetWarnSound( i ) );
  306. m_bWarnedOnFinalCap[i] = true;
  307. m_flLastCapWarningTime[i] = gpGlobals->curtime;
  308. }
  309. }
  310. }
  311. }
  312. }
  313. }
  314. else if ( GetOwningTeam(i) == TEAM_UNASSIGNED && GetTeamInZone(i) != TEAM_UNASSIGNED )
  315. {
  316. bDeteriorateNormally = false;
  317. m_flCapTimeLeft[i] += flReduction;
  318. }
  319. }
  320. if ( bDeteriorateNormally )
  321. {
  322. // Caps deteriorate over time
  323. // If we're not cappable at all right now, wipe all progress
  324. if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_iCappingTeam[i],i) )
  325. {
  326. float flCapLength = m_flTeamCapTime[ TEAM_ARRAY(i,m_iCappingTeam[i]) ];
  327. float flDecrease = (flCapLength / mp_capdeteriorate_time.GetFloat()) * (gpGlobals->curtime - m_flCapLastThinkTime[i]);
  328. if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() )
  329. {
  330. flDecrease *= 6;
  331. }
  332. m_flCapTimeLeft[i] += flDecrease;
  333. }
  334. else
  335. {
  336. m_flCapTimeLeft[i] = 0.0;
  337. }
  338. m_bWarnedOnFinalCap[i] = false;
  339. }
  340. }
  341. UpdateControlPoint( "controlpoint_updatelayout", i );
  342. m_flCapLastThinkTime[i] = gpGlobals->curtime;
  343. }
  344. }
  345. SetNextClientThink( gpGlobals->curtime + RESOURCE_THINK_TIME );
  346. }