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.

340 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: The CS game stats header
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef CS_GAMESTATS_H
  8. #define CS_GAMESTATS_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "cs_blackmarket.h"
  13. #include "gamestats.h"
  14. #include "cs_gamestats_shared.h"
  15. #include "GameEventListener.h"
  16. #include "steamworks_gamestats.h"
  17. #include "weapon_csbase.h"
  18. // forward declares
  19. class CBreakableProp;
  20. #define CS_STATS_BLOB_VERSION 3
  21. const float cDisseminationTimeHigh = 0.25f; // Time interval for high priority stats sent to the player
  22. const float cDisseminationTimeLow = 2.5f; // Time interval for medium priority stats sent to the player
  23. int GetCSLevelIndex( const char *pLevelName );
  24. typedef struct
  25. {
  26. char szGameName[8];
  27. byte iVersion;
  28. char szMapName[32];
  29. char ipAddr[4];
  30. short port;
  31. int serverid;
  32. } gamestats_header_t;
  33. typedef struct
  34. {
  35. gamestats_header_t header;
  36. short iMinutesPlayed;
  37. short iTerroristVictories[CS_NUM_LEVELS];
  38. short iCounterTVictories[CS_NUM_LEVELS];
  39. short iBlackMarketPurchases[WEAPON_MAX];
  40. short iAutoBuyPurchases;
  41. short iReBuyPurchases;
  42. short iAutoBuyM4A1Purchases;
  43. short iAutoBuyAK47Purchases;
  44. short iAutoBuyFamasPurchases;
  45. short iAutoBuyGalilPurchases;
  46. short iAutoBuyVestHelmPurchases;
  47. short iAutoBuyVestPurchases;
  48. } cs_gamestats_t;
  49. extern short g_iWeaponPurchases[WEAPON_MAX];
  50. extern float g_flGameStatsUpdateTime;
  51. extern short g_iTerroristVictories[CS_NUM_LEVELS];
  52. extern short g_iCounterTVictories[CS_NUM_LEVELS];
  53. extern short g_iWeaponPurchases[WEAPON_MAX];
  54. extern short g_iAutoBuyPurchases;
  55. extern short g_iReBuyPurchases;
  56. extern short g_iAutoBuyM4A1Purchases;
  57. extern short g_iAutoBuyAK47Purchases;
  58. extern short g_iAutoBuyFamasPurchases;
  59. extern short g_iAutoBuyGalilPurchases;
  60. extern short g_iAutoBuyVestHelmPurchases;
  61. extern short g_iAutoBuyVestPurchases;
  62. struct sHappyCamperSnipePosition
  63. {
  64. sHappyCamperSnipePosition( int userid, Vector pos ) : m_iUserID(userid), m_vPos(pos) {}
  65. int m_iUserID;
  66. Vector m_vPos;
  67. };
  68. struct SMarketPurchases : public BaseStatData
  69. {
  70. SMarketPurchases( uint64 ulPlayerID, int iPrice, const char *pName ) : m_nPlayerID(ulPlayerID), ItemCost(iPrice)
  71. {
  72. if ( pName )
  73. {
  74. Q_strncpy( ItemID, pName, ARRAYSIZE(ItemID) );
  75. }
  76. else
  77. {
  78. Q_strncpy( ItemID, "unknown", ARRAYSIZE(ItemID) );
  79. }
  80. }
  81. uint64 m_nPlayerID;
  82. int ItemCost;
  83. char ItemID[64];
  84. BEGIN_STAT_TABLE( "CSSMarketPurchase" )
  85. REGISTER_STAT( m_nPlayerID )
  86. REGISTER_STAT( ItemCost )
  87. REGISTER_STAT_STRING( ItemID )
  88. END_STAT_TABLE()
  89. };
  90. typedef CUtlVector< SMarketPurchases* > VectorMarketPurchaseData;
  91. struct WeaponStats
  92. {
  93. int shots;
  94. int hits;
  95. int kills;
  96. int damage;
  97. };
  98. struct SCSSWeaponData : public BaseStatData
  99. {
  100. SCSSWeaponData( const char *pWeaponName, const WeaponStats &wpnData )
  101. {
  102. if ( pWeaponName )
  103. {
  104. Q_strncpy( WeaponID, pWeaponName, ARRAYSIZE(WeaponID) );
  105. }
  106. else
  107. {
  108. Q_strncpy( WeaponID, "unknown", ARRAYSIZE(WeaponID) );
  109. }
  110. Shots = wpnData.shots;
  111. Hits = wpnData.hits;
  112. Kills = wpnData.kills;
  113. Damage = wpnData.damage;
  114. }
  115. char WeaponID[64];
  116. int Shots;
  117. int Hits;
  118. int Kills;
  119. int Damage;
  120. BEGIN_STAT_TABLE( "CSSWeaponData" )
  121. REGISTER_STAT_STRING( WeaponID )
  122. REGISTER_STAT( Shots )
  123. REGISTER_STAT( Hits )
  124. REGISTER_STAT( Kills )
  125. REGISTER_STAT( Damage )
  126. END_STAT_TABLE()
  127. };
  128. typedef CUtlVector< SCSSWeaponData* > CSSWeaponData;
  129. struct SCSSDeathData : public BaseStatData
  130. {
  131. SCSSDeathData( CBasePlayer *pVictim, const CTakeDamageInfo &info )
  132. {
  133. m_bUseGlobalData = false;
  134. m_DeathPos = info.GetDamagePosition();
  135. m_iVictimTeam = pVictim->GetTeamNumber();
  136. CCSPlayer *pCSPlayer = ToCSPlayer( info.GetAttacker() );
  137. if ( pCSPlayer )
  138. {
  139. m_iKillerTeam = pCSPlayer->GetTeamNumber();
  140. }
  141. else
  142. {
  143. m_iKillerTeam = -1;
  144. }
  145. const char *pszWeaponName = info.GetInflictor() ? info.GetInflictor()->GetClassname() : "unknown";
  146. if ( pszWeaponName )
  147. {
  148. if ( V_strcmp(pszWeaponName, "player") == 0 )
  149. {
  150. // get the player's weapon
  151. if ( pCSPlayer && pCSPlayer->GetActiveCSWeapon() )
  152. {
  153. pszWeaponName = pCSPlayer->GetActiveCSWeapon()->GetClassname();
  154. }
  155. }
  156. }
  157. m_uiDeathParam = WEAPON_NONE;
  158. if ( (m_uiDeathParam = AliasToWeaponID( pszWeaponName )) == WEAPON_NONE )
  159. {
  160. m_uiDeathParam = AliasToWeaponID( pszWeaponName );
  161. }
  162. const char *pszMapName = gpGlobals->mapname.ToCStr() ? gpGlobals->mapname.ToCStr() : "unknown";
  163. Q_strncpy( m_szMapName, pszMapName, ARRAYSIZE(m_szMapName) );
  164. }
  165. Vector m_DeathPos;
  166. int m_iVictimTeam;
  167. int m_iKillerTeam;
  168. int m_iDamageType;
  169. uint64 m_uiDeathParam;
  170. char m_szMapName[64];
  171. BEGIN_STAT_TABLE( "Deaths" )
  172. REGISTER_STAT_NAMED( m_DeathPos.x, "XCoord" )
  173. REGISTER_STAT_NAMED( m_DeathPos.y, "YCoord" )
  174. REGISTER_STAT_NAMED( m_DeathPos.z, "ZCoord" )
  175. REGISTER_STAT_NAMED( m_iVictimTeam, "Team" )
  176. REGISTER_STAT_NAMED( m_iKillerTeam, "DeathCause" )
  177. REGISTER_STAT_NAMED( m_uiDeathParam, "DeathParam" )
  178. REGISTER_STAT_NAMED( m_szMapName, "DeathMap" )
  179. END_STAT_TABLE()
  180. };
  181. typedef CUtlVector< SCSSDeathData* > CSSDeathData;
  182. //=============================================================================
  183. //
  184. // CS Game Stats Class
  185. //
  186. class CCSGameStats : public CBaseGameStats, public CGameEventListener, public CAutoGameSystemPerFrame, public IGameStatTracker
  187. {
  188. public:
  189. // Constructor/Destructor.
  190. CCSGameStats( void );
  191. ~CCSGameStats( void );
  192. virtual void Clear( void );
  193. virtual bool Init();
  194. virtual void PreClientUpdate();
  195. virtual void PostInit();
  196. virtual void LevelShutdownPreClearSteamAPIContext();
  197. void UploadRoundStats( void );
  198. // Overridden events
  199. virtual void Event_LevelInit( void );
  200. virtual void Event_LevelShutdown( float flElapsed );
  201. virtual void Event_ShotFired( CBasePlayer *pPlayer, CBaseCombatWeapon* pWeapon );
  202. virtual void Event_ShotHit( CBasePlayer *pPlayer, const CTakeDamageInfo &info );
  203. virtual void Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info );
  204. virtual void Event_PlayerKilled_PreWeaponDrop( CBasePlayer *pPlayer, const CTakeDamageInfo &info );
  205. void UpdatePlayerRoundStats(int winner);
  206. virtual void Event_PlayerConnected( CBasePlayer *pPlayer );
  207. virtual void Event_PlayerDisconnected( CBasePlayer *pPlayer );
  208. virtual void Event_WindowShattered( CBasePlayer *pPlayer );
  209. virtual void Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info );
  210. // CSS specific events
  211. void Event_BombPlanted( CCSPlayer *pPlayer );
  212. void Event_BombDefused( CCSPlayer *pPlayer );
  213. void Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info );
  214. void Event_BombExploded( CCSPlayer *pPlayer );
  215. void Event_MoneyEarned( CCSPlayer *pPlayer, int moneyEarned );
  216. void Event_MoneySpent( CCSPlayer *pPlayer, int moneySpent, const char *pItemName );
  217. void Event_HostageRescued( CCSPlayer *pPlayer );
  218. void Event_PlayerSprayedDecal( CCSPlayer*pPlayer );
  219. void Event_AllHostagesRescued();
  220. void Event_BreakProp( CCSPlayer *pPlayer, CBreakableProp *pProp );
  221. void Event_PlayerDonatedWeapon (CCSPlayer* pPlayer);
  222. void Event_PlayerDominatedOther( CCSPlayer* pAttacker, CCSPlayer* pVictim);
  223. void Event_PlayerRevenge( CCSPlayer* pAttacker );
  224. void Event_PlayerAvengedTeammate( CCSPlayer* pAttacker, CCSPlayer* pAvengedPlayer );
  225. void Event_MVPEarned( CCSPlayer* pPlayer );
  226. void Event_KnifeUse( CCSPlayer* pPlayer, bool bStab, int iDamage );
  227. virtual void FireGameEvent( IGameEvent *event );
  228. void DumpMatchWeaponMetrics();
  229. const PlayerStats_t& FindPlayerStats( CBasePlayer *pPlayer ) const;
  230. void ResetPlayerStats( CBasePlayer *pPlayer );
  231. void ResetKillHistory( CBasePlayer *pPlayer );
  232. void ResetRoundStats();
  233. void ResetPlayerClassMatchStats();
  234. const StatsCollection_t& GetTeamStats( int iTeamIndex ) const;
  235. void ResetAllTeamStats();
  236. void ResetAllStats();
  237. void ResetWeaponStats();
  238. void IncrementTeamStat( int iTeamIndex, int iStatIndex, int iAmount );
  239. void CalcDominationAndRevenge( CCSPlayer *pAttacker, CCSPlayer *pVictim, int *piDeathFlags );
  240. void CalculateOverkill( CCSPlayer* pAttacker, CCSPlayer* pVictim );
  241. void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info );
  242. void IncrementStat( CCSPlayer* pPlayer, CSStatType_t statId, int iValue, bool bPlayerOnly = false );
  243. // Steamworks Gamestats
  244. virtual void SubmitGameStats( KeyValues *pKV );
  245. virtual StatContainerList_t* GetStatContainerList( void )
  246. {
  247. return s_StatLists;
  248. }
  249. protected:
  250. void SetStat( CCSPlayer *pPlayer, CSStatType_t statId, int iValue );
  251. void TrackKillStats( CCSPlayer *pAttacker, CCSPlayer *pVictim );
  252. void ComputeRollingStatAverages();
  253. void ComputeDirectStatAverages();
  254. void SendRollingStatsAveragesToAllPlayers();
  255. void SendDirectStatsAveragesToAllPlayers();
  256. void SendStatsToPlayer( CCSPlayer * pPlayer, int iMinStatPriority );
  257. private:
  258. PlayerStats_t m_aPlayerStats[MAX_PLAYERS+1]; // List of stats for each player for current life - reset after each death
  259. StatsCollection_t m_aTeamStats[TEAM_MAXCOUNT - FIRST_GAME_TEAM];
  260. RoundStatsRollingAverage_t m_rollingCTStatAverages;
  261. RoundStatsRollingAverage_t m_rollingTStatAverages;
  262. RoundStatsRollingAverage_t m_rollingPlayerStatAverages;
  263. RoundStatsDirectAverage_t m_directCTStatAverages;
  264. RoundStatsDirectAverage_t m_directTStatAverages;
  265. RoundStatsDirectAverage_t m_directPlayerStatAverages;
  266. float m_fDisseminationTimerLow; // how long since last medium priority stat update
  267. float m_fDisseminationTimerHigh; // how long since last high priority stat update
  268. int m_numberOfRoundsForDirectAverages;
  269. int m_numberOfTerroristEntriesForDirectAverages;
  270. int m_numberOfCounterTerroristEntriesForDirectAverages;
  271. CUtlDict< CSStatType_t, short > m_PropStatTable;
  272. CUtlLinkedList<sHappyCamperSnipePosition, int> m_PlayerSnipedPosition;
  273. WeaponStats m_weaponStats[WEAPON_MAX][2];
  274. // Steamworks Gamestats
  275. VectorMarketPurchaseData m_MarketPurchases;
  276. CSSWeaponData m_WeaponData;
  277. CSSDeathData m_DeathData;
  278. // A static list of all the stat containers, one for each data structure being tracked
  279. static StatContainerList_t * s_StatLists;
  280. bool m_bInRound;
  281. };
  282. extern CCSGameStats CCS_GameStats;
  283. #endif // CS_GAMESTATS_H