#pragma once #include #include "../../sdk/virtual.hpp" #include #define HOOK_FUNCTION(hook) hook, #hook inline funchook_t *g_funchookCtx = nullptr; inline bool g_isShuttingDown = false; template class CHook { public: std::add_pointer_t m_pOriginal; // Template has been used to avoid casts. template void Hook(OriginalT _pOriginalFn, HookT &pHookFn, const char *szHookName) { if (this->m_pOriginal) { LOG("%s tried rehooking.\n", szHookName); return; } void *pOriginalFn = static_cast(_pOriginalFn); if (!pOriginalFn) { LOG("%s tried hooking null.\n", szHookName); return; } this->m_pOriginal = reinterpret_castm_pOriginal)>(pOriginalFn); int rv = funchook_prepare(g_funchookCtx, reinterpret_cast(&this->m_pOriginal), reinterpret_cast(pHookFn)); if (rv == FUNCHOOK_ERROR_SUCCESS) { LOG("%s hooked successfully. [ %p -> %p ]\n", szHookName, pOriginalFn, pHookFn); } else { this->m_pOriginal = nullptr; LOG("%s hook failed. [ %s ]\n", szHookName, funchook_error_message(g_funchookCtx)); } } template void HookVirtual(void *pClass, int index, HookT &pHookFn, const char *szHookName) { this->Hook(vmt::GetVMethod(index, pClass), pHookFn, szHookName); } // Shorthand for calling original. template auto operator()(Args &&...args) { return std::invoke(this->m_pOriginal, std::forward(args)...); } };