//========= Copyright Valve Corporation, All rights reserved. ============// //=======================================================================================// #if defined(REPLAY_ENABLED) #ifndef GENERICCLASSBASED_REPLAY_H #define GENERICCLASSBASED_REPLAY_H #ifdef _WIN32 #pragma once #endif //---------------------------------------------------------------------------------------- #include "GameEventListener.h" #include "replay/iclientreplaycontext.h" #include "replay/replay.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 &vec, int nVictimId, int nAssisterId = 0); void AddKillStatFromFriendIds(CUtlVector &vec, uint32 nVictimFriendId, uint32 nAssisterFriendId = 0); void WriteKillStatVector(CUtlVector const &vec, const char *pSubKeyName, const char *pElementKeyName, KeyValues *pRootKey, int nNumMembersToWrite) const; void AddKillStats(CUtlVector &vecKillStats, KeyValues *pIn, const char *pSubKeyName, int iStatIndex); void RecordUpdatedStats(); CUtlVector m_vecKills; CUtlVector m_vecDominations; CUtlVector m_vecAssisterDominations; CUtlVector m_vecRevenges; CUtlVector m_vecAssisterRevenges; // TODO... dominations, achievements, etc. }; //---------------------------------------------------------------------------------------- inline CGenericClassBasedReplay *ToGenericClassBasedReplay( CReplay *pClientReplay) { return static_cast(pClientReplay); } inline const CGenericClassBasedReplay *ToGenericClassBasedReplay( const CReplay *pClientReplay) { return static_cast(pClientReplay); } inline CGenericClassBasedReplay *GetGenericClassBasedReplay( ReplayHandle_t hReplay) { return ToGenericClassBasedReplay( g_pClientReplayContext->GetReplay(hReplay)); } //---------------------------------------------------------------------------------------- #endif // GENERICCLASSBASED_REPLAY_H #endif