mirror of
https://github.com/rehlds/reapi.git
synced 2025-02-10 13:48:55 +03:00
Refactoring
This commit is contained in:
parent
392026e50b
commit
50b5649257
@ -17,22 +17,27 @@
|
|||||||
#include <reapi_engine.inc> // NOTE: only for ReHLDS
|
#include <reapi_engine.inc> // NOTE: only for ReHLDS
|
||||||
#include <reapi_gamedll.inc> // NOTE: only for gamedll Counter-Strike (ReGameDLL_CS)
|
#include <reapi_gamedll.inc> // NOTE: only for gamedll Counter-Strike (ReGameDLL_CS)
|
||||||
|
|
||||||
|
// return constants
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RH_UNSET = 0,
|
HC_CONTINUE = 0,
|
||||||
RH_IGNORED, // plugin didn't take any action
|
HC_OVERRIDE,
|
||||||
RH_HANDLED, // plugin did something, but real function should still be called
|
HC_SUPERCEDE,
|
||||||
RH_OVERRIDE, // call real function, but use my return value
|
HC_BREAK
|
||||||
RH_SUPERCEDE // skip real function; use my return value
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// for hookchain return
|
// hookchain types
|
||||||
enum HookChainReturn
|
enum AType
|
||||||
{
|
{
|
||||||
RHV_STRING = 0, // string
|
ATYPE_INTEGER = 0,
|
||||||
RHV_FLOAT, // float
|
ATYPE_FLOAT,
|
||||||
RHV_INTEGER, // returns an integer or boolean
|
ATYPE_STRING,
|
||||||
RHV_CLASSPTR // for CBaseEntity *, CBasePlayer * etc
|
ATYPE_CLASSPTR
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HookChain
|
||||||
|
{
|
||||||
|
INVALID_HOOKCHAIN = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -76,11 +81,37 @@ native bool:EnableHookChain(HookChain:hook);
|
|||||||
* @param type To specify the type RHV_*, look at the enum HookChainReturn
|
* @param type To specify the type RHV_*, look at the enum HookChainReturn
|
||||||
* @param value The value to set the return to.
|
* @param value The value to set the return to.
|
||||||
*
|
*
|
||||||
* native SetHookChainReturn(HookChainReturn:type, any:...);
|
* native SetHookChainReturn(AType:type, any:...);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
native SetHookChainReturn(HookChainReturn:type, any:...);
|
native SetHookChainReturn(HookChainReturn:type, any:...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the return value of a hookchain.
|
||||||
|
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
||||||
|
*
|
||||||
|
* @param type To specify the type RHV_*, look at the enum HookChainReturn
|
||||||
|
* @param value The value to set the return to.
|
||||||
|
*
|
||||||
|
* native GetHookChainReturn(AType:type, any:...);
|
||||||
|
*/
|
||||||
|
|
||||||
|
native GetHookChainReturn(AType:type, any:...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set hookchain argument.
|
||||||
|
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
||||||
|
*
|
||||||
|
* @param number Number of argument
|
||||||
|
* @param value New value
|
||||||
|
* @param [maxlen] Max length of string (optional)
|
||||||
|
* @return Returns if the function is successful executed true otherwise false
|
||||||
|
*
|
||||||
|
* native SetHookChainArg(number, AType:type, any:...);
|
||||||
|
*/
|
||||||
|
|
||||||
|
native SetHookChainArg(number, AType:type, any:...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the callback from the module that gives major/minor versions for verifying compatibility reapi API versions
|
* This is the callback from the module that gives major/minor versions for verifying compatibility reapi API versions
|
||||||
* If will be amxx plugin a failure, then you do need to upgrade to the latest version of the module reapi or do update files included for amxx plugins
|
* If will be amxx plugin a failure, then you do need to upgrade to the latest version of the module reapi or do update files included for amxx plugins
|
||||||
@ -90,13 +121,17 @@ public __reapi_version_check(const majorVersion, const minorVersion)
|
|||||||
{
|
{
|
||||||
if (majorVersion != REAPI_VERISON_MAJOR)
|
if (majorVersion != REAPI_VERISON_MAJOR)
|
||||||
{
|
{
|
||||||
set_fail_state("[ReAPI]: Api major version mismatch; expected %d, real %d", REAPI_VERISON_MAJOR, majorVersion);
|
new temp[512];
|
||||||
|
formatex(temp, sizeof temp - 1, "[ReAPI]: Api major version mismatch; expected %d, real %d", REAPI_VERISON_MAJOR, majorVersion);
|
||||||
|
set_fail_state(temp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minorVersion < REAPI_VERISON_MINOR)
|
if (minorVersion < REAPI_VERISON_MINOR)
|
||||||
{
|
{
|
||||||
set_fail_state("[ReAPI]: Api minor version mismatch; expected at least %d, real %d", REAPI_VERISON_MINOR, minorVersion);
|
new temp[512];
|
||||||
|
formatex(temp, sizeof temp - 1, "[ReAPI]: Api minor version mismatch; expected at least %d, real %d", REAPI_VERISON_MINOR, minorVersion);
|
||||||
|
set_fail_state(temp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ typedef IHookChain<int> IReGameHook_CBasePlayer_Classify;
|
|||||||
typedef IHookChainRegistryClass<int, class CBasePlayer> IReGameHookRegistry_CBasePlayer_Classify;
|
typedef IHookChainRegistryClass<int, class CBasePlayer> IReGameHookRegistry_CBasePlayer_Classify;
|
||||||
|
|
||||||
// CBasePlayer::TraceAttack hook
|
// CBasePlayer::TraceAttack hook
|
||||||
typedef IVoidHookChain<struct entvars_s *, float, Vector, struct TraceResult *, int> IReGameHook_CBasePlayer_TraceAttack;
|
typedef IVoidHookChain<struct entvars_s *, float, Vector&, struct TraceResult *, int> IReGameHook_CBasePlayer_TraceAttack;
|
||||||
typedef IVoidHookChainRegistryClass<class CBasePlayer, struct entvars_s *, float, Vector, struct TraceResult *, int> IReGameHookRegistry_CBasePlayer_TraceAttack;
|
typedef IVoidHookChainRegistryClass<class CBasePlayer, struct entvars_s *, float, Vector&, struct TraceResult *, int> IReGameHookRegistry_CBasePlayer_TraceAttack;
|
||||||
|
|
||||||
// CBasePlayer::TakeDamage hook
|
// CBasePlayer::TakeDamage hook
|
||||||
typedef IHookChain<int, struct entvars_s *, struct entvars_s *, float, int> IReGameHook_CBasePlayer_TakeDamage;
|
typedef IHookChain<int, struct entvars_s *, struct entvars_s *, float, int> IReGameHook_CBasePlayer_TakeDamage;
|
||||||
|
@ -52,7 +52,7 @@ typedef IBaseInterface* (*CreateInterfaceFn)(const char *pName, int *pReturnCode
|
|||||||
typedef IBaseInterface* (*InstantiateInterfaceFn)();
|
typedef IBaseInterface* (*InstantiateInterfaceFn)();
|
||||||
|
|
||||||
|
|
||||||
// Used internally to register classes.
|
// Used internally to classes.
|
||||||
class InterfaceReg
|
class InterfaceReg
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -358,6 +358,9 @@
|
|||||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -206,3 +206,25 @@ NOINLINE void MF_LogError(AMX *amx, int err, const char *fmt, ...)
|
|||||||
|
|
||||||
g_amxxapi.LogError(amx, err, "[%s] %s", g_ModuleInfo.logtag, msg);
|
g_amxxapi.LogError(amx, err, "[%s] %s", g_ModuleInfo.logtag, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len)
|
||||||
|
{
|
||||||
|
char* start = dest;
|
||||||
|
|
||||||
|
while (*src && --max)
|
||||||
|
*dest++ = (char)*src++;
|
||||||
|
*dest = '\0';
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
*len = dest - start;
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAmxString(cell* dest, const char* string, size_t max)
|
||||||
|
{
|
||||||
|
while (*string && max--)
|
||||||
|
*dest++ = (cell)*string++;
|
||||||
|
|
||||||
|
*dest = 0;
|
||||||
|
}
|
||||||
|
@ -378,15 +378,6 @@ typedef edict_t * ( *PFN_GET_PLAYER_EDICT ) ( int /*id*/ );
|
|||||||
typedef void * ( *PFN_GET_PLAYER_EDICT ) ( int /*id*/ );
|
typedef void * ( *PFN_GET_PLAYER_EDICT ) ( int /*id*/ );
|
||||||
#endif
|
#endif
|
||||||
typedef void * ( *PFN_PLAYER_PROP_ADDR ) ( int /*id*/, int /*prop*/ );
|
typedef void * ( *PFN_PLAYER_PROP_ADDR ) ( int /*id*/, int /*prop*/ );
|
||||||
|
|
||||||
#ifdef MEMORY_TEST
|
|
||||||
typedef void * ( *PFN_ALLOCATOR ) ( const char* /*filename*/, const unsigned int /*line*/, const char* /*func*/,
|
|
||||||
const unsigned int /*type*/, const size_t /*size*/ );
|
|
||||||
typedef void * ( *PFN_REALLOCATOR ) ( const char* /*filename*/, const unsigned int /*line*/, const char* /*func*/,
|
|
||||||
const unsigned int /*type*/, const size_t /*size*/, void* /*addr*/ );
|
|
||||||
typedef void(*PFN_DEALLOCATOR) ( const char* /*filename*/, const unsigned int /*line*/, const char* /*func*/,
|
|
||||||
const unsigned int /*type*/, const void* /*addr*/ );
|
|
||||||
#endif
|
|
||||||
typedef int(*PFN_AMX_EXEC) ( AMX* /*amx*/, cell* /*return val*/, int /*index*/ );
|
typedef int(*PFN_AMX_EXEC) ( AMX* /*amx*/, cell* /*return val*/, int /*index*/ );
|
||||||
typedef int(*PFN_AMX_EXECV) ( AMX* /*amx*/, cell* /*return val*/, int /*index*/, int /*numparams*/, cell[] /*params*/ );
|
typedef int(*PFN_AMX_EXECV) ( AMX* /*amx*/, cell* /*return val*/, int /*index*/, int /*numparams*/, cell[] /*params*/ );
|
||||||
typedef int(*PFN_AMX_ALLOT) ( AMX* /*amx*/, int /*length*/, cell* /*amx_addr*/, cell** /*phys_addr*/ );
|
typedef int(*PFN_AMX_ALLOT) ( AMX* /*amx*/, int /*length*/, cell* /*amx_addr*/, cell** /*phys_addr*/ );
|
||||||
@ -503,5 +494,27 @@ extern amxxapi_t g_amxxapi;
|
|||||||
|
|
||||||
void MF_Log(const char *fmt, ...);
|
void MF_Log(const char *fmt, ...);
|
||||||
void MF_LogError(AMX *amx, int err, const char *fmt, ...);
|
void MF_LogError(AMX *amx, int err, const char *fmt, ...);
|
||||||
|
char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len);
|
||||||
|
void setAmxString(cell* dest, const char* string, size_t max);
|
||||||
|
|
||||||
|
inline cell* getAmxAddr(AMX *amx, cell amx_addr)
|
||||||
|
{
|
||||||
|
return (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct getAmxString
|
||||||
|
{
|
||||||
|
getAmxString(cell* src, size_t* len)
|
||||||
|
{
|
||||||
|
getAmxStringTemp(src, temp, sizeof temp - 1, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator char *()
|
||||||
|
{
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
char temp[1024];
|
||||||
|
};
|
||||||
|
|
||||||
#endif // __AMXXMODULE_H__
|
#endif // __AMXXMODULE_H__
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
CAPI_Config api_cfg;
|
CAPI_Config api_cfg;
|
||||||
|
|
||||||
|
CAPI_Config::CAPI_Config() : m_api_rehlds(false), m_api_regame(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool CAPI_Config::Init()
|
bool CAPI_Config::Init()
|
||||||
{
|
{
|
||||||
m_api_rehlds = RehldsApi_Init();
|
m_api_rehlds = RehldsApi_Init();
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
class CAPI_Config {
|
class CAPI_Config {
|
||||||
public:
|
public:
|
||||||
|
CAPI_Config();
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
||||||
bool hasReHLDS() const { return m_api_rehlds; }
|
bool hasReHLDS() const { return m_api_rehlds; }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "precompiled.h"
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
extern void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
extern void ServerDeactivate_Post();
|
extern void ServerDeactivate_Post();
|
||||||
|
|
||||||
DLL_FUNCTIONS gFunctionTable =
|
DLL_FUNCTIONS gFunctionTable =
|
||||||
@ -79,8 +80,8 @@ DLL_FUNCTIONS gFunctionTable_Post =
|
|||||||
NULL, // pfnClientPutInServer
|
NULL, // pfnClientPutInServer
|
||||||
NULL, // pfnClientCommand
|
NULL, // pfnClientCommand
|
||||||
NULL, // pfnClientUserInfoChanged
|
NULL, // pfnClientUserInfoChanged
|
||||||
NULL, // pfnServerActivate
|
&ServerActivate_Post, // pfnServerActivate
|
||||||
&ServerDeactivate_Post, // pfnServerDeactivate
|
&ServerDeactivate_Post, // pfnServerDeactivate
|
||||||
NULL, // pfnPlayerPreThink
|
NULL, // pfnPlayerPreThink
|
||||||
NULL, // pfnPlayerPostThink
|
NULL, // pfnPlayerPostThink
|
||||||
NULL, // pfnStartFrame
|
NULL, // pfnStartFrame
|
||||||
|
@ -1,36 +1,48 @@
|
|||||||
#include "precompiled.h"
|
#include "precompiled.h"
|
||||||
|
|
||||||
CHook *g_currentHookChain = nullptr;
|
hookctx_t* g_hookCtx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ReHLDS functions
|
* ReHLDS functions
|
||||||
*/
|
*/
|
||||||
void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch)
|
void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_SV_StartSound, recipients, ENTINDEX(entity), channel, sample, volume, attenuation, fFlags, pitch)) {
|
auto original = [chain](int _recipients, int _entity, int _channel, const char *_sample, int _volume, float _attenuation, int _fFlags, int _pitch)
|
||||||
chain->callNext(recipients, entity, channel, sample, volume, attenuation, fFlags, pitch);
|
{
|
||||||
}
|
chain->callNext(_recipients, INDEXENT(_entity), _channel, _sample, _volume, _attenuation, _fFlags, _pitch);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_SV_StartSound, recipients, ENTINDEX(entity), channel, sample, volume, attenuation, fFlags, pitch);
|
callVoidForward(RH_SV_StartSound, original, recipients, indexOfEdict(entity), channel, sample, volume, attenuation, fFlags, pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt)
|
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_SV_DropClient, cl->GetId(), crash, fmt)) {
|
auto original = [chain](int _cl, bool _crash, const char *_fmt)
|
||||||
chain->callNext(cl, crash, fmt);
|
{
|
||||||
}
|
chain->callNext(g_RehldsSvs->GetClient(_cl), _crash, _fmt);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_SV_DropClient, cl->GetId(), crash, fmt);
|
callVoidForward(RH_SV_DropClient, original, cl->GetId(), crash, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics)
|
void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics)
|
||||||
{
|
{
|
||||||
callVoidForward(chain, RH_SV_ActivateServer, runPhysics);
|
auto original = [chain](int _runPhysics)
|
||||||
|
{
|
||||||
|
chain->callNext(_runPhysics);
|
||||||
|
};
|
||||||
|
|
||||||
|
callVoidForward(RH_SV_ActivateServer, original, runPhysics);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value)
|
void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value)
|
||||||
{
|
{
|
||||||
callVoidForward(chain, RH_Cvar_DirectSet, var, value);
|
auto original = [chain](cvar_t *_var, const char *_value)
|
||||||
|
{
|
||||||
|
chain->callNext(_var, _value);
|
||||||
|
};
|
||||||
|
|
||||||
|
callVoidForward(RH_Cvar_DirectSet, original, var, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -38,297 +50,241 @@ void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *
|
|||||||
*/
|
*/
|
||||||
void CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *pthis)
|
void CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Spawn, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Spawn, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_Spawn, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis)
|
void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Precache, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Precache, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_Precache, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis)
|
int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext();
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_ObjectCaps, pthis->entindex())) {
|
return callForward<int>(RH_CBasePlayer_ObjectCaps, original, pthis->entindex());
|
||||||
origresult = chain->callNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_ObjectCaps, pthis->entindex())) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBasePlayer_Classify(IReGameHook_CBasePlayer_Classify *chain, CBasePlayer *pthis)
|
int CBasePlayer_Classify(IReGameHook_CBasePlayer_Classify *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
//int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext();
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_Classify, pthis->entindex())) {
|
return callForward<int>(RH_CBasePlayer_Classify, original, pthis->entindex());
|
||||||
origresult = chain->callNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_Classify, pthis->entindex())) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_TraceAttack(IReGameHook_CBasePlayer_TraceAttack *chain, CBasePlayer *pthis, entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
void CBasePlayer_TraceAttack(IReGameHook_CBasePlayer_TraceAttack *chain, CBasePlayer *pthis, entvars_t *pevAttacker, float flDamage, Vector& vecDir, TraceResult *ptr, int bitsDamageType)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_TraceAttack, pthis->entindex(), ENTINDEX(pevAttacker), flDamage, g_amxxapi.PrepareCellArrayA(reinterpret_cast<cell *>(&vecDir), 3, false), ptr, bitsDamageType)) {
|
Vector vecDirCopy(vecDir);
|
||||||
chain->callNext(pevAttacker, flDamage, vecDir, ptr, bitsDamageType);
|
|
||||||
}
|
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_TraceAttack, pthis->entindex(), ENTINDEX(pevAttacker), flDamage, g_amxxapi.PrepareCellArrayA(reinterpret_cast<cell *>(&vecDir), 3, false), ptr, bitsDamageType);
|
auto original = [chain, &vecDirCopy](int _pthis, int _pevAttacker, float _flDamage, cell _vecDir, int _ptr, int _bitsDamageType)
|
||||||
|
{
|
||||||
|
chain->callNext(PEV(_pevAttacker), _flDamage, vecDirCopy, (TraceResult *)_ptr, _bitsDamageType);
|
||||||
|
};
|
||||||
|
|
||||||
|
callVoidForward(RH_CBasePlayer_TraceAttack, original, pthis->entindex(), indexOfEdict(pevAttacker), flDamage, g_amxxapi.PrepareCellArrayA(reinterpret_cast<cell *>(&vecDirCopy), 3, true), int(ptr), bitsDamageType);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBasePlayer_TakeDamage(IReGameHook_CBasePlayer_TakeDamage *chain, CBasePlayer *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType)
|
int CBasePlayer_TakeDamage(IReGameHook_CBasePlayer_TakeDamage *chain, CBasePlayer *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType)
|
||||||
{
|
{
|
||||||
//int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis, int _pevInflictor, int _pevAttacker, float _flDamage, int _bitsDamageType)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(PEV(_pevInflictor), PEV(_pevAttacker), _flDamage, _bitsDamageType);
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_TakeDamage, pthis->entindex(), ENTINDEX(pevInflictor), ENTINDEX(pevAttacker), flDamage, bitsDamageType)) {
|
return callForward<int>(RH_CBasePlayer_TakeDamage, original, pthis->entindex(), indexOfEdict(pevInflictor), indexOfEdict(pevAttacker), flDamage, bitsDamageType);
|
||||||
origresult = chain->callNext(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_TakeDamage, pthis->entindex(), ENTINDEX(pevInflictor), ENTINDEX(pevAttacker), flDamage, bitsDamageType)) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBasePlayer_TakeHealth(IReGameHook_CBasePlayer_TakeHealth *chain, CBasePlayer *pthis, float flHealth, int bitsDamageType)
|
int CBasePlayer_TakeHealth(IReGameHook_CBasePlayer_TakeHealth *chain, CBasePlayer *pthis, float flHealth, int bitsDamageType)
|
||||||
{
|
{
|
||||||
//int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis, float _flHealth, int _bitsDamageType)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(_flHealth, _bitsDamageType);
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_TakeHealth, pthis->entindex(), flHealth, bitsDamageType)) {
|
return callForward<int>(RH_CBasePlayer_TakeHealth, original, pthis->entindex(), flHealth, bitsDamageType);
|
||||||
origresult = chain->callNext(flHealth, bitsDamageType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_TakeHealth, pthis->entindex(), flHealth, bitsDamageType)) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_Killed(IReGameHook_CBasePlayer_Killed *chain, CBasePlayer *pthis, entvars_t *pevAttacker, int iGib)
|
void CBasePlayer_Killed(IReGameHook_CBasePlayer_Killed *chain, CBasePlayer *pthis, entvars_t *pevAttacker, int iGib)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Killed, pthis->entindex(), ENTINDEX(pevAttacker), iGib)) {
|
auto original = [chain](int _pthis, int _pevAttacker, int _iGib)
|
||||||
chain->callNext(pevAttacker, iGib);
|
{
|
||||||
}
|
chain->callNext(PEV(_pevAttacker), _iGib);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Killed, pthis->entindex(), ENTINDEX(pevAttacker), iGib);
|
callVoidForward(RH_CBasePlayer_Killed, original, pthis->entindex(), indexOfEdict(pevAttacker), iGib);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_AddPoints(IReGameHook_CBasePlayer_AddPoints *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore)
|
void CBasePlayer_AddPoints(IReGameHook_CBasePlayer_AddPoints *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_AddPoints, pthis->entindex(), score, bAllowNegativeScore)) {
|
auto original = [chain](int _pthis, int _score, BOOL _bAllowNegativeScore)
|
||||||
chain->callNext(score, bAllowNegativeScore);
|
{
|
||||||
}
|
chain->callNext(_score, _bAllowNegativeScore);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_AddPoints, pthis->entindex(), score, bAllowNegativeScore);
|
callVoidForward(RH_CBasePlayer_AddPoints, original, pthis->entindex(), score, bAllowNegativeScore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_AddPointsToTeam(IReGameHook_CBasePlayer_AddPointsToTeam *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore)
|
void CBasePlayer_AddPointsToTeam(IReGameHook_CBasePlayer_AddPointsToTeam *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_AddPointsToTeam, pthis->entindex(), score, bAllowNegativeScore)) {
|
auto original = [chain](int _pthis, int _score, BOOL _bAllowNegativeScore)
|
||||||
chain->callNext(score, bAllowNegativeScore);
|
{
|
||||||
}
|
chain->callNext(_score, _bAllowNegativeScore);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_AddPointsToTeam, pthis->entindex(), score, bAllowNegativeScore);
|
callVoidForward(RH_CBasePlayer_AddPointsToTeam, original, pthis->entindex(), score, bAllowNegativeScore);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CBasePlayer_AddPlayerItem(IReGameHook_CBasePlayer_AddPlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem)
|
BOOL CBasePlayer_AddPlayerItem(IReGameHook_CBasePlayer_AddPlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem)
|
||||||
{
|
{
|
||||||
//BOOL ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis, int _pItem)
|
||||||
BOOL origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(getPrivate<CBasePlayerItem>(_pItem));
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_AddPlayerItem, pthis->entindex(), pItem->entindex())) {
|
return callForward<BOOL>(RH_CBasePlayer_AddPlayerItem, original, pthis->entindex(), pItem->entindex());
|
||||||
origresult = chain->callNext(pItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_AddPlayerItem, pthis->entindex(), pItem->entindex())) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return (BOOL)g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CBasePlayer_RemovePlayerItem(IReGameHook_CBasePlayer_RemovePlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem)
|
BOOL CBasePlayer_RemovePlayerItem(IReGameHook_CBasePlayer_RemovePlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem)
|
||||||
{
|
{
|
||||||
//BOOL ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis, int _pItem)
|
||||||
BOOL origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(getPrivate<CBasePlayerItem>(_pItem));
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_RemovePlayerItem, pthis->entindex(), pItem->entindex())) {
|
return callForward<BOOL>(RH_CBasePlayer_RemovePlayerItem, original, pthis->entindex(), pItem->entindex());
|
||||||
origresult = chain->callNext(pItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_RemovePlayerItem, pthis->entindex(), pItem->entindex())) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return (BOOL)g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBasePlayer_GiveAmmo(IReGameHook_CBasePlayer_GiveAmmo *chain, CBasePlayer *pthis, int iAmount, char *szName, int iMax)
|
int CBasePlayer_GiveAmmo(IReGameHook_CBasePlayer_GiveAmmo *chain, CBasePlayer *pthis, int iAmount, char *szName, int iMax)
|
||||||
{
|
{
|
||||||
//int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pthis, int _iAmount, char *_szName, int _iMax)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(_iAmount, _szName, _iMax);
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_GiveAmmo, pthis->entindex(), iAmount, szName, iMax)) {
|
return callForward<int>(RH_CBasePlayer_GiveAmmo, original, pthis->entindex(), iAmount, szName, iMax);
|
||||||
origresult = chain->callNext(iAmount, szName, iMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_GiveAmmo, pthis->entindex(), iAmount, szName, iMax)) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_ResetMaxSpeed(IReGameHook_CBasePlayer_ResetMaxSpeed *chain, CBasePlayer *pthis)
|
void CBasePlayer_ResetMaxSpeed(IReGameHook_CBasePlayer_ResetMaxSpeed *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_ResetMaxSpeed, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_ResetMaxSpeed, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_ResetMaxSpeed, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_Jump(IReGameHook_CBasePlayer_Jump *chain, CBasePlayer *pthis)
|
void CBasePlayer_Jump(IReGameHook_CBasePlayer_Jump *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Jump, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Jump, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_Jump, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_Duck(IReGameHook_CBasePlayer_Duck *chain, CBasePlayer *pthis)
|
void CBasePlayer_Duck(IReGameHook_CBasePlayer_Duck *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Duck, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Duck, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_Duck, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_PreThink(IReGameHook_CBasePlayer_PreThink *chain, CBasePlayer *pthis)
|
void CBasePlayer_PreThink(IReGameHook_CBasePlayer_PreThink *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_PreThink, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_PreThink, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_PreThink, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_PostThink(IReGameHook_CBasePlayer_PostThink *chain, CBasePlayer *pthis)
|
void CBasePlayer_PostThink(IReGameHook_CBasePlayer_PostThink *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_PostThink, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_PostThink, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_PostThink, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_UpdateClientData(IReGameHook_CBasePlayer_UpdateClientData *chain, CBasePlayer *pthis)
|
void CBasePlayer_UpdateClientData(IReGameHook_CBasePlayer_UpdateClientData *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_UpdateClientData, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_UpdateClientData, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_UpdateClientData, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_ImpulseCommands(IReGameHook_CBasePlayer_ImpulseCommands *chain, CBasePlayer *pthis)
|
void CBasePlayer_ImpulseCommands(IReGameHook_CBasePlayer_ImpulseCommands *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_ImpulseCommands, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
callVoidForward(RH_CBasePlayer_ImpulseCommands, original, pthis->entindex());
|
||||||
callVoidForward_Post(RH_CBasePlayer_ImpulseCommands, pthis->entindex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_RoundRespawn(IReGameHook_CBasePlayer_RoundRespawn *chain, CBasePlayer *pthis)
|
void CBasePlayer_RoundRespawn(IReGameHook_CBasePlayer_RoundRespawn *chain, CBasePlayer *pthis)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_RoundRespawn, pthis->entindex())) {
|
auto original = [chain](int _pthis)
|
||||||
|
{
|
||||||
chain->callNext();
|
chain->callNext();
|
||||||
}
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_RoundRespawn, pthis->entindex());
|
callVoidForward(RH_CBasePlayer_RoundRespawn, original, pthis->entindex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBasePlayer_Blind(IReGameHook_CBasePlayer_Blind *chain, CBasePlayer *pthis, float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha)
|
void CBasePlayer_Blind(IReGameHook_CBasePlayer_Blind *chain, CBasePlayer *pthis, float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha)
|
||||||
{
|
{
|
||||||
if (callVoidForward_Pre(RH_CBasePlayer_Blind, pthis->entindex(), flUntilTime, flHoldTime, flFadeTime, iAlpha)) {
|
auto original = [chain](int _pthis, float _flUntilTime, float _flHoldTime, float _flFadeTime, int _iAlpha)
|
||||||
chain->callNext(flUntilTime, flHoldTime, flFadeTime, iAlpha);
|
{
|
||||||
}
|
chain->callNext(_flUntilTime, _flHoldTime, _flFadeTime, _iAlpha);
|
||||||
|
};
|
||||||
|
|
||||||
callVoidForward_Post(RH_CBasePlayer_Blind, pthis->entindex(), flUntilTime, flHoldTime, flFadeTime, iAlpha);
|
callVoidForward(RH_CBasePlayer_Blind, original, pthis->entindex(), flUntilTime, flHoldTime, flFadeTime, iAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBaseEntity *CBasePlayer_Observer_IsValidTarget(IReGameHook_CBasePlayer_Observer_IsValidTarget *chain, CBasePlayer *pthis, int iPlayerIndex, bool bSameTeam)
|
CBaseEntity *CBasePlayer_Observer_IsValidTarget(IReGameHook_CBasePlayer_Observer_IsValidTarget *chain, CBasePlayer *pthis, int iPlayerIndex, bool bSameTeam)
|
||||||
{
|
{
|
||||||
//CBaseEntity *ownresult = nullptr; // return own for OVERRIDE
|
auto original = [chain](int _pthis, int _iPlayerIndex, bool _bSameTeam)
|
||||||
CBaseEntity *origresult = nullptr; // return by call original function
|
{
|
||||||
|
return chain->callNext(_iPlayerIndex, _bSameTeam);
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_CBasePlayer_Observer_IsValidTarget, pthis->entindex(), iPlayerIndex, bSameTeam)) {
|
return callForward<CBaseEntity *>(RH_CBasePlayer_Observer_IsValidTarget, original, pthis->entindex(), iPlayerIndex, bSameTeam);
|
||||||
origresult = chain->callNext(iPlayerIndex, bSameTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_CBasePlayer_Observer_IsValidTarget, pthis->entindex(), iPlayerIndex, bSameTeam)) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_classptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver)
|
int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver)
|
||||||
{
|
{
|
||||||
//int ownresult = 0; // return own for OVERRIDE
|
auto original = [chain](int _pObserver)
|
||||||
int origresult = 0; // return by call original function
|
{
|
||||||
|
return chain->callNext(getPrivate<CBasePlayer>(_pObserver));
|
||||||
|
};
|
||||||
|
|
||||||
if (callForward_Pre(RH_GetForceCamera, pObserver->entindex())) {
|
return callForward<int>(RH_GetForceCamera, original, pObserver->entindex());
|
||||||
origresult = chain->callNext(pObserver);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callForward_Post(RH_GetForceCamera, pObserver->entindex())) {
|
|
||||||
// return original
|
|
||||||
return origresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return from override
|
|
||||||
return g_currentHookChain->m_data.m_interger;
|
|
||||||
}
|
}
|
||||||
|
@ -1,119 +1,176 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum
|
// hookchain return type
|
||||||
|
enum HookChainState
|
||||||
{
|
{
|
||||||
RH_UNSET = 0,
|
HC_CONTINUE = 0,
|
||||||
RH_IGNORED, // plugin didn't take any action
|
HC_OVERRIDE,
|
||||||
RH_HANDLED, // plugin did something, but real function should still be called
|
HC_SUPERCEDE,
|
||||||
RH_OVERRIDE, // call real function, but use my return value
|
HC_BREAK
|
||||||
RH_SUPERCEDE // skip real function; use my return value
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// for hookchain return
|
// api types
|
||||||
enum HookChainReturn
|
enum AType : uint8
|
||||||
{
|
{
|
||||||
RHV_STRING = 0,
|
ATYPE_INTEGER = 0,
|
||||||
RHV_FLOAT,
|
ATYPE_FLOAT,
|
||||||
RHV_INTEGER,
|
ATYPE_STRING,
|
||||||
RHV_CLASSPTR
|
ATYPE_CLASSPTR
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHook *g_currentHookChain;
|
struct retval_t
|
||||||
|
{
|
||||||
template <typename ...t_args>
|
bool set;
|
||||||
inline bool callVoidForward_Pre(int func, t_args... args)
|
AType type;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char* _string;
|
||||||
|
float _float;
|
||||||
|
int _interger;
|
||||||
|
CBaseEntity* _classptr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AType getApiType(int) { return ATYPE_INTEGER; }
|
||||||
|
inline AType getApiType(unsigned) { return ATYPE_INTEGER; }
|
||||||
|
inline AType getApiType(cvar_s *) { return ATYPE_INTEGER; }
|
||||||
|
inline AType getApiType(float) { return ATYPE_FLOAT; }
|
||||||
|
inline AType getApiType(const char *) { return ATYPE_STRING; }
|
||||||
|
inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; }
|
||||||
|
|
||||||
|
template<size_t current>
|
||||||
|
void setupArgTypes(AType args_type[])
|
||||||
{
|
{
|
||||||
auto hook = hooklist[func];
|
|
||||||
register int ret = RH_UNSET;
|
|
||||||
for (auto it = hook->pre.begin(), end = hook->pre.end(); it != end; ++it)
|
|
||||||
{
|
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
|
||||||
{
|
|
||||||
ret = g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no supercede, continue to call original func
|
|
||||||
return (ret < RH_SUPERCEDE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ...t_args>
|
#define MAX_ARGS 10u
|
||||||
inline void callVoidForward_Post(int func, t_args... args)
|
|
||||||
|
template<size_t current, typename T, typename ...t_args>
|
||||||
|
void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args)
|
||||||
{
|
{
|
||||||
auto hook = hooklist[func];
|
args_type[current] = getApiType(arg);
|
||||||
for (auto it = hook->post.begin(), end = hook->post.end(); it != end; ++it)
|
if (sizeof...(args) && current + 1 < MAX_ARGS)
|
||||||
{
|
setupArgTypes<current + 1>(args_type, args...);
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
|
||||||
{
|
|
||||||
g_currentHookChain = (*it);
|
|
||||||
g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename t_chain, typename ...t_args>
|
struct hookctx_t
|
||||||
inline void callVoidForward(t_chain chain, int func, t_args... args)
|
|
||||||
{
|
{
|
||||||
auto hook = hooklist[func];
|
template<typename ...t_args>
|
||||||
register int ret = RH_UNSET;
|
hookctx_t(size_t count, size_t ptr, t_args... args)
|
||||||
for (auto it = hook->pre.begin(), end = hook->pre.end(); it != end; ++it)
|
|
||||||
{
|
{
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
args_count = min(count, MAX_ARGS);
|
||||||
|
args_ptr = ptr;
|
||||||
|
setupArgTypes<0>(this->args_type, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval_t retVal;
|
||||||
|
size_t args_count;
|
||||||
|
size_t args_ptr;
|
||||||
|
AType args_type[MAX_ARGS];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern hookctx_t* g_hookCtx;
|
||||||
|
|
||||||
|
template <typename original_t, typename ...f_args>
|
||||||
|
void callVoidForward(int func, original_t original, f_args... args)
|
||||||
|
{
|
||||||
|
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
|
||||||
|
hookCtx.retVal.set = false;
|
||||||
|
g_hookCtx = &hookCtx;
|
||||||
|
|
||||||
|
int hc_state = HC_CONTINUE;
|
||||||
|
auto hook = g_hookManager.getHook(func);
|
||||||
|
|
||||||
|
for (auto& fwd : hook->pre)
|
||||||
|
{
|
||||||
|
if (fwd->GetState() == FSTATE_ENABLED)
|
||||||
{
|
{
|
||||||
ret = g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
|
||||||
|
|
||||||
|
if (ret == HC_BREAK) {
|
||||||
|
g_hookCtx = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > hc_state)
|
||||||
|
hc_state = ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no supercede, continue to call original func
|
if (hc_state != HC_SUPERCEDE)
|
||||||
if (ret < RH_SUPERCEDE)
|
original(args...);
|
||||||
{
|
|
||||||
chain->callNext(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post
|
for (auto& fwd : hook->post)
|
||||||
for (auto it = hook->post.begin(), end = hook->post.end(); it != end; ++it)
|
|
||||||
{
|
{
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
if (fwd->GetState() == FSTATE_ENABLED)
|
||||||
{
|
{
|
||||||
g_currentHookChain = (*it);
|
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
|
||||||
g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
|
||||||
|
if (ret == HC_BREAK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_hookCtx = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ...t_args>
|
template <typename R, typename original_t, typename ...f_args>
|
||||||
inline bool callForward_Pre(int func, t_args... args)
|
R callForward(int func, original_t original, f_args... args)
|
||||||
{
|
{
|
||||||
auto hook = hooklist[func];
|
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
|
||||||
register int ret = RH_UNSET;
|
hookCtx.retVal.set = false;
|
||||||
for (auto it = hook->pre.begin(), end = hook->pre.end(); it != end; ++it)
|
hookCtx.retVal.type = getApiType(R());
|
||||||
|
g_hookCtx = &hookCtx;
|
||||||
|
|
||||||
|
int hc_state = HC_CONTINUE;
|
||||||
|
auto hook = g_hookManager.getHook(func);
|
||||||
|
|
||||||
|
for (auto& fwd : hook->pre)
|
||||||
{
|
{
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
if (fwd->GetState() == FSTATE_ENABLED)
|
||||||
{
|
{
|
||||||
ret = g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
|
||||||
|
|
||||||
|
if (ret == HC_CONTINUE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!hookCtx.retVal.set)
|
||||||
|
{
|
||||||
|
g_amxxapi.LogError(fwd->GetAmx(), AMX_ERR_CALLBACK, "%s", "can't suppress original function call without new return value set");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == HC_BREAK) {
|
||||||
|
g_hookCtx = nullptr;
|
||||||
|
return (R)hookCtx.retVal._interger;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > hc_state)
|
||||||
|
hc_state = ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no supercede, continue to call original func
|
if (hc_state != HC_SUPERCEDE)
|
||||||
return (ret < RH_SUPERCEDE);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ...t_args>
|
|
||||||
inline bool callForward_Post(int func, t_args... args)
|
|
||||||
{
|
|
||||||
auto hook = hooklist[func];
|
|
||||||
register int ret = RH_UNSET;
|
|
||||||
for (auto it = hook->post.begin(), end = hook->post.end(); it != end; ++it)
|
|
||||||
{
|
{
|
||||||
if ((*it)->GetState() == FSTATE_OK)
|
auto retVal = original(args...);
|
||||||
{
|
|
||||||
g_currentHookChain = (*it);
|
if (hc_state != HC_OVERRIDE)
|
||||||
ret = g_amxxapi.ExecuteForward((*it)->GetForwardID(), args...);
|
hookCtx.retVal._interger = *(int *)&retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& fwd : hook->post) {
|
||||||
|
if (fwd->GetState() == FSTATE_ENABLED) {
|
||||||
|
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
|
||||||
|
|
||||||
|
if (ret == HC_BREAK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no override
|
g_hookCtx = nullptr;
|
||||||
return (ret < RH_OVERRIDE);
|
return (R)hookCtx.retVal._interger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rehlds functions
|
// rehlds functions
|
||||||
@ -130,7 +187,7 @@ void CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *pthis)
|
|||||||
void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis);
|
void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis);
|
||||||
int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis);
|
int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis);
|
||||||
int CBasePlayer_Classify(IReGameHook_CBasePlayer_Classify *chain, CBasePlayer *pthis);
|
int CBasePlayer_Classify(IReGameHook_CBasePlayer_Classify *chain, CBasePlayer *pthis);
|
||||||
void CBasePlayer_TraceAttack(IReGameHook_CBasePlayer_TraceAttack *chain, CBasePlayer *pthis, entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
void CBasePlayer_TraceAttack(IReGameHook_CBasePlayer_TraceAttack *chain, CBasePlayer *pthis, entvars_t *pevAttacker, float flDamage, Vector& vecDir, TraceResult *ptr, int bitsDamageType);
|
||||||
int CBasePlayer_TakeDamage(IReGameHook_CBasePlayer_TakeDamage *chain, CBasePlayer *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
|
int CBasePlayer_TakeDamage(IReGameHook_CBasePlayer_TakeDamage *chain, CBasePlayer *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
|
||||||
int CBasePlayer_TakeHealth(IReGameHook_CBasePlayer_TakeHealth *chain, CBasePlayer *pthis, float flHealth, int bitsDamageType);
|
int CBasePlayer_TakeHealth(IReGameHook_CBasePlayer_TakeHealth *chain, CBasePlayer *pthis, float flHealth, int bitsDamageType);
|
||||||
void CBasePlayer_Killed(IReGameHook_CBasePlayer_Killed *chain, CBasePlayer *pthis, entvars_t *pevAttacker, int iGib);
|
void CBasePlayer_Killed(IReGameHook_CBasePlayer_Killed *chain, CBasePlayer *pthis, entvars_t *pevAttacker, int iGib);
|
||||||
|
@ -41,14 +41,12 @@ hook_t hooklist_player[] = {
|
|||||||
DLL(CBasePlayer_Observer_IsValidTarget),
|
DLL(CBasePlayer_Observer_IsValidTarget),
|
||||||
};
|
};
|
||||||
|
|
||||||
hooklist_t hooklist;
|
|
||||||
|
|
||||||
hook_t *hooklist_t::operator[](size_t hook) const
|
hook_t *hooklist_t::operator[](size_t hook) const
|
||||||
{
|
{
|
||||||
#define CASE(h) case ht_##h: if (index < arraysize(hooklist_##h)) return &hooklist_##h[index]; else break;
|
#define CASE(h) case ht_##h: if (index < arraysize(hooklist_##h)) return &hooklist_##h[index]; else break;
|
||||||
|
|
||||||
const auto table = hooks_tables_e(hook / MAX_RANGE_REGION);
|
const auto table = hooks_tables_e(hook / MAX_REGION_RANGE);
|
||||||
const auto index = hook & (MAX_RANGE_REGION - 1);
|
const auto index = hook & (MAX_REGION_RANGE - 1);
|
||||||
|
|
||||||
switch (table) {
|
switch (table) {
|
||||||
CASE(engine)
|
CASE(engine)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "reapi_utils.h"
|
|
||||||
|
|
||||||
#define MAX_RANGE_REGION 1024
|
#define MAX_REGION_RANGE 1024
|
||||||
#define BEGIN_FUNC_REGION(x) (MAX_RANGE_REGION * hooklist_t::hooks_tables_e::ht_##x)
|
#define BEGIN_FUNC_REGION(x) (MAX_REGION_RANGE * hooklist_t::hooks_tables_e::ht_##x)
|
||||||
|
#define MAX_HOOK_FORWARDS 1024
|
||||||
|
|
||||||
typedef bool (*ablfunc_t)();
|
typedef bool (*ablfunc_t)();
|
||||||
typedef int (*regfunc_t)(AMX *, const char *);
|
typedef int (*regfunc_t)(AMX *, const char *);
|
||||||
@ -36,7 +36,7 @@ struct regfunc
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
regfunc(R (*)(T *, CBasePlayer *, entvars_t *, float, Vector, TraceResult *, int)) {
|
regfunc(R (*)(T *, CBasePlayer *, entvars_t *, float, Vector&, TraceResult *, int)) {
|
||||||
func = [](AMX *amx, const char *name) { return g_amxxapi.RegisterSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_CELL, FP_CELL, FP_DONE); };
|
func = [](AMX *amx, const char *name) { return g_amxxapi.RegisterSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_CELL, FP_CELL, FP_DONE); };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,16 +89,16 @@ struct regfunc
|
|||||||
|
|
||||||
struct hook_t
|
struct hook_t
|
||||||
{
|
{
|
||||||
std::vector<class CHook *> pre; // array pre forward
|
std::vector<class CAmxxHook *> pre; // pre forwards
|
||||||
std::vector<class CHook *> post; // array post forward
|
std::vector<class CAmxxHook *> post; // post forwards
|
||||||
|
|
||||||
const char *func_name; // name functions
|
const char *func_name; // function name
|
||||||
const char *depend_name; // platform dependency
|
const char *depend_name; // platform dependency
|
||||||
|
|
||||||
ablfunc_t availableFunc;
|
ablfunc_t checkRequirements;
|
||||||
regfunc_t registerForward; // register AMXX forward and get ID
|
regfunc_t registerForward; // AMXX forward registration function
|
||||||
regchain_t registerHookchain; // register function-hook API
|
regchain_t registerHookchain; // register re* API hook
|
||||||
regchain_t unregisterHookchain; // unregister function-hook API
|
regchain_t unregisterHookchain; // unregister re* API hook
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hooklist_t
|
struct hooklist_t
|
||||||
@ -200,4 +200,3 @@ enum GamedllFunc_CBasePlayer
|
|||||||
|
|
||||||
extern hook_t hooklist_engine[];
|
extern hook_t hooklist_engine[];
|
||||||
extern hook_t hooklist_player[];
|
extern hook_t hooklist_player[];
|
||||||
extern hooklist_t hooklist;
|
|
||||||
|
@ -2,39 +2,67 @@
|
|||||||
|
|
||||||
CHookManager g_hookManager;
|
CHookManager g_hookManager;
|
||||||
|
|
||||||
CHook *CHookManager::addHandler(int func, int forward, bool post)
|
int CHookManager::addHandler(AMX* amx, int func, int forward, bool post) const
|
||||||
{
|
{
|
||||||
if (!hooklist[func]->post.size() && !hooklist[func]->pre.size())
|
if (!m_hooklist[func]->post.size() && !m_hooklist[func]->pre.size())
|
||||||
{
|
{
|
||||||
// register API hookchain
|
// API hookchain
|
||||||
hooklist[func]->registerHookchain();
|
m_hooklist[func]->registerHookchain();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHook *hook = new CHook(forward);
|
auto& dest = post ? m_hooklist[func]->post : m_hooklist[func]->pre;
|
||||||
if (post)
|
dest.push_back(new CAmxxHook(amx, forward));
|
||||||
{
|
int id = func * MAX_HOOK_FORWARDS + dest.size();
|
||||||
hooklist[func]->post.push_back(hook);
|
return post ? -id : id; // use unsigned ids for post hooks
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hooklist[func]->pre.push_back(hook);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hook;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHookManager::clearHandlers()
|
AMX* CAmxxHook::GetAmx() const
|
||||||
|
{
|
||||||
|
return m_amx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHookManager::clearHandlers() const
|
||||||
{
|
{
|
||||||
#define CLEAR_HOOKLIST(__END__, __START__)\
|
#define CLEAR_HOOKLIST(__END__, __START__)\
|
||||||
for (size_t i = BEGIN_FUNC_REGION(__START__); i < RH_##__END__##_End; ++i) {\
|
for (size_t i = BEGIN_FUNC_REGION(__START__); i < RH_##__END__##_End; ++i) {\
|
||||||
if (hooklist[i] == nullptr)\
|
if (m_hooklist[i] == nullptr)\
|
||||||
continue;\
|
continue;\
|
||||||
hooklist[i]->pre.clear();\
|
m_hooklist[i]->pre.clear();\
|
||||||
hooklist[i]->post.clear();\
|
m_hooklist[i]->post.clear();\
|
||||||
hooklist[i]->unregisterHookchain();\
|
m_hooklist[i]->unregisterHookchain();\
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEAR_HOOKLIST(EngineFunc, engine);
|
CLEAR_HOOKLIST(EngineFunc, engine);
|
||||||
CLEAR_HOOKLIST(GameDLL, gamedll);
|
CLEAR_HOOKLIST(GameDLL, gamedll);
|
||||||
CLEAR_HOOKLIST(CBasePlayer, player);
|
CLEAR_HOOKLIST(CBasePlayer, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook_t* CHookManager::getHook(size_t func) const
|
||||||
|
{
|
||||||
|
return m_hooklist[func];
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmxxHook* CHookManager::getAmxxHook(cell handle) const
|
||||||
|
{
|
||||||
|
bool post = false;
|
||||||
|
|
||||||
|
if (handle < 0) // post
|
||||||
|
{
|
||||||
|
handle = ~handle;
|
||||||
|
post = true;
|
||||||
|
}
|
||||||
|
else handle--;
|
||||||
|
|
||||||
|
const size_t func = handle / MAX_HOOK_FORWARDS;
|
||||||
|
const size_t id = handle & (MAX_HOOK_FORWARDS - 1);
|
||||||
|
auto hook = m_hooklist[func];
|
||||||
|
|
||||||
|
if (hook)
|
||||||
|
{
|
||||||
|
auto& forwards = post ? hook->post : hook->pre;
|
||||||
|
if (id < forwards.size())
|
||||||
|
return forwards[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
@ -6,38 +6,36 @@
|
|||||||
enum fwdstate
|
enum fwdstate
|
||||||
{
|
{
|
||||||
FSTATE_INVALID = 0,
|
FSTATE_INVALID = 0,
|
||||||
FSTATE_OK,
|
FSTATE_ENABLED,
|
||||||
FSTATE_PAUSE,
|
FSTATE_PAUSED,
|
||||||
FSTATE_STOP
|
FSTATE_STOPPED
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHook
|
class CAmxxHook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CHook(int forward_index) : m_forward(forward_index), m_state(FSTATE_OK) {};
|
CAmxxHook(AMX* amx, int forward_index) : m_forward(forward_index), m_state(FSTATE_ENABLED), m_amx(amx) {};
|
||||||
|
|
||||||
int GetForwardID() const { return m_forward; }
|
int GetForwardID() const { return m_forward; }
|
||||||
fwdstate GetState() const { return m_state; }
|
fwdstate GetState() const { return m_state; }
|
||||||
|
AMX* GetAmx() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_forward;
|
int m_forward;
|
||||||
fwdstate m_state;
|
fwdstate m_state;
|
||||||
|
AMX* m_amx;
|
||||||
struct data_return_t
|
|
||||||
{
|
|
||||||
char* m_string;
|
|
||||||
float m_float;
|
|
||||||
int m_interger;
|
|
||||||
CBaseEntity* m_classptr;
|
|
||||||
};
|
|
||||||
data_return_t m_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHookManager
|
class CHookManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void clearHandlers();
|
void clearHandlers() const;
|
||||||
CHook *addHandler(int func, int forward, bool post);
|
cell addHandler(AMX* amx, int func, int forward, bool post) const;
|
||||||
|
hook_t* getHook(size_t func) const;
|
||||||
|
CAmxxHook* getAmxxHook(cell hook) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
hooklist_t m_hooklist;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHookManager g_hookManager;
|
extern CHookManager g_hookManager;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "precompiled.h"
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
edict_t* g_pEdicts;
|
||||||
|
|
||||||
bool OnMetaAttach()
|
bool OnMetaAttach()
|
||||||
{
|
{
|
||||||
// initialize API
|
// initialize API
|
||||||
@ -15,7 +17,14 @@ void OnMetaDetach()
|
|||||||
g_hookManager.clearHandlers();
|
g_hookManager.clearHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
|
||||||
|
{
|
||||||
|
g_pEdicts = pEdictList;
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
void ServerDeactivate_Post()
|
void ServerDeactivate_Post()
|
||||||
{
|
{
|
||||||
g_hookManager.clearHandlers();
|
g_hookManager.clearHandlers();
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
@ -318,8 +318,8 @@ member_t *memberlist_t::operator[](size_t members) const
|
|||||||
{
|
{
|
||||||
#define CASE(h) case ht_##h: if (index < arraysize(memberlist_##h)) return &memberlist_##h[index]; else break;
|
#define CASE(h) case ht_##h: if (index < arraysize(memberlist_##h)) return &memberlist_##h[index]; else break;
|
||||||
|
|
||||||
const auto table = members_tables_e(members / MAX_RANGE_REGION);
|
const auto table = members_tables_e(members / MAX_REGION_RANGE);
|
||||||
const auto index = members & (MAX_RANGE_REGION - 1);
|
const auto index = members & (MAX_REGION_RANGE - 1);
|
||||||
|
|
||||||
switch (table) {
|
switch (table) {
|
||||||
CASE(gamerules)
|
CASE(gamerules)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define BEGIN_MEMBER_REGION(x) (MAX_RANGE_REGION * memberlist_t::members_tables_e::ht_##x)
|
#define BEGIN_MEMBER_REGION(x) (MAX_REGION_RANGE * memberlist_t::members_tables_e::ht_##x)
|
||||||
|
|
||||||
enum enum_membertypes
|
enum enum_membertypes
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* @param function The function to hook.
|
* @param function The function to hook.
|
||||||
* @param callback The forward to call.
|
* @param callback The forward to call.
|
||||||
* @param post Whether or not to forward this in post.
|
* @param post Whether or not to forward this in post.
|
||||||
* @return Returns a handle to the hook. Use EnableHookChain/DisableHookChain to toggle the forward on or off.
|
* @return Returns a handle to the hook. Use EnableHookChain/DisableHookChain to toggle the forward on or off.
|
||||||
*
|
*
|
||||||
* native RegisterHookChain(any:function_id, const callback[], post = 0);
|
* native RegisterHookChain(any:function_id, const callback[], post = 0);
|
||||||
*/
|
*/
|
||||||
@ -18,16 +18,17 @@ static cell AMX_NATIVE_CALL RegisterHookChain(AMX *amx, cell *params)
|
|||||||
|
|
||||||
int func = params[arg_func];
|
int func = params[arg_func];
|
||||||
int post = params[arg_post];
|
int post = params[arg_post];
|
||||||
|
auto hook = g_hookManager.getHook(func);
|
||||||
|
|
||||||
if (hooklist[func] == nullptr)
|
if (hook == nullptr)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Function (%d) doesn't match hook definition.", func);
|
MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: function with id (%d) doesn't exist in current API version.", func);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hooklist[func]->availableFunc())
|
if (!hook->checkRequirements())
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Function (%s) is not available, required %s", hooklist[func]->func_name, hooklist[func]->depend_name);
|
MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: function (%s) is not available, %s required", hook->func_name, hook->depend_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,26 +36,26 @@ static cell AMX_NATIVE_CALL RegisterHookChain(AMX *amx, cell *params)
|
|||||||
const char *funcname = g_amxxapi.GetAmxString(amx, params[arg_handler], 0, &len);
|
const char *funcname = g_amxxapi.GetAmxString(amx, params[arg_handler], 0, &len);
|
||||||
if (g_amxxapi.amx_FindPublic(amx, funcname, &funcid) != AMX_ERR_NONE)
|
if (g_amxxapi.amx_FindPublic(amx, funcname, &funcid) != AMX_ERR_NONE)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Public function \"%s\" not found.", funcname);
|
MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: public function \"%s\" not found.", funcname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fwid = hooklist[func]->registerForward(amx, funcname);
|
int fwid = hook->registerForward(amx, funcname);
|
||||||
if (fwid == -1)
|
if (fwid == -1)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Public function \"%s\" not found.", funcname);
|
MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: register forward failed.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cell)g_hookManager.addHandler(func, fwid, post != 0);
|
return g_hookManager.addHandler(amx, func, fwid, post != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Starts a hook back up.
|
* Disable hook by handle.
|
||||||
* Use the return value from RegisterHookChain as the parameter here!
|
* Use the return value from RegisterHookChain as the parameter here!
|
||||||
*
|
*
|
||||||
* @param fwd The hook to re-enable.
|
* @param fwd The hook to re-enable.
|
||||||
* @return Returns if the function is successful executed true otherwise false
|
* @return Returns if the function is successful executed true otherwise false
|
||||||
*
|
*
|
||||||
* native bool:EnableHookChain(any:fwd);
|
* native bool:EnableHookChain(any:fwd);
|
||||||
*/
|
*/
|
||||||
@ -63,20 +64,20 @@ static cell AMX_NATIVE_CALL EnableHookChain(AMX *amx, cell *params)
|
|||||||
{
|
{
|
||||||
enum args_e { arg_count, arg_handle_hook };
|
enum args_e { arg_count, arg_handle_hook };
|
||||||
|
|
||||||
CHook *hook = reinterpret_cast<CHook *>(params[arg_handle_hook]);
|
auto hook = g_hookManager.getAmxxHook(params[arg_handle_hook]);
|
||||||
|
|
||||||
if (hook == nullptr)
|
if (hook == nullptr)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid HookChain handle.");
|
MF_LogError(amx, AMX_ERR_NATIVE, "EnableHookChain: invalid HookChain handle.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hook->m_state = FSTATE_OK;
|
hook->m_state = FSTATE_ENABLED;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stops a hook from triggering.
|
* Enable hook by handle.
|
||||||
* Use the return value from RegisterHookChain as the parameter here!
|
* Use the return value from RegisterHookChain as the parameter here!
|
||||||
*
|
*
|
||||||
* @param fwd The hook to stop.
|
* @param fwd The hook to stop.
|
||||||
@ -88,15 +89,15 @@ static cell AMX_NATIVE_CALL DisableHookChain(AMX *amx, cell *params)
|
|||||||
{
|
{
|
||||||
enum args_e { arg_count, arg_handle_hook };
|
enum args_e { arg_count, arg_handle_hook };
|
||||||
|
|
||||||
CHook *hook = reinterpret_cast<CHook *>(params[arg_handle_hook]);
|
auto hook = g_hookManager.getAmxxHook(params[arg_handle_hook]);
|
||||||
|
|
||||||
if (hook == nullptr)
|
if (hook == nullptr)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid HookChain handle.");
|
MF_LogError(amx, AMX_ERR_NATIVE, "DisableHookChain: invalid HookChain handle.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hook->m_state = FSTATE_STOP;
|
hook->m_state = FSTATE_STOPPED;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,49 +105,164 @@ static cell AMX_NATIVE_CALL DisableHookChain(AMX *amx, cell *params)
|
|||||||
* Sets the return value of a hookchain.
|
* Sets the return value of a hookchain.
|
||||||
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
||||||
*
|
*
|
||||||
* @param type To specify the type RHV_*, look at the enum HookChainReturn
|
* @param type To specify the type RHV_*, look at the enum AType
|
||||||
* @param value The value to set the return to.
|
* @param value The value to set the return to.
|
||||||
*
|
*
|
||||||
* native SetHookChainReturn(HookChainReturn:type, any:...);
|
* native SetHookChainReturn(AType:type, any:...);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
if (!g_currentHookChain)
|
if (!g_hookCtx)
|
||||||
{
|
{
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Trying get return value without active hook.");
|
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set return value without active hook.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum args_e { arg_count, arg_type, arg_value };
|
enum args_e { arg_count, arg_type, arg_value };
|
||||||
|
auto& retVal = g_hookCtx->retVal;
|
||||||
|
|
||||||
switch (params[arg_type])
|
if (params[arg_type] != retVal.type)
|
||||||
{
|
{
|
||||||
case RHV_STRING:
|
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set incompatible return type.");
|
||||||
{
|
return 0;
|
||||||
if (g_currentHookChain->m_data.m_string != NULL) {
|
}
|
||||||
delete [] g_currentHookChain->m_data.m_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len;
|
cell* srcAddr = getAmxAddr(amx, params[arg_value]);
|
||||||
char *dest = g_amxxapi.GetAmxString(amx, params[arg_value], 0, &len);
|
|
||||||
g_currentHookChain->m_data.m_string = new char [len + 1];
|
switch (retVal.type)
|
||||||
strcpy(g_currentHookChain->m_data.m_string, dest);
|
{
|
||||||
|
case ATYPE_INTEGER:
|
||||||
|
case ATYPE_FLOAT:
|
||||||
|
retVal._interger = *srcAddr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATYPE_STRING:
|
||||||
|
{
|
||||||
|
if (retVal._string != nullptr)
|
||||||
|
delete[] retVal._string;
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
const char *dest = getAmxString(srcAddr, &len);
|
||||||
|
retVal._string = strcpy(new char[len + 1], dest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RHV_FLOAT:
|
case ATYPE_CLASSPTR:
|
||||||
g_currentHookChain->m_data.m_float = *(float *)g_amxxapi.GetAmxAddr(amx, params[arg_value]);
|
retVal._classptr = CBaseEntity::Instance(INDEXENT(*srcAddr));
|
||||||
break;
|
|
||||||
case RHV_INTEGER:
|
|
||||||
g_currentHookChain->m_data.m_interger = *g_amxxapi.GetAmxAddr(amx, params[arg_value]);
|
|
||||||
break;
|
|
||||||
case RHV_CLASSPTR:
|
|
||||||
g_currentHookChain->m_data.m_classptr = CBaseEntity::Instance(INDEXENT(*g_amxxapi.GetAmxAddr(amx, params[arg_value])));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retVal.set = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the return value of a hookchain.
|
||||||
|
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
||||||
|
*
|
||||||
|
* @param value The value to set the return to.
|
||||||
|
* @param [maxlen] Max length of string (optional)
|
||||||
|
* @return Returns if the function is successful executed true otherwise false
|
||||||
|
*
|
||||||
|
* native GetHookChainReturn(AType:type, any:...);
|
||||||
|
*/
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
if (!g_hookCtx)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum args_e { arg_count, arg_value, arg_maxlen };
|
||||||
|
|
||||||
|
auto& retVal = g_hookCtx->retVal;
|
||||||
|
cell* dstAddr = getAmxAddr(amx, params[arg_value]);
|
||||||
|
|
||||||
|
switch (retVal.type)
|
||||||
|
{
|
||||||
|
case ATYPE_INTEGER:
|
||||||
|
case ATYPE_FLOAT:
|
||||||
|
*dstAddr = retVal._interger;
|
||||||
|
break;
|
||||||
|
case ATYPE_STRING:
|
||||||
|
{
|
||||||
|
if (params[arg_count] != 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
setAmxString(dstAddr, retVal._string, params[arg_maxlen]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ATYPE_CLASSPTR:
|
||||||
|
*dstAddr = retVal._classptr->entindex();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set hookchain argument.
|
||||||
|
* This needs to be used in conjunction with RH_OVERRIDE or RH_SUPERCEDE.
|
||||||
|
*
|
||||||
|
* @param number Number of argument
|
||||||
|
* @param value New value
|
||||||
|
* @param [maxlen] Max length of string (optional)
|
||||||
|
* @return Returns if the function is successful executed true otherwise false
|
||||||
|
*
|
||||||
|
* native SetHookChainArg(number, AType:type, any:...);
|
||||||
|
*/
|
||||||
|
|
||||||
|
static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
if (!g_hookCtx)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum args_e { arg_count, arg_number, arg_type, arg_value };
|
||||||
|
|
||||||
|
size_t number = params[arg_number] - 1;
|
||||||
|
|
||||||
|
if (number >= g_hookCtx->args_count)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: can't set argument %i of hookchain with %i args.", params[arg_number], g_hookCtx->args_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AType type = g_hookCtx->args_type[number];
|
||||||
|
|
||||||
|
if (params[arg_type] != type)
|
||||||
|
{
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: invalid argument type provided.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char temp_strings[MAX_ARGS][1024];
|
||||||
|
|
||||||
|
cell* srcAddr = getAmxAddr(amx, params[arg_value]);
|
||||||
|
size_t destAddr = g_hookCtx->args_ptr + number * sizeof(int);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ATYPE_INTEGER:
|
||||||
|
case ATYPE_FLOAT:
|
||||||
|
*(cell *)destAddr = *srcAddr;
|
||||||
|
break;
|
||||||
|
case ATYPE_STRING:
|
||||||
|
*(char **)destAddr = getAmxStringTemp(srcAddr, temp_strings[number], 1023, nullptr);
|
||||||
|
break;
|
||||||
|
case ATYPE_CLASSPTR:
|
||||||
|
*(CBaseEntity **)destAddr = CBaseEntity::Instance(INDEXENT(*srcAddr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +274,9 @@ AMX_NATIVE_INFO Func_Natives[] =
|
|||||||
{ "DisableHookChain", DisableHookChain },
|
{ "DisableHookChain", DisableHookChain },
|
||||||
|
|
||||||
{ "SetHookChainReturn", SetHookChainReturn },
|
{ "SetHookChainReturn", SetHookChainReturn },
|
||||||
|
{ "GetHookChainReturn", GetHookChainReturn },
|
||||||
|
|
||||||
|
{ "SetHookChainArg", SetHookChainArg },
|
||||||
|
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
@ -7,17 +7,18 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
|
|||||||
member_t *member = memberlist[params[arg_member]];
|
member_t *member = memberlist[params[arg_member]];
|
||||||
|
|
||||||
if (member == nullptr) {
|
if (member == nullptr) {
|
||||||
MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]);
|
MF_LogError(amx, AMX_ERR_NATIVE, "set_member: unknown member id %i", params[arg_member]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
edict_t *pEdict = INDEXENT(params[arg_index]);
|
edict_t *pEdict = INDEXENT(params[arg_index]);
|
||||||
if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) {
|
if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) {
|
||||||
|
MF_LogError(amx, AMX_ERR_NATIVE, "set_member: invalid or uninitialized entity", params[arg_member]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t value = *g_amxxapi.GetAmxAddr(amx, params[arg_value]);
|
size_t value = *getAmxAddr(amx, params[arg_value]);
|
||||||
size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]);
|
size_t element = *getAmxAddr(amx, params[arg_elem]);
|
||||||
|
|
||||||
switch (member->type)
|
switch (member->type)
|
||||||
{
|
{
|
||||||
@ -122,6 +123,12 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
|
|||||||
signal.Signal(value);
|
signal.Signal(value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
case MEMBER_DOUBLE:
|
||||||
|
{
|
||||||
|
// native set_member(_index, any:_member, any:_value, _elem);
|
||||||
|
set_member<double>(pEdict, member->offset, *(float *)&value, element);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
case MEBMER_REBUYSTRUCT:
|
case MEBMER_REBUYSTRUCT:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -172,7 +179,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
|
|||||||
// native any:get_member(_index, any:_member, element);
|
// native any:get_member(_index, any:_member, element);
|
||||||
edict_t *pEntity = get_member<edict_t *>(pEdict, member->offset, element);
|
edict_t *pEntity = get_member<edict_t *>(pEdict, member->offset, element);
|
||||||
if (pEntity != nullptr) {
|
if (pEntity != nullptr) {
|
||||||
return ENTINDEX(pEntity);
|
return indexOfEdict(pEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <vector> // std::vector
|
#include <vector> // std::vector
|
||||||
|
|
||||||
#include <extdll.h>
|
#include <extdll.h>
|
||||||
|
#include "reapi_utils.h"
|
||||||
#include <cbase.h>
|
#include <cbase.h>
|
||||||
|
|
||||||
#include "osdep.h" // win32 vsnprintf, etc
|
#include "osdep.h" // win32 vsnprintf, etc
|
||||||
|
@ -4,6 +4,37 @@ template <typename T, size_t N>
|
|||||||
char(&ArraySizeHelper(T(&array)[N]))[N];
|
char(&ArraySizeHelper(T(&array)[N]))[N];
|
||||||
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
||||||
|
|
||||||
|
#define INDEXENT edictByIndex
|
||||||
|
#define ENTINDEX indexOfEdict
|
||||||
|
|
||||||
|
extern edict_t* g_pEdicts;
|
||||||
|
|
||||||
|
inline size_t indexOfEdict(edict_t* ed)
|
||||||
|
{
|
||||||
|
return ed - g_pEdicts;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t indexOfEdict(entvars_t* pev)
|
||||||
|
{
|
||||||
|
return indexOfEdict(pev->pContainingEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline edict_t* edictByIndex(size_t index)
|
||||||
|
{
|
||||||
|
return g_pEdicts + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* getPrivate(int index)
|
||||||
|
{
|
||||||
|
return (T *)edictByIndex(index)->pvPrivateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entvars_t* PEV(int index)
|
||||||
|
{
|
||||||
|
return &edictByIndex(index)->v;
|
||||||
|
}
|
||||||
|
|
||||||
// HLTypeConversion.h -> AMXModX
|
// HLTypeConversion.h -> AMXModX
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T &ref_member(void *ptr, int offset, int element = 0)
|
inline T &ref_member(void *ptr, int offset, int element = 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user