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.

378 lines
12 KiB

  1. //===== Copyright � 1996-2006, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "team_control_point_master.h"
  9. #include "teamplayroundbased_gamerules.h"
  10. #include "team_control_point_round.h"
  11. // NOTE: This has to be the last file included!
  12. #include "tier0/memdbgon.h"
  13. BEGIN_DATADESC( CTeamControlPointRound )
  14. DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
  15. DEFINE_KEYFIELD( m_iszCPNames, FIELD_STRING, "cpr_cp_names" ),
  16. DEFINE_KEYFIELD( m_nPriority, FIELD_INTEGER, "cpr_priority" ),
  17. DEFINE_KEYFIELD( m_iInvalidCapWinner, FIELD_INTEGER, "cpr_restrict_team_cap_win" ),
  18. DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "cpr_printname" ),
  19. // DEFINE_FIELD( m_ControlPoints, CUtlVector < CHandle < CTeamControlPoint > > ),
  20. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  21. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  22. DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ),
  23. DEFINE_OUTPUT( m_OnStart, "OnStart" ),
  24. DEFINE_OUTPUT( m_OnEnd, "OnEnd" ),
  25. DEFINE_OUTPUT( m_OnWonByTeam1, "OnWonByTeam1" ),
  26. DEFINE_OUTPUT( m_OnWonByTeam2, "OnWonByTeam2" ),
  27. END_DATADESC()
  28. LINK_ENTITY_TO_CLASS( team_control_point_round, CTeamControlPointRound );
  29. //-----------------------------------------------------------------------------
  30. // Purpose:
  31. //-----------------------------------------------------------------------------
  32. void CTeamControlPointRound::Spawn( void )
  33. {
  34. SetTouch( NULL );
  35. BaseClass::Spawn();
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Purpose:
  39. //-----------------------------------------------------------------------------
  40. void CTeamControlPointRound::Activate( void )
  41. {
  42. BaseClass::Activate();
  43. FindControlPoints();
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. void CTeamControlPointRound::FindControlPoints( void )
  49. {
  50. // Let out control point masters know that the round has started
  51. CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
  52. if ( pMaster )
  53. {
  54. // go through all the points
  55. CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetControlPointName() );
  56. while( pEnt )
  57. {
  58. CTeamControlPoint *pPoint = assert_cast<CTeamControlPoint *>(pEnt);
  59. if ( pPoint )
  60. {
  61. const char *pString = STRING( m_iszCPNames );
  62. const char *pName = STRING( pPoint->GetEntityName() );
  63. // HACK to work around a problem with cp_a being returned for an entity name with cp_A
  64. const char *pos = Q_stristr( pString, pName );
  65. if ( pos )
  66. {
  67. int len = Q_strlen( STRING( pPoint->GetEntityName() ) );
  68. if ( *(pos + len) == ' ' || *(pos + len) == '\0' )
  69. {
  70. if( m_ControlPoints.Find( pPoint ) == m_ControlPoints.InvalidIndex() )
  71. {
  72. DevMsg( 2, "Adding control point %s to control point round %s\n", pPoint->GetEntityName().ToCStr(), GetEntityName().ToCStr() );
  73. m_ControlPoints.AddToHead( pPoint );
  74. }
  75. }
  76. }
  77. }
  78. pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetControlPointName() );
  79. }
  80. }
  81. if( m_ControlPoints.Count() == 0 )
  82. {
  83. Warning( "Error! No control points found in map for team_game_round %s!\n", GetEntityName().ToCStr() );
  84. }
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Purpose: Check that the points aren't all held by one team if they are
  88. // this will reset the round and will reset all the points
  89. //-----------------------------------------------------------------------------
  90. int CTeamControlPointRound::CheckWinConditions( void )
  91. {
  92. int iWinners = TeamOwnsAllPoints();
  93. if ( ( iWinners >= FIRST_GAME_TEAM ) &&
  94. ( iWinners != m_iInvalidCapWinner ) )
  95. {
  96. FireTeamWinOutput( iWinners );
  97. return iWinners;
  98. }
  99. return -1;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. //-----------------------------------------------------------------------------
  104. void CTeamControlPointRound::FireTeamWinOutput( int iWinningTeam )
  105. {
  106. // Remap team so that first game team = 1
  107. switch( iWinningTeam - FIRST_GAME_TEAM+1 )
  108. {
  109. case 1:
  110. m_OnWonByTeam1.FireOutput( this, this );
  111. break;
  112. case 2:
  113. m_OnWonByTeam2.FireOutput( this, this );
  114. break;
  115. default:
  116. Assert(0);
  117. break;
  118. }
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. //-----------------------------------------------------------------------------
  123. int CTeamControlPointRound::GetPointOwner( int point )
  124. {
  125. Assert( point >= 0 );
  126. Assert( point < MAX_CONTROL_POINTS );
  127. CTeamControlPoint *pPoint = m_ControlPoints[point];
  128. if ( pPoint )
  129. return pPoint->GetOwner();
  130. return TEAM_UNASSIGNED;
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose: This function returns the team that owns all the cap points.
  134. // If its not the case that one team owns them all, it returns 0.
  135. //
  136. // Can be passed an overriding team. If this is not null, the passed team
  137. // number will be used for that cp. Used to predict if that CP changing would
  138. // win the game.
  139. //-----------------------------------------------------------------------------
  140. int CTeamControlPointRound::TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint /* = NULL */, int iOverrideNewTeam /* = TEAM_UNASSIGNED */ )
  141. {
  142. int iWinningTeam = TEAM_INVALID;
  143. // if TEAM_INVALID, haven't found a flag yet
  144. // if TEAM_UNASSIGNED, it's still being contested
  145. // for each control point
  146. for( int i = 0 ; i < m_ControlPoints.Count() ; i++ )
  147. {
  148. int owner = m_ControlPoints[i]->GetOwner();
  149. if ( pOverridePoint == m_ControlPoints[i] )
  150. {
  151. owner = iOverrideNewTeam;
  152. }
  153. // the first one we find, set the win to true
  154. if ( iWinningTeam == TEAM_INVALID )
  155. {
  156. iWinningTeam = owner;
  157. }
  158. // unassigned means this is being contested, move on
  159. else if ( iWinningTeam == TEAM_UNASSIGNED )
  160. {
  161. continue;
  162. }
  163. // if we find another one in the group that isn't the same owner, set the win to false
  164. else if ( owner != iWinningTeam )
  165. {
  166. iWinningTeam = TEAM_UNASSIGNED;
  167. }
  168. }
  169. // report the first win we find as the winner
  170. if ( iWinningTeam >= FIRST_GAME_TEAM )
  171. {
  172. return iWinningTeam;
  173. }
  174. // no wins yet
  175. return TEAM_UNASSIGNED;
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose:
  179. //-----------------------------------------------------------------------------
  180. bool CTeamControlPointRound::WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner )
  181. {
  182. return ( TeamOwnsAllPoints( pPoint, iNewOwner ) == iNewOwner );
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Purpose:
  186. //-----------------------------------------------------------------------------
  187. void CTeamControlPointRound::InputEnable( inputdata_t &input )
  188. {
  189. m_bDisabled = false;
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Purpose:
  193. //-----------------------------------------------------------------------------
  194. void CTeamControlPointRound::InputDisable( inputdata_t &input )
  195. {
  196. m_bDisabled = true;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Purpose:
  200. //-----------------------------------------------------------------------------
  201. void CTeamControlPointRound::InputRoundSpawn( inputdata_t &input )
  202. {
  203. // clear out old control points
  204. m_ControlPoints.RemoveAll();
  205. // find the control points
  206. FindControlPoints();
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose:
  210. //-----------------------------------------------------------------------------
  211. void CTeamControlPointRound::SetupSpawnPoints( void )
  212. {
  213. CTeamplayRoundBasedRules *pRules = TeamplayRoundBasedRules();
  214. if ( pRules )
  215. {
  216. pRules->SetupSpawnPointsForRound();
  217. }
  218. }
  219. //-----------------------------------------------------------------------------
  220. // Purpose:
  221. //-----------------------------------------------------------------------------
  222. void CTeamControlPointRound::SelectedToPlay( void )
  223. {
  224. SetupSpawnPoints();
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Purpose:
  228. //-----------------------------------------------------------------------------
  229. void CTeamControlPointRound::FireOnStartOutput( void )
  230. {
  231. m_OnStart.FireOutput( this, this );
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose:
  235. //-----------------------------------------------------------------------------
  236. void CTeamControlPointRound::FireOnEndOutput( void )
  237. {
  238. m_OnEnd.FireOutput( this, this );
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Purpose:
  242. //-----------------------------------------------------------------------------
  243. bool CTeamControlPointRound::IsControlPointInRound( CTeamControlPoint *pPoint )
  244. {
  245. if ( !pPoint )
  246. {
  247. return false;
  248. }
  249. return ( m_ControlPoints.Find( pPoint ) != m_ControlPoints.InvalidIndex() );
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Purpose:
  253. //-----------------------------------------------------------------------------
  254. bool CTeamControlPointRound::IsPlayable( void )
  255. {
  256. int iWinners = TeamOwnsAllPoints();
  257. if ( ( iWinners >= FIRST_GAME_TEAM ) &&
  258. ( iWinners != m_iInvalidCapWinner ) )
  259. {
  260. return false; // someone has already won this round
  261. }
  262. return true;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // Purpose:
  266. //-----------------------------------------------------------------------------
  267. bool CTeamControlPointRound::MakePlayable( void )
  268. {
  269. CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
  270. if ( pMaster )
  271. {
  272. if ( !IsPlayable() )
  273. {
  274. // we need to try switching the owners of the teams to make this round playable
  275. for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams() ; i++ )
  276. {
  277. for ( int j = 0 ; j < m_ControlPoints.Count() ; j++ )
  278. {
  279. if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[j]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team)
  280. ( !WouldNewCPOwnerWinGame( m_ControlPoints[j], i ) ) ) // making this change would make this round playable
  281. {
  282. // need to find the trigger area associated with this point
  283. CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetTriggerAreaCaptureName() );
  284. while( pEnt )
  285. {
  286. CTriggerAreaCapture *pArea = assert_cast<CTriggerAreaCapture*>( pEnt );
  287. if ( pArea )
  288. {
  289. if ( pArea->TeamCanCap( i ) )
  290. {
  291. CHandle<CTeamControlPoint> hPoint = pArea->GetControlPoint();
  292. if ( hPoint == m_ControlPoints[j] )
  293. {
  294. // found!
  295. pArea->ForceOwner( i ); // this updates the trigger_area *and* the control_point
  296. return true;
  297. }
  298. }
  299. }
  300. pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetTriggerAreaCaptureName() );
  301. }
  302. }
  303. }
  304. }
  305. }
  306. }
  307. return false;
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Purpose: returns the first point found that the given team owns
  311. //-----------------------------------------------------------------------------
  312. CHandle<CTeamControlPoint> CTeamControlPointRound::GetPointOwnedBy( int iTeam )
  313. {
  314. for( int i = 0 ; i < m_ControlPoints.Count() ; i++ )
  315. {
  316. if ( m_ControlPoints[i]->GetOwner() == iTeam )
  317. {
  318. return m_ControlPoints[i];
  319. }
  320. }
  321. return NULL;
  322. }