2
0
mirror of https://github.com/rehlds/reapi.git synced 2024-12-28 15:45:31 +03:00

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

* Implement "CBaseEntity::Fire<Bullets[3]|Buckshots>" hooks.
* Added new hook table "GamedllFunc_CBaseEntity".
* Added new hookchain argument type "ATYPE_VECTOR"
* Added ATYPE_VECTOR case in Get|Set<HookChainReturn> natives
* Added ATYPE_VECTOR in SetHookChainArg native
This commit is contained in:
FEDERICOMB 2021-08-01 05:44:46 -03:00 committed by GitHub
parent 5b4fc4f132
commit 97aea0f397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 172 additions and 18 deletions

View File

@ -24,7 +24,8 @@ enum hooks_tables_e
ht_grenade,
ht_weaponbox,
ht_weapon,
ht_gib
ht_gib,
ht_cbaseentity
};
enum members_tables_e
@ -128,7 +129,8 @@ enum AType
ATYPE_CLASSPTR,
ATYPE_EDICT,
ATYPE_EVARS,
ATYPE_BOOL
ATYPE_BOOL,
ATYPE_VECTOR
};
enum HookChain
@ -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.

View File

@ -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
*/

View File

@ -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() {}
@ -611,6 +624,10 @@ public:
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 {

View File

@ -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)

View File

@ -20,7 +20,8 @@ enum AType : uint8
ATYPE_CLASSPTR,
ATYPE_EDICT,
ATYPE_EVARS,
ATYPE_BOOL
ATYPE_BOOL,
ATYPE_VECTOR
};
struct retval_t
@ -36,11 +37,13 @@ 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; }
@ -48,6 +51,7 @@ 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; }
@ -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;
@ -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))
@ -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;
@ -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;
}
@ -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...)) {
@ -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;

View File

@ -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; }
@ -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),
@ -246,6 +253,7 @@ hook_t* hooklist_t::getHookSafe(size_t hook)
CASE(weaponbox)
CASE(weapon)
CASE(gib)
CASE(cbaseentity)
}
return nullptr;
@ -265,6 +273,7 @@ void hooklist_t::clear()
FOREACH_CLEAR(weaponbox);
FOREACH_CLEAR(weapon);
FOREACH_CLEAR(gib);
FOREACH_CLEAR(cbaseentity);
}
void hook_t::clear()

View File

@ -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
{
@ -63,6 +64,7 @@ struct hooklist_t
CASE(weaponbox)
CASE(weapon)
CASE(gib)
CASE(cbaseentity)
}
#undef CASE
@ -85,6 +87,7 @@ struct hooklist_t
ht_weaponbox,
ht_weapon,
ht_gib,
ht_cbaseentity,
};
};
@ -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),

View File

@ -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.
*
@ -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:
@ -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;
}
@ -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]);
@ -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;
}

View File

@ -4,3 +4,18 @@
#define NATIVE_MEMBER_REQUIRE(a,x) if (!api_cfg.has##x()) { AMXX_LogError(amx, AMX_ERR_NATIVE, "Member (%s) is not available, required %s", memberlist[a]->member_name, #x); return 0; }
void RegisterNatives_HookChains();
template <typename T, size_t BUF_MAX, size_t BUF_SIZE = 1>
class CTempAnyData
{
public:
T *Alloc()
{
m_current = (m_current + 1) % BUF_MAX;
return m_data[m_current];
}
private:
size_t m_current = 0;
T m_data[BUF_MAX][BUF_SIZE];
};

View File

@ -459,7 +459,7 @@ cell AMX_NATIVE_CALL rg_round_end(AMX *amx, cell *params)
{
CSGameRules()->EndRoundMessage(message, _event);
CSGameRules()->TerminateRound(_tmDelay, _winStatus);
return TRUE;
return true;
},
winstatus, event, tmDelay);
}

View File

@ -231,7 +231,8 @@ const char *getATypeStr(AType type)
"ATYPE_CLASSPTR",
"ATYPE_EDICT",
"ATYPE_EVARS",
"ATYPE_BOOL"
"ATYPE_BOOL",
"ATYPE_VECTOR"
};
if (type >= arraysize(s_ATypes))