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.

345 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Team management class. Contains all the details for a specific team
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "team.h"
  9. #include "player.h"
  10. #include "team_spawnpoint.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. CUtlVector< CTeam * > g_Teams;
  14. //-----------------------------------------------------------------------------
  15. // Purpose: SendProxy that converts the Team's player UtlVector to entindexes
  16. //-----------------------------------------------------------------------------
  17. void SendProxy_PlayerList( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
  18. {
  19. CTeam *pTeam = (CTeam*)pData;
  20. // If this assertion fails, then SendProxyArrayLength_PlayerArray must have failed.
  21. Assert( iElement < pTeam->m_aPlayers.Size() );
  22. CBasePlayer *pPlayer = pTeam->m_aPlayers[iElement];
  23. pOut->m_Int = pPlayer->entindex();
  24. }
  25. int SendProxyArrayLength_PlayerArray( const void *pStruct, int objectID )
  26. {
  27. CTeam *pTeam = (CTeam*)pStruct;
  28. return pTeam->m_aPlayers.Count();
  29. }
  30. // Datatable
  31. IMPLEMENT_SERVERCLASS_ST_NOBASE(CTeam, DT_Team)
  32. SendPropInt( SENDINFO(m_iTeamNum), 5 ),
  33. SendPropInt( SENDINFO(m_iScore), 0 ),
  34. SendPropInt( SENDINFO(m_iRoundsWon), 8 ),
  35. SendPropString( SENDINFO( m_szTeamname ) ),
  36. SendPropArray2(
  37. SendProxyArrayLength_PlayerArray,
  38. SendPropInt("player_array_element", 0, 4, 10, SPROP_UNSIGNED, SendProxy_PlayerList),
  39. MAX_PLAYERS,
  40. 0,
  41. "player_array"
  42. )
  43. END_SEND_TABLE()
  44. LINK_ENTITY_TO_CLASS( team_manager, CTeam );
  45. //-----------------------------------------------------------------------------
  46. // Purpose: Get a pointer to the specified team manager
  47. //-----------------------------------------------------------------------------
  48. CTeam *GetGlobalTeam( int iIndex )
  49. {
  50. if ( iIndex < 0 || iIndex >= GetNumberOfTeams() )
  51. return NULL;
  52. return g_Teams[ iIndex ];
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: Get the number of team managers
  56. //-----------------------------------------------------------------------------
  57. int GetNumberOfTeams( void )
  58. {
  59. return g_Teams.Size();
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose: Needed because this is an entity, but should never be used
  63. //-----------------------------------------------------------------------------
  64. CTeam::CTeam( void )
  65. {
  66. memset( m_szTeamname.GetForModify(), 0, sizeof(m_szTeamname) );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. //-----------------------------------------------------------------------------
  71. CTeam::~CTeam( void )
  72. {
  73. m_aSpawnPoints.Purge();
  74. m_aPlayers.Purge();
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose: Called every frame
  78. //-----------------------------------------------------------------------------
  79. void CTeam::Think( void )
  80. {
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Teams are always transmitted to clients
  84. //-----------------------------------------------------------------------------
  85. int CTeam::UpdateTransmitState()
  86. {
  87. return SetTransmitState( FL_EDICT_ALWAYS );
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Visibility/scanners
  91. //-----------------------------------------------------------------------------
  92. bool CTeam::ShouldTransmitToPlayer( CBasePlayer* pRecipient, CBaseEntity* pEntity ) const
  93. {
  94. // Always transmit the observer target to players
  95. if ( pRecipient && pRecipient->IsObserver() && pRecipient->GetObserverTarget() == pEntity )
  96. return true;
  97. return false;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Initialization
  101. //-----------------------------------------------------------------------------
  102. void CTeam::Init( const char *pName, int iNumber )
  103. {
  104. InitializeSpawnpoints();
  105. InitializePlayers();
  106. m_iScore = 0;
  107. Q_strncpy( m_szTeamname.GetForModify(), pName, MAX_TEAM_NAME_LENGTH );
  108. m_iTeamNum = iNumber;
  109. }
  110. //-----------------------------------------------------------------------------
  111. // DATA HANDLING
  112. //-----------------------------------------------------------------------------
  113. int CTeam::GetTeamNumber( void ) const
  114. {
  115. return m_iTeamNum;
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose: Get the team's name
  119. //-----------------------------------------------------------------------------
  120. const char *CTeam::GetName( void ) const
  121. {
  122. return m_szTeamname;
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Purpose: Update the player's client data
  126. //-----------------------------------------------------------------------------
  127. void CTeam::UpdateClientData( CBasePlayer *pPlayer )
  128. {
  129. }
  130. //------------------------------------------------------------------------------------------------------------------
  131. // SPAWNPOINTS
  132. //-----------------------------------------------------------------------------
  133. // Purpose:
  134. //-----------------------------------------------------------------------------
  135. void CTeam::InitializeSpawnpoints( void )
  136. {
  137. m_iLastSpawn = 0;
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. //-----------------------------------------------------------------------------
  142. void CTeam::AddSpawnpoint( CTeamSpawnPoint *pSpawnpoint )
  143. {
  144. m_aSpawnPoints.AddToTail( pSpawnpoint );
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Purpose:
  148. //-----------------------------------------------------------------------------
  149. void CTeam::RemoveSpawnpoint( CTeamSpawnPoint *pSpawnpoint )
  150. {
  151. for (int i = 0; i < m_aSpawnPoints.Size(); i++ )
  152. {
  153. if ( m_aSpawnPoints[i] == pSpawnpoint )
  154. {
  155. m_aSpawnPoints.Remove( i );
  156. return;
  157. }
  158. }
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Purpose: Spawn the player at one of this team's spawnpoints. Return true if successful.
  162. //-----------------------------------------------------------------------------
  163. CBaseEntity *CTeam::SpawnPlayer( CBasePlayer *pPlayer )
  164. {
  165. if ( m_aSpawnPoints.Size() == 0 )
  166. return NULL;
  167. // Randomize the start spot
  168. int iSpawn = m_iLastSpawn + random->RandomInt( 1,3 );
  169. if ( iSpawn >= m_aSpawnPoints.Size() )
  170. iSpawn -= m_aSpawnPoints.Size();
  171. int iStartingSpawn = iSpawn;
  172. // Now loop through the spawnpoints and pick one
  173. int loopCount = 0;
  174. do
  175. {
  176. if ( iSpawn >= m_aSpawnPoints.Size() )
  177. {
  178. ++loopCount;
  179. iSpawn = 0;
  180. }
  181. // check if pSpot is valid, and that the player is on the right team
  182. if ( (loopCount > 3) || m_aSpawnPoints[iSpawn]->IsValid( pPlayer ) )
  183. {
  184. // DevMsg( 1, "player: spawning at (%s)\n", STRING(m_aSpawnPoints[iSpawn]->m_iName) );
  185. m_aSpawnPoints[iSpawn]->m_OnPlayerSpawn.FireOutput( pPlayer, m_aSpawnPoints[iSpawn] );
  186. m_iLastSpawn = iSpawn;
  187. return m_aSpawnPoints[iSpawn];
  188. }
  189. iSpawn++;
  190. } while ( iSpawn != iStartingSpawn ); // loop if we're not back to the start
  191. return NULL;
  192. }
  193. //------------------------------------------------------------------------------------------------------------------
  194. // PLAYERS
  195. //-----------------------------------------------------------------------------
  196. // Purpose:
  197. //-----------------------------------------------------------------------------
  198. void CTeam::InitializePlayers( void )
  199. {
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Purpose: Add the specified player to this team. Remove them from their current team, if any.
  203. //-----------------------------------------------------------------------------
  204. void CTeam::AddPlayer( CBasePlayer *pPlayer )
  205. {
  206. m_aPlayers.AddToTail( pPlayer );
  207. NetworkStateChanged();
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Purpose: Remove this player from the team
  211. //-----------------------------------------------------------------------------
  212. void CTeam::RemovePlayer( CBasePlayer *pPlayer )
  213. {
  214. m_aPlayers.FindAndRemove( pPlayer );
  215. NetworkStateChanged();
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose: Return the number of players in this team.
  219. //-----------------------------------------------------------------------------
  220. int CTeam::GetNumPlayers( void ) const
  221. {
  222. return m_aPlayers.Size();
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose: Get a specific player
  226. //-----------------------------------------------------------------------------
  227. CBasePlayer *CTeam::GetPlayer( int iIndex ) const
  228. {
  229. Assert( iIndex >= 0 && iIndex < m_aPlayers.Size() );
  230. return m_aPlayers[ iIndex ];
  231. }
  232. //------------------------------------------------------------------------------------------------------------------
  233. // SCORING
  234. //-----------------------------------------------------------------------------
  235. // Purpose: Add / Remove score for this team
  236. //-----------------------------------------------------------------------------
  237. void CTeam::AddScore( int iScore )
  238. {
  239. m_iScore += iScore;
  240. }
  241. void CTeam::SetScore( int iScore )
  242. {
  243. m_iScore = iScore;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose: Get this team's score
  247. //-----------------------------------------------------------------------------
  248. int CTeam::GetScore( void ) const
  249. {
  250. return m_iScore;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose:
  254. //-----------------------------------------------------------------------------
  255. void CTeam::ResetScores( void )
  256. {
  257. SetScore(0);
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose:
  261. //-----------------------------------------------------------------------------
  262. void CTeam::AwardAchievement( int iAchievement )
  263. {
  264. Assert( iAchievement >= 0 && iAchievement < 255 ); // must fit in short
  265. CRecipientFilter filter;
  266. int iNumPlayers = GetNumPlayers();
  267. for ( int i=0;i<iNumPlayers;i++ )
  268. {
  269. if ( GetPlayer(i) )
  270. {
  271. filter.AddRecipient( GetPlayer(i) );
  272. }
  273. }
  274. UserMessageBegin( filter, "AchievementEvent" );
  275. WRITE_SHORT( iAchievement );
  276. MessageEnd();
  277. }
  278. int CTeam::GetAliveMembers( void ) const
  279. {
  280. int iAlive = 0;
  281. int iNumPlayers = GetNumPlayers();
  282. for ( int i=0;i<iNumPlayers;i++ )
  283. {
  284. if ( GetPlayer(i) && GetPlayer(i)->IsAlive() )
  285. {
  286. iAlive++;
  287. }
  288. }
  289. return iAlive;
  290. }