summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_gamestats_shared.h
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf/tf_gamestats_shared.h')
-rw-r--r--game/shared/tf/tf_gamestats_shared.h706
1 files changed, 706 insertions, 0 deletions
diff --git a/game/shared/tf/tf_gamestats_shared.h b/game/shared/tf/tf_gamestats_shared.h
new file mode 100644
index 0000000..52c5f99
--- /dev/null
+++ b/game/shared/tf/tf_gamestats_shared.h
@@ -0,0 +1,706 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+#ifndef TF_GAMESTATS_SHARED_H
+#define TF_GAMESTATS_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+#include "cbase.h"
+#include "tier1/utlvector.h"
+#include "tier1/utldict.h"
+#include "shareddefs.h"
+#include "tf_shareddefs.h"
+
+//=============================================================================
+//
+// TF Game Stats Enums
+//
+// NOTE: You may add to the end, but do not insert to this list!
+//
+enum TFStatType_t
+{
+ TFSTAT_UNDEFINED = 0,
+ TFSTAT_SHOTS_HIT,
+ TFSTAT_SHOTS_FIRED,
+ TFSTAT_KILLS,
+ TFSTAT_DEATHS,
+ TFSTAT_DAMAGE,
+ TFSTAT_CAPTURES,
+ TFSTAT_DEFENSES,
+ TFSTAT_DOMINATIONS,
+ TFSTAT_REVENGE,
+ TFSTAT_POINTSSCORED,
+ TFSTAT_BUILDINGSDESTROYED,
+ TFSTAT_HEADSHOTS,
+ TFSTAT_PLAYTIME,
+ TFSTAT_HEALING,
+ TFSTAT_INVULNS,
+ TFSTAT_KILLASSISTS,
+ TFSTAT_BACKSTABS,
+ TFSTAT_HEALTHLEACHED,
+ TFSTAT_BUILDINGSBUILT,
+ TFSTAT_MAXSENTRYKILLS,
+ TFSTAT_TELEPORTS,
+ TFSTAT_FIREDAMAGE,
+ TFSTAT_BONUS_POINTS,
+ TFSTAT_BLASTDAMAGE,
+ TFSTAT_DAMAGETAKEN,
+ TFSTAT_HEALTHKITS,
+ TFSTAT_AMMOKITS,
+ TFSTAT_CLASSCHANGES,
+ TFSTAT_CRITS,
+ TFSTAT_SUICIDES,
+ TFSTAT_CURRENCY_COLLECTED,
+ TFSTAT_DAMAGE_ASSIST,
+ TFSTAT_HEALING_ASSIST,
+ TFSTAT_DAMAGE_BOSS,
+ TFSTAT_DAMAGE_BLOCKED,
+ TFSTAT_DAMAGE_RANGED,
+ TFSTAT_DAMAGE_RANGED_CRIT_RANDOM,
+ TFSTAT_DAMAGE_RANGED_CRIT_BOOSTED,
+ TFSTAT_REVIVED,
+ TFSTAT_THROWABLEHIT,
+ TFSTAT_THROWABLEKILL,
+ TFSTAT_KILLSTREAK_MAX,
+ TFSTAT_KILLS_RUNECARRIER,
+ TFSTAT_FLAGRETURNS,
+ TFSTAT_TOTAL
+};
+
+#define TFSTAT_FIRST (TFSTAT_UNDEFINED+1)
+#define TFSTAT_LAST (TFSTAT_TOTAL-1)
+
+extern const char *s_pStatStrings[ TFSTAT_TOTAL ];
+
+enum TFMapStatType_t
+{
+ TFMAPSTAT_UNDEFINED = 0,
+ TFMAPSTAT_PLAYTIME,
+ TFMAPSTAT_TOTAL
+};
+
+#define TFMAPSTAT_FIRST (TFMAPSTAT_UNDEFINED+1)
+#define TFMAPSTAT_LAST (TFMAPSTAT_TOTAL-1)
+
+extern const char *s_pMapStatStrings[ TFMAPSTAT_TOTAL ];
+
+enum TFRoundEndReason_t
+{
+ RE_ROUND_END,
+ RE_CLIENT_DISCONNECT,
+ RE_CLIENT_QUIT,
+ RE_SERVER_MAP_CHANGE,
+ RE_SERVER_SHUTDOWN,
+ RE_TIME_LIMIT,
+ RE_WIN_LIMIT,
+ RE_WIN_DIFF_LIMIT,
+ RE_ROUND_LIMIT,
+ RE_NEXT_LEVEL_CVAR,
+ MAX_ROUND_END_REASON
+};
+
+extern const char *g_aRoundEndReasons[MAX_ROUND_END_REASON];
+
+//=============================================================================
+//
+// TF Player Round Stats
+//
+struct RoundStats_t
+{
+ int m_iStat[TFSTAT_TOTAL];
+
+ RoundStats_t() { Reset(); };
+
+ inline int Get( int i ) const
+ {
+ AssertMsg( i >= TFSTAT_UNDEFINED && i < TFSTAT_TOTAL, "Stat index out of range!" );
+ return m_iStat[ i ];
+ }
+
+ inline void Set( int i, int nValue )
+ {
+ AssertMsg( i >= TFSTAT_UNDEFINED && i < TFSTAT_TOTAL, "Stat index out of range!" );
+ m_iStat[ i ] = nValue;
+ }
+
+ void Reset()
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_iStat ); i++ )
+ {
+ m_iStat[i] = 0;
+ }
+ };
+
+ void AccumulateRound( const RoundStats_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_iStat ); i++ )
+ {
+ m_iStat[i] += other.m_iStat[i];
+ }
+ };
+};
+
+struct RoundMapStats_t
+{
+ int m_iStat[ TFMAPSTAT_TOTAL ];
+
+ RoundMapStats_t() { Reset(); };
+
+ inline int Get( int i ) const
+ {
+ AssertMsg( i >= TFMAPSTAT_UNDEFINED && i < TFMAPSTAT_TOTAL, "Map stat index out of range!" );
+ return m_iStat[ i ];
+ }
+
+ inline void Set( int i, int nValue )
+ {
+ AssertMsg( i >= TFMAPSTAT_UNDEFINED && i < TFMAPSTAT_TOTAL, "Map stat index out of range!" );
+ m_iStat[ i ] = nValue;
+ }
+
+ void Reset()
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_iStat ); i++ )
+ {
+ m_iStat[i] = 0;
+ }
+ };
+
+ void AccumulateRound( const RoundMapStats_t &other )
+ {
+ for ( int i = 0; i < ARRAYSIZE( m_iStat ); i++ )
+ {
+ m_iStat[i] += other.m_iStat[i];
+ }
+ };
+};
+
+enum TFGameStatsVersions_t
+{
+ TF_GAMESTATS_FILE_VERSION = 006,
+ TF_GAMESTATS_MAGIC = 0xDEADBEEF
+};
+
+enum TFGameStatsLumpIds_t
+{
+ TFSTATS_LUMP_VERSION = 1,
+ TFSTATS_LUMP_MAPHEADER,
+ TFSTATS_LUMP_MAPDEATH,
+ TFSTATS_LUMP_MAPDAMAGE,
+ TFSTATS_LUMP_CLASS,
+ TFSTATS_LUMP_WEAPON,
+ TFSTATS_LUMP_ENDTAG,
+ MAX_LUMP_COUNT
+};
+
+struct TF_Gamestats_Version_t
+{
+ int m_iMagic; // always TF_GAMESTATS_MAGIC
+ int m_iVersion;
+};
+
+struct TF_Gamestats_ClassStats_t
+{
+ static const unsigned short LumpId = TFSTATS_LUMP_CLASS; // Lump ids.
+ int iSpawns; // total # of spawns of this class
+ int iTotalTime; // aggregate player time in seconds in this class
+ int iScore; // total # of points scored by this class
+ int iKills; // total # of kills by this class
+ int iDeaths; // total # of deaths by this class
+ int iAssists; // total # of assists by this class
+ int iCaptures; // total # of captures by this class
+ int iClassChanges; // total # of times someone changed to this class
+
+ void Accumulate( TF_Gamestats_ClassStats_t &other )
+ {
+ iSpawns += other.iSpawns;
+ iTotalTime += other.iTotalTime;
+ iScore += other.iScore;
+ iKills += other.iKills;
+ iDeaths += other.iDeaths;
+ iAssists += other.iAssists;
+ iCaptures += other.iCaptures;
+ iClassChanges += other.iClassChanges;
+ }
+};
+
+struct TF_Gamestats_WeaponStats_t
+{
+ static const unsigned short LumpId = TFSTATS_LUMP_WEAPON; // Lump ids.
+ int iShotsFired;
+ int iCritShotsFired;
+ int iHits;
+ int iTotalDamage;
+ int iHitsWithKnownDistance;
+ int64 iTotalDistance;
+
+ void Accumulate( TF_Gamestats_WeaponStats_t &other )
+ {
+ iShotsFired += other.iShotsFired;
+ iCritShotsFired += other.iCritShotsFired;
+ iHits += other.iHits;
+ iTotalDamage += other.iTotalDamage;
+ iHitsWithKnownDistance += other.iHitsWithKnownDistance;
+ iTotalDistance += other.iTotalDistance;
+ }
+};
+
+//=============================================================================
+//
+// TF Game Level Stats Data
+//
+struct TF_Gamestats_LevelStats_t
+{
+public:
+
+ TF_Gamestats_LevelStats_t();
+ ~TF_Gamestats_LevelStats_t();
+ TF_Gamestats_LevelStats_t( const TF_Gamestats_LevelStats_t &stats );
+
+ // Level start and end
+ void Init( const char *pszMapName, int nMapVersion, int nIPAddr, short nPort, float flStartTime );
+ void Shutdown( float flEndTime );
+
+ void Accumulate( TF_Gamestats_LevelStats_t *pOther )
+ {
+ m_Header.Accumulate( pOther->m_Header );
+ //m_aPlayerDeaths.AddVectorToTail( pOther->m_aPlayerDeaths );
+ //m_aPlayerDamage.AddVectorToTail( pOther->m_aPlayerDamage );
+ int i;
+ for ( i = 0; i < ARRAYSIZE( m_aClassStats ); i++ )
+ {
+ m_aClassStats[i].Accumulate( pOther->m_aClassStats[i] );
+ }
+ for ( i = 0; i < ARRAYSIZE( m_aWeaponStats ); i++ )
+ {
+ m_aWeaponStats[i].Accumulate( pOther->m_aWeaponStats[i] );
+ }
+
+ }
+public:
+
+ // Level header data.
+ struct LevelHeader_t
+ {
+ static const unsigned short LumpId = TFSTATS_LUMP_MAPHEADER; // Lump ids.
+ char m_szMapName[64]; // Name of the map.
+ int m_nMapRevision; // Version number for the map.
+ unsigned int m_nIPAddr; // IP Address of the server - 4 bytes stored as an int.
+ unsigned short m_nPort; // Port the server is using.
+ int m_iRoundsPlayed; // # of rounds played
+ int m_iTotalTime; // total # of seconds of all rounds
+ int m_iBlueWins; // # of blue team wins
+ int m_iRedWins; // # of red team wins
+ int m_iStalemates; // # of stalemates
+ int m_iBlueSuddenDeathWins; // # of blue team wins during sudden death
+ int m_iRedSuddenDeathWins; // # of red team wins during sudden death
+ int m_iLastCapChangedInRound[MAX_CONTROL_POINTS+1]; // # of times a round ended on each control point
+
+ void Accumulate( LevelHeader_t &other )
+ {
+ m_iRoundsPlayed += other.m_iRoundsPlayed;
+ m_iTotalTime += other.m_iTotalTime;
+ m_iBlueWins += other.m_iBlueWins;
+ m_iRedWins += other.m_iRedWins;
+ m_iStalemates += other.m_iStalemates;
+ m_iBlueSuddenDeathWins += other.m_iBlueSuddenDeathWins;
+ m_iRedSuddenDeathWins += other.m_iRedSuddenDeathWins;
+ for ( int i = 0; i <= MAX_CONTROL_POINTS; i++ )
+ {
+ m_iLastCapChangedInRound[i] += other.m_iLastCapChangedInRound[i];
+ }
+ }
+ };
+
+ // Player deaths.
+ struct PlayerDeathsLump_t
+ {
+ static const unsigned short LumpId = TFSTATS_LUMP_MAPDEATH; // Lump ids.
+ short nPosition[3]; // Position of death.
+ short iWeapon; // Weapon that killed the player.
+ unsigned short iDistance; // Distance the attacker was from the player.
+ byte iAttackClass; // Class that killed the player.
+ byte iTargetClass; // Class of the player killed.
+ };
+
+ // Player damage.
+ struct PlayerDamageLump_t
+ {
+ static const unsigned short LumpId = TFSTATS_LUMP_MAPDAMAGE; // Lump ids.
+ float fTime; // Time of the damage event
+ short nTargetPosition[3]; // Position of target.
+ short nAttackerPosition[3]; // Position of attacker.
+ short iDamage; // Total damage.
+ short iWeapon; // Weapon used.
+ byte iAttackClass; // Class of the attacker
+ byte iTargetClass; // Class of the target
+ byte iCrit; // was the shot a crit?
+ byte iKill; // did the shot kill the target?
+ };
+
+ // Data.
+ LevelHeader_t m_Header; // Level header.
+ // Disabling These Fields
+ //CUtlVector<PlayerDeathsLump_t> m_aPlayerDeaths; // Vector of player deaths.
+ //CUtlVector<PlayerDamageLump_t> m_aPlayerDamage; // Vector of player damage.
+ bool m_bIsRealServer;
+ TF_Gamestats_ClassStats_t m_aClassStats[TF_CLASS_COUNT_ALL]; // Vector of class data
+ TF_Gamestats_WeaponStats_t m_aWeaponStats[TF_WEAPON_COUNT]; // Vector of weapon data
+ // Temporary data.
+ bool m_bInitialized; // Has the map Map Stat Data been initialized.
+ time_t m_iMapStartTime;
+ time_t m_iRoundStartTime; // time_t version for steamworks stats
+ float m_flRoundStartTime;
+ int m_iPeakPlayerCount[TF_TEAM_COUNT];
+};
+
+struct TF_Gamestats_RoundStats_t
+{
+public:
+
+ TF_Gamestats_RoundStats_t();
+ ~TF_Gamestats_RoundStats_t();
+
+private:
+ TF_Gamestats_RoundStats_t( const TF_Gamestats_RoundStats_t &stats ) {}
+
+public:
+ void Reset();
+ void ResetSummary();
+
+ struct RoundSummary_t
+ {
+ int iTeamQuit;
+ int iPoints;
+ int iBonusPoints;
+ int iKills;
+ int iDeaths;
+ int iSuicides;
+ int iAssists;
+ int iBuildingsBuilt;
+ int iBuildingsDestroyed;
+ int iHeadshots;
+ int iDominations;
+ int iRevenges;
+ int iInvulns;
+ int iTeleports;
+ int iDamageDone;
+ int iHealingDone;
+ int iCrits;
+ int iBackstabs;
+ int iThrowableHits;
+ int iThrowableKills;
+ };
+
+ RoundSummary_t m_Summary;
+
+ static time_t m_iRoundStartTime;
+ static int m_iNumRounds;
+};
+
+struct TF_Gamestats_KillStats_t
+{
+public:
+ TF_Gamestats_KillStats_t();
+ ~TF_Gamestats_KillStats_t();
+
+private:
+ TF_Gamestats_KillStats_t( const TF_Gamestats_KillStats_t &stats ) {}
+
+public:
+ void Reset();
+};
+
+// Old style killstats matrix.
+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 every other player
+ int iNumKilledBy[MAX_PLAYERS+1]; // how many times this player has been killed by every other player
+ int iNumKilledByUnanswered[MAX_PLAYERS+1]; // how many unanswered kills this player has been dealt by every other player
+};
+
+//=============================================================================
+// LoadoutStats
+struct LoadoutStats_t
+{
+ LoadoutStats_t() { Reset(); }
+
+ void Reset()
+ {
+ V_memset( iLoadoutItemDefIndices, INVALID_ITEM_DEF_INDEX, sizeof( iLoadoutItemDefIndices ) );
+ V_memset( iLoadoutItemQualities, AE_UNDEFINED, sizeof( iLoadoutItemQualities ) );
+ V_memset( iLoadoutItemStyles, 0, sizeof( iLoadoutItemStyles ) );
+
+ flStartTime = 0;
+ iClass = TF_CLASS_UNDEFINED;
+ }
+
+ void Set ( int iPlayerClass )
+ {
+ iClass = iPlayerClass;
+ flStartTime = gpGlobals->curtime;
+ }
+
+ void SetItemDef ( int iSlot, itemid_t iItemDef, entityquality_t iItemQuality, style_index_t iStyle )
+ {
+ iLoadoutItemDefIndices[iSlot] = iItemDef;
+ iLoadoutItemQualities[iSlot] = iItemQuality;
+ iLoadoutItemStyles[iSlot] = iStyle;
+ }
+
+ item_definition_index_t iLoadoutItemDefIndices[CLASS_LOADOUT_POSITION_COUNT];
+ entityquality_t iLoadoutItemQualities[CLASS_LOADOUT_POSITION_COUNT];
+ style_index_t iLoadoutItemStyles[CLASS_LOADOUT_POSITION_COUNT];
+ float flStartTime;
+ int iClass;
+};
+
+//=============================================================================
+//
+// TF Player Stats
+//
+struct PlayerStats_t
+{
+ PlayerStats_t()
+ {
+ Reset();
+ };
+
+ void Reset()
+ {
+ statsCurrentLife.Reset();
+ statsCurrentRound.Reset();
+ statsAccumulated.Reset();
+ mapStatsCurrentLife.Reset();
+ mapStatsCurrentRound.Reset();
+ mapStatsAccumulated.Reset();
+ statsKills.Reset();
+ loadoutStats.Reset();
+ iConnectTime = 0;
+ iDisconnectTime = 0;
+ }
+
+ PlayerStats_t( const PlayerStats_t &other )
+ {
+ statsCurrentLife = other.statsCurrentLife;
+ statsCurrentRound = other.statsCurrentRound;
+ statsAccumulated = other.statsAccumulated;
+ mapStatsCurrentLife = other.mapStatsCurrentLife;
+ mapStatsCurrentRound = other.mapStatsCurrentRound;
+ mapStatsAccumulated = other.mapStatsAccumulated;
+ loadoutStats = other.loadoutStats;
+ iConnectTime = other.iConnectTime;
+ iDisconnectTime = other.iDisconnectTime;
+ }
+
+ RoundStats_t statsCurrentLife;
+ RoundStats_t statsCurrentRound;
+ RoundStats_t statsAccumulated;
+ RoundMapStats_t mapStatsCurrentLife;
+ RoundMapStats_t mapStatsCurrentRound;
+ RoundMapStats_t mapStatsAccumulated;
+ KillStats_t statsKills;
+ LoadoutStats_t loadoutStats;
+ int iConnectTime;
+ int iDisconnectTime;
+};
+
+// reported stats structure that contains all stats data uploaded from TF server to Steam. Note that this
+// code is shared between TF server and processgamestats, which cracks the data file on the back end
+struct TFReportedStats_t
+{
+ TFReportedStats_t();
+ ~TFReportedStats_t();
+ void Clear();
+ TF_Gamestats_LevelStats_t *FindOrAddMapStats( const char *szMapName );
+#ifdef GAME_DLL
+ void AppendCustomDataToSaveBuffer( CUtlBuffer &SaveBuffer );
+ bool LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer );
+#endif
+
+ bool m_bValidData;
+ TF_Gamestats_LevelStats_t *m_pCurrentGame;
+ CUtlDict<TF_Gamestats_LevelStats_t, unsigned short> m_dictMapStats;
+};
+
+struct ClassStats_t
+{
+ int iPlayerClass; // which class these stats refer to
+ int iNumberOfRounds; // how many times player has played this class
+ RoundStats_t accumulated;
+ RoundStats_t max;
+ RoundStats_t currentRound;
+
+ RoundStats_t accumulatedMVM;
+ RoundStats_t maxMVM;
+
+ ClassStats_t()
+ {
+ iPlayerClass = TF_CLASS_UNDEFINED;
+ iNumberOfRounds = 0;
+ }
+
+ void AccumulateRound( const RoundStats_t &other )
+ {
+ iNumberOfRounds++;
+ accumulated.AccumulateRound( other );
+ currentRound = other;
+ }
+
+ void AccumulateMVMRound( const RoundStats_t &other )
+ {
+ iNumberOfRounds++;
+ accumulatedMVM.AccumulateRound( other );
+ currentRound = other;
+ }
+};
+
+struct MapStats_t
+{
+ map_identifier_t iMapID; // which map these stats refer to
+ int iNumberOfRounds; // how many times player has played this map
+ RoundMapStats_t accumulated;
+ RoundMapStats_t currentRound;
+
+ MapStats_t()
+ {
+ iMapID = 0xFFFFFFFF;
+ iNumberOfRounds = 0;
+ }
+
+ void AccumulateRound( const RoundMapStats_t &other )
+ {
+ iNumberOfRounds++;
+ accumulated.AccumulateRound( other );
+ currentRound = other;
+ }
+};
+
+//=============================================================================
+// Beta Map Stats
+//=============================================================================
+
+//=============================================================================
+// Robot Destruction
+struct RobotDestructionStats_t
+{
+ RobotDestructionStats_t();
+
+ void Clear();
+ int GetRobotInteractionCount();
+ int GetRobotCoreInteractionCount();
+ int GetFlagInteractionCount();
+
+ // Robot Cores Collected
+ int iCoresCollectedByTeam[ TF_TEAM_COUNT ];
+
+ // Collected By What Class
+ int iCoreCollectedByClass[ TF_CLASS_COUNT ];
+
+ // Robots Killed By Type
+ // eRobotType::NUM_ROBOT_TYPES
+ int iBlueRobotsKilledByType[ 3 ];
+ int iRedRobotsKilledByType[ 3 ];
+
+ int iRobotsDamageFromClass[ TF_CLASS_COUNT ];
+
+ // Player Interaction
+ int iRobotInteraction[MAX_PLAYERS];
+ int iRobotCoreInteraction[MAX_PLAYERS];
+ int iFlagInteraction[MAX_PLAYERS];
+};
+
+//=============================================================================
+// Cactus Canyon
+
+//=============================================================================
+// Passtime
+struct PasstimeStats_t
+{
+ PasstimeStats_t() { Clear(); }
+ void Clear();
+ void AddBallFracSample( float f );
+ void AddPassTravelDistSample( float f );
+
+ // To get comprehensive class stats, we need an event log instead of a summary.
+ // But for now this should cover what we need.
+ // These class stats were specifically requested by Travis@br, in addition to
+ // total kills by class. The total kills by class is tracked by TF already.
+ struct Classes_t
+ {
+ int nTotalScores;
+ int nTotalCarrySec;
+ } classes[TF_CLASS_COUNT_ALL];
+
+ struct RoundSummary_t
+ {
+ int nTotalPassesStarted;
+ int nTotalPassesFailed;
+ int nTotalPassesShotDown;
+ int nTotalPassesCompleted;
+ int nTotalPassesCompletedNearGoal;
+ int nTotalPassesIntercepted;
+ int nTotalPassesInterceptedNearGoal;
+ int nTotalPassRequests;
+ int nTotalTosses;
+ int nTotalTossesCompleted;
+ int nTotalTossesIntercepted;
+ int nTotalTossesInterceptedNearGoal;
+ int nTotalSteals;
+ int nTotalStealsNearGoal;
+ int nTotalBallSpawnShots;
+ int nTotalScores;
+ int nTotalRecoveries;
+ int nTotalCarrySec;
+ int nTotalWinningTeamBallCarrySec;
+ int nTotalLosingTeamBallCarrySec;
+ int nTotalThrowCancels;
+ int nTotalSpeedBoosts;
+ int nTotalJumpPads;
+ int nTotalCarrierSpeedBoosts;
+ int nTotalCarrierJumpPads;
+ int nTotalBallDeflects;
+ int nBallNeutralSec;
+ int nGoalType;
+ int nRoundEndReason;
+ int nRoundRemainingSec;
+ int nRoundMaxSec;
+ int nPlayersRedMax;
+ int nPlayersBlueMax;
+ int nScoreBlue;
+ int nScoreRed;
+ bool bStalemate;
+ bool bSuddenDeath;
+ bool bMeleeOnlySuddenDeath;
+
+ // histogram used to create min/max/mean/med/mode/stdev stats
+ uint32 nBallFracSampleCount;
+ uint32 arrBallFracHist[ 256 ];
+ uint32 nBallFracHistSum;
+
+ // sample set used to create min/max/mean/med/stdev stats
+ static const uint32 k_nMaxPassTravelDistSamples = 1024;
+ uint32 nPassTravelDistSampleCount;
+ uint16 arrPassTravelDistSamples[ k_nMaxPassTravelDistSamples ];
+ } summary;
+};
+
+const char* GetGameTypeID();
+
+#ifdef CLIENT_DLL
+MapStats_t &GetMapStats( map_identifier_t iMapID );
+#endif
+
+#endif // TF_GAMESTATS_SHARED_H