Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement CBaseEntity::Fire<Bullets[3]|Buckshots> hooks. #202

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions reapi/extra/amxmodx/scripting/include/reapi.inc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ enum hooks_tables_e
ht_grenade,
ht_weaponbox,
ht_weapon,
ht_gib
ht_gib,
ht_cbaseentity
};

enum members_tables_e
Expand Down Expand Up @@ -128,7 +129,8 @@ enum AType
ATYPE_CLASSPTR,
ATYPE_EDICT,
ATYPE_EVARS,
ATYPE_BOOL
ATYPE_BOOL,
ATYPE_VECTOR
};

enum HookChain
Expand All @@ -146,7 +148,7 @@ enum HookChain
*
* @return Returns a hook handle. Use EnableHookChain/DisableHookChain to toggle the forward on or off
*/
native HookChain:RegisterHookChain({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib}:function_id, const callback[], post = 0);
native HookChain:RegisterHookChain({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib, GamedllFunc_CBaseEntity}:function_id, const callback[], post = 0);

/*
* Stops a hook from triggering.
Expand Down
28 changes: 28 additions & 0 deletions reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,34 @@ enum GamedllFunc_CGib
RG_CGib_WaitTillLand,
};

/**
* GamedllFunc CBaseEntity
*/
enum GamedllFunc_CBaseEntity
{
/*
* Description: -
* Return type: void
* Params: (pEntity, cShots, Float:vecSrc[3], Float:vecDirShooting[3], Float:vecSpread[3], Float:flDistance, iBulletType, iTracerFreq, iDamage, pevAttacker)

*/
RG_CBaseEntity_FireBullets = BEGIN_FUNC_REGION(cbaseentity),

/*
* Description: -
* Return type: void
* Params: (pEntity, cShots, Float:vecSrc[3], Float:vecDirShooting[3], Float:vecSpread[3], Float:flDistance, iTracerFreq, iDamage, pevAttacker)
*/
RG_CBaseEntity_FireBuckshots,

/*
* Description: -
* Return type: Vector [3]
* Params: (pEntity, Float:vecSrc[3], Float:vecDirShooting[3], Float:vecSpread, Float:flDistance, iPenetration, iBulletType, iDamage, Float:flRangeModifier, pevAttacker, bool:bPistol, shared_rand)
*/
RG_CBaseEntity_FireBullets3,
};

/**
* GamedllFunc CSGameRules
*/
Expand Down
17 changes: 17 additions & 0 deletions reapi/include/cssdk/dlls/regamedll_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,19 @@ typedef IHookChainRegistryClass<void, class CGib, CBaseEntity *> IReGameHookRegi
typedef IHookChainClass<void, class CGib> IReGameHook_CGib_WaitTillLand;
typedef IHookChainRegistryClass<void, class CGib> IReGameHookRegistry_CGib_WaitTillLand;

// CBaseEntity::FireBullets hook
typedef IHookChainClass<void, class CBaseEntity, ULONG, Vector&, Vector&, Vector&, float, int, int, int, entvars_t*> IReGameHook_CBaseEntity_FireBullets;
typedef IHookChainRegistryClass<void, class CBaseEntity, ULONG, Vector&, Vector&, Vector&, float, int, int, int, entvars_t*> IReGameHookRegistry_CBaseEntity_FireBullets;

// CBaseEntity::FireBuckshots hook
typedef IHookChainClass<void, class CBaseEntity, ULONG, Vector&, Vector&, Vector&, float, int, int, entvars_t*> IReGameHook_CBaseEntity_FireBuckshots;
typedef IHookChainRegistryClass<void, class CBaseEntity, ULONG, Vector&, Vector&, Vector&, float, int, int, entvars_t*> IReGameHookRegistry_CBaseEntity_FireBuckshots;

// CBaseEntity::FireBullets3 hook
typedef IHookChainClass<Vector&, class CBaseEntity, Vector&, Vector&, float, float, int, int, int, float, entvars_t*, bool, int> IReGameHook_CBaseEntity_FireBullets3;
typedef IHookChainRegistryClass<Vector&, class CBaseEntity, Vector&, Vector&, float, float, int, int, int, float, entvars_t*, bool, int> IReGameHookRegistry_CBaseEntity_FireBullets3;


class IReGameHookchains {
public:
virtual ~IReGameHookchains() {}
Expand Down Expand Up @@ -611,6 +624,10 @@ class IReGameHookchains {
virtual IReGameHookRegistry_CGib_Spawn *CGib_Spawn() = 0;
virtual IReGameHookRegistry_CGib_BounceGibTouch *CGib_BounceGibTouch() = 0;
virtual IReGameHookRegistry_CGib_WaitTillLand *CGib_WaitTillLand() = 0;

virtual IReGameHookRegistry_CBaseEntity_FireBullets *CBaseEntity_FireBullets() = 0;
virtual IReGameHookRegistry_CBaseEntity_FireBuckshots *CBaseEntity_FireBuckshots() = 0;
virtual IReGameHookRegistry_CBaseEntity_FireBullets3 *CBaseEntity_FireBullets3() = 0;
};

struct ReGameFuncs_t {
Expand Down
42 changes: 42 additions & 0 deletions reapi/src/hook_callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,48 @@ void CGib_WaitTillLand(IReGameHook_CGib_WaitTillLand *chain, CGib *pthis)
callVoidForward(RG_CGib_WaitTillLand, original, indexOfEdict(pthis->pev));
}

void CBaseEntity_FireBullets(IReGameHook_CBaseEntity_FireBullets *chain, CBaseEntity *pEntity, ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker)
{
Vector vecSrcCopy(vecSrc), vecDirShootingCopy(vecDirShooting), vecSpreadCopy(vecSpread);

auto original = [chain, &vecSrcCopy, &vecDirShootingCopy, &vecSpreadCopy](int _pEntity, ULONG _cShots, cell _vecSrc, cell _vecDirShooting, cell _vecSpread, float _flDistance, int _iBulletType, int _iTracerFreq, int _iDamage, int _pevAttacker)
{
chain->callNext(getPrivate<CBaseEntity>(_pEntity), _cShots, vecSrcCopy, vecDirShootingCopy, vecSpreadCopy, _flDistance, _iBulletType, _iTracerFreq, _iDamage, PEV(_pevAttacker));
};

callVoidForward(RG_CBaseEntity_FireBullets, original, indexOfEdict(pEntity->pev), cShots, getAmxVector(vecSrcCopy), getAmxVector(vecDirShootingCopy), getAmxVector(vecSpreadCopy), flDistance, iBulletType, iTracerFreq, iDamage, indexOfEdict(pevAttacker));
}

void CBaseEntity_FireBuckshots(IReGameHook_CBaseEntity_FireBuckshots *chain, CBaseEntity *pEntity, ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iTracerFreq, int iDamage, entvars_t *pevAttacker)
{
Vector vecSrcCopy(vecSrc), vecDirShootingCopy(vecDirShooting), vecSpreadCopy(vecSpread);

auto original = [chain, &vecSrcCopy, &vecDirShootingCopy, &vecSpreadCopy](int _pEntity, ULONG _cShots, cell _vecSrc, cell _vecDirShooting, cell _vecSpread, float _flDistance, int _iTracerFreq, int _iDamage, int _pevAttacker)
{
chain->callNext(getPrivate<CBaseEntity>(_pEntity), _cShots, vecSrcCopy, vecDirShootingCopy, vecSpreadCopy, _flDistance, _iTracerFreq, _iDamage, PEV(_pevAttacker));
};

callVoidForward(RG_CBaseEntity_FireBuckshots, original, indexOfEdict(pEntity->pev), cShots, getAmxVector(vecSrcCopy), getAmxVector(vecDirShootingCopy), getAmxVector(vecSpreadCopy), flDistance, iTracerFreq, iDamage, indexOfEdict(pevAttacker));
}

Vector &CBaseEntity_FireBullets3(IReGameHook_CBaseEntity_FireBullets3 *chain, CBaseEntity *pEntity, Vector &vecSrc, Vector &vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand)
{
Vector vecSrcCopy(vecSrc), vecDirShootingCopy(vecDirShooting);

auto original = [chain, &vecSrcCopy, &vecDirShootingCopy](int _pEntity, cell _vecSrc, cell _vecDirShooting, float _vecSpread, float _flDistance, int _iPenetration, int _iBulletType, int _iDamage, float _flRangeModifier, int _pevAttacker, bool _bPistol, int _shared_rand) -> Vector&
{
return chain->callNext(getPrivate<CBaseEntity>(_pEntity), vecSrcCopy, vecDirShootingCopy, _vecSpread, _flDistance, _iPenetration, _iBulletType, _iDamage, _flRangeModifier, PEV(_pevAttacker), _bPistol, _shared_rand);
};

return callForward<Vector &>(RG_CBaseEntity_FireBullets3, original,
indexOfEdict(pEntity->pev),
getAmxVector(vecSrcCopy), getAmxVector(vecDirShootingCopy),
vecSpread, flDistance, iPenetration, iBulletType, iDamage, flRangeModifier,
indexOfEdict(pevAttacker),
bPistol,
shared_rand);
}

int g_iClientStartSpeak, g_iClientStopSpeak;

void OnClientStartSpeak(size_t clientIndex)
Expand Down
31 changes: 23 additions & 8 deletions reapi/src/hook_callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ enum AType : uint8
ATYPE_CLASSPTR,
ATYPE_EDICT,
ATYPE_EVARS,
ATYPE_BOOL
ATYPE_BOOL,
ATYPE_VECTOR
};

struct retval_t
Expand All @@ -36,18 +37,21 @@ struct retval_t
CBaseEntity* _classptr;
edict_t* _edict;
entvars_t* _pev;
Vector* _vector;
};
};

inline AType getApiType(int) { return ATYPE_INTEGER; }
inline AType getApiType(unsigned) { return ATYPE_INTEGER; }
inline AType getApiType(ULONG) { return ATYPE_INTEGER; }
inline AType getApiType(float) { return ATYPE_FLOAT; }
inline AType getApiType(const char *) { return ATYPE_STRING; }
inline AType getApiType(char[]) { return ATYPE_STRING; }
inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; }
inline AType getApiType(edict_t *) { return ATYPE_EDICT; }
inline AType getApiType(entvars_t *) { return ATYPE_EVARS; }
inline AType getApiType(bool) { return ATYPE_BOOL; }
inline AType getApiType(Vector) { return ATYPE_VECTOR; }

template<typename T>
inline AType getApiType(T *) { return ATYPE_INTEGER; }
Expand Down Expand Up @@ -214,8 +218,10 @@ void callVoidForward(size_t func, original_t original, f_args&&... args)
template <typename R, typename original_t, typename ...f_args>
NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&... args)
{
using R2 = typename std::decay<R>::type;

auto hookCtx = g_hookCtx;
hookCtx->reset(getApiType(R()));
hookCtx->reset(getApiType(R2()));

int hc_state = HC_CONTINUE;

Expand All @@ -239,7 +245,7 @@ NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&...
}

if (unlikely(ret == HC_BREAK)) {
return *(R *)&hookCtx->retVal._integer;
return *(R2 *)&hookCtx->retVal._integer;
}

if (unlikely(ret > hc_state))
Expand All @@ -250,7 +256,7 @@ NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&...
if (likely(hc_state != HC_SUPERCEDE))
{
g_hookCtx = nullptr;
auto retVal = original(std::forward<f_args &&>(args)...);
R retVal = original(std::forward<f_args &&>(args)...);
g_hookCtx = hookCtx;
hook->wasCalled = true;

Expand All @@ -265,6 +271,9 @@ NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&...
case sizeof(int32):
hookCtx->retVal._integer = *(int32 *)&retVal;
break;
case sizeof(Vector):
hookCtx->retVal._vector = (Vector *)&retVal;
break;
}
hookCtx->retVal.set = true;
}
Expand All @@ -285,19 +294,20 @@ NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&...

hook->wasCalled = false;

return *(R *)&hookCtx->retVal._integer;
if (std::is_reference<R>::value)
return *(R2 *)hookCtx->retVal._integer;
else
return *(R2 *)&hookCtx->retVal._integer;
}

template <typename R, typename original_t, typename ...f_args>
R callForward(size_t func, original_t original, f_args&&... args)
{
static_assert(sizeof(R) <= sizeof(int), "invalid hookchain return type size > sizeof(int)");

hookctx_t hookCtx(sizeof...(args), args...);
hookctx_t* save = g_hookCtx;

g_hookCtx = &hookCtx;
auto ret = _callForward<R>(g_hookManager.getHookFast(func), original, args...);
R ret = _callForward<R>(g_hookManager.getHookFast(func), original, args...);
g_hookCtx = save;

if (hasStringArgs(args...)) {
Expand Down Expand Up @@ -465,6 +475,11 @@ void CGib_Spawn(IReGameHook_CGib_Spawn *chain, CGib *pthis, const char *szGibMod
void CGib_BounceGibTouch(IReGameHook_CGib_BounceGibTouch *chain, CGib *pthis, CBaseEntity *pOther);
void CGib_WaitTillLand(IReGameHook_CGib_WaitTillLand *chain, CGib *pthis);

// regamedll functions - cbaseentity
void CBaseEntity_FireBullets(IReGameHook_CBaseEntity_FireBullets *chain, CBaseEntity *pEntity, ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker);
void CBaseEntity_FireBuckshots(IReGameHook_CBaseEntity_FireBuckshots *chain, CBaseEntity *pEntity, ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iTracerFreq, int iDamage, entvars_t *pevAttacker);
Vector &CBaseEntity_FireBullets3(IReGameHook_CBaseEntity_FireBullets3 *chain, CBaseEntity *pEntity, Vector &vecSrc, Vector &vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand);

extern int g_iClientStartSpeak;
extern int g_iClientStopSpeak;

Expand Down
9 changes: 9 additions & 0 deletions reapi/src/hook_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ inline size_t getFwdParamType(void(*)(int)) { return FP_CELL
inline size_t getFwdParamType(void(*)(size_t)) { return FP_CELL; }
inline size_t getFwdParamType(void(*)(short)) { return FP_CELL; }
inline size_t getFwdParamType(void(*)(unsigned short)) { return FP_CELL; }
inline size_t getFwdParamType(void(*)(ULONG)) { return FP_CELL; }
inline size_t getFwdParamType(void(*)(bool)) { return FP_CELL; }
inline size_t getFwdParamType(void(*)(Vector&)) { return FP_ARRAY; }
inline size_t getFwdParamType(void(*)(TeamName)) { return FP_CELL; }
Expand Down Expand Up @@ -221,6 +222,12 @@ hook_t hooklist_gib[] = {
DLL(CGib_WaitTillLand),
};

hook_t hooklist_cbaseentity[] = {
DLL(CBaseEntity_FireBullets),
DLL(CBaseEntity_FireBuckshots),
DLL(CBaseEntity_FireBullets3),
};

#define RCHECK(h,...) { {}, {}, #h, "ReChecker", [](){ return api_cfg.hasRechecker(); }, ((!(RC_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RC_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RecheckerHookchains->h()->registerHook(&h); }, [](){ g_RecheckerHookchains->h()->unregisterHook(&h); }, false}
hook_t hooklist_rechecker[] = {
RCHECK(FileConsistencyProcess, _AMXX),
Expand All @@ -246,6 +253,7 @@ hook_t* hooklist_t::getHookSafe(size_t hook)
CASE(weaponbox)
CASE(weapon)
CASE(gib)
CASE(cbaseentity)
}

return nullptr;
Expand All @@ -265,6 +273,7 @@ void hooklist_t::clear()
FOREACH_CLEAR(weaponbox);
FOREACH_CLEAR(weapon);
FOREACH_CLEAR(gib);
FOREACH_CLEAR(cbaseentity);
}

void hook_t::clear()
Expand Down
12 changes: 12 additions & 0 deletions reapi/src/hook_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern hook_t hooklist_grenade[];
extern hook_t hooklist_weaponbox[];
extern hook_t hooklist_weapon[];
extern hook_t hooklist_gib[];
extern hook_t hooklist_cbaseentity[];

enum
{
Expand All @@ -63,6 +64,7 @@ struct hooklist_t
CASE(weaponbox)
CASE(weapon)
CASE(gib)
CASE(cbaseentity)
}

#undef CASE
Expand All @@ -85,6 +87,7 @@ struct hooklist_t
ht_weaponbox,
ht_weapon,
ht_gib,
ht_cbaseentity,
};
};

Expand Down Expand Up @@ -262,6 +265,15 @@ enum GamedllFunc_CGib
// [...]
};

enum GamedllFunc_CBaseEntity
{
RG_CBaseEntity_FireBullets = BEGIN_FUNC_REGION(cbaseentity),
RG_CBaseEntity_FireBuckshots,
RG_CBaseEntity_FireBullets3,

// [...]
};

enum ReCheckerFunc
{
RC_FileConsistencyProcess = BEGIN_FUNC_REGION(rechecker),
Expand Down
23 changes: 18 additions & 5 deletions reapi/src/natives/natives_hookchains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ cell AMX_NATIVE_CALL DisableHookChain(AMX *amx, cell *params)
return TRUE;
}

static CTempAnyData<Vector, 16> s_tmpVectors;
static CTempAnyData<char, 16, 1024> s_tmpStrings;

/*
* Sets the return value of a hookchain.
*
Expand Down Expand Up @@ -148,12 +151,9 @@ cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)

case ATYPE_STRING:
{
if (retVal._string != nullptr)
delete[] retVal._string;

size_t len;
const char *dest = getAmxString(srcAddr, string, &len);
retVal._string = strcpy(new char[len + 1], dest);
retVal._string = strcpy(s_tmpStrings.Alloc(), dest);
break;
}
case ATYPE_CLASSPTR:
Expand All @@ -165,6 +165,10 @@ cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
case ATYPE_EVARS:
retVal._pev = PEV(*srcAddr);
break;
case ATYPE_VECTOR:
retVal._vector = s_tmpVectors.Alloc();
*retVal._vector = *(Vector *)srcAddr;
break;
default:
return FALSE;
}
Expand Down Expand Up @@ -224,7 +228,7 @@ cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
return retVal._integer != 0 ? TRUE : FALSE;
case ATYPE_STRING:
{
if (PARAMS_COUNT != 2)
if (PARAMS_COUNT != 3)
return FALSE;

setAmxString(dstAddr, retVal._string, params[arg_maxlen]);
Expand All @@ -236,6 +240,15 @@ cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
return indexOfEdict(retVal._edict);
case ATYPE_EVARS:
return indexOfEdict(retVal._pev);
case ATYPE_VECTOR:
{
if (PARAMS_COUNT != 2)
return FALSE;

Vector &pDest = *(Vector *)dstAddr;
pDest = *retVal._vector;
return TRUE;
}
default:
return FALSE;
}
Expand Down
Loading