diff options
Diffstat (limited to 'game/server/cstrike/cs_gamestats.h')
| -rw-r--r-- | game/server/cstrike/cs_gamestats.h | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/game/server/cstrike/cs_gamestats.h b/game/server/cstrike/cs_gamestats.h new file mode 100644 index 0000000..4a24efb --- /dev/null +++ b/game/server/cstrike/cs_gamestats.h @@ -0,0 +1,340 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The CS game stats header +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CS_GAMESTATS_H +#define CS_GAMESTATS_H +#ifdef _WIN32 +#pragma once +#endif + +#include "cs_blackmarket.h" +#include "gamestats.h" +#include "cs_gamestats_shared.h" +#include "GameEventListener.h" +#include "steamworks_gamestats.h" +#include "weapon_csbase.h" + +// forward declares +class CBreakableProp; + +#define CS_STATS_BLOB_VERSION 3 + +const float cDisseminationTimeHigh = 0.25f; // Time interval for high priority stats sent to the player +const float cDisseminationTimeLow = 2.5f; // Time interval for medium priority stats sent to the player + +int GetCSLevelIndex( const char *pLevelName ); + +typedef struct +{ + char szGameName[8]; + byte iVersion; + char szMapName[32]; + char ipAddr[4]; + short port; + int serverid; +} gamestats_header_t; + +typedef struct +{ + gamestats_header_t header; + short iMinutesPlayed; + + short iTerroristVictories[CS_NUM_LEVELS]; + short iCounterTVictories[CS_NUM_LEVELS]; + short iBlackMarketPurchases[WEAPON_MAX]; + + short iAutoBuyPurchases; + short iReBuyPurchases; + short iAutoBuyM4A1Purchases; + short iAutoBuyAK47Purchases; + short iAutoBuyFamasPurchases; + short iAutoBuyGalilPurchases; + short iAutoBuyVestHelmPurchases; + short iAutoBuyVestPurchases; + +} cs_gamestats_t; + +extern short g_iWeaponPurchases[WEAPON_MAX]; +extern float g_flGameStatsUpdateTime; +extern short g_iTerroristVictories[CS_NUM_LEVELS]; +extern short g_iCounterTVictories[CS_NUM_LEVELS]; +extern short g_iWeaponPurchases[WEAPON_MAX]; + +extern short g_iAutoBuyPurchases; +extern short g_iReBuyPurchases; +extern short g_iAutoBuyM4A1Purchases; +extern short g_iAutoBuyAK47Purchases; +extern short g_iAutoBuyFamasPurchases; +extern short g_iAutoBuyGalilPurchases; +extern short g_iAutoBuyVestHelmPurchases; +extern short g_iAutoBuyVestPurchases; + + +struct sHappyCamperSnipePosition +{ + sHappyCamperSnipePosition( int userid, Vector pos ) : m_iUserID(userid), m_vPos(pos) {} + + int m_iUserID; + Vector m_vPos; +}; + +struct SMarketPurchases : public BaseStatData +{ + SMarketPurchases( uint64 ulPlayerID, int iPrice, const char *pName ) : m_nPlayerID(ulPlayerID), ItemCost(iPrice) + { + if ( pName ) + { + Q_strncpy( ItemID, pName, ARRAYSIZE(ItemID) ); + } + else + { + Q_strncpy( ItemID, "unknown", ARRAYSIZE(ItemID) ); + } + } + uint64 m_nPlayerID; + int ItemCost; + char ItemID[64]; + + BEGIN_STAT_TABLE( "CSSMarketPurchase" ) + REGISTER_STAT( m_nPlayerID ) + REGISTER_STAT( ItemCost ) + REGISTER_STAT_STRING( ItemID ) + END_STAT_TABLE() +}; +typedef CUtlVector< SMarketPurchases* > VectorMarketPurchaseData; + +struct WeaponStats +{ + int shots; + int hits; + int kills; + int damage; +}; + +struct SCSSWeaponData : public BaseStatData +{ + SCSSWeaponData( const char *pWeaponName, const WeaponStats &wpnData ) + { + if ( pWeaponName ) + { + Q_strncpy( WeaponID, pWeaponName, ARRAYSIZE(WeaponID) ); + } + else + { + Q_strncpy( WeaponID, "unknown", ARRAYSIZE(WeaponID) ); + } + + Shots = wpnData.shots; + Hits = wpnData.hits; + Kills = wpnData.kills; + Damage = wpnData.damage; + } + + char WeaponID[64]; + int Shots; + int Hits; + int Kills; + int Damage; + + BEGIN_STAT_TABLE( "CSSWeaponData" ) + REGISTER_STAT_STRING( WeaponID ) + REGISTER_STAT( Shots ) + REGISTER_STAT( Hits ) + REGISTER_STAT( Kills ) + REGISTER_STAT( Damage ) + END_STAT_TABLE() +}; +typedef CUtlVector< SCSSWeaponData* > CSSWeaponData; + +struct SCSSDeathData : public BaseStatData +{ + SCSSDeathData( CBasePlayer *pVictim, const CTakeDamageInfo &info ) + { + m_bUseGlobalData = false; + + m_DeathPos = info.GetDamagePosition(); + m_iVictimTeam = pVictim->GetTeamNumber(); + + CCSPlayer *pCSPlayer = ToCSPlayer( info.GetAttacker() ); + if ( pCSPlayer ) + { + m_iKillerTeam = pCSPlayer->GetTeamNumber(); + } + else + { + m_iKillerTeam = -1; + } + + const char *pszWeaponName = info.GetInflictor() ? info.GetInflictor()->GetClassname() : "unknown"; + + if ( pszWeaponName ) + { + if ( V_strcmp(pszWeaponName, "player") == 0 ) + { + // get the player's weapon + if ( pCSPlayer && pCSPlayer->GetActiveCSWeapon() ) + { + pszWeaponName = pCSPlayer->GetActiveCSWeapon()->GetClassname(); + } + } + } + + + m_uiDeathParam = WEAPON_NONE; + if ( (m_uiDeathParam = AliasToWeaponID( pszWeaponName )) == WEAPON_NONE ) + { + m_uiDeathParam = AliasToWeaponID( pszWeaponName ); + } + + const char *pszMapName = gpGlobals->mapname.ToCStr() ? gpGlobals->mapname.ToCStr() : "unknown"; + Q_strncpy( m_szMapName, pszMapName, ARRAYSIZE(m_szMapName) ); + } + Vector m_DeathPos; + int m_iVictimTeam; + int m_iKillerTeam; + int m_iDamageType; + uint64 m_uiDeathParam; + char m_szMapName[64]; + + BEGIN_STAT_TABLE( "Deaths" ) + REGISTER_STAT_NAMED( m_DeathPos.x, "XCoord" ) + REGISTER_STAT_NAMED( m_DeathPos.y, "YCoord" ) + REGISTER_STAT_NAMED( m_DeathPos.z, "ZCoord" ) + REGISTER_STAT_NAMED( m_iVictimTeam, "Team" ) + REGISTER_STAT_NAMED( m_iKillerTeam, "DeathCause" ) + REGISTER_STAT_NAMED( m_uiDeathParam, "DeathParam" ) + REGISTER_STAT_NAMED( m_szMapName, "DeathMap" ) + END_STAT_TABLE() +}; +typedef CUtlVector< SCSSDeathData* > CSSDeathData; + +//============================================================================= +// +// CS Game Stats Class +// +class CCSGameStats : public CBaseGameStats, public CGameEventListener, public CAutoGameSystemPerFrame, public IGameStatTracker +{ +public: + + // Constructor/Destructor. + CCSGameStats( void ); + ~CCSGameStats( void ); + + virtual void Clear( void ); + virtual bool Init(); + virtual void PreClientUpdate(); + virtual void PostInit(); + virtual void LevelShutdownPreClearSteamAPIContext(); + + void UploadRoundStats( void ); + // Overridden events + virtual void Event_LevelInit( void ); + virtual void Event_LevelShutdown( float flElapsed ); + virtual void Event_ShotFired( CBasePlayer *pPlayer, CBaseCombatWeapon* pWeapon ); + virtual void Event_ShotHit( CBasePlayer *pPlayer, const CTakeDamageInfo &info ); + virtual void Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ); + virtual void Event_PlayerKilled_PreWeaponDrop( CBasePlayer *pPlayer, const CTakeDamageInfo &info ); + void UpdatePlayerRoundStats(int winner); + virtual void Event_PlayerConnected( CBasePlayer *pPlayer ); + virtual void Event_PlayerDisconnected( CBasePlayer *pPlayer ); + virtual void Event_WindowShattered( CBasePlayer *pPlayer ); + virtual void Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ); + + + // CSS specific events + void Event_BombPlanted( CCSPlayer *pPlayer ); + void Event_BombDefused( CCSPlayer *pPlayer ); + void Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ); + void Event_BombExploded( CCSPlayer *pPlayer ); + void Event_MoneyEarned( CCSPlayer *pPlayer, int moneyEarned ); + void Event_MoneySpent( CCSPlayer *pPlayer, int moneySpent, const char *pItemName ); + void Event_HostageRescued( CCSPlayer *pPlayer ); + void Event_PlayerSprayedDecal( CCSPlayer*pPlayer ); + void Event_AllHostagesRescued(); + void Event_BreakProp( CCSPlayer *pPlayer, CBreakableProp *pProp ); + void Event_PlayerDonatedWeapon (CCSPlayer* pPlayer); + void Event_PlayerDominatedOther( CCSPlayer* pAttacker, CCSPlayer* pVictim); + void Event_PlayerRevenge( CCSPlayer* pAttacker ); + void Event_PlayerAvengedTeammate( CCSPlayer* pAttacker, CCSPlayer* pAvengedPlayer ); + void Event_MVPEarned( CCSPlayer* pPlayer ); + void Event_KnifeUse( CCSPlayer* pPlayer, bool bStab, int iDamage ); + + virtual void FireGameEvent( IGameEvent *event ); + + void DumpMatchWeaponMetrics(); + + const PlayerStats_t& FindPlayerStats( CBasePlayer *pPlayer ) const; + void ResetPlayerStats( CBasePlayer *pPlayer ); + void ResetKillHistory( CBasePlayer *pPlayer ); + void ResetRoundStats(); + void ResetPlayerClassMatchStats(); + + const StatsCollection_t& GetTeamStats( int iTeamIndex ) const; + void ResetAllTeamStats(); + void ResetAllStats(); + void ResetWeaponStats(); + void IncrementTeamStat( int iTeamIndex, int iStatIndex, int iAmount ); + void CalcDominationAndRevenge( CCSPlayer *pAttacker, CCSPlayer *pVictim, int *piDeathFlags ); + void CalculateOverkill( CCSPlayer* pAttacker, CCSPlayer* pVictim ); + void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); + + void IncrementStat( CCSPlayer* pPlayer, CSStatType_t statId, int iValue, bool bPlayerOnly = false ); + // Steamworks Gamestats + virtual void SubmitGameStats( KeyValues *pKV ); + + virtual StatContainerList_t* GetStatContainerList( void ) + { + return s_StatLists; + } + +protected: + void SetStat( CCSPlayer *pPlayer, CSStatType_t statId, int iValue ); + void TrackKillStats( CCSPlayer *pAttacker, CCSPlayer *pVictim ); + void ComputeRollingStatAverages(); + void ComputeDirectStatAverages(); + void SendRollingStatsAveragesToAllPlayers(); + void SendDirectStatsAveragesToAllPlayers(); + void SendStatsToPlayer( CCSPlayer * pPlayer, int iMinStatPriority ); + +private: + PlayerStats_t m_aPlayerStats[MAX_PLAYERS+1]; // List of stats for each player for current life - reset after each death + StatsCollection_t m_aTeamStats[TEAM_MAXCOUNT - FIRST_GAME_TEAM]; + + RoundStatsRollingAverage_t m_rollingCTStatAverages; + RoundStatsRollingAverage_t m_rollingTStatAverages; + RoundStatsRollingAverage_t m_rollingPlayerStatAverages; + + RoundStatsDirectAverage_t m_directCTStatAverages; + RoundStatsDirectAverage_t m_directTStatAverages; + RoundStatsDirectAverage_t m_directPlayerStatAverages; + + float m_fDisseminationTimerLow; // how long since last medium priority stat update + float m_fDisseminationTimerHigh; // how long since last high priority stat update + + int m_numberOfRoundsForDirectAverages; + int m_numberOfTerroristEntriesForDirectAverages; + int m_numberOfCounterTerroristEntriesForDirectAverages; + + CUtlDict< CSStatType_t, short > m_PropStatTable; + + CUtlLinkedList<sHappyCamperSnipePosition, int> m_PlayerSnipedPosition; + WeaponStats m_weaponStats[WEAPON_MAX][2]; + + // Steamworks Gamestats + VectorMarketPurchaseData m_MarketPurchases; + CSSWeaponData m_WeaponData; + CSSDeathData m_DeathData; + + // A static list of all the stat containers, one for each data structure being tracked + static StatContainerList_t * s_StatLists; + + bool m_bInRound; +}; + +extern CCSGameStats CCS_GameStats; + +#endif // CS_GAMESTATS_H |