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.

371 lines
9.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Entity that propagates general data needed by clients for every player.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "c_playerresource.h"
  9. #include "c_team.h"
  10. #include "gamestringpool.h"
  11. #ifdef HL2MP
  12. #include "hl2mp_gamerules.h"
  13. #endif
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. const float PLAYER_RESOURCE_THINK_INTERVAL = 0.2f;
  17. IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_PlayerResource, DT_PlayerResource, CPlayerResource)
  18. RecvPropArray3( RECVINFO_ARRAY(m_iPing), RecvPropInt( RECVINFO(m_iPing[0]))),
  19. RecvPropArray3( RECVINFO_ARRAY(m_iScore), RecvPropInt( RECVINFO(m_iScore[0]))),
  20. RecvPropArray3( RECVINFO_ARRAY(m_iDeaths), RecvPropInt( RECVINFO(m_iDeaths[0]))),
  21. RecvPropArray3( RECVINFO_ARRAY(m_bConnected), RecvPropInt( RECVINFO(m_bConnected[0]))),
  22. RecvPropArray3( RECVINFO_ARRAY(m_iTeam), RecvPropInt( RECVINFO(m_iTeam[0]))),
  23. RecvPropArray3( RECVINFO_ARRAY(m_bAlive), RecvPropInt( RECVINFO(m_bAlive[0]))),
  24. RecvPropArray3( RECVINFO_ARRAY(m_iHealth), RecvPropInt( RECVINFO(m_iHealth[0]))),
  25. RecvPropArray3( RECVINFO_ARRAY(m_iAccountID), RecvPropInt( RECVINFO(m_iAccountID[0]))),
  26. RecvPropArray3( RECVINFO_ARRAY(m_bValid), RecvPropInt( RECVINFO(m_bValid[0]))),
  27. END_RECV_TABLE()
  28. BEGIN_PREDICTION_DATA( C_PlayerResource )
  29. DEFINE_PRED_ARRAY( m_szName, FIELD_STRING, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  30. DEFINE_PRED_ARRAY( m_iPing, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  31. DEFINE_PRED_ARRAY( m_iScore, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  32. DEFINE_PRED_ARRAY( m_iDeaths, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  33. DEFINE_PRED_ARRAY( m_bConnected, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  34. DEFINE_PRED_ARRAY( m_iTeam, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  35. DEFINE_PRED_ARRAY( m_bAlive, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  36. DEFINE_PRED_ARRAY( m_iHealth, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  37. DEFINE_PRED_ARRAY( m_iAccountID, FIELD_INTEGER, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  38. DEFINE_PRED_ARRAY( m_bValid, FIELD_BOOLEAN, MAX_PLAYERS+1, FTYPEDESC_PRIVATE ),
  39. END_PREDICTION_DATA()
  40. C_PlayerResource *g_PR;
  41. IGameResources * GameResources( void ) { return g_PR; }
  42. //-----------------------------------------------------------------------------
  43. // Purpose:
  44. //-----------------------------------------------------------------------------
  45. C_PlayerResource::C_PlayerResource()
  46. {
  47. memset( m_iPing, 0, sizeof( m_iPing ) );
  48. // memset( m_iPacketloss, 0, sizeof( m_iPacketloss ) );
  49. memset( m_iScore, 0, sizeof( m_iScore ) );
  50. memset( m_iDeaths, 0, sizeof( m_iDeaths ) );
  51. memset( m_bConnected, 0, sizeof( m_bConnected ) );
  52. memset( m_iTeam, 0, sizeof( m_iTeam ) );
  53. memset( m_bAlive, 0, sizeof( m_bAlive ) );
  54. memset( m_iHealth, 0, sizeof( m_iHealth ) );
  55. memset( m_iAccountID, 0, sizeof( m_iAccountID ) );
  56. memset( m_bValid, 0, sizeof( m_bValid ) );
  57. m_szUnconnectedName = 0;
  58. for ( int i=0; i<MAX_TEAMS; i++ )
  59. {
  60. m_Colors[i] = COLOR_GREY;
  61. }
  62. #ifdef HL2MP
  63. m_Colors[TEAM_COMBINE] = COLOR_BLUE;
  64. m_Colors[TEAM_REBELS] = COLOR_RED;
  65. m_Colors[TEAM_UNASSIGNED] = COLOR_YELLOW;
  66. #endif
  67. g_PR = this;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose:
  71. //-----------------------------------------------------------------------------
  72. C_PlayerResource::~C_PlayerResource()
  73. {
  74. g_PR = NULL;
  75. }
  76. void C_PlayerResource::OnDataChanged(DataUpdateType_t updateType)
  77. {
  78. BaseClass::OnDataChanged( updateType );
  79. if ( updateType == DATA_UPDATE_CREATED )
  80. {
  81. SetNextClientThink( gpGlobals->curtime + PLAYER_RESOURCE_THINK_INTERVAL );
  82. }
  83. }
  84. void C_PlayerResource::UpdatePlayerName( int slot )
  85. {
  86. if ( slot < 1 || slot > MAX_PLAYERS )
  87. {
  88. Error( "UpdatePlayerName with bogus slot %d\n", slot );
  89. return;
  90. }
  91. if ( !m_szUnconnectedName )
  92. {
  93. m_szUnconnectedName = AllocPooledString( PLAYER_UNCONNECTED_NAME );
  94. }
  95. player_info_t sPlayerInfo;
  96. if ( IsConnected( slot ) && engine->GetPlayerInfo( slot, &sPlayerInfo ) )
  97. {
  98. m_szName[slot] = AllocPooledString( sPlayerInfo.name );
  99. }
  100. else
  101. {
  102. if ( !IsValid( slot ) )
  103. {
  104. m_szName[slot] = m_szUnconnectedName;
  105. }
  106. }
  107. }
  108. void C_PlayerResource::ClientThink()
  109. {
  110. BaseClass::ClientThink();
  111. for ( int i = 1; i <= MAX_PLAYERS; ++i )
  112. {
  113. UpdatePlayerName( i );
  114. }
  115. SetNextClientThink( gpGlobals->curtime + PLAYER_RESOURCE_THINK_INTERVAL );
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose:
  119. //-----------------------------------------------------------------------------
  120. const char *C_PlayerResource::GetPlayerName( int iIndex )
  121. {
  122. if ( iIndex < 1 || iIndex > MAX_PLAYERS )
  123. {
  124. Assert( false );
  125. return PLAYER_ERROR_NAME;
  126. }
  127. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  128. return PLAYER_UNCONNECTED_NAME;
  129. // X360TBD: Network - figure out why the name isn't set
  130. if ( !m_szName[ iIndex ] || !Q_stricmp( m_szName[ iIndex ], PLAYER_UNCONNECTED_NAME ) )
  131. {
  132. // If you get a full "reset" uncompressed update from server, then you can have NULLNAME show up in the scoreboard
  133. UpdatePlayerName( iIndex );
  134. }
  135. // This gets updated in ClientThink, so it could be up to 1 second out of date, oh well.
  136. return m_szName[iIndex];
  137. }
  138. bool C_PlayerResource::IsAlive(int iIndex )
  139. {
  140. return m_bAlive[iIndex];
  141. }
  142. int C_PlayerResource::GetTeam(int iIndex )
  143. {
  144. if ( iIndex < 1 || iIndex > MAX_PLAYERS )
  145. {
  146. Assert( false );
  147. return 0;
  148. }
  149. else
  150. {
  151. return m_iTeam[iIndex];
  152. }
  153. }
  154. const char * C_PlayerResource::GetTeamName(int index_)
  155. {
  156. C_Team *team = GetGlobalTeam( index_ );
  157. if ( !team )
  158. return "Unknown";
  159. return team->Get_Name();
  160. }
  161. int C_PlayerResource::GetTeamScore(int index_ )
  162. {
  163. C_Team *team = GetGlobalTeam( index_ );
  164. if ( !team )
  165. return 0;
  166. return team->Get_Score();
  167. }
  168. int C_PlayerResource::GetFrags(int index_ )
  169. {
  170. return 666;
  171. }
  172. bool C_PlayerResource::IsLocalPlayer(int index_ )
  173. {
  174. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  175. if ( !pPlayer )
  176. return false;
  177. return (index_ == pPlayer->entindex() );
  178. }
  179. bool C_PlayerResource::IsHLTV(int index_ )
  180. {
  181. if ( !IsConnected( index_ ) && !IsValid( index_ ) )
  182. return false;
  183. player_info_t sPlayerInfo;
  184. if ( engine->GetPlayerInfo( index_, &sPlayerInfo ) )
  185. {
  186. return sPlayerInfo.ishltv;
  187. }
  188. return false;
  189. }
  190. bool C_PlayerResource::IsReplay(int index_ )
  191. {
  192. #if defined( REPLAY_ENABLED )
  193. if ( !IsConnected( index_ ) && !IsValid( index_ ) )
  194. return false;
  195. player_info_t sPlayerInfo;
  196. if ( engine->GetPlayerInfo( index_, &sPlayerInfo ) )
  197. {
  198. return sPlayerInfo.isreplay;
  199. }
  200. #endif
  201. return false;
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose:
  205. //-----------------------------------------------------------------------------
  206. bool C_PlayerResource::IsFakePlayer( int iIndex )
  207. {
  208. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  209. return false;
  210. // Yuck, make sure it's up to date
  211. player_info_t sPlayerInfo;
  212. if ( engine->GetPlayerInfo( iIndex, &sPlayerInfo ) )
  213. {
  214. return sPlayerInfo.fakeplayer;
  215. }
  216. return false;
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. //-----------------------------------------------------------------------------
  221. int C_PlayerResource::GetPing( int iIndex )
  222. {
  223. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  224. return 0;
  225. return m_iPing[iIndex];
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Purpose:
  229. /*-----------------------------------------------------------------------------
  230. int C_PlayerResource::GetPacketloss( int iIndex )
  231. {
  232. if ( !IsConnected( iIndex ) && !IsPreservedData( iIndex ) )
  233. return 0;
  234. return m_iPacketloss[iIndex];
  235. }*/
  236. //-----------------------------------------------------------------------------
  237. // Purpose:
  238. //-----------------------------------------------------------------------------
  239. int C_PlayerResource::GetPlayerScore( int iIndex )
  240. {
  241. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  242. return 0;
  243. return m_iScore[iIndex];
  244. }
  245. //-----------------------------------------------------------------------------
  246. // Purpose:
  247. //-----------------------------------------------------------------------------
  248. int C_PlayerResource::GetDeaths( int iIndex )
  249. {
  250. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  251. return 0;
  252. return m_iDeaths[iIndex];
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose:
  256. //-----------------------------------------------------------------------------
  257. int C_PlayerResource::GetHealth( int iIndex )
  258. {
  259. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  260. return 0;
  261. return m_iHealth[iIndex];
  262. }
  263. const Color &C_PlayerResource::GetTeamColor(int index_ )
  264. {
  265. if ( index_ < 0 || index_ >= MAX_TEAMS )
  266. {
  267. Assert( false );
  268. static Color blah;
  269. return blah;
  270. }
  271. else
  272. {
  273. return m_Colors[index_];
  274. }
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Purpose:
  278. //-----------------------------------------------------------------------------
  279. bool C_PlayerResource::IsConnected( int iIndex )
  280. {
  281. if ( iIndex < 1 || iIndex > MAX_PLAYERS )
  282. return false;
  283. else
  284. return m_bConnected[iIndex];
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose:
  288. //-----------------------------------------------------------------------------
  289. uint32 C_PlayerResource::GetAccountID( int iIndex )
  290. {
  291. if ( ( iIndex < 0 ) || ( iIndex >= ARRAYSIZE( m_iAccountID ) ) )
  292. return 0;
  293. if ( !IsConnected( iIndex ) && !IsValid( iIndex ) )
  294. return 0;
  295. return m_iAccountID[iIndex];
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Purpose:
  299. //-----------------------------------------------------------------------------
  300. bool C_PlayerResource::IsValid( int iIndex )
  301. {
  302. if ( ( iIndex < 0 ) || ( iIndex >= ARRAYSIZE( m_bValid ) ) )
  303. return false;
  304. return m_bValid[iIndex];
  305. }