summaryrefslogtreecommitdiff
path: root/game/shared/cstrike/cs_gamestats_shared.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/cstrike/cs_gamestats_shared.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/cstrike/cs_gamestats_shared.h')
-rw-r--r--game/shared/cstrike/cs_gamestats_shared.h824
1 files changed, 824 insertions, 0 deletions
diff --git a/game/shared/cstrike/cs_gamestats_shared.h b/game/shared/cstrike/cs_gamestats_shared.h
new file mode 100644
index 0000000..dc58a77
--- /dev/null
+++ b/game/shared/cstrike/cs_gamestats_shared.h
@@ -0,0 +1,824 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+#ifndef CS_GAMESTATS_SHARED_H
+#define CS_GAMESTATS_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+#include "cbase.h"
+// #include "tier1/utlvector.h"
+// #include "tier1/utldict.h"
+#include "shareddefs.h"
+#include "cs_shareddefs.h"
+#include "cs_weapon_parse.h"
+#include "fmtstr.h"
+
+
+#define CS_NUM_LEVELS 18
+
+//=============================================================================
+// Helper class for simple manipulation of bit arrays.
+// Used for server->client packets containing delta stats
+//=============================================================================
+
+template <int BitLength>
+class BitArray
+{
+ enum { ByteLength = (BitLength + 7) / 8 };
+public:
+ BitArray() { ClearAll(); }
+
+ void SetBit(int n) { m_bytes[n / 8] |= 1 << (n & 7); }
+ void ClearBit(int n) { m_bytes[n / 8] &= (~(1 << (n & 7))); }
+ bool IsBitSet(int n) const { return (m_bytes[n / 8] & (1 << (n & 7))) != 0;}
+
+ void ClearAll() { V_memset(m_bytes, 0, sizeof(m_bytes)); }
+ int NumBits() { return BitLength; }
+ int NumBytes() { return ByteLength; }
+
+ byte* RawPointer() { return m_bytes; }
+
+private:
+ byte m_bytes[ByteLength];
+};
+
+
+//=============================================================================
+//
+// CS Game Stats Enums
+//
+// WARNING! ANY CHANGE TO THE ORDERING OR NUMBER OF STATS WILL REQUIRE
+// SYNCHRONOUS UPDATE OF CLIENT AND SERVER DLLS. If you change these enums
+// (including adding new stats) without forcing an update of both the client
+// and server, stats will become corrupted on the game client and these
+// corrupted values will be uploaded to steam, which is very very bad.
+//
+// If you add new stats, if will be safest to add them at the end of the enum
+// (although this will still require a server update); make sure you also add
+// the stats to the CSStatProperty_Table in cs_gamestats_shared.cpp at the
+// appropriate location.
+
+enum CSStatType_t
+{
+ CSSTAT_UNDEFINED = -1,
+ CSSTAT_SHOTS_HIT,
+ CSSTAT_SHOTS_FIRED,
+ CSSTAT_KILLS,
+ CSSTAT_DEATHS,
+ CSSTAT_DAMAGE,
+ CSSTAT_NUM_BOMBS_PLANTED,
+ CSSTAT_NUM_BOMBS_DEFUSED,
+ CSSTAT_PLAYTIME,
+ CSSTAT_ROUNDS_WON,
+ CSSTAT_T_ROUNDS_WON,
+ CSSTAT_CT_ROUNDS_WON,
+ CSSTAT_ROUNDS_PLAYED,
+ CSSTAT_PISTOLROUNDS_WON,
+ CSSTAT_MONEY_EARNED,
+ CSSTAT_OBJECTIVES_COMPLETED,
+ CSSTAT_BOMBS_DEFUSED_WITHKIT,
+
+ CSSTAT_KILLS_DEAGLE,
+ CSSTAT_KILLS_USP,
+ CSSTAT_KILLS_GLOCK,
+ CSSTAT_KILLS_P228,
+ CSSTAT_KILLS_ELITE,
+ CSSTAT_KILLS_FIVESEVEN,
+ CSSTAT_KILLS_AWP,
+ CSSTAT_KILLS_AK47,
+ CSSTAT_KILLS_M4A1,
+ CSSTAT_KILLS_AUG,
+ CSSTAT_KILLS_SG552,
+ CSSTAT_KILLS_SG550,
+ CSSTAT_KILLS_GALIL,
+ CSSTAT_KILLS_FAMAS,
+ CSSTAT_KILLS_SCOUT,
+ CSSTAT_KILLS_G3SG1,
+ CSSTAT_KILLS_P90,
+ CSSTAT_KILLS_MP5NAVY,
+ CSSTAT_KILLS_TMP,
+ CSSTAT_KILLS_MAC10,
+ CSSTAT_KILLS_UMP45,
+ CSSTAT_KILLS_M3,
+ CSSTAT_KILLS_XM1014,
+ CSSTAT_KILLS_M249,
+ CSSTAT_KILLS_KNIFE,
+ CSSTAT_KILLS_HEGRENADE,
+
+ CSSTAT_SHOTS_DEAGLE,
+ CSSTAT_SHOTS_USP,
+ CSSTAT_SHOTS_GLOCK,
+ CSSTAT_SHOTS_P228,
+ CSSTAT_SHOTS_ELITE,
+ CSSTAT_SHOTS_FIVESEVEN,
+ CSSTAT_SHOTS_AWP,
+ CSSTAT_SHOTS_AK47,
+ CSSTAT_SHOTS_M4A1,
+ CSSTAT_SHOTS_AUG,
+ CSSTAT_SHOTS_SG552,
+ CSSTAT_SHOTS_SG550,
+ CSSTAT_SHOTS_GALIL,
+ CSSTAT_SHOTS_FAMAS,
+ CSSTAT_SHOTS_SCOUT,
+ CSSTAT_SHOTS_G3SG1,
+ CSSTAT_SHOTS_P90,
+ CSSTAT_SHOTS_MP5NAVY,
+ CSSTAT_SHOTS_TMP,
+ CSSTAT_SHOTS_MAC10,
+ CSSTAT_SHOTS_UMP45,
+ CSSTAT_SHOTS_M3,
+ CSSTAT_SHOTS_XM1014,
+ CSSTAT_SHOTS_M249,
+ CSSTAT_SHOTS_KNIFE,
+ CSSTAT_SHOTS_HEGRENADE,
+
+ CSSTAT_HITS_DEAGLE,
+ CSSTAT_HITS_USP,
+ CSSTAT_HITS_GLOCK,
+ CSSTAT_HITS_P228,
+ CSSTAT_HITS_ELITE,
+ CSSTAT_HITS_FIVESEVEN,
+ CSSTAT_HITS_AWP,
+ CSSTAT_HITS_AK47,
+ CSSTAT_HITS_M4A1,
+ CSSTAT_HITS_AUG,
+ CSSTAT_HITS_SG552,
+ CSSTAT_HITS_SG550,
+ CSSTAT_HITS_GALIL,
+ CSSTAT_HITS_FAMAS,
+ CSSTAT_HITS_SCOUT,
+ CSSTAT_HITS_G3SG1,
+ CSSTAT_HITS_P90,
+ CSSTAT_HITS_MP5NAVY,
+ CSSTAT_HITS_TMP,
+ CSSTAT_HITS_MAC10,
+ CSSTAT_HITS_UMP45,
+ CSSTAT_HITS_M3,
+ CSSTAT_HITS_XM1014,
+ CSSTAT_HITS_M249,
+ CSSTAT_HITS_KNIFE,
+ CSSTAT_HITS_HEGRENADE,
+
+ CSSTAT_DAMAGE_DEAGLE,
+ CSSTAT_DAMAGE_USP,
+ CSSTAT_DAMAGE_GLOCK,
+ CSSTAT_DAMAGE_P228,
+ CSSTAT_DAMAGE_ELITE,
+ CSSTAT_DAMAGE_FIVESEVEN,
+ CSSTAT_DAMAGE_AWP,
+ CSSTAT_DAMAGE_AK47,
+ CSSTAT_DAMAGE_M4A1,
+ CSSTAT_DAMAGE_AUG,
+ CSSTAT_DAMAGE_SG552,
+ CSSTAT_DAMAGE_SG550,
+ CSSTAT_DAMAGE_GALIL,
+ CSSTAT_DAMAGE_FAMAS,
+ CSSTAT_DAMAGE_SCOUT,
+ CSSTAT_DAMAGE_G3SG1,
+ CSSTAT_DAMAGE_P90,
+ CSSTAT_DAMAGE_MP5NAVY,
+ CSSTAT_DAMAGE_TMP,
+ CSSTAT_DAMAGE_MAC10,
+ CSSTAT_DAMAGE_UMP45,
+ CSSTAT_DAMAGE_M3,
+ CSSTAT_DAMAGE_XM1014,
+ CSSTAT_DAMAGE_M249,
+ CSSTAT_DAMAGE_KNIFE,
+ CSSTAT_DAMAGE_HEGRENADE,
+
+ CSSTAT_KILLS_HEADSHOT,
+ CSSTAT_KILLS_ENEMY_BLINDED,
+ CSSTAT_KILLS_WHILE_BLINDED,
+ CSSTAT_KILLS_WITH_LAST_ROUND,
+ CSSTAT_KILLS_ENEMY_WEAPON,
+ CSSTAT_KILLS_KNIFE_FIGHT,
+ CSSTAT_KILLS_WHILE_DEFENDING_BOMB,
+
+ CSSTAT_DECAL_SPRAYS,
+ CSSTAT_TOTAL_JUMPS,
+ CSSTAT_NIGHTVISION_DAMAGE,
+ CSSTAT_KILLS_WHILE_LAST_PLAYER_ALIVE,
+ CSSTAT_KILLS_ENEMY_WOUNDED,
+ CSSTAT_FALL_DAMAGE,
+
+ CSSTAT_NUM_HOSTAGES_RESCUED,
+
+ CSSTAT_NUM_BROKEN_WINDOWS,
+ CSSTAT_PROPSBROKEN_ALL,
+ CSSTAT_PROPSBROKEN_MELON,
+ CSSTAT_PROPSBROKEN_OFFICEELECTRONICS,
+ CSSTAT_PROPSBROKEN_OFFICERADIO,
+ CSSTAT_PROPSBROKEN_OFFICEJUNK,
+ CSSTAT_PROPSBROKEN_ITALY_MELON,
+
+ CSSTAT_KILLS_AGAINST_ZOOMED_SNIPER,
+
+ CSSTAT_WEAPONS_DONATED,
+
+ CSSTAT_ITEMS_PURCHASED,
+ CSSTAT_MONEY_SPENT,
+
+ CSSTAT_DOMINATIONS,
+ CSSTAT_DOMINATION_OVERKILLS,
+ CSSTAT_REVENGES,
+
+ CSSTAT_MVPS,
+
+ CSSTAT_GRENADE_DAMAGE,
+ CSSTAT_GRENADE_POSTHUMOUSKILLS,
+ CSSTAT_GRENADES_THROWN,
+
+ CSTAT_ITEMS_DROPPED_VALUE,
+
+ //Map win stats
+ CSSTAT_MAP_WINS_CS_ASSAULT,
+ CSSTAT_MAP_WINS_CS_COMPOUND,
+ CSSTAT_MAP_WINS_CS_HAVANA,
+ CSSTAT_MAP_WINS_CS_ITALY,
+ CSSTAT_MAP_WINS_CS_MILITIA,
+ CSSTAT_MAP_WINS_CS_OFFICE,
+ CSSTAT_MAP_WINS_DE_AZTEC,
+ CSSTAT_MAP_WINS_DE_CBBLE,
+ CSSTAT_MAP_WINS_DE_CHATEAU,
+ CSSTAT_MAP_WINS_DE_DUST2,
+ CSSTAT_MAP_WINS_DE_DUST,
+ CSSTAT_MAP_WINS_DE_INFERNO,
+ CSSTAT_MAP_WINS_DE_NUKE,
+ CSSTAT_MAP_WINS_DE_PIRANESI,
+ CSSTAT_MAP_WINS_DE_PORT,
+ CSSTAT_MAP_WINS_DE_PRODIGY,
+ CSSTAT_MAP_WINS_DE_TIDES,
+ CSSTAT_MAP_WINS_DE_TRAIN,
+
+ CSSTAT_MAP_ROUNDS_CS_ASSAULT,
+ CSSTAT_MAP_ROUNDS_CS_COMPOUND,
+ CSSTAT_MAP_ROUNDS_CS_HAVANA,
+ CSSTAT_MAP_ROUNDS_CS_ITALY,
+ CSSTAT_MAP_ROUNDS_CS_MILITIA,
+ CSSTAT_MAP_ROUNDS_CS_OFFICE,
+ CSSTAT_MAP_ROUNDS_DE_AZTEC,
+ CSSTAT_MAP_ROUNDS_DE_CBBLE,
+ CSSTAT_MAP_ROUNDS_DE_CHATEAU,
+ CSSTAT_MAP_ROUNDS_DE_DUST2,
+ CSSTAT_MAP_ROUNDS_DE_DUST,
+ CSSTAT_MAP_ROUNDS_DE_INFERNO,
+ CSSTAT_MAP_ROUNDS_DE_NUKE,
+ CSSTAT_MAP_ROUNDS_DE_PIRANESI,
+ CSSTAT_MAP_ROUNDS_DE_PORT,
+ CSSTAT_MAP_ROUNDS_DE_PRODIGY,
+ CSSTAT_MAP_ROUNDS_DE_TIDES,
+ CSSTAT_MAP_ROUNDS_DE_TRAIN,
+
+ CSSTAT_LASTMATCH_T_ROUNDS_WON,
+ CSSTAT_LASTMATCH_CT_ROUNDS_WON,
+ CSSTAT_LASTMATCH_ROUNDS_WON,
+ CSSTAT_LASTMATCH_KILLS,
+ CSSTAT_LASTMATCH_DEATHS,
+ CSSTAT_LASTMATCH_MVPS,
+ CSSTAT_LASTMATCH_DAMAGE,
+ CSSTAT_LASTMATCH_MONEYSPENT,
+ CSSTAT_LASTMATCH_DOMINATIONS,
+ CSSTAT_LASTMATCH_REVENGES,
+ CSSTAT_LASTMATCH_MAX_PLAYERS,
+ CSSTAT_LASTMATCH_FAVWEAPON_ID,
+ CSSTAT_LASTMATCH_FAVWEAPON_SHOTS,
+ CSSTAT_LASTMATCH_FAVWEAPON_HITS,
+ CSSTAT_LASTMATCH_FAVWEAPON_KILLS,
+
+ CSSTAT_MAX //Must be last entry.
+};
+
+
+#define CSSTAT_FIRST (CSSTAT_UNDEFINED+1)
+#define CSSTAT_LAST (CSSTAT_MAX-1)
+
+//
+// CS Game Stats Flags
+//
+#define CSSTAT_PRIORITY_MASK 0x000F
+#define CSSTAT_PRIORITY_NEVER 0x0000 // not sent to client
+#define CSSTAT_PRIORITY_ENDROUND 0x0001 // sent at end of round
+#define CSSTAT_PRIORITY_LOW 0x0002 // sent every 2500ms
+#define CSSTAT_PRIORITY_HIGH 0x0003 // sent every 250ms
+
+struct CSStatProperty
+{
+ int statId; // verify that table ordering is correct
+ const char* szSteamName; // name of the stat on steam
+ const char* szLocalizationToken; // localization token for the stat
+ uint flags; // priority flags for sending to client
+};
+
+extern CSStatProperty CSStatProperty_Table[];
+
+
+//=============================================================================
+//
+// CS Player Round Stats
+//
+struct StatsCollection_t
+{
+ StatsCollection_t() { Reset(); }
+
+ inline int Get( int i ) const
+ {
+ AssertMsg( i >= CSSTAT_FIRST && i < CSSTAT_MAX, "Stat index out of range!" );
+ if ( i >= 0 )
+ return m_iValue[ i ];
+ return 0;
+ }
+
+ inline void Set( int i, int nValue )
+ {
+ AssertMsg( i >= CSSTAT_FIRST && i < CSSTAT_MAX, "Stat index out of range!" );
+ if ( i >= 0 )
+ m_iValue[ i ] = nValue;
+ }
+
+ void Reset()
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_iValue ); i++ )
+ {
+ m_iValue[i] = 0;
+ }
+ }
+
+ int operator[] ( int index ) const
+ {
+ Assert(index >= 0 && index < ARRAYSIZE(m_iValue));
+ return m_iValue[index];
+ }
+
+ int& operator[] ( int index )
+ {
+ Assert(index >= 0 && index < ARRAYSIZE(m_iValue));
+ return m_iValue[index];
+ }
+
+ void Aggregate( const StatsCollection_t& other );
+
+private:
+ int m_iValue[CSSTAT_MAX];
+};
+
+
+//=============================================================================
+// HPE_BEGIN:
+// [tj] A couple variations on the RoundStats structure to handle extra operations
+// for averaging and accumulating
+//=============================================================================
+struct RoundStatsDirectAverage_t
+{
+ float m_fStat[CSSTAT_MAX];
+
+
+ RoundStatsDirectAverage_t()
+ {
+ Reset();
+ }
+
+ void Reset()
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] = 0;
+ }
+ }
+
+ RoundStatsDirectAverage_t& operator +=( const StatsCollection_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] += other[i];
+ }
+ return *this;
+ }
+
+ RoundStatsDirectAverage_t& operator /=( const float &divisor)
+ {
+ if (divisor > 0)
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] /= divisor;
+ }
+ }
+ return *this;
+ }
+
+ RoundStatsDirectAverage_t& operator *=( const float &divisor)
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] *= divisor;
+ }
+ return *this;
+ }
+};
+
+
+struct RoundStatsRollingAverage_t
+{
+ float m_fStat[CSSTAT_MAX];
+ int m_numberOfDataSets;
+
+ RoundStatsRollingAverage_t()
+ {
+ Reset();
+ }
+
+ void Reset()
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] = 0;
+ }
+ m_numberOfDataSets = 0;
+ }
+
+ RoundStatsRollingAverage_t& operator +=( const RoundStatsRollingAverage_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] += other.m_fStat[i];
+ }
+ return *this;
+ }
+
+ RoundStatsRollingAverage_t& operator +=( const StatsCollection_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] += other[i];
+ }
+ return *this;
+ }
+
+ RoundStatsRollingAverage_t& operator /=( const float &divisor)
+ {
+ if (divisor > 0)
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] /= divisor;
+ }
+ }
+ return *this;
+ }
+
+ void RollDataSetIntoAverage ( const RoundStatsRollingAverage_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_fStat ); i++ )
+ {
+ m_fStat[i] *= m_numberOfDataSets;
+ m_fStat[i] += other.m_fStat[i];
+ m_fStat[i] /= (m_numberOfDataSets + 1);
+ }
+ m_numberOfDataSets++;
+ }
+};
+//=============================================================================
+// HPE_END
+//=============================================================================
+
+enum CSGameStatsVersions_t
+{
+ CS_GAMESTATS_FILE_VERSION = 006,
+ CS_GAMESTATS_MAGIC = 0xDEADBEEF
+};
+
+struct CS_Gamestats_Version_t
+{
+ int m_iMagic; // always CS_GAMESTATS_MAGIC
+ int m_iVersion;
+};
+
+
+struct KillStats_t
+{
+ KillStats_t() { Reset(); }
+
+ void Reset()
+ {
+ Q_memset( iNumKilled, 0, sizeof( iNumKilled ) );
+ Q_memset( iNumKilledBy, 0, sizeof( iNumKilledBy ) );
+ Q_memset( iNumKilledByUnanswered, 0, sizeof( iNumKilledByUnanswered ) );
+ }
+
+ int iNumKilled[MAX_PLAYERS+1]; // how many times this player has killed each other player
+ int iNumKilledBy[MAX_PLAYERS+1]; // how many times this player has been killed by each other player
+ int iNumKilledByUnanswered[MAX_PLAYERS+1]; // how many unanswered kills this player has been dealt by each other player
+};
+
+//=============================================================================
+//
+// CS Player Stats
+//
+struct PlayerStats_t
+{
+ PlayerStats_t()
+ {
+ Reset();
+ }
+
+ void Reset()
+ {
+ statsDelta.Reset();
+ statsCurrentRound.Reset();
+ statsCurrentMatch.Reset();
+ statsKills.Reset();
+ }
+
+ PlayerStats_t( const PlayerStats_t &other )
+ {
+ statsDelta = other.statsDelta;
+ statsCurrentRound = other.statsCurrentRound;
+ statsCurrentMatch = other.statsCurrentMatch;
+ }
+
+ StatsCollection_t statsDelta;
+ StatsCollection_t statsCurrentRound;
+ StatsCollection_t statsCurrentMatch;
+ KillStats_t statsKills;
+};
+
+
+struct WeaponName_StatId
+{
+ CSWeaponID weaponId;
+ CSStatType_t killStatId;
+ CSStatType_t shotStatId;
+ CSStatType_t hitStatId;
+ CSStatType_t damageStatId;
+};
+
+struct MapName_MapStatId
+{
+ const char* szMapName;
+ CSStatType_t statWinsId;
+ CSStatType_t statRoundsId;
+};
+
+extern const MapName_MapStatId MapName_StatId_Table[];
+
+//A mapping from weapon names to weapon stat IDs
+extern const WeaponName_StatId WeaponName_StatId_Table[];
+
+//Used to look up the appropriate entry by the ID of the actual weapon
+const WeaponName_StatId& GetWeaponTableEntryFromWeaponId(CSWeaponID id);
+
+#include "steamworks_gamestats.h"
+
+//=============================================================================
+//
+// Helper functions for creating key values
+//
+void AddDataToKV( KeyValues* pKV, const char* name, int data );
+void AddDataToKV( KeyValues* pKV, const char* name, uint64 data );
+void AddDataToKV( KeyValues* pKV, const char* name, float data );
+void AddDataToKV( KeyValues* pKV, const char* name, bool data );
+void AddDataToKV( KeyValues* pKV, const char* name, const char* data );
+void AddDataToKV( KeyValues* pKV, const char* name, const Color& data );
+void AddDataToKV( KeyValues* pKV, const char* name, short data );
+void AddDataToKV( KeyValues* pKV, const char* name, unsigned data );
+void AddDataToKV( KeyValues* pKV, const char* name, const Vector& data );
+void AddPositionDataToKV( KeyValues* pKV, const char* name, const Vector &data );
+//=============================================================================
+
+//=============================================================================
+//
+// Helper functions for creating key values from arrays
+//
+void AddArrayDataToKV( KeyValues* pKV, const char* name, const short *data, unsigned size );
+void AddArrayDataToKV( KeyValues* pKV, const char* name, const byte *data, unsigned size );
+void AddArrayDataToKV( KeyValues* pKV, const char* name, const unsigned *data, unsigned size );
+void AddStringDataToKV( KeyValues* pKV, const char* name, const char *data );
+
+//=============================================================================
+
+// Macros to ease the creation of SendData method for stats structs/classes
+#define BEGIN_STAT_TABLE( tableName ) \
+ static const char* GetStatTableName( void ) { return tableName; } \
+ void BuildGamestatDataTable( KeyValues* pKV ) \
+{ \
+ pKV->SetName( GetStatTableName() );
+
+#define REGISTER_STAT( varName ) \
+ AddDataToKV(pKV, #varName, varName);
+
+#define REGISTER_STAT_NAMED( varName, dbName ) \
+ AddDataToKV(pKV, dbName, varName);
+
+#define REGISTER_STAT_POSITION( varName ) \
+ AddPositionDataToKV(pKV, #varName, varName);
+
+#define REGISTER_STAT_POSITION_NAMED( varName, dbName ) \
+ AddPositionDataToKV(pKV, dbName, varName);
+
+#define REGISTER_STAT_ARRAY( varName ) \
+ AddArrayDataToKV( pKV, #varName, varName, ARRAYSIZE( varName ) );
+
+#define REGISTER_STAT_ARRAY_NAMED( varName, dbName ) \
+ AddArrayDataToKV( pKV, dbName, varName, ARRAYSIZE( varName ) );
+
+#define REGISTER_STAT_STRING( varName ) \
+ AddStringDataToKV( pKV, #varName, varName );
+
+#define REGISTER_STAT_STRING_NAMED( varName, dbName ) \
+ AddStringDataToKV( pKV, dbName, varName );
+
+#define AUTO_STAT_TABLE_KEY() \
+ pKV->SetInt( "TimeSubmitted", GetUniqueIDForStatTable( *this ) );
+
+#define END_STAT_TABLE() \
+ pKV->SetUint64( ::BaseStatData::m_bUseGlobalData ? "TimeSubmitted" : "SessionTime", ::BaseStatData::TimeSubmitted ); \
+ GetSteamWorksSGameStatsUploader().AddStatsForUpload( pKV ); \
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Templatized class for getting unique ID's for stat tables that need
+// to be submitted multiple times per-session.
+//-----------------------------------------------------------------------------
+
+template < typename T >
+class UniqueStatID_t
+{
+public:
+ static unsigned GetNext( void )
+ {
+ return ++s_nLastID;
+ }
+
+ static void Reset( void )
+ {
+ s_nLastID = 0;
+ }
+
+private:
+ static unsigned s_nLastID;
+};
+
+template < typename T >
+unsigned UniqueStatID_t< T >::s_nLastID = 0;
+
+template < typename T >
+unsigned GetUniqueIDForStatTable( const T &table )
+{
+ return UniqueStatID_t< T >::GetNext();
+}
+
+
+//=============================================================================
+//
+// An interface for tracking gamestats.
+//
+class IGameStatTracker
+{
+public:
+
+ //-----------------------------------------------------------------------------
+ // Templatized methods to track a per-mission stat.
+ // The stat is copied, then deleted after it's sent to the SQL server.
+ //-----------------------------------------------------------------------------
+ template < typename T >
+ void SubmitStat( T& stat )
+ {
+ // Make a copy of the stat. All of the stat lists require pointers,
+ // so we need to protect against a stat allocated on the stack
+ T* pT = new T();
+ if( !pT )
+ return;
+
+ *pT = stat;
+ SubmitStat( pT );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Templatized methods to track a per-mission stat (by pointer)
+ // The stat is deleted after it's sent to the SQL server
+ //-----------------------------------------------------------------------------
+ template < typename T >
+ void SubmitStat( T* pStat )
+ {
+ // Get the static stat table for this type and add the stat to it
+ GetStatTable<T>()->AddToTail( pStat );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Add all stats to an existing key value file for submit.
+ //-----------------------------------------------------------------------------
+ virtual void SubmitGameStats( KeyValues *pKV ) = 0;
+
+ //-----------------------------------------------------------------------------
+ // Prints the memory usage of all of the stats being tracked
+ //-----------------------------------------------------------------------------
+ void PrintGamestatMemoryUsage( void );
+
+protected:
+ //=============================================================================
+ //
+ // Used as a base interface to store a list of all templatized stat containers
+ //
+ class IStatContainer
+ {
+ public:
+ virtual void SendData( KeyValues *pKV ) = 0;
+ virtual void Clear( void ) = 0;
+ virtual void PrintMemoryUsage( void ) = 0;
+ };
+
+ // Defines a list of stat containers.
+ typedef CUtlVector< IStatContainer* > StatContainerList_t;
+
+ //-----------------------------------------------------------------------------
+ // Used to get a list of all stats containers being tracked by the deriving class
+ //-----------------------------------------------------------------------------
+ virtual StatContainerList_t* GetStatContainerList( void ) = 0;
+
+private:
+
+ //=============================================================================
+ //
+ // Templatized list of stats submitted
+ //
+ template < typename T >
+ class CGameStatList : public IStatContainer, public CUtlVector< T* >
+ {
+ public:
+ //-----------------------------------------------------------------------------
+ // Get data ready to send to the SQL server
+ //-----------------------------------------------------------------------------
+ virtual void SendData( KeyValues *pKV )
+ {
+ //ASSERT( pKV != NULL );
+
+ // Duplicate the master KeyValue for each stat instance
+ for( int i=0; i < this->m_Size; ++i )
+ {
+ // Make a copy of the master key value and build the stat table
+ KeyValues *pKVCopy = this->operator [](i)->m_bUseGlobalData ? pKV->MakeCopy() : new KeyValues( "" );
+ this->operator [](i)->BuildGamestatDataTable( pKVCopy );
+ }
+
+ // Reset unique ID counter for the stat type
+ UniqueStatID_t< T >::Reset();
+ }
+
+ //-----------------------------------------------------------------------------
+ // Clear and delete every stat in this list
+ //-----------------------------------------------------------------------------
+ virtual void Clear( void )
+ {
+ this->PurgeAndDeleteElements();
+ }
+
+ //-----------------------------------------------------------------------------
+ // Print out details about this lists memory usage
+ //-----------------------------------------------------------------------------
+ virtual void PrintMemoryUsage( void )
+ {
+ if( this->m_Size == 0 )
+ return;
+
+ // Compute the memory used as the size of type times the list count
+ unsigned uMemoryUsed = this->m_Size * ( sizeof( T ) );
+
+ Msg( " %d\tbytes used by %s table\n", uMemoryUsed, T::GetStatTableName() );
+ }
+ };
+
+ //-----------------------------------------------------------------------------
+ // Templatized method to get a single instance of a stat list per data type.
+ //-----------------------------------------------------------------------------
+ template < typename T >
+ CGameStatList< T >* GetStatTable( void )
+ {
+ static CGameStatList< T > *s_vecOfType = 0;
+ if( s_vecOfType == 0 )
+ {
+ s_vecOfType = new CGameStatList< T >();
+ GetStatContainerList()->AddToTail( s_vecOfType );
+ }
+ return s_vecOfType;
+ }
+
+};
+
+struct BaseStatData
+{
+ BaseStatData( bool bUseGlobalData = true ) : m_bUseGlobalData( bUseGlobalData )
+ {
+ TimeSubmitted = GetSteamWorksSGameStatsUploader().GetTimeSinceEpoch();
+ }
+
+ bool m_bUseGlobalData;
+ uint64 TimeSubmitted;
+
+};
+
+extern ConVar sv_noroundstats;
+
+#endif // CS_GAMESTATS_SHARED_H