diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/cstrike/cs_gamestats_shared.h | |
| download | archived-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.h | 824 |
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 |