//========= Copyright Valve Corporation, All rights reserved. ============// //=======================================================================================// #if defined( REPLAY_ENABLED ) #ifndef GENERICCLASSBASED_REPLAY_H #define GENERICCLASSBASED_REPLAY_H #ifdef _WIN32 #pragma once #endif //---------------------------------------------------------------------------------------- #include "replay/replay.h" #include "replay/iclientreplaycontext.h" #include "GameEventListener.h" // For RoundStats_t #include "replay/gamedefs.h" //---------------------------------------------------------------------------------------- extern IClientReplayContext *g_pClientReplayContext; //---------------------------------------------------------------------------------------- class CGenericClassBasedReplay : public CReplay, public CGameEventListener { typedef CReplay BaseClass; public: CGenericClassBasedReplay(); ~CGenericClassBasedReplay(); virtual void OnBeginRecording(); virtual void OnEndRecording(); virtual void OnComplete(); virtual bool ShouldAllowDelete() const; virtual void OnDelete(); virtual void FireGameEvent( IGameEvent *pEvent ); virtual bool Read( KeyValues *pIn ); virtual void Write( KeyValues *pOut ); virtual void DumpGameSpecificData() const; void SetPlayerClass( int nPlayerClass ); void SetPlayerTeam( int nPlayerTeam ); void RecordPlayerDeath( const char *pKillerName, int nKillerClass ); // Add a new kill to the list void AddKill( const char *pPlayerName, int nPlayerClass ); // Get the player class as a string virtual const char *GetPlayerClass() const; // Get the player team as a string virtual const char *GetPlayerTeam() const = 0; // Utility to get the material-friendly player class (demoman->demo, heavyweapons->heavy) virtual const char *GetMaterialFriendlyPlayerClass() const; // Was there a killer? inline bool WasKilled() const { return m_szKillerName[0] != 0; } // Get killer name const char *GetKillerName() const; // Get the killer class, if there was a killer const char *GetKillerClass() const; int GetDownloadStatus() const; // Kill info struct KillData_t { char m_szPlayerName[MAX_OSPATH]; int m_nPlayerClass; }; inline int GetKillCount() const { return m_vecKills.Count(); } inline const KillData_t *GetKill( int nKillIndex ) { return m_vecKills[ nKillIndex ]; } // A generic info struct used for dominations, assisted dominations, revenges, assisted revenged... // Not all data members are necessarily used struct GenericStatInfo_t { GenericStatInfo_t() : m_nVictimFriendId( 0 ), m_nAssisterFriendId( 0 ) {} uint32 m_nVictimFriendId; uint32 m_nAssisterFriendId; }; inline int GetDominationCount() const { return m_vecDominations.Count(); } inline const GenericStatInfo_t *GetDomination( int nIndex ) const { return m_vecDominations[ nIndex ]; } inline int GetAssisterDominationCount() const { return m_vecAssisterDominations.Count(); } inline const GenericStatInfo_t *GetAssisterDomination( int nIndex ) const { return m_vecAssisterDominations[ nIndex ]; } inline int GetRevengeCount() const { return m_vecRevenges.Count(); } inline const GenericStatInfo_t *GetRevenge( int nIndex ) const { return m_vecRevenges[ nIndex ]; } inline int GetAssisterRevengeCount() const { return m_vecAssisterRevenges.Count(); } inline const GenericStatInfo_t *GetAssisterRevenge( int nIndex ) const { return m_vecAssisterRevenges[ nIndex ]; } RoundStats_t const &GetStats() const { return m_lifeStats; } protected: int m_nPlayerClass; int m_nPlayerTeam; int m_nStatUndefined; char m_szKillerName[ MAX_OSPATH ]; int m_nKillerClass; virtual bool IsValidClass( int nClass ) const = 0; virtual bool IsValidTeam( int iTeam ) const = 0; virtual bool GetCurrentStats( RoundStats_t &out ) = 0; virtual const char *GetStatString( int iStat ) const = 0; virtual const char *GetPlayerClass( int iClass ) const = 0; virtual void Update(); // Domination void AddDomination( int nVictimID ); void AddAssisterDomination( int nVictimID, int nAssiterID ); void AddRevenge( int nVictimID ); void AddAssisterRevenge( int nVictimID, int nAssiterID ); float GetKillScreenshotDelay(); RoundStats_t m_refStats; // Reference stats, used to compute current stats RoundStats_t m_lifeStats; // Stats for this life, based on reference stats (m_refStats) private: void MedicUpdate(); bool GetFriendIdFromUserId( int nPlayerIndex, uint32 &nFriendIdOut ) const; // Get a friend ID based on player index. Returns true on success void AddKillStatFromUserIds( CUtlVector< GenericStatInfo_t * > &vec, int nVictimId, int nAssisterId = 0 ); void AddKillStatFromFriendIds( CUtlVector< GenericStatInfo_t * > &vec, uint32 nVictimFriendId, uint32 nAssisterFriendId = 0 ); void WriteKillStatVector( CUtlVector< GenericStatInfo_t * > const &vec, const char *pSubKeyName, const char *pElementKeyName, KeyValues *pRootKey, int nNumMembersToWrite ) const; void AddKillStats( CUtlVector< GenericStatInfo_t * > &vecKillStats, KeyValues *pIn, const char *pSubKeyName, int iStatIndex ); void RecordUpdatedStats(); CUtlVector< KillData_t * > m_vecKills; CUtlVector< GenericStatInfo_t * > m_vecDominations; CUtlVector< GenericStatInfo_t * > m_vecAssisterDominations; CUtlVector< GenericStatInfo_t * > m_vecRevenges; CUtlVector< GenericStatInfo_t * > m_vecAssisterRevenges; // TODO... dominations, achievements, etc. }; //---------------------------------------------------------------------------------------- inline CGenericClassBasedReplay *ToGenericClassBasedReplay( CReplay *pClientReplay ) { return static_cast< CGenericClassBasedReplay * >( pClientReplay ); } inline const CGenericClassBasedReplay *ToGenericClassBasedReplay( const CReplay *pClientReplay ) { return static_cast< const CGenericClassBasedReplay * >( pClientReplay ); } inline CGenericClassBasedReplay *GetGenericClassBasedReplay( ReplayHandle_t hReplay ) { return ToGenericClassBasedReplay( g_pClientReplayContext->GetReplay( hReplay ) ); } //---------------------------------------------------------------------------------------- #endif // GENERICCLASSBASED_REPLAY_H #endif