diff --git a/core/TimerSys.cpp b/core/TimerSys.cpp index 5831dd40..633de682 100644 --- a/core/TimerSys.cpp +++ b/core/TimerSys.cpp @@ -234,7 +234,7 @@ void TimerSystem::GameFrame(bool simulating) g_fTimerThink = CalcNextThink(g_fTimerThink, TIMER_MIN_ACCURACY); } - RunFrameHooks(); + RunFrameHooks(simulating); if (m_pOnGameFrame->GetFunctionCount()) { diff --git a/core/frame_hooks.cpp b/core/frame_hooks.cpp index 5603e881..09a38a67 100644 --- a/core/frame_hooks.cpp +++ b/core/frame_hooks.cpp @@ -39,11 +39,12 @@ float g_LastMenuTime = 0.0f; float g_LastAuthCheck = 0.0f; -void RunFrameHooks() +void RunFrameHooks(bool simulating) { /* Frame based hooks */ g_DBMan.RunFrame(); g_HL2.ProcessFakeCliCmdQueue(); + g_SourceMod.ProcessGameFrameHooks(simulating); float curtime = *g_pUniversalTime; @@ -60,4 +61,3 @@ void RunFrameHooks() g_LastAuthCheck = curtime; } } - diff --git a/core/frame_hooks.h b/core/frame_hooks.h index 098ff428..f99d560c 100644 --- a/core/frame_hooks.h +++ b/core/frame_hooks.h @@ -32,6 +32,6 @@ #ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ #define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ -void RunFrameHooks(); +void RunFrameHooks(bool simulating); #endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 9b88b66c..5a44e775 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -670,6 +670,36 @@ time_t SourceModBase::GetAdjustedTime() return GetAdjustedTime(); } +void SourceModBase::AddGameFrameHook(GAME_FRAME_HOOK hook) +{ + m_frame_hooks.push_back(hook); +} + +void SourceModBase::RemoveGameFrameHook(GAME_FRAME_HOOK hook) +{ + for (size_t i = 0; i < m_frame_hooks.size(); i++) + { + if (m_frame_hooks[i] == hook) + { + m_frame_hooks.erase(m_frame_hooks.iterAt(i)); + return; + } + } +} + +void SourceModBase::ProcessGameFrameHooks(bool simulating) +{ + if (m_frame_hooks.size() == 0) + { + return; + } + + for (size_t i = 0; i < m_frame_hooks.size(); i++) + { + m_frame_hooks[i](simulating); + } +} + SMGlobalClass *SMGlobalClass::head = NULL; SMGlobalClass::SMGlobalClass() diff --git a/core/sourcemod.h b/core/sourcemod.h index 1b222c80..cb4ff880 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -35,6 +35,7 @@ #include "sm_globals.h" #include #include +#include #include "CDataPack.h" using namespace SourceHook; @@ -114,6 +115,9 @@ public: // ISourceMod void GlobalPause(); void GlobalUnpause(); void DoGlobalPluginLoads(); + void AddGameFrameHook(GAME_FRAME_HOOK hook); + void RemoveGameFrameHook(GAME_FRAME_HOOK hook); + void ProcessGameFrameHooks(bool simulating); private: CStack m_freepacks; char m_SMBaseDir[PLATFORM_MAX_PATH]; @@ -124,6 +128,7 @@ private: bool m_ExecOnMapEnd; unsigned int m_target; bool m_GotBasePath; + CVector m_frame_hooks; }; extern bool g_Loaded; diff --git a/public/ISourceMod.h b/public/ISourceMod.h index 5782b772..66b21090 100644 --- a/public/ISourceMod.h +++ b/public/ISourceMod.h @@ -43,7 +43,7 @@ #include #define SMINTERFACE_SOURCEMOD_NAME "ISourceMod" -#define SMINTERFACE_SOURCEMOD_VERSION 5 +#define SMINTERFACE_SOURCEMOD_VERSION 6 /** * @brief Forward declaration of the KeyValues class. @@ -63,6 +63,13 @@ namespace SourceMod Path_SM_Rel, /**< Base path is relative to SourceMod */ }; + /** + * @brief Called when a game frame is fired. + * + * @param simulating Whether or not the game is ticking. + */ + typedef void (*GAME_FRAME_HOOK)(bool simulating); + /** * @brief Contains miscellaneous helper functions. */ @@ -225,6 +232,20 @@ namespace SourceMod * @return Global client value. */ virtual unsigned int GetGlobalTarget() const =0; + + /** + * @brief Adds a function to be called each game frame. + * + * @param hook Hook function. + */ + virtual void AddGameFrameHook(GAME_FRAME_HOOK hook) =0; + + /** + * @brief Removes one game frame hook matching the given function. + * + * @param hook Hook function. + */ + virtual void RemoveGameFrameHook(GAME_FRAME_HOOK hook) =0; }; }