From 15aca1d7997d1c145dbb60450efe564837872641 Mon Sep 17 00:00:00 2001 From: Nord1cWarr1or <47604048+Nord1cWarr1or@users.noreply.github.com> Date: Tue, 28 Dec 2021 18:32:53 +0300 Subject: [PATCH 01/50] Fix wrong native error description (#236) * Update natives_common.cpp * Update reapi_engine.inc * Update reapi_engine.inc add error description * Update natives_common.cpp * reapi_engine.inc: add error in `set_key_value` desc * natives_common.cpp: add error in `set_key_value` desc --- reapi/extra/amxmodx/scripting/include/reapi_engine.inc | 4 ++-- reapi/src/natives/natives_common.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index 52c17a5d..e5a2ac8d 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -39,8 +39,7 @@ native any:get_ucmd(const ucmd, const UCmd:var, any:...); * @param maxlen Maximum size of the buffer * * @return Number of cells written to buffer -* @error If the index is not within the range of 1 to MaxClients or -* the client is not connected, an error will be thrown. +* @error If invalid buffer handler provided, an error will be thrown. */ native get_key_value(const pbuffer, const key[], const value[], const maxlen); @@ -52,6 +51,7 @@ native get_key_value(const pbuffer, const key[], const value[], const maxlen); * @param value Value to set * * @noreturn +* @error If invalid buffer handler provided, an error will be thrown. */ native set_key_value(const pbuffer, const key[], const value[]); diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index 18d8a8ee..6315653c 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -122,8 +122,7 @@ cell AMX_NATIVE_CALL amx_get_viewent(AMX *amx, cell *params) * @param maxlen Maximum size of the buffer * * @return Number of cells written to buffer -* @error If the index is not within the range of 1 to MaxClients or -* the client is not connected, an error will be thrown. +* @error If invalid buffer handler provided, an error will be thrown. * * native get_key_value(const pbuffer, const key[], const value[], const maxlen); */ @@ -152,6 +151,7 @@ cell AMX_NATIVE_CALL amx_get_key_value(AMX *amx, cell *params) * @param value Value to set * * @noreturn +* @error If invalid buffer handler provided, an error will be thrown. * * native set_key_value(const &pbuffer, const key[], const value[]); */ From fe6150a5d3c34dcec980d628502d87eb207d9c86 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Mon, 31 Jan 2022 04:25:31 +0700 Subject: [PATCH 02/50] Implemented native REU_GetAuthKey --- .../scripting/include/reapi_reunion.inc | 12 +++++++ reapi/src/natives/natives_reunion.cpp | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc b/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc index ea85bcee..311f0c2c 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc @@ -39,6 +39,18 @@ native REU_GetProtocol(const index); */ native client_auth_type:REU_GetAuthtype(const index); +/* +* Get client authkey +* +* @param index Client index +* @param index Buffer to copy the authkey +* @param index Maximum buffer size +* +* @return Number of cells copied to buffer +* +*/ +native REU_GetAuthKey(const index, dest[], maxlen); + /* * Check if the client is running RevEmu with limited user rights. * diff --git a/reapi/src/natives/natives_reunion.cpp b/reapi/src/natives/natives_reunion.cpp index 3437b4aa..4dad5789 100644 --- a/reapi/src/natives/natives_reunion.cpp +++ b/reapi/src/natives/natives_reunion.cpp @@ -36,6 +36,36 @@ cell AMX_NATIVE_CALL REU_GetAuthtype(AMX *amx, cell *params) return g_ReunionApi->GetClientAuthtype(params[arg_index] - 1); } +/* +* Get client authkey +* +* @param index Client index +* @param index Buffer to copy the authkey +* @param index Maximum buffer size +* +* @return Number of cells copied to buffer +* +* native REU_GetAuthKey(const index, dest[], maxlen); +*/ +cell AMX_NATIVE_CALL REU_GetAuthKey(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_output, arg_maxlen }; + + CHECK_ISPLAYER(arg_index); + + int clientId = params[arg_index] - 1; + + char buffer[256]; + size_t size = g_ReunionApi->GetClientAuthdata(clientId, buffer, sizeof buffer); + if (size <= 0) + return 0; + + size_t numToCopy = min(size, params[arg_maxlen]); + cell *dest = getAmxAddr(amx, params[arg_output]); + setAmxString(dest, buffer, numToCopy); + return numToCopy; +} + /* * Check if the client is running RevEmu with limited user rights. * @@ -70,6 +100,7 @@ AMX_NATIVE_INFO Reunion_Natives[] = { { "REU_GetProtocol", REU_GetProtocol }, { "REU_GetAuthtype", REU_GetAuthtype }, + { "REU_GetAuthKey", REU_GetAuthKey }, { "REU_IsRevemuWithoutAdminRights", REU_IsRevemuWithoutAdminRights }, { nullptr, nullptr } From 2bda2c303c1330f78394d052bc9b53a3f36ef8d9 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 26 Feb 2022 13:46:50 +0700 Subject: [PATCH 03/50] Update workflows/build.yml Set windows job container as windows-2019 instead of windows-latest which now run on windows-2022 https://github.com/actions/virtual-environments/issues/4856 Fixes windows build --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e72430b..b191a309 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ on: jobs: windows: name: 'Windows' - runs-on: windows-latest + runs-on: windows-2019 env: solution: 'msvc/reapi.sln' From 4e23c6573b9367594545cbe0a87236b23742b277 Mon Sep 17 00:00:00 2001 From: Adrian Cirstea <54354938+ShadowsAdi@users.noreply.github.com> Date: Mon, 19 Sep 2022 19:08:46 +0300 Subject: [PATCH 04/50] Implement `RH_*_Precache_*`, `RH_SV_AddResource`, `RH_SV_ClientPrintf` & `RH_SV_CheckUserInfo` hooks (#249) Co-authored-by: Sergey Shorokhov --- .../scripting/include/reapi_engine_const.inc | 69 +++++++++++++++- reapi/include/cssdk/engine/rehlds_api.h | 37 ++++++++- reapi/src/hook_callback.cpp | 78 ++++++++++++++++++- reapi/src/hook_callback.h | 15 ++++ reapi/src/hook_list.cpp | 10 +++ reapi/src/hook_list.h | 7 ++ reapi/version/version.h | 2 +- 7 files changed, 214 insertions(+), 4 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc index 3c8cd50c..b40be50f 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc @@ -13,6 +13,23 @@ enum MapNameType MNT_SET // return the name of the current map }; +/* +* For RH_SV_AddResource hook +*/ +enum ResourceType_t +{ + t_sound = 0, + t_skin, + t_model, + t_decal, + t_generic, + t_eventscript, + t_world, // Fake type for world, is really t_model + rt_unk, + + rt_max +}; + /** * rh_emit_sound2 flags */ @@ -91,10 +108,60 @@ enum EngineFunc RH_ED_Free, /* - * Description: - + * Description: Called when a message is being sent to the server's console. * Params: (const string[]) */ RH_Con_Printf, + + /* + * Description: Called when a player's userinfo is being checked. + * Params: (adr, userinfo[], bool:reconnect, reconnectSlot, name[]) + * + * @note Param adr is unused, guaranteed to return nothing also, don't send anything through it. + * @note In order for param name work, hook needs to be registered as Post. + */ + RH_SV_CheckUserInfo, + + /* + * Description: Called when a generic resource is being added to generic precache list. + * Return type: int + * Params: (const string[]) + */ + RH_PF_precache_generic_I, + + /* + * Description: Called when a model is being added to model precache list. + * Return type: int + * Params: (const string[]) + */ + RH_PF_precache_model_I, + + /* + * Description: Called when a sound is being added to sound precache list. + * Return type: int + * Params: (const string[]) + */ + RH_PF_precache_sound_I, + + /* + * Description: Called when an event is being added to event precache list. + * Return type: int + * Params: (const string[]) + */ + RH_EV_Precache, + + /* + * Description: Called when a resource is being added to resource list. + * Params: (ResourceType_t:type, const filename[], size, flags, index) + */ + RH_SV_AddResource, + + /* + * Description: Called when message is being printed to client console. + * Params: (const string[]) + */ + RH_SV_ClientPrintf, + }; /** diff --git a/reapi/include/cssdk/engine/rehlds_api.h b/reapi/include/cssdk/engine/rehlds_api.h index ab1cd9e2..a76ec9f9 100644 --- a/reapi/include/cssdk/engine/rehlds_api.h +++ b/reapi/include/cssdk/engine/rehlds_api.h @@ -36,7 +36,7 @@ #include "pr_dlls.h" #define REHLDS_API_VERSION_MAJOR 3 -#define REHLDS_API_VERSION_MINOR 11 +#define REHLDS_API_VERSION_MINOR 12 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -226,6 +226,34 @@ typedef IVoidHookChainRegistry IRehldsHookRegistry_ED_Free; typedef IHookChain IRehldsHook_Con_Printf; typedef IHookChainRegistry IRehldsHookRegistry_Con_Printf; +//SV_CheckUserInfo hook +typedef IHookChain IRehldsHook_SV_CheckUserInfo; +typedef IHookChainRegistry IRehldsHookRegistry_SV_CheckUserInfo; + +//PF_precache_generic_I hook +typedef IHookChain IRehldsHook_PF_precache_generic_I; +typedef IHookChainRegistry IRehldsHookRegistry_PF_precache_generic_I; + +//PF_precache_model_I hook +typedef IHookChain IRehldsHook_PF_precache_model_I; +typedef IHookChainRegistry IRehldsHookRegistry_PF_precache_model_I; + +//PF_precache_sound_I hook +typedef IHookChain IRehldsHook_PF_precache_sound_I; +typedef IHookChainRegistry IRehldsHookRegistry_PF_precache_sound_I; + +//EV_Precache hook +typedef IHookChain IRehldsHook_EV_Precache; +typedef IHookChainRegistry IRehldsHookRegistry_EV_Precache; + +//SV_AddResource hook +typedef IVoidHookChain IRehldsHook_SV_AddResource; +typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_AddResource; + +//SV_ClientPrintf hook +typedef IVoidHookChain IRehldsHook_SV_ClientPrintf; +typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_ClientPrintf; + class IRehldsHookchains { public: virtual ~IRehldsHookchains() { } @@ -277,6 +305,13 @@ class IRehldsHookchains { virtual IRehldsHookRegistry_ED_Alloc* ED_Alloc() = 0; virtual IRehldsHookRegistry_ED_Free* ED_Free() = 0; virtual IRehldsHookRegistry_Con_Printf* Con_Printf() = 0; + virtual IRehldsHookRegistry_SV_CheckUserInfo* SV_CheckUserInfo() = 0; + virtual IRehldsHookRegistry_PF_precache_generic_I* PF_precache_generic_I() = 0; + virtual IRehldsHookRegistry_PF_precache_model_I* PF_precache_model_I() = 0; + virtual IRehldsHookRegistry_PF_precache_sound_I* PF_precache_sound_I() = 0; + virtual IRehldsHookRegistry_EV_Precache* EV_Precache() = 0; + virtual IRehldsHookRegistry_SV_AddResource* SV_AddResource() = 0; + virtual IRehldsHookRegistry_SV_ClientPrintf* SV_ClientPrintf() = 0; }; struct RehldsFuncs_t { diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 78b3a5c4..67fe1d12 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -115,7 +115,6 @@ void SV_EmitPings_AMXX(SV_EmitPings_t* data, IGameClient* cl) void SV_EmitPings(IRehldsHook_SV_EmitPings *chain, IGameClient *cl, sizebuf_t *msg) { - SV_EmitPings_args_t args(cl, msg); SV_EmitPings_t data(chain, args); SV_EmitPings_AMXX(&data, cl); @@ -141,6 +140,83 @@ void ED_Free(IRehldsHook_ED_Free* chain, edict_t *entity) callVoidForward(RH_ED_Free, original, indexOfEdict(entity)); } +int SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name) +{ + auto original = [chain](netadr_t *_adr, char *_userinfo, qboolean _bIsReconnecting, int _iReconnectSlot, char *_name) + { + return chain->callNext(_adr, _userinfo, _bIsReconnecting, _iReconnectSlot, _name); + }; + + return callForward(RH_SV_CheckUserInfo, original, adr, userinfo, bIsReconnecting, iReconnectSlot, name); +} + +int PF_precache_generic_I(IRehldsHook_PF_precache_generic_I *chain, const char *s) +{ + auto original = [chain](const char *_s) + { + return chain->callNext(_s); + }; + + return callForward(RH_PF_precache_generic_I, original, s); +} + +int PF_precache_model_I(IRehldsHook_PF_precache_model_I *chain, char *s) +{ + auto original = [chain](char *_s) + { + return chain->callNext(_s); + }; + + return callForward(RH_PF_precache_model_I, original, s); +} + +int PF_precache_sound_I(IRehldsHook_PF_precache_sound_I *chain, const char *s) +{ + auto original = [chain](const char *_s) + { + return chain->callNext(_s); + }; + + return callForward(RH_PF_precache_sound_I, original, s); +} + +unsigned short EV_Precache_AMXX(EventPrecache_t *data, const char *psz) +{ + auto original = [data](const char *_psz) + { + return data->m_chain->callNext(data->m_args.type, _psz); + }; + + return callForward(RH_EV_Precache, original, psz); +} + +unsigned short EV_Precache(IRehldsHook_EV_Precache *chain, int type, const char *psz) +{ + EventPrecache_args_t args(type); + EventPrecache_t data(chain, args); + return EV_Precache_AMXX(&data, psz); +} + +void SV_AddResource(IRehldsHook_SV_AddResource *chain, resourcetype_t type, const char *name, int size, unsigned char flags, int index) +{ + auto original = [chain](resourcetype_t _type, const char *_name, int _size, unsigned char _flags, int _index) + { + chain->callNext(_type, _name, _size, _flags, _index); + }; + + callVoidForward(RH_SV_AddResource, original, type, name, size, flags, index); +} + +void SV_ClientPrintf(IRehldsHook_SV_ClientPrintf *chain, const char *string) +{ + auto original = [chain](const char *_string) + { + chain->callNext(_string); + }; + + callVoidForward(RH_SV_ClientPrintf, original, string); +} + /* * ReGameDLL functions */ diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 9925b729..3ebec5f2 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -334,6 +334,7 @@ void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics); void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value); void ClientConnected(IRehldsHook_ClientConnected* chain, IGameClient* cl); void SV_ConnectClient(IRehldsHook_SV_ConnectClient* chain); +int SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo* chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name); struct SV_WriteFullClientUpdate_args_t { @@ -360,9 +361,23 @@ using SV_EmitPings_t = hookdata_t; +unsigned short EV_Precache_AMXX(EventPrecache_t *data, const char *psz); +unsigned short EV_Precache(IRehldsHook_EV_Precache *chain, int type, const char *psz); +void SV_AddResource(IRehldsHook_SV_AddResource *chain, resourcetype_t type, const char *name, int size, unsigned char flags, int index); edict_t *ED_Alloc(IRehldsHook_ED_Alloc* chain); void ED_Free(IRehldsHook_ED_Free* chain, edict_t *entity); +void SV_ClientPrintf(IRehldsHook_SV_ClientPrintf* chain, const char *string); // regamedll functions int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 2b9df5cb..32b7dc29 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -20,6 +20,8 @@ inline size_t getFwdParamType(void(*)(float&)) { return FP_FLOA inline size_t getFwdParamType(void(*)(const char *)) { return FP_STRING; } inline size_t getFwdParamType(void(*)(char *)) { return FP_STRING; } inline size_t getFwdParamType(void(*)(IResourceBuffer*)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(unsigned char)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(resourcetype_t)) { return FP_CELL; } template inline size_t getFwdParamType(void(*)(T *)) { return FP_CELL; } @@ -94,6 +96,14 @@ hook_t hooklist_engine[] = { ENG(ED_Alloc), ENG(ED_Free), ENG(Con_Printf), + ENG(SV_CheckUserInfo), + ENG(PF_precache_generic_I), + ENG(PF_precache_model_I), + ENG(PF_precache_sound_I), + ENG(EV_Precache, _AMXX), + ENG(SV_AddResource), + ENG(SV_ClientPrintf), + }; #define DLL(h,...) { {}, {}, #h, "ReGameDLL", [](){ return api_cfg.hasReGameDLL(); }, ((!(RG_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RG_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_ReGameHookchains->h()->registerHook(&h); }, [](){ g_ReGameHookchains->h()->unregisterHook(&h); }, false} diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index bf798827..fad1da67 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -105,6 +105,13 @@ enum EngineFunc RH_ED_Alloc, RH_ED_Free, RH_Con_Printf, + RH_SV_CheckUserInfo, + RH_PF_precache_generic_I, + RH_PF_precache_model_I, + RH_PF_precache_sound_I, + RH_EV_Precache, + RH_SV_AddResource, + RH_SV_ClientPrintf, // [...] }; diff --git a/reapi/version/version.h b/reapi/version/version.h index ba22bb75..b65ba1ab 100644 --- a/reapi/version/version.h +++ b/reapi/version/version.h @@ -6,5 +6,5 @@ #pragma once #define VERSION_MAJOR 5 -#define VERSION_MINOR 21 +#define VERSION_MINOR 22 #define VERSION_MAINTENANCE 0 From 7d9bd65e4fd6d12360587ec05c1af40125d22c19 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Fri, 18 Nov 2022 20:48:47 +0700 Subject: [PATCH 05/50] Fixed typo into hook CBasePlayer::SwitchTeam --- reapi/src/hook_callback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 67fe1d12..95847d6b 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -651,7 +651,7 @@ void CBasePlayer_SwitchTeam(IReGameHook_CBasePlayer_SwitchTeam *chain, CBasePlay chain->callNext(getPrivate(_pthis)); }; - callVoidForward(RG_CBasePlayer_CanSwitchTeam, original, indexOfEdict(pthis->pev)); + callVoidForward(RG_CBasePlayer_SwitchTeam, original, indexOfEdict(pthis->pev)); } bool CBasePlayer_CanSwitchTeam(IReGameHook_CBasePlayer_CanSwitchTeam *chain, CBasePlayer *pthis, TeamName teamToSwap) From aeabd1fa10180bb47f902646b572eab850b9fb73 Mon Sep 17 00:00:00 2001 From: Hamdi Date: Sat, 11 Feb 2023 11:44:28 +0000 Subject: [PATCH 06/50] Implement RH_SV_AllowPhysent hook (#265) --- .../amxmodx/scripting/include/reapi_engine_const.inc | 7 +++++++ reapi/include/cssdk/engine/rehlds_api.h | 7 ++++++- reapi/src/hook_callback.cpp | 10 ++++++++++ reapi/src/hook_callback.h | 1 + reapi/src/hook_list.cpp | 1 + reapi/src/hook_list.h | 1 + reapi/version/version.h | 2 +- 7 files changed, 27 insertions(+), 2 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc index b40be50f..3835e426 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc @@ -162,6 +162,13 @@ enum EngineFunc */ RH_SV_ClientPrintf, + /* + * Description: Called before adding an entity to the physents of a player. + * Return type: bool + * Params: (const entity, const client) + */ + RH_SV_AllowPhysent, + }; /** diff --git a/reapi/include/cssdk/engine/rehlds_api.h b/reapi/include/cssdk/engine/rehlds_api.h index a76ec9f9..3e2b4ecc 100644 --- a/reapi/include/cssdk/engine/rehlds_api.h +++ b/reapi/include/cssdk/engine/rehlds_api.h @@ -36,7 +36,7 @@ #include "pr_dlls.h" #define REHLDS_API_VERSION_MAJOR 3 -#define REHLDS_API_VERSION_MINOR 12 +#define REHLDS_API_VERSION_MINOR 13 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -254,6 +254,10 @@ typedef IVoidHookChainRegistry IRehldsHook_SV_ClientPrintf; typedef IVoidHookChainRegistry IRehldsHookRegistry_SV_ClientPrintf; +//SV_AllowPhysent hook +typedef IHookChain IRehldsHook_SV_AllowPhysent; +typedef IHookChainRegistry IRehldsHookRegistry_SV_AllowPhysent; + class IRehldsHookchains { public: virtual ~IRehldsHookchains() { } @@ -312,6 +316,7 @@ class IRehldsHookchains { virtual IRehldsHookRegistry_EV_Precache* EV_Precache() = 0; virtual IRehldsHookRegistry_SV_AddResource* SV_AddResource() = 0; virtual IRehldsHookRegistry_SV_ClientPrintf* SV_ClientPrintf() = 0; + virtual IRehldsHookRegistry_SV_AllowPhysent* SV_AllowPhysent() = 0; }; struct RehldsFuncs_t { diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 95847d6b..e785b20d 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -140,6 +140,16 @@ void ED_Free(IRehldsHook_ED_Free* chain, edict_t *entity) callVoidForward(RH_ED_Free, original, indexOfEdict(entity)); } +bool SV_AllowPhysent(IRehldsHook_SV_AllowPhysent* chain, edict_t* check, edict_t* sv_player) +{ + auto original = [chain](int _check, int _sv_player) + { + return chain->callNext(edictByIndexAmx(_check), edictByIndexAmx(_sv_player)); + }; + + return callForward(RH_SV_AllowPhysent, original, indexOfEdict(check), indexOfEdict(sv_player)); +} + int SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name) { auto original = [chain](netadr_t *_adr, char *_userinfo, qboolean _bIsReconnecting, int _iReconnectSlot, char *_name) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 3ebec5f2..7e6d93bc 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -378,6 +378,7 @@ void SV_AddResource(IRehldsHook_SV_AddResource *chain, resourcetype_t type, cons edict_t *ED_Alloc(IRehldsHook_ED_Alloc* chain); void ED_Free(IRehldsHook_ED_Free* chain, edict_t *entity); void SV_ClientPrintf(IRehldsHook_SV_ClientPrintf* chain, const char *string); +bool SV_AllowPhysent(IRehldsHook_SV_AllowPhysent* chain, edict_t* check, edict_t* sv_player); // regamedll functions int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 32b7dc29..1d4bc7db 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -103,6 +103,7 @@ hook_t hooklist_engine[] = { ENG(EV_Precache, _AMXX), ENG(SV_AddResource), ENG(SV_ClientPrintf), + ENG(SV_AllowPhysent), }; diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index fad1da67..985af8a6 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -112,6 +112,7 @@ enum EngineFunc RH_EV_Precache, RH_SV_AddResource, RH_SV_ClientPrintf, + RH_SV_AllowPhysent, // [...] }; diff --git a/reapi/version/version.h b/reapi/version/version.h index b65ba1ab..554ac429 100644 --- a/reapi/version/version.h +++ b/reapi/version/version.h @@ -6,5 +6,5 @@ #pragma once #define VERSION_MAJOR 5 -#define VERSION_MINOR 22 +#define VERSION_MINOR 23 #define VERSION_MAINTENANCE 0 From ab94d098503add1bd847b3c290e65f8a3c98d9c5 Mon Sep 17 00:00:00 2001 From: fl0werD Date: Thu, 2 Mar 2023 14:41:52 +0400 Subject: [PATCH 07/50] Add ITEM_FLAG_NOFIREUNDERWATER to cssdk_const.inc (#267) --- reapi/extra/amxmodx/scripting/include/cssdk_const.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 8ce08874..99070c04 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -272,6 +272,7 @@ #define ITEM_FLAG_NOAUTOSWITCHEMPTY (1<<2) #define ITEM_FLAG_LIMITINWORLD (1<<3) #define ITEM_FLAG_EXHAUSTIBLE (1<<4) +#define ITEM_FLAG_NOFIREUNDERWATER (1<<5) /** * @section get_entvar(entity, var_spawnflags) values From 867368f56d28fa15500eaa6ffc25db7cdca89703 Mon Sep 17 00:00:00 2001 From: Nord1cWarr1or <47604048+Nord1cWarr1or@users.noreply.github.com> Date: Fri, 17 Mar 2023 20:53:44 +0000 Subject: [PATCH 08/50] Improved description for `rg_get_weapon_info` (#269) --- reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc | 2 ++ reapi/src/natives/natives_misc.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 00b8970c..92cc4d8a 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -466,6 +466,8 @@ native bool:rg_has_item_by_name(const index, const item[]); * @param weapon name or id Weapon id, see WEAPON_* constants, WeaponIdType or weapon_* name * @param WpnInfo:type Info type, see WI_* constants * +* @note weapon_* name can only be used to get WI_ID +* * @return Weapon information * @error If weapon_id or type are out of bounds, an error will be thrown */ diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index d06a1224..a4f6065d 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -752,6 +752,8 @@ cell AMX_NATIVE_CALL rg_has_item_by_name(AMX *amx, cell *params) * @param weapon name or id Weapon id, see WEAPON_* constants, WeaponIdType or weapon_* name * @param WpnInfo:type Info type, see WI_* constants * +* @note weapon_* name can only be used to get WI_ID +* * @return Weapon information * @error If weapon_id or type are out of bounds, an error will be thrown * From d2347e8678dbf7676db51e6ee8e2601efb1e10a2 Mon Sep 17 00:00:00 2001 From: Adrian Cirstea <54354938+ShadowsAdi@users.noreply.github.com> Date: Fri, 31 Mar 2023 20:41:43 +0300 Subject: [PATCH 09/50] `API`: Implement `RH_ExecuteServerStringCmd` hook (#263) * `API`: Implement `RH_ExecuteServerStringCmd` hook --- .../amxmodx/scripting/include/reapi_engine_const.inc | 6 ++++++ reapi/src/hook_callback.cpp | 10 ++++++++++ reapi/src/hook_callback.h | 1 + reapi/src/hook_list.cpp | 2 ++ reapi/src/hook_list.h | 3 ++- 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc index 3835e426..81c4c16b 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc @@ -161,6 +161,12 @@ enum EngineFunc * Params: (const string[]) */ RH_SV_ClientPrintf, + + /* + * Description: Called when a command is being sent to server. + * Params: (const cmd[], source, id) + */ + RH_ExecuteServerStringCmd, /* * Description: Called before adding an entity to the physents of a player. diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index e785b20d..46f662c5 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -227,6 +227,16 @@ void SV_ClientPrintf(IRehldsHook_SV_ClientPrintf *chain, const char *string) callVoidForward(RH_SV_ClientPrintf, original, string); } +void ExecuteServerStringCmd(IRehldsHook_ExecuteServerStringCmd* chain, const char* cmdName, cmd_source_t cmdSrc, IGameClient* cl) +{ + auto original = [chain](const char* _cmdName, cmd_source_t _cmdSrc, int client) + { + chain->callNext(_cmdName, _cmdSrc, _cmdSrc == src_client ? g_RehldsSvs->GetClient(client) - 1 : 0); + }; + + callVoidForward(RH_ExecuteServerStringCmd, original, cmdName, cmdSrc, cmdSrc == src_client ? cl->GetId() + 1 : 0); +} + /* * ReGameDLL functions */ diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 7e6d93bc..6340010d 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -348,6 +348,7 @@ using SV_WriteFullClientUpdate_t = hookdata_t inline size_t getFwdParamType(void(*)(T *)) { return FP_CELL; } @@ -104,6 +105,7 @@ hook_t hooklist_engine[] = { ENG(SV_AddResource), ENG(SV_ClientPrintf), ENG(SV_AllowPhysent), + ENG(ExecuteServerStringCmd), }; diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 985af8a6..91125824 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -113,7 +113,8 @@ enum EngineFunc RH_SV_AddResource, RH_SV_ClientPrintf, RH_SV_AllowPhysent, - + RH_ExecuteServerStringCmd, + // [...] }; From b85d4ae41e6df3f719cf2ef51ceb19f65b3ffbc9 Mon Sep 17 00:00:00 2001 From: RauliTop Date: Fri, 31 Mar 2023 19:42:29 +0200 Subject: [PATCH 10/50] Improve include descriptions `rg_fire_bullets`, `rg_fire_buckshots` and `rg_fire_bullets3` (#245) --- .../extra/amxmodx/scripting/include/reapi_gamedll.inc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 92cc4d8a..984fb563 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -338,12 +338,15 @@ native rg_multidmg_add(const inflictor, const victim, const Float:flDamage, cons * @param iTracerFreq Tracer frequency * @param iDamage Damage amount * +* @note: This native doesn't create a decal effect +* @note: Decal creation is handled by PlaybackEvent, including shot animation and shot sound +* * @noreturn */ native rg_fire_bullets(const inflictor, const attacker, const shots, Float:vecSrc[3], Float:vecDirShooting[3], Float:vecSpread[3], const Float:flDistance, const Bullet:iBulletType, const iTracerFreq, const iDamage); /* -* Fires buckshots from entity. +* Fires buckshots from entity (used at XM1014 and M3 weapons). * * @param inflictor Inflictor is the entity that caused the damage (such as a gun) * @param attacker Attacker is the entity that triggered the damage (such as the gun's owner) @@ -355,6 +358,9 @@ native rg_fire_bullets(const inflictor, const attacker, const shots, Float:vecSr * @param iTracerFreq Tracer frequency * @param iDamage Damage amount * +* @note: This native doesn't create a decal effect +* @note: Decal creation is handled by PlaybackEvent, including shot animation and shot sound +* * @noreturn */ native rg_fire_buckshots(const inflictor, const attacker, const shots, Float:vecSrc[3], Float:vecDirShooting[3], Float:vecSpread[3], const Float:flDistance, const iTracerFreq, const iDamage); @@ -375,6 +381,9 @@ native rg_fire_buckshots(const inflictor, const attacker, const shots, Float:vec * @param bPistol Pistol shot * @param shared_rand Use player's random seed, get circular gaussian spread * +* @note: This native doesn't create a decal effect +* @note: Decal creation is handled by PlaybackEvent, including shot animation and shot sound +* * @return Float:[3] The spread result */ native Float:[3] rg_fire_bullets3(const inflictor, const attacker, Float:vecSrc[3], Float:vecDirShooting[3], const Float:vecSpread, const Float:flDistance, const iPenetration, const Bullet:iBulletType, const iDamage, const Float:flRangeModifier, const bool:bPistol, const shared_rand); From ac3d641406777fc0c6ee63b8da56e584d50873fc Mon Sep 17 00:00:00 2001 From: Giferns <47265743+Giferns@users.noreply.github.com> Date: Fri, 31 Mar 2023 20:43:57 +0300 Subject: [PATCH 11/50] `rg_give_defusekit()`: Add player team check (#234) Add player team check to avoid unexpected behavior --- reapi/src/natives/natives_misc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index a4f6065d..3c2cebd8 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -1259,6 +1259,10 @@ cell AMX_NATIVE_CALL rg_give_defusekit(AMX *amx, cell *params) if (CSGameRules() != nullptr && !CSGameRules()->m_bMapHasBombTarget && !CSGameRules()->m_bMapHasBombZone) { return FALSE; } + + if (pPlayer->m_iTeam != CT) { + return FALSE; + } pPlayer->m_bHasDefuser = params[arg_def] ? true : false; pPlayer->pev->body = params[arg_def] ? 1 : 0; From 7be36cc3071ab5f88c743a59b623fc8affc76b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Federico=20Mat=C3=ADas?= <41979395+FEDERICOMB96@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:44:20 -0300 Subject: [PATCH 12/50] Implement `rh_get_client_connect_time()` native (#259) * Implement `rh_get_client_connect_time()` native --- .../scripting/include/reapi_engine.inc | 9 +++++++ reapi/src/natives/natives_misc.cpp | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index e5a2ac8d..a98f50b4 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -159,3 +159,12 @@ native rh_drop_client(const index, const message[] = ""); * */ native rh_get_net_from(output[], len); + +/* +* Returns client's netchan playing time in seconds. +* +* @param index Client index +* +* @return Netchan connection time in seconds or 0 if client index is invalid or client is not connected +*/ +native rh_get_client_connect_time(const index); diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 3c2cebd8..24b19f04 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -2751,6 +2751,31 @@ cell AMX_NATIVE_CALL rh_get_net_from(AMX* amx, cell* params) return TRUE; } +/* +* Returns client's netchan playing time in seconds. +* +* @param index Client index +* +* @return Netchan connection time in seconds or 0 if client index is invalid or client is not connected +* +* native rh_get_client_connect_time(const index); +*/ +cell AMX_NATIVE_CALL rh_get_client_connect_time(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index); + + client_t *pClient = clientOfIndex(params[arg_index]); + if (unlikely(pClient == nullptr || !(pClient->active | pClient->spawned | pClient->connected))) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[arg_index]); + return FALSE; + } + + return (cell)(g_RehldsFuncs->GetRealTime() - pClient->netchan.connect_time); +} + AMX_NATIVE_INFO Misc_Natives_RH[] = { { "rh_set_mapname", rh_set_mapname }, @@ -2761,6 +2786,8 @@ AMX_NATIVE_INFO Misc_Natives_RH[] = { "rh_drop_client", rh_drop_client }, { "rh_get_net_from", rh_get_net_from }, + { "rh_get_client_connect_time", rh_get_client_connect_time }, + { nullptr, nullptr } }; From 60f32302ee7dff1c508533499ed6fdfd2a681ed5 Mon Sep 17 00:00:00 2001 From: RauliTop Date: Fri, 31 Mar 2023 19:48:51 +0200 Subject: [PATCH 13/50] Fix ``TimeBasedDamage enum`` typo at cssdk_const.inc (#256) * Fix typo at cssdk_const.inc ITDB_PARALYZE enum --- reapi/extra/amxmodx/scripting/include/cssdk_const.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 99070c04..65ced5b3 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -898,10 +898,11 @@ enum WeaponIdType /** * For CBaseMonster::m_rgbTimeBasedDamage +* prefix should be ITBD_ */ enum TimeBasedDamage { - ITDB_PRALYZE, + ITDB_PARALYZE, ITDB_NERVEGAS, ITDB_POISON, ITDB_RADIATION, From 5c5478c879f7b18d2885d4b46a687b6b93171bc8 Mon Sep 17 00:00:00 2001 From: Sergey Shorokhov Date: Sat, 1 Jul 2023 13:49:45 +0300 Subject: [PATCH 14/50] SetHookChainArg: handle `default` case. fix #276 --- reapi/src/natives/natives_hookchains.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reapi/src/natives/natives_hookchains.cpp b/reapi/src/natives/natives_hookchains.cpp index e0a1d9c9..95ef2a24 100644 --- a/reapi/src/natives/natives_hookchains.cpp +++ b/reapi/src/natives/natives_hookchains.cpp @@ -322,6 +322,8 @@ cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) case ATYPE_EVARS: *(entvars_t **)destAddr = PEV(*srcAddr); break; + default: + return FALSE; } return TRUE; From 8c670fa40febdc22b1ad0c94b139b8a378845a8c Mon Sep 17 00:00:00 2001 From: s1lentq Date: Tue, 4 Jul 2023 01:48:13 +0700 Subject: [PATCH 15/50] GetBonePosition/GetAttachment: Added index bounds check --- reapi/src/natives/natives_common.cpp | 6 ++--- reapi/src/reapi_utils.cpp | 34 +++++++++++++++++++++------- reapi/src/reapi_utils.h | 4 ++-- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index 6315653c..8b2b8508 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -236,7 +236,7 @@ cell AMX_NATIVE_CALL amx_GetBonePosition(AMX *amx, cell *params) */ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_bone, arg_attachment, arg_angles }; + enum args_e { arg_count, arg_index, arg_attachment, arg_origin, arg_angles }; CHECK_ISENTITY(arg_index); @@ -251,9 +251,9 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params) return FALSE; } - Vector *pVecOrigin = (Vector *)getAmxAddr(amx, params[arg_attachment]); + Vector *pVecOrigin = (Vector *)getAmxAddr(amx, params[arg_origin]); Vector *pVecAngles = (PARAMS_COUNT == 4) ? (Vector *)getAmxAddr(amx, params[arg_angles]) : nullptr; - GetAttachment(pEntity, params[arg_bone], pVecOrigin, pVecAngles); + GetAttachment(pEntity, params[arg_attachment], pVecOrigin, pVecAngles); return TRUE; } diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 2d30416e..47394aa6 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -97,7 +97,7 @@ CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *p return pEntity; } -void StudioFrameAdvanceEnt(edict_t *pEdict) +void StudioFrameAdvanceEnt(studiohdr_t *pstudiohdr, edict_t *pEdict) { float flInterval = gpGlobals->time - pEdict->v.animtime; if (flInterval <= 0.001f) { @@ -109,10 +109,8 @@ void StudioFrameAdvanceEnt(edict_t *pEdict) flInterval = 0.0f; } - studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEdict)); - if (!pstudiohdr) { + if (!pstudiohdr) return; - } if (pEdict->v.sequence >= pstudiohdr->numseq || pEdict->v.sequence < 0) { return; @@ -160,8 +158,18 @@ void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector Vector vecOrigin, vecAngles; edict_t *pEdict = pEntity->edict(); + if (pVecOrigin) *pVecOrigin = Vector(0, 0, 0); + if (pVecAngles) *pVecAngles = Vector(0, 0, 0); + + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEdict)); + if (!pstudiohdr) + return; + + if (iBone < 0 || iBone >= pstudiohdr->numbones) + return; // invalid bone + // force to update frame - StudioFrameAdvanceEnt(pEdict); + StudioFrameAdvanceEnt(pstudiohdr, pEdict); pEntity->pev->angles.x = -pEntity->pev->angles.x; GET_BONE_POSITION(pEdict, iBone, vecOrigin, vecAngles); @@ -180,15 +188,25 @@ void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector } } -void GetAttachment(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles) +void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Vector *pVecAngles) { Vector vecOrigin, vecAngles; edict_t *pEdict = pEntity->edict(); + if (pVecOrigin) *pVecOrigin = Vector(0, 0, 0); + if (pVecAngles) *pVecAngles = Vector(0, 0, 0); + + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEdict)); + if (!pstudiohdr) + return; + + if (iAttachment < 0 || iAttachment >= pstudiohdr->numattachments) + return; // invalid attachment + // force to update frame - StudioFrameAdvanceEnt(pEdict); + StudioFrameAdvanceEnt(pstudiohdr, pEdict); - GET_ATTACHMENT(pEdict, iBone, vecOrigin, vecAngles); + GET_ATTACHMENT(pEdict, iAttachment, vecOrigin, vecAngles); if (!pEntity->IsPlayer()) { FixupAngles(pEdict, vecOrigin); diff --git a/reapi/src/reapi_utils.h b/reapi/src/reapi_utils.h index 994864c3..7f261457 100644 --- a/reapi/src/reapi_utils.h +++ b/reapi/src/reapi_utils.h @@ -53,8 +53,8 @@ ModelName GetModelAuto(TeamName team); void UTIL_ServerPrint(const char *fmt, ...); CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *pszItemName, const size_t uid = 0); -void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *vecOrigin, Vector *vecAngles); -void GetAttachment(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles); +void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles); +void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Vector *pVecAngles); void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType type); const char *getATypeStr(AType type); From 7c959fa9bd74b7631c5a6375ba6e531df0cfdb1f Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 15 Jul 2023 03:39:05 +0700 Subject: [PATCH 16/50] Implemented ATYPE_TRACE for SetHookChainArg native useful for replacement data on tracehandle argument --- reapi/extra/amxmodx/scripting/include/reapi.inc | 3 ++- reapi/src/hook_callback.h | 4 +++- reapi/src/natives/natives_hookchains.cpp | 3 +++ reapi/src/reapi_utils.cpp | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi.inc b/reapi/extra/amxmodx/scripting/include/reapi.inc index 45338253..aac39c33 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi.inc @@ -130,7 +130,8 @@ enum AType ATYPE_EDICT, ATYPE_EVARS, ATYPE_BOOL, - ATYPE_VECTOR + ATYPE_VECTOR, + ATYPE_TRACE }; enum HookChain diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 6340010d..0816bf58 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -21,7 +21,8 @@ enum AType : uint8 ATYPE_EDICT, ATYPE_EVARS, ATYPE_BOOL, - ATYPE_VECTOR + ATYPE_VECTOR, + ATYPE_TRACE }; struct retval_t @@ -53,6 +54,7 @@ inline AType getApiType(entvars_t *) { return ATYPE_EVARS; } inline AType getApiType(bool) { return ATYPE_BOOL; } inline AType getApiType(Vector) { return ATYPE_VECTOR; } inline AType getApiType(ENTITYINIT) { return ATYPE_INTEGER; } +inline AType getApiType(TraceResult*) { return ATYPE_TRACE; } template inline AType getApiType(T *) { return ATYPE_INTEGER; } diff --git a/reapi/src/natives/natives_hookchains.cpp b/reapi/src/natives/natives_hookchains.cpp index 95ef2a24..87c8c0f0 100644 --- a/reapi/src/natives/natives_hookchains.cpp +++ b/reapi/src/natives/natives_hookchains.cpp @@ -322,6 +322,9 @@ cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) case ATYPE_EVARS: *(entvars_t **)destAddr = PEV(*srcAddr); break; + case ATYPE_TRACE: + **(TraceResult **)destAddr = *(TraceResult *)(*srcAddr); + break; default: return FALSE; } diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 47394aa6..5fc7f6e6 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -250,7 +250,8 @@ const char *getATypeStr(AType type) "ATYPE_EDICT", "ATYPE_EVARS", "ATYPE_BOOL", - "ATYPE_VECTOR" + "ATYPE_VECTOR", + "ATYPE_TRACE" }; if (type >= arraysize(s_ATypes)) From 1b4ee4e11270d05eab7e5d09940c53e13ae7d85d Mon Sep 17 00:00:00 2001 From: Hamdi Date: Sat, 15 Jul 2023 20:29:33 +0100 Subject: [PATCH 17/50] Add new trace flags to cssdk_const.inc (#278) --- reapi/extra/amxmodx/scripting/include/cssdk_const.inc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 65ced5b3..8aa09a01 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -71,6 +71,14 @@ #define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time #define FL_DORMANT (1<<31) // Entity is dormant, no updates to client +/** +* global_get(glb_trace_flags) values +* @note Custom flags that we can retrieve in pfnShouldCollide/TraceLine/TraceHull +*/ +#define FTRACE_BULLET (1<<16) +#define FTRACE_FLASH (1<<17) +#define FTRACE_KNIFE (1<<18) + /** * get_entvar(entity, var_movetype) values */ From e4783140ffac93e86ab8690296f898411e017631 Mon Sep 17 00:00:00 2001 From: RauliTop Date: Sat, 15 Jul 2023 21:29:54 +0200 Subject: [PATCH 18/50] Add m_flEjectBrass description (#274) --- reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 5265f7ed..38270e55 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -2278,7 +2278,7 @@ enum CBasePlayer_Members m_bResumeZoom, /* - * Description: - + * Description: Delay to call EjectBrass function on M3, Scout and AWP (rest of weapons are client-side). * Member type: float * Get params: Float:get_member(index, member); * Set params: set_member(index, member, Float:value); From 3cbdc162a5469efac66584de99ce06eaa715c698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sat, 15 Jul 2023 15:30:59 -0400 Subject: [PATCH 19/50] Implement RG_CreateWeaponBox hook (#275) Interface was coded but never implemented. It needs tests --- .../scripting/include/reapi_gamedll_const.inc | 7 +++++++ reapi/src/hook_callback.cpp | 12 ++++++++++++ reapi/src/hook_callback.h | 1 + reapi/src/hook_list.cpp | 1 + reapi/src/hook_list.h | 2 ++ 5 files changed, 23 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 38270e55..abc4bc9f 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -400,6 +400,13 @@ enum GamedllFunc * Params: (pevVictim, cGibs, human) */ RG_SpawnRandomGibs, + + /* + * Description: Called when a player drops a weapon (usually manual drop or death) + * Return type: CWeaponBox * (Entity index of weaponbox) + * Params: (const weaponent, const owner, modelName[], Float:origin[3], Float:angles[3], Float:velocity[3], Float:lifeTime, bool:packAmmo) + */ + RG_CreateWeaponBox, }; /** diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 46f662c5..4cca12d0 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -1329,6 +1329,18 @@ bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, V return callForward(RG_IsPenetrableEntity, original, getAmxVector(vecSrcCopy), getAmxVector(vecEndCopy), indexOfEdict(pevAttacker), indexOfEdict(pHit)); } +CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo) +{ + Vector vecOriginCopy(origin), vecAnglesCopy(angles), vecVelocityCopy(velocity); + + auto original = [chain, &vecOriginCopy, &vecAnglesCopy, &vecVelocityCopy](int _pItem, int _pPlayerOwner, const char *_modelName, cell _origin, cell _angles, cell _velocity, float _lifeTime, bool _packAmmo) + { + return indexOfPDataAmx(chain->callNext(getPrivate(_pItem), getPrivate(_pPlayerOwner), _modelName, vecOriginCopy, vecAnglesCopy, vecVelocityCopy, _lifeTime, _packAmmo)); + }; + + return getPrivate(callForward(RG_CreateWeaponBox, original, indexOfEdictAmx(pItem->pev), indexOfEdictAmx(pPlayerOwner->pev), modelName, getAmxVector(vecOriginCopy), getAmxVector(vecAnglesCopy), getAmxVector(vecVelocityCopy), lifeTime, packAmmo)); +} + CGib *SpawnHeadGib(IReGameHook_SpawnHeadGib *chain, entvars_t *pevVictim) { auto original = [chain](int _pevVictim) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 0816bf58..0dc0df1a 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -413,6 +413,7 @@ CGrenade *ThrowFlashbang(IReGameHook_ThrowFlashbang *chain, entvars_t *pevOwner, CGrenade *ThrowSmokeGrenade(IReGameHook_ThrowSmokeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, unsigned short usEvent); CGrenade *PlantBomb(IReGameHook_PlantBomb *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity); bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, Vector &vecEnd, entvars_t *pevAttacker, edict_t *pHit); +CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo); CGib *SpawnHeadGib(IReGameHook_SpawnHeadGib *chain, entvars_t *pevVictim); void SpawnRandomGibs(IReGameHook_SpawnRandomGibs *chain, entvars_t *pevVictim, int cGibs, int human); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 5699ecf6..312ef37f 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -130,6 +130,7 @@ hook_t hooklist_gamedll[] = { DLL(IsPenetrableEntity), DLL(SpawnHeadGib), DLL(SpawnRandomGibs), + DLL(CreateWeaponBox), }; hook_t hooklist_animating[] = { diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 91125824..14b45b26 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -144,6 +144,8 @@ enum GamedllFunc RG_SpawnHeadGib, RG_SpawnRandomGibs, + RG_CreateWeaponBox, + // [...] }; From d9b72bf3a369c614234cc0dc9611748d22ce3c1a Mon Sep 17 00:00:00 2001 From: Adrian Cirstea <54354938+ShadowsAdi@users.noreply.github.com> Date: Sat, 15 Jul 2023 22:40:32 +0300 Subject: [PATCH 20/50] `API`: Implement `RG_PM_LadderMove` hook (#254) --- .../scripting/include/reapi_gamedll_const.inc | 6 ++++++ reapi/include/cssdk/dlls/regamedll_api.h | 6 ++++++ reapi/src/hook_callback.cpp | 17 +++++++++++++++++ reapi/src/hook_callback.h | 12 ++++++++++++ reapi/src/hook_list.cpp | 1 + reapi/src/hook_list.h | 1 + 6 files changed, 43 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index abc4bc9f..58d254c4 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -407,6 +407,12 @@ enum GamedllFunc * Params: (const weaponent, const owner, modelName[], Float:origin[3], Float:angles[3], Float:velocity[3], Float:lifeTime, bool:packAmmo) */ RG_CreateWeaponBox, + + /* + * Description: Called when a player is on a ladder. + * Params: (const playerIndex) + */ + RG_PM_LadderMove, }; /** diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index 53a6d661..7a9f2386 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -237,6 +237,10 @@ typedef IHookChainRegistry IReGameHookRegistry typedef IHookChain IReGameHook_PM_AirMove; typedef IHookChainRegistry IReGameHookRegistry_PM_AirMove; +// PM_LadderMove hook +typedef IHookChain IReGameHook_PM_LadderMove; +typedef IHookChainRegistry IReGameHookRegistry_PM_LadderMove; + // HandleMenu_ChooseAppearance hook typedef IHookChain IReGameHook_HandleMenu_ChooseAppearance; typedef IHookChainRegistry IReGameHookRegistry_HandleMenu_ChooseAppearance; @@ -654,6 +658,8 @@ class IReGameHookchains { virtual IReGameHookRegistry_CBasePlayer_Pain *CBasePlayer_Pain() = 0; virtual IReGameHookRegistry_CBasePlayer_DeathSound *CBasePlayer_DeathSound() = 0; virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink() = 0; + + virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove() = 0; }; struct ReGameFuncs_t { diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 4cca12d0..6a35ca82 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -899,6 +899,23 @@ void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex) callVoidForward(RG_PM_AirMove, original, playerIndex); } +void PM_LadderMove_AMXX(Phys_T *data, int playerIndex) +{ + auto original = [data](int _playerIndex) + { + data->m_chain->callNext(data->m_args.pLadder); + }; + + callVoidForward(RG_PM_LadderMove, original, playerIndex); +} + +void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder) +{ + PM_LadderMove_args_t args(pLadder); + Phys_T data(chain, args); + PM_LadderMove_AMXX(&data, pLadder->player + 1); +} + BOOL CSGameRules_FShouldSwitchWeapon(IReGameHook_CSGameRules_FShouldSwitchWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) { auto original = [chain](int _pPlayer, int _pWeapon) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 0dc0df1a..6bff756f 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -402,6 +402,18 @@ void PM_Move_AMXX(Move_t *data, int playerIndex); void PM_Move(IReGameHook_PM_Move *chain, playermove_t *ppmove, int server); void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex); + +struct PM_LadderMove_args_t +{ + PM_LadderMove_args_t(physent_t *_ladder) : pLadder(_ladder) {} + + physent_t *pLadder; +}; + +using Phys_T = hookdata_t; +void PM_LadderMove_AMXX(Phys_T *data); +void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder); + void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot); BOOL HandleMenu_ChooseTeam(IReGameHook_HandleMenu_ChooseTeam *chain, CBasePlayer *pPlayer, int slot); void ShowMenu(IReGameHook_ShowMenu *chain, CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 312ef37f..bd44eba8 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -131,6 +131,7 @@ hook_t hooklist_gamedll[] = { DLL(SpawnHeadGib), DLL(SpawnRandomGibs), DLL(CreateWeaponBox), + DLL(PM_LadderMove), }; hook_t hooklist_animating[] = { diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 14b45b26..352472cf 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -145,6 +145,7 @@ enum GamedllFunc RG_SpawnRandomGibs, RG_CreateWeaponBox, + RG_PM_LadderMove, // [...] }; From 87e4858476f3128ad378051a09e0e615936e5cc8 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 16 Jul 2023 03:57:03 +0700 Subject: [PATCH 21/50] Update SDK Reworked PM_AirMove hook, add physent argument --- .../scripting/include/reapi_gamedll_const.inc | 6 +++--- reapi/include/cssdk/dlls/regamedll_api.h | 12 ++++++++++-- reapi/src/hook_callback.cpp | 12 +++++------- reapi/src/hook_callback.h | 11 +---------- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 58d254c4..1b0b963a 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -410,7 +410,7 @@ enum GamedllFunc /* * Description: Called when a player is on a ladder. - * Params: (const playerIndex) + * Params: (const pLadder, const playerIndex) */ RG_PM_LadderMove, }; @@ -819,14 +819,14 @@ enum GamedllFunc_CBasePlayer * Params: (const this) */ RG_CBasePlayer_Pain, - + /* * Description: Called when a client emits a "death sound" after death. * Return type: void * Params: (const this, lastHitGroup, bool:hasArmour) */ RG_CBasePlayer_DeathSound, - + /* * Description: Called when a client "thinks for the join status". * (permanently called on each call of "CBasePlayer::PreThink", and only when he is not assigned as specatator or not playing) diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index 7a9f2386..e971ef56 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -39,7 +39,7 @@ #include #define REGAMEDLL_API_VERSION_MAJOR 5 -#define REGAMEDLL_API_VERSION_MINOR 21 +#define REGAMEDLL_API_VERSION_MINOR 22 // CBasePlayer::Spawn hook typedef IHookChainClass IReGameHook_CBasePlayer_Spawn; @@ -525,6 +525,10 @@ typedef IHookChainRegistryClass IReGameHookRegistry_CBa typedef IHookChainClass IReGameHook_CBasePlayer_JoiningThink; typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_JoiningThink; +// FreeGameRules hook +typedef IHookChain IReGameHook_FreeGameRules; +typedef IHookChainRegistry IReGameHookRegistry_FreeGameRules; + class IReGameHookchains { public: virtual ~IReGameHookchains() {} @@ -658,7 +662,8 @@ class IReGameHookchains { virtual IReGameHookRegistry_CBasePlayer_Pain *CBasePlayer_Pain() = 0; virtual IReGameHookRegistry_CBasePlayer_DeathSound *CBasePlayer_DeathSound() = 0; virtual IReGameHookRegistry_CBasePlayer_JoiningThink *CBasePlayer_JoiningThink() = 0; - + + virtual IReGameHookRegistry_FreeGameRules *FreeGameRules() = 0; virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove() = 0; }; @@ -677,6 +682,9 @@ struct ReGameFuncs_t { class CGrenade *(*PlantBomb)(entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity); class CGib *(*SpawnHeadGib)(entvars_t *pevVictim); void (*SpawnRandomGibs)(entvars_t *pevVictim, int cGibs, int human); + void (*UTIL_RestartOther)(const char *szClassname); + void (*UTIL_ResetEntities)(); + void (*UTIL_RemoveOther)(const char *szClassname, int nCount); }; class IReGameApi { diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 6a35ca82..35066aed 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -899,21 +899,19 @@ void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex) callVoidForward(RG_PM_AirMove, original, playerIndex); } -void PM_LadderMove_AMXX(Phys_T *data, int playerIndex) +void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex) { - auto original = [data](int _playerIndex) + auto original = [chain](physent_t *_pLadder, int _playerIndex) { - data->m_chain->callNext(data->m_args.pLadder); + chain->callNext(_pLadder); }; - callVoidForward(RG_PM_LadderMove, original, playerIndex); + callVoidForward(RG_PM_LadderMove, original, pLadder, playerIndex); } void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder) { - PM_LadderMove_args_t args(pLadder); - Phys_T data(chain, args); - PM_LadderMove_AMXX(&data, pLadder->player + 1); + PM_LadderMove_AMXX(chain, pLadder, pLadder->player + 1); } BOOL CSGameRules_FShouldSwitchWeapon(IReGameHook_CSGameRules_FShouldSwitchWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 6bff756f..ee8fd3d9 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -402,16 +402,7 @@ void PM_Move_AMXX(Move_t *data, int playerIndex); void PM_Move(IReGameHook_PM_Move *chain, playermove_t *ppmove, int server); void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex); - -struct PM_LadderMove_args_t -{ - PM_LadderMove_args_t(physent_t *_ladder) : pLadder(_ladder) {} - - physent_t *pLadder; -}; - -using Phys_T = hookdata_t; -void PM_LadderMove_AMXX(Phys_T *data); +void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex); void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder); void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot); From 4155dd42b2a8c694279c7a2332f3d1106830de6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sat, 15 Jul 2023 17:42:14 -0400 Subject: [PATCH 22/50] `API`: CSPlayer and CKnife additions + headers refactory (#277) * Reordered hook_callback.cpp/h declarations based on regamedll_api.h order * Update CKnife members and include descriptions * Update CSPlayer members and include descriptions --- .../scripting/include/reapi_gamedll_const.inc | 34 +- reapi/include/cssdk/dlls/API/CSPlayer.h | 11 +- reapi/include/cssdk/dlls/weapons.h | 1 + reapi/src/hook_callback.cpp | 459 +++++++++--------- reapi/src/hook_callback.h | 131 ++--- reapi/src/member_list.cpp | 3 + reapi/src/member_list.h | 3 + 7 files changed, 346 insertions(+), 296 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 1b0b963a..df3ebb7e 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -4656,6 +4656,22 @@ enum CCSPlayer_Members * Set params: set_member(index, member, bool:value); */ m_bMegaBunnyJumping, + + /* + * Description: - + * Member type: bool + * Get params: get_member(index, member); + * Set params: set_member(index, member, bool:value); + */ + m_bPlantC4Anywhere, + + /* + * Description: - + * Member type: bool + * Get params: get_member(index, member); + * Set params: set_member(index, member, bool:value); + */ + m_bSpawnProtectionEffects, }; /** @@ -5950,7 +5966,7 @@ enum CKnife_Members m_Knife_usKnife, /* - * Description: - + * Description: Stab damage (default: 65.0) * Member type: float * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -5958,7 +5974,7 @@ enum CKnife_Members m_Knife_flStabBaseDamage, /* - * Description: - + * Description: Swing damage (default: 15.0) * Member type: float * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -5966,7 +5982,7 @@ enum CKnife_Members m_Knife_flSwingBaseDamage, /* - * Description: - + * Description: Fast Swing (first one) damage (default: 20.0) * Member type: float * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -5974,7 +5990,7 @@ enum CKnife_Members m_Knife_flSwingBaseDamage_Fast, /* - * Description: - + * Description: Stab distance (default: 32.0) * Member type: float * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -5982,12 +5998,20 @@ enum CKnife_Members m_Knife_flStabDistance, /* - * Description: - + * Description: Swing distance (default: 64.0) * Member type: float * Get params: get_member(index, member); * Set params: set_member(index, member, value); */ m_Knife_flSwingDistance, + + /* + * Description: Back Stab damage multiplier (default: 3.0) + * Member type: float + * Get params: get_member(index, member); + * Set params: set_member(index, member, value); + */ + m_Knife_flBackStabMultiplier, }; /** diff --git a/reapi/include/cssdk/dlls/API/CSPlayer.h b/reapi/include/cssdk/dlls/API/CSPlayer.h index 99273c97..3f63d5c3 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayer.h +++ b/reapi/include/cssdk/dlls/API/CSPlayer.h @@ -50,7 +50,9 @@ class CCSPlayer: public CCSMonster m_bCanShootOverride(false), m_bGameForcingRespawn(false), m_bAutoBunnyHopping(false), - m_bMegaBunnyJumping(false) + m_bMegaBunnyJumping(false), + m_bPlantC4Anywhere(false), + m_bSpawnProtectionEffects(false) { m_szModel[0] = '\0'; } @@ -100,8 +102,11 @@ class CCSPlayer: public CCSMonster virtual void SetSpawnProtection(float flProtectionTime) = 0; virtual void RemoveSpawnProtection() = 0; virtual bool HintMessageEx(const char *pMessage, float duration = 6.0f, bool bDisplayIfPlayerDead = false, bool bOverride = false) = 0; + virtual void Reset() = 0; + virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true) = 0; + virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr) = 0; - void Reset(); + void ResetVars(); void OnSpawn(); void OnKilled(); @@ -131,6 +136,8 @@ class CCSPlayer: public CCSMonster bool m_bGameForcingRespawn; bool m_bAutoBunnyHopping; bool m_bMegaBunnyJumping; + bool m_bPlantC4Anywhere; + bool m_bSpawnProtectionEffects; }; // Inlines diff --git a/reapi/include/cssdk/dlls/weapons.h b/reapi/include/cssdk/dlls/weapons.h index 609ea915..14f6df48 100644 --- a/reapi/include/cssdk/dlls/weapons.h +++ b/reapi/include/cssdk/dlls/weapons.h @@ -623,6 +623,7 @@ class CKnife: public CBasePlayerWeapon float m_flSwingBaseDamage_Fast; float m_flStabDistance; float m_flSwingDistance; + float m_flBackStabMultiplier; }; class CM249: public CBasePlayerWeapon diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 35066aed..bd43ff7b 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -472,16 +472,6 @@ CBasePlayer *CBasePlayer_Observer_IsValidTarget(IReGameHook_CBasePlayer_Observer return getPrivate(callForward(RG_CBasePlayer_Observer_IsValidTarget, original, indexOfEdict(pthis->pev), iPlayerIndex, bSameTeam)); } -void CBasePlayer_Observer_FindNextPlayer(IReGameHook_CBasePlayer_Observer_FindNextPlayer *chain, CBasePlayer *pthis, bool bReverse, const char *name) -{ - auto original = [chain](int _pthis, bool _bReverse, const char *_name) - { - chain->callNext(getPrivate(_pthis), _bReverse, _name); - }; - - callVoidForward(RG_CBasePlayer_Observer_FindNextPlayer, original, indexOfEdict(pthis->pev), bReverse, name); -} - void CBasePlayer_SetAnimation(IReGameHook_CBasePlayer_SetAnimation *chain, CBasePlayer *pthis, PLAYER_ANIM playerAnim) { auto original = [chain](int _pthis, PLAYER_ANIM _playerAnim) @@ -654,128 +644,6 @@ bool CBasePlayer_GetIntoGame(IReGameHook_CBasePlayer_GetIntoGame *chain, CBasePl return callForward(RG_CBasePlayer_GetIntoGame, original, indexOfEdict(pthis->pev)); } -void CBasePlayer_StartDeathCam(IReGameHook_CBasePlayer_StartDeathCam *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_StartDeathCam, original, indexOfEdict(pthis->pev)); -} - -void CBasePlayer_SwitchTeam(IReGameHook_CBasePlayer_SwitchTeam *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_SwitchTeam, original, indexOfEdict(pthis->pev)); -} - -bool CBasePlayer_CanSwitchTeam(IReGameHook_CBasePlayer_CanSwitchTeam *chain, CBasePlayer *pthis, TeamName teamToSwap) -{ - auto original = [chain](int _pthis, TeamName _teamToSwap) - { - return chain->callNext(getPrivate(_pthis), _teamToSwap); - }; - - return callForward(RG_CBasePlayer_CanSwitchTeam, original, indexOfEdict(pthis->pev), teamToSwap); -} - -CGrenade *CBasePlayer_ThrowGrenade(IReGameHook_CBasePlayer_ThrowGrenade *chain, CBasePlayer *pthis, CBasePlayerWeapon *pWeapon, Vector &vecSrc, Vector &vecThrow, float time, unsigned short usEvent) -{ - Vector vecSrcCopy(vecSrc), vecThrowCopy(vecThrow); - - auto original = [chain, &vecSrcCopy, &vecThrowCopy](int _pthis, int _pWeapon, cell _vecSrc, cell _vecThrow, float _time, unsigned short _usEvent) - { - return indexOfPDataAmx(chain->callNext(getPrivate(_pthis), getPrivate(_pWeapon), vecSrcCopy, vecThrowCopy, _time, _usEvent)); - }; - - return getPrivate(callForward(RG_CBasePlayer_ThrowGrenade, original, indexOfEdict(pthis->pev), indexOfEdict(pWeapon->pev), getAmxVector(vecSrcCopy), getAmxVector(vecThrowCopy), time, usEvent)); -} - -void CBasePlayer_SetSpawnProtection(IReGameHook_CBasePlayer_SetSpawnProtection *chain, CBasePlayer *pthis, float flProtectionTime) -{ - auto original = [chain](int _pthis, float _flProtectionTime) - { - return chain->callNext(getPrivate(_pthis), _flProtectionTime); - }; - - callVoidForward(RG_CBasePlayer_SetSpawnProtection, original, indexOfEdict(pthis->pev), flProtectionTime); -} - -void CBasePlayer_RemoveSpawnProtection(IReGameHook_CBasePlayer_RemoveSpawnProtection *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_RemoveSpawnProtection, original, indexOfEdict(pthis->pev)); -} - -bool CBasePlayer_HintMessageEx(IReGameHook_CBasePlayer_HintMessageEx *chain, CBasePlayer *pthis, const char *pMessage, float duration, bool bDisplayIfPlayerDead, bool bOverride) -{ - auto original = [chain](int _pthis, const char *_pMessage, float _duration, bool _bDisplayIfPlayerDead, bool _bOverride) - { - return chain->callNext(getPrivate(_pthis), _pMessage, _duration, _bDisplayIfPlayerDead, _bOverride); - }; - - return callForward(RG_CBasePlayer_HintMessageEx, original, indexOfEdict(pthis->pev), pMessage, duration, bDisplayIfPlayerDead, bOverride); -} - -void CBasePlayer_UseEmpty(IReGameHook_CBasePlayer_UseEmpty *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_UseEmpty, original, indexOfEdict(pthis->pev)); -} - -void CBasePlayer_DropIdlePlayer(IReGameHook_CBasePlayer_DropIdlePlayer *chain, CBasePlayer *pthis, const char *reason) -{ - auto original = [chain](int _pthis, const char *_reason) - { - return chain->callNext(getPrivate(_pthis), _reason); - }; - - callVoidForward(RG_CBasePlayer_DropIdlePlayer, original, indexOfEdict(pthis->pev), reason); -} - -void CBasePlayer_Pain(IReGameHook_CBasePlayer_Pain *chain, CBasePlayer *pthis, int iLastHitGroup, bool bHasArmour) -{ - auto original = [chain](int _pthis, int _iLastHitGroup, bool _bHasArmour) - { - return chain->callNext(getPrivate(_pthis), _iLastHitGroup, _bHasArmour); - }; - - callVoidForward(RG_CBasePlayer_Pain, original, indexOfEdict(pthis->pev), iLastHitGroup, bHasArmour); -} - -void CBasePlayer_DeathSound(IReGameHook_CBasePlayer_DeathSound *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_DeathSound, original, indexOfEdict(pthis->pev)); -} - -void CBasePlayer_JoiningThink(IReGameHook_CBasePlayer_JoiningThink *chain, CBasePlayer *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - callVoidForward(RG_CBasePlayer_JoiningThink, original, indexOfEdict(pthis->pev)); -} - void CBaseAnimating_ResetSequenceInfo(IReGameHook_CBaseAnimating_ResetSequenceInfo *chain, CBaseAnimating *pthis) { auto original = [chain](int _pthis) @@ -786,46 +654,6 @@ void CBaseAnimating_ResetSequenceInfo(IReGameHook_CBaseAnimating_ResetSequenceIn callVoidForward(RG_CBaseAnimating_ResetSequenceInfo, original, indexOfEdict(pthis->pev)); } -BOOL CBasePlayerWeapon_CanDeploy(IReGameHook_CBasePlayerWeapon_CanDeploy *chain, CBasePlayerWeapon *pthis) -{ - auto original = [chain](int _pthis) - { - return chain->callNext(getPrivate(_pthis)); - }; - - return callForward(RG_CBasePlayerWeapon_CanDeploy, original, indexOfEdict(pthis->pev)); -} - -BOOL CBasePlayerWeapon_DefaultDeploy(IReGameHook_CBasePlayerWeapon_DefaultDeploy *chain, CBasePlayerWeapon *pthis, char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal) -{ - auto original = [chain](int _pthis, char *_szViewModel, char *_szWeaponModel, int _iAnim, char *_szAnimExt, int _skiplocal) - { - return chain->callNext(getPrivate(_pthis), _szViewModel, _szWeaponModel, _iAnim, _szAnimExt, _skiplocal); - }; - - return callForward(RG_CBasePlayerWeapon_DefaultDeploy, original, indexOfEdict(pthis->pev), szViewModel, szWeaponModel, iAnim, szAnimExt, skiplocal); -} - -int CBasePlayerWeapon_DefaultReload(IReGameHook_CBasePlayerWeapon_DefaultReload *chain, CBasePlayerWeapon *pthis, int iClipSize, int iAnim, float fDelay) -{ - auto original = [chain](int _pthis, int _iClipSize, int _iAnim, float _fDelay) - { - return chain->callNext(getPrivate(_pthis), _iClipSize, _iAnim, _fDelay); - }; - - return callForward(RG_CBasePlayerWeapon_DefaultReload, original, indexOfEdict(pthis->pev), iClipSize, iAnim, fDelay); -} - -bool CBasePlayerWeapon_DefaultShotgunReload(IReGameHook_CBasePlayerWeapon_DefaultShotgunReload *chain, CBasePlayerWeapon *pthis, int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2) -{ - auto original = [chain](int _pthis, int _iAnim, int _iStartAnim, float _fDelay, float _fStartDelay, const char *_pszReloadSound1, const char *_pszReloadSound2) - { - return chain->callNext(getPrivate(_pthis), _iAnim, _iStartAnim, _fDelay, _fStartDelay, _pszReloadSound1, _pszReloadSound2); - }; - - return callForward(RG_CBasePlayerWeapon_DefaultShotgunReload, original, indexOfEdict(pthis->pev), iAnim, iStartAnim, fDelay, fStartDelay, pszReloadSound1, pszReloadSound2); -} - int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver) { auto original = [chain](int _pObserver) @@ -899,19 +727,64 @@ void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex) callVoidForward(RG_PM_AirMove, original, playerIndex); } -void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex) +void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot) { - auto original = [chain](physent_t *_pLadder, int _playerIndex) + auto original = [chain](int _pPlayer, int _slot) { - chain->callNext(_pLadder); + chain->callNext(getPrivate(_pPlayer), _slot); }; - callVoidForward(RG_PM_LadderMove, original, pLadder, playerIndex); + callVoidForward(RG_HandleMenu_ChooseAppearance, original, indexOfEdict(pPlayer->pev), slot); } -void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder) +BOOL HandleMenu_ChooseTeam(IReGameHook_HandleMenu_ChooseTeam *chain, CBasePlayer *pPlayer, int slot) { - PM_LadderMove_AMXX(chain, pLadder, pLadder->player + 1); + auto original = [chain](int _pPlayer, int _slot) + { + return chain->callNext(getPrivate(_pPlayer), _slot); + }; + + return callForward(RG_HandleMenu_ChooseTeam, original, indexOfEdict(pPlayer->pev), slot); +} + +void ShowMenu(IReGameHook_ShowMenu *chain, CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText) +{ + auto original = [chain](int _pPlayer, int _bitsValidSlots, int _nDisplayTime, BOOL _fNeedMore, char *_pszText) + { + chain->callNext(getPrivate(_pPlayer), _bitsValidSlots, _nDisplayTime, _fNeedMore, _pszText); + }; + + callVoidForward(RG_ShowMenu, original, indexOfEdict(pPlayer->pev), bitsValidSlots, nDisplayTime, fNeedMore, pszText); +} + +void ShowVGUIMenu(IReGameHook_ShowVGUIMenu *chain, CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu) +{ + auto original = [chain](int _pPlayer, int _MenuType, int _BitMask, char *_szOldMenu) + { + chain->callNext(getPrivate(_pPlayer), _MenuType, _BitMask, _szOldMenu); + }; + + callVoidForward(RG_ShowVGUIMenu, original, indexOfEdict(pPlayer->pev), MenuType, BitMask, szOldMenu); +} + +bool BuyGunAmmo(IReGameHook_BuyGunAmmo *chain, CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney) +{ + auto original = [chain](int _player, int _weapon, bool _bBlinkMoney) + { + return chain->callNext(getPrivate(_player), getPrivate(_weapon), _bBlinkMoney); + }; + + return callForward(RG_BuyGunAmmo, original, indexOfEdict(player->pev), indexOfEdict(weapon->pev), bBlinkMoney); +} + +CBaseEntity *BuyWeaponByWeaponID(IReGameHook_BuyWeaponByWeaponID *chain, CBasePlayer *pPlayer, WeaponIdType weaponID) +{ + auto original = [chain](int _pPlayer, WeaponIdType _weaponID) + { + return indexOfPDataAmx(chain->callNext(getPrivate(_pPlayer), _weaponID)); + }; + + return getPrivate(callForward(RG_BuyWeaponByWeaponID, original, indexOfEdict(pPlayer->pev), weaponID)); } BOOL CSGameRules_FShouldSwitchWeapon(IReGameHook_CSGameRules_FShouldSwitchWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) @@ -1144,6 +1017,48 @@ void CSGameRules_OnRoundFreezeEnd(IReGameHook_CSGameRules_OnRoundFreezeEnd *chai callVoidForward(RG_CSGameRules_OnRoundFreezeEnd, original); } +void CBasePlayer_StartDeathCam(IReGameHook_CBasePlayer_StartDeathCam *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + return chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_StartDeathCam, original, indexOfEdict(pthis->pev)); +} + +void CBasePlayer_SwitchTeam(IReGameHook_CBasePlayer_SwitchTeam *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_SwitchTeam, original, indexOfEdict(pthis->pev)); +} + +bool CBasePlayer_CanSwitchTeam(IReGameHook_CBasePlayer_CanSwitchTeam *chain, CBasePlayer *pthis, TeamName teamToSwap) +{ + auto original = [chain](int _pthis, TeamName _teamToSwap) + { + return chain->callNext(getPrivate(_pthis), _teamToSwap); + }; + + return callForward(RG_CBasePlayer_CanSwitchTeam, original, indexOfEdict(pthis->pev), teamToSwap); +} + +CGrenade *CBasePlayer_ThrowGrenade(IReGameHook_CBasePlayer_ThrowGrenade *chain, CBasePlayer *pthis, CBasePlayerWeapon *pWeapon, Vector &vecSrc, Vector &vecThrow, float time, unsigned short usEvent) +{ + Vector vecSrcCopy(vecSrc), vecThrowCopy(vecThrow); + + auto original = [chain, &vecSrcCopy, &vecThrowCopy](int _pthis, int _pWeapon, cell _vecSrc, cell _vecThrow, float _time, unsigned short _usEvent) + { + return indexOfPDataAmx(chain->callNext(getPrivate(_pthis), getPrivate(_pWeapon), vecSrcCopy, vecThrowCopy, _time, _usEvent)); + }; + + return getPrivate(callForward(RG_CBasePlayer_ThrowGrenade, original, indexOfEdict(pthis->pev), indexOfEdict(pWeapon->pev), getAmxVector(vecSrcCopy), getAmxVector(vecThrowCopy), time, usEvent)); +} + bool CSGameRules_CanPlayerHearPlayer(IReGameHook_CSGameRules_CanPlayerHearPlayer *chain, CBasePlayer *pListener, CBasePlayer *pSender) { auto original = [chain](int _pListener, int _pSender) @@ -1224,124 +1139,154 @@ void CGrenade_ExplodeBomb(IReGameHook_CGrenade_ExplodeBomb *chain, CGrenade *pth callVoidForward(RG_CGrenade_ExplodeBomb, original, indexOfEdict(pthis->pev), ptr, bitsDamageType); } -void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot) +CGrenade *ThrowHeGrenade(IReGameHook_ThrowHeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, int iTeam, unsigned short usEvent) { - auto original = [chain](int _pPlayer, int _slot) + Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + + auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time, int _iTeam, unsigned short _usEvent) { - chain->callNext(getPrivate(_pPlayer), _slot); + return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time, _iTeam, _usEvent)); }; - callVoidForward(RG_HandleMenu_ChooseAppearance, original, indexOfEdict(pPlayer->pev), slot); + return getPrivate(callForward(RG_ThrowHeGrenade, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time, iTeam, usEvent)); } -BOOL HandleMenu_ChooseTeam(IReGameHook_HandleMenu_ChooseTeam *chain, CBasePlayer *pPlayer, int slot) +CGrenade *ThrowFlashbang(IReGameHook_ThrowFlashbang *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time) { - auto original = [chain](int _pPlayer, int _slot) + Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + + auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time) { - return chain->callNext(getPrivate(_pPlayer), _slot); + return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time)); }; - return callForward(RG_HandleMenu_ChooseTeam, original, indexOfEdict(pPlayer->pev), slot); + return getPrivate(callForward(RG_ThrowFlashbang, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time)); } -void ShowMenu(IReGameHook_ShowMenu *chain, CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText) +CGrenade *ThrowSmokeGrenade(IReGameHook_ThrowSmokeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, unsigned short usEvent) { - auto original = [chain](int _pPlayer, int _bitsValidSlots, int _nDisplayTime, BOOL _fNeedMore, char *_pszText) + Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + + auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time, unsigned short _usEvent) { - chain->callNext(getPrivate(_pPlayer), _bitsValidSlots, _nDisplayTime, _fNeedMore, _pszText); + return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time, _usEvent)); }; - callVoidForward(RG_ShowMenu, original, indexOfEdict(pPlayer->pev), bitsValidSlots, nDisplayTime, fNeedMore, pszText); + return getPrivate(callForward(RG_ThrowSmokeGrenade, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time, usEvent)); } -void ShowVGUIMenu(IReGameHook_ShowVGUIMenu *chain, CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu) +CGrenade *PlantBomb(IReGameHook_PlantBomb *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity) { - auto original = [chain](int _pPlayer, int _MenuType, int _BitMask, char *_szOldMenu) + Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + + auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity) { - chain->callNext(getPrivate(_pPlayer), _MenuType, _BitMask, _szOldMenu); + return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy)); }; - callVoidForward(RG_ShowVGUIMenu, original, indexOfEdict(pPlayer->pev), MenuType, BitMask, szOldMenu); + return getPrivate(callForward(RG_PlantBomb, original, indexOfEdictAmx(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy))); } -bool BuyGunAmmo(IReGameHook_BuyGunAmmo *chain, CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney) +void CBasePlayer_RemoveSpawnProtection(IReGameHook_CBasePlayer_RemoveSpawnProtection *chain, CBasePlayer *pthis) { - auto original = [chain](int _player, int _weapon, bool _bBlinkMoney) + auto original = [chain](int _pthis) { - return chain->callNext(getPrivate(_player), getPrivate(_weapon), _bBlinkMoney); + return chain->callNext(getPrivate(_pthis)); }; - return callForward(RG_BuyGunAmmo, original, indexOfEdict(player->pev), indexOfEdict(weapon->pev), bBlinkMoney); + callVoidForward(RG_CBasePlayer_RemoveSpawnProtection, original, indexOfEdict(pthis->pev)); } -CBaseEntity *BuyWeaponByWeaponID(IReGameHook_BuyWeaponByWeaponID *chain, CBasePlayer *pPlayer, WeaponIdType weaponID) +void CBasePlayer_SetSpawnProtection(IReGameHook_CBasePlayer_SetSpawnProtection *chain, CBasePlayer *pthis, float flProtectionTime) { - auto original = [chain](int _pPlayer, WeaponIdType _weaponID) + auto original = [chain](int _pthis, float _flProtectionTime) { - return indexOfPDataAmx(chain->callNext(getPrivate(_pPlayer), _weaponID)); + return chain->callNext(getPrivate(_pthis), _flProtectionTime); }; - return getPrivate(callForward(RG_BuyWeaponByWeaponID, original, indexOfEdict(pPlayer->pev), weaponID)); + callVoidForward(RG_CBasePlayer_SetSpawnProtection, original, indexOfEdict(pthis->pev), flProtectionTime); } -CGrenade *ThrowHeGrenade(IReGameHook_ThrowHeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, int iTeam, unsigned short usEvent) +bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, Vector &vecEnd, entvars_t *pevAttacker, edict_t *pHit) { - Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + Vector vecSrcCopy(vecSrc), vecEndCopy(vecEnd); - auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time, int _iTeam, unsigned short _usEvent) + auto original = [chain, &vecSrcCopy, &vecEndCopy](cell _vecSrc, cell _vecEnd, int _pevAttacker, int _pHit) { - return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time, _iTeam, _usEvent)); + return chain->callNext(vecSrcCopy, vecEndCopy, PEV(_pevAttacker), edictByIndexAmx(_pHit)); }; - return getPrivate(callForward(RG_ThrowHeGrenade, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time, iTeam, usEvent)); + return callForward(RG_IsPenetrableEntity, original, getAmxVector(vecSrcCopy), getAmxVector(vecEndCopy), indexOfEdict(pevAttacker), indexOfEdict(pHit)); } -CGrenade *ThrowFlashbang(IReGameHook_ThrowFlashbang *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time) +bool CBasePlayer_HintMessageEx(IReGameHook_CBasePlayer_HintMessageEx *chain, CBasePlayer *pthis, const char *pMessage, float duration, bool bDisplayIfPlayerDead, bool bOverride) { - Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); - - auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time) + auto original = [chain](int _pthis, const char *_pMessage, float _duration, bool _bDisplayIfPlayerDead, bool _bOverride) { - return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time)); + return chain->callNext(getPrivate(_pthis), _pMessage, _duration, _bDisplayIfPlayerDead, _bOverride); }; - return getPrivate(callForward(RG_ThrowFlashbang, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time)); + return callForward(RG_CBasePlayer_HintMessageEx, original, indexOfEdict(pthis->pev), pMessage, duration, bDisplayIfPlayerDead, bOverride); } -CGrenade *ThrowSmokeGrenade(IReGameHook_ThrowSmokeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, unsigned short usEvent) +void CBasePlayer_UseEmpty(IReGameHook_CBasePlayer_UseEmpty *chain, CBasePlayer *pthis) { - Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + auto original = [chain](int _pthis) + { + return chain->callNext(getPrivate(_pthis)); + }; - auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity, float _time, unsigned short _usEvent) + callVoidForward(RG_CBasePlayer_UseEmpty, original, indexOfEdict(pthis->pev)); +} + +BOOL CBasePlayerWeapon_CanDeploy(IReGameHook_CBasePlayerWeapon_CanDeploy *chain, CBasePlayerWeapon *pthis) +{ + auto original = [chain](int _pthis) { - return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy, _time, _usEvent)); + return chain->callNext(getPrivate(_pthis)); }; - return getPrivate(callForward(RG_ThrowSmokeGrenade, original, indexOfEdict(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy), time, usEvent)); + return callForward(RG_CBasePlayerWeapon_CanDeploy, original, indexOfEdict(pthis->pev)); } -CGrenade *PlantBomb(IReGameHook_PlantBomb *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity) +BOOL CBasePlayerWeapon_DefaultDeploy(IReGameHook_CBasePlayerWeapon_DefaultDeploy *chain, CBasePlayerWeapon *pthis, char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal) { - Vector vecStartCopy(vecStart), vecVelocityCopy(vecVelocity); + auto original = [chain](int _pthis, char *_szViewModel, char *_szWeaponModel, int _iAnim, char *_szAnimExt, int _skiplocal) + { + return chain->callNext(getPrivate(_pthis), _szViewModel, _szWeaponModel, _iAnim, _szAnimExt, _skiplocal); + }; - auto original = [chain, &vecStartCopy, &vecVelocityCopy](int _pevOwner, cell _vecStart, cell _vecVelocity) + return callForward(RG_CBasePlayerWeapon_DefaultDeploy, original, indexOfEdict(pthis->pev), szViewModel, szWeaponModel, iAnim, szAnimExt, skiplocal); +} + +int CBasePlayerWeapon_DefaultReload(IReGameHook_CBasePlayerWeapon_DefaultReload *chain, CBasePlayerWeapon *pthis, int iClipSize, int iAnim, float fDelay) +{ + auto original = [chain](int _pthis, int _iClipSize, int _iAnim, float _fDelay) { - return indexOfPDataAmx(chain->callNext(PEV(_pevOwner), vecStartCopy, vecVelocityCopy)); + return chain->callNext(getPrivate(_pthis), _iClipSize, _iAnim, _fDelay); }; - return getPrivate(callForward(RG_PlantBomb, original, indexOfEdictAmx(pevOwner), getAmxVector(vecStartCopy), getAmxVector(vecVelocityCopy))); + return callForward(RG_CBasePlayerWeapon_DefaultReload, original, indexOfEdict(pthis->pev), iClipSize, iAnim, fDelay); } -bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, Vector &vecEnd, entvars_t *pevAttacker, edict_t *pHit) +bool CBasePlayerWeapon_DefaultShotgunReload(IReGameHook_CBasePlayerWeapon_DefaultShotgunReload *chain, CBasePlayerWeapon *pthis, int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2) { - Vector vecSrcCopy(vecSrc), vecEndCopy(vecEnd); + auto original = [chain](int _pthis, int _iAnim, int _iStartAnim, float _fDelay, float _fStartDelay, const char *_pszReloadSound1, const char *_pszReloadSound2) + { + return chain->callNext(getPrivate(_pthis), _iAnim, _iStartAnim, _fDelay, _fStartDelay, _pszReloadSound1, _pszReloadSound2); + }; - auto original = [chain, &vecSrcCopy, &vecEndCopy](cell _vecSrc, cell _vecEnd, int _pevAttacker, int _pHit) + return callForward(RG_CBasePlayerWeapon_DefaultShotgunReload, original, indexOfEdict(pthis->pev), iAnim, iStartAnim, fDelay, fStartDelay, pszReloadSound1, pszReloadSound2); +} + +void CBasePlayer_DropIdlePlayer(IReGameHook_CBasePlayer_DropIdlePlayer *chain, CBasePlayer *pthis, const char *reason) +{ + auto original = [chain](int _pthis, const char *_reason) { - return chain->callNext(vecSrcCopy, vecEndCopy, PEV(_pevAttacker), edictByIndexAmx(_pHit)); + return chain->callNext(getPrivate(_pthis), _reason); }; - return callForward(RG_IsPenetrableEntity, original, getAmxVector(vecSrcCopy), getAmxVector(vecEndCopy), indexOfEdict(pevAttacker), indexOfEdict(pHit)); + callVoidForward(RG_CBasePlayer_DropIdlePlayer, original, indexOfEdict(pthis->pev), reason); } CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo) @@ -1458,6 +1403,64 @@ void CBasePlayer_Observer_SetMode(IReGameHook_CBasePlayer_Observer_SetMode *chai callVoidForward(RG_CBasePlayer_Observer_SetMode, original, indexOfEdict(pthis->pev), iMode); } +void CBasePlayer_Observer_FindNextPlayer(IReGameHook_CBasePlayer_Observer_FindNextPlayer *chain, CBasePlayer *pthis, bool bReverse, const char *name) +{ + auto original = [chain](int _pthis, bool _bReverse, const char *_name) + { + chain->callNext(getPrivate(_pthis), _bReverse, _name); + }; + + callVoidForward(RG_CBasePlayer_Observer_FindNextPlayer, original, indexOfEdict(pthis->pev), bReverse, name); +} + +void CBasePlayer_Pain(IReGameHook_CBasePlayer_Pain *chain, CBasePlayer *pthis, int iLastHitGroup, bool bHasArmour) +{ + auto original = [chain](int _pthis, int _iLastHitGroup, bool _bHasArmour) + { + return chain->callNext(getPrivate(_pthis), _iLastHitGroup, _bHasArmour); + }; + + callVoidForward(RG_CBasePlayer_Pain, original, indexOfEdict(pthis->pev), iLastHitGroup, bHasArmour); +} + +void CBasePlayer_DeathSound(IReGameHook_CBasePlayer_DeathSound *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + return chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_DeathSound, original, indexOfEdict(pthis->pev)); +} + +void CBasePlayer_JoiningThink(IReGameHook_CBasePlayer_JoiningThink *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + return chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_JoiningThink, original, indexOfEdict(pthis->pev)); +} + +void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex) +{ + auto original = [chain](physent_t *_pLadder, int _playerIndex) + { + chain->callNext(_pLadder); + }; + + callVoidForward(RG_PM_LadderMove, original, pLadder, playerIndex); +} + +void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder) +{ + PM_LadderMove_AMXX(chain, pLadder, pLadder->player + 1); +} + +/* +* VTC functions +*/ int g_iClientStartSpeak, g_iClientStopSpeak; void OnClientStartSpeak(size_t clientIndex) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index ee8fd3d9..49457023 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -329,7 +329,9 @@ struct hookdata_t A m_args; }; -// 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_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt); void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics); @@ -383,44 +385,9 @@ void ED_Free(IRehldsHook_ED_Free* chain, edict_t *entity); void SV_ClientPrintf(IRehldsHook_SV_ClientPrintf* chain, const char *string); bool SV_AllowPhysent(IRehldsHook_SV_AllowPhysent* chain, edict_t* check, edict_t* sv_player); -// regamedll functions -int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver); -void PlayerBlind(IReGameHook_PlayerBlind *chain, CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, float fadeTime, float fadeHold, int alpha, Vector& color); -void RadiusFlash_TraceLine(IReGameHook_RadiusFlash_TraceLine *chain, CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, Vector& vecSrc, Vector& vecSpot, TraceResult *ptr); -bool RoundEnd(IReGameHook_RoundEnd *chain, int winStatus, ScenarioEventEndRound event, float tmDelay); - -struct Move_args_t -{ - Move_args_t(playermove_t *_ppmove, int _server) : ppmove(_ppmove), server(_server) {} - - playermove_t *ppmove; - int server; -}; - -using Move_t = hookdata_t; -void PM_Move_AMXX(Move_t *data, int playerIndex); -void PM_Move(IReGameHook_PM_Move *chain, playermove_t *ppmove, int server); - -void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex); -void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex); -void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder); - -void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot); -BOOL HandleMenu_ChooseTeam(IReGameHook_HandleMenu_ChooseTeam *chain, CBasePlayer *pPlayer, int slot); -void ShowMenu(IReGameHook_ShowMenu *chain, CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText); -void ShowVGUIMenu(IReGameHook_ShowVGUIMenu *chain, CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu); -bool BuyGunAmmo(IReGameHook_BuyGunAmmo *chain, CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney); -CBaseEntity *BuyWeaponByWeaponID(IReGameHook_BuyWeaponByWeaponID *chain, CBasePlayer *pPlayer, WeaponIdType weaponID); -CGrenade *ThrowHeGrenade(IReGameHook_ThrowHeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, int iTeam, unsigned short usEvent); -CGrenade *ThrowFlashbang(IReGameHook_ThrowFlashbang *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time); -CGrenade *ThrowSmokeGrenade(IReGameHook_ThrowSmokeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, unsigned short usEvent); -CGrenade *PlantBomb(IReGameHook_PlantBomb *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity); -bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, Vector &vecEnd, entvars_t *pevAttacker, edict_t *pHit); -CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo); -CGib *SpawnHeadGib(IReGameHook_SpawnHeadGib *chain, entvars_t *pevVictim); -void SpawnRandomGibs(IReGameHook_SpawnRandomGibs *chain, entvars_t *pevVictim, int cGibs, int human); - -// regamedll functions - player +/* +* ReGameDLL functions +*/ void CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *pthis); void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis); int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis); @@ -445,7 +412,6 @@ void CBasePlayer_RoundRespawn(IReGameHook_CBasePlayer_RoundRespawn *chain, CBase void CBasePlayer_Blind(IReGameHook_CBasePlayer_Blind *chain, CBasePlayer *pthis, float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha); CBasePlayer *CBasePlayer_Observer_IsValidTarget(IReGameHook_CBasePlayer_Observer_IsValidTarget *chain, CBasePlayer *pthis, int iPlayerIndex, bool bSameTeam); -void CBasePlayer_Observer_FindNextPlayer(IReGameHook_CBasePlayer_Observer_FindNextPlayer *chain, CBasePlayer *pthis, bool bReverse, const char *name); void CBasePlayer_SetAnimation(IReGameHook_CBasePlayer_SetAnimation *chain, CBasePlayer *pthis, PLAYER_ANIM playerAnim); void CBasePlayer_GiveDefaultItems(IReGameHook_CBasePlayer_GiveDefaultItems *chain, CBasePlayer *pthis); CBaseEntity *CBasePlayer_GiveNamedItem(IReGameHook_CBasePlayer_GiveNamedItem *chain, CBasePlayer *pthis, const char *pszName); @@ -463,26 +429,33 @@ void CBasePlayer_MakeVIP(IReGameHook_CBasePlayer_MakeVIP *chain, CBasePlayer *pt bool CBasePlayer_MakeBomber(IReGameHook_CBasePlayer_MakeBomber *chain, CBasePlayer *pthis); void CBasePlayer_StartObserver(IReGameHook_CBasePlayer_StartObserver *chain, CBasePlayer *pthis, Vector &vecPosition, Vector &vecViewAngle); bool CBasePlayer_GetIntoGame(IReGameHook_CBasePlayer_GetIntoGame *chain, CBasePlayer *pthis); -void CBasePlayer_StartDeathCam(IReGameHook_CBasePlayer_StartDeathCam *chain, CBasePlayer *pthis); -void CBasePlayer_SwitchTeam(IReGameHook_CBasePlayer_SwitchTeam *chain, CBasePlayer *pthis); -bool CBasePlayer_CanSwitchTeam(IReGameHook_CBasePlayer_CanSwitchTeam *chain, CBasePlayer *pthis, TeamName teamToSwap); -CGrenade *CBasePlayer_ThrowGrenade(IReGameHook_CBasePlayer_ThrowGrenade *chain, CBasePlayer *pthis, CBasePlayerWeapon *pWeapon, Vector &vecSrc, Vector &vecThrow, float time, unsigned short usEvent); -void CBasePlayer_SetSpawnProtection(IReGameHook_CBasePlayer_SetSpawnProtection *chain, CBasePlayer *pthis, float flProtectionTime); -void CBasePlayer_RemoveSpawnProtection(IReGameHook_CBasePlayer_RemoveSpawnProtection *chain, CBasePlayer *pthis); -bool CBasePlayer_HintMessageEx(IReGameHook_CBasePlayer_HintMessageEx *chain, CBasePlayer *pthis, const char *pMessage, float duration, bool bDisplayIfPlayerDead, bool bOverride); -void CBasePlayer_UseEmpty(IReGameHook_CBasePlayer_UseEmpty *chain, CBasePlayer *pthis); -void CBasePlayer_DropIdlePlayer(IReGameHook_CBasePlayer_DropIdlePlayer *chain, CBasePlayer *pthis, const char *reason); -void CBasePlayer_Observer_SetMode(IReGameHook_CBasePlayer_Observer_SetMode *chain, CBasePlayer *pthis, int iMode); -void CBasePlayer_Pain(IReGameHook_CBasePlayer_Pain *chain, CBasePlayer *pthis, int iLastHitGroup, bool bHasArmour); -void CBasePlayer_DeathSound(IReGameHook_CBasePlayer_DeathSound *chain, CBasePlayer *pthis); -void CBasePlayer_JoiningThink(IReGameHook_CBasePlayer_JoiningThink *chain, CBasePlayer *pthis); void CBaseAnimating_ResetSequenceInfo(IReGameHook_CBaseAnimating_ResetSequenceInfo *chain, CBaseAnimating *pthis); -BOOL CBasePlayerWeapon_CanDeploy(IReGameHook_CBasePlayerWeapon_CanDeploy *chain, CBasePlayerWeapon *pthis); -BOOL CBasePlayerWeapon_DefaultDeploy(IReGameHook_CBasePlayerWeapon_DefaultDeploy *chain, CBasePlayerWeapon *pthis, char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal); -int CBasePlayerWeapon_DefaultReload(IReGameHook_CBasePlayerWeapon_DefaultReload *chain, CBasePlayerWeapon *pthis, int iClipSize, int iAnim, float fDelay); -bool CBasePlayerWeapon_DefaultShotgunReload(IReGameHook_CBasePlayerWeapon_DefaultShotgunReload *chain, CBasePlayerWeapon *pthis, int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2); +int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver); +void PlayerBlind(IReGameHook_PlayerBlind *chain, CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, float fadeTime, float fadeHold, int alpha, Vector& color); +void RadiusFlash_TraceLine(IReGameHook_RadiusFlash_TraceLine *chain, CBasePlayer *pPlayer, entvars_t *pevInflictor, entvars_t *pevAttacker, Vector& vecSrc, Vector& vecSpot, TraceResult *ptr); +bool RoundEnd(IReGameHook_RoundEnd *chain, int winStatus, ScenarioEventEndRound event, float tmDelay); +// TODO: pending InstallGameRules +// TODO: pending PM_Init +struct Move_args_t +{ + Move_args_t(playermove_t *_ppmove, int _server) : ppmove(_ppmove), server(_server) {} + + playermove_t *ppmove; + int server; +}; +using Move_t = hookdata_t; +void PM_Move_AMXX(Move_t *data, int playerIndex); +void PM_Move(IReGameHook_PM_Move *chain, playermove_t *ppmove, int server); +void PM_AirMove(IReGameHook_PM_AirMove *chain, int playerIndex); +void HandleMenu_ChooseAppearance(IReGameHook_HandleMenu_ChooseAppearance *chain, CBasePlayer *pPlayer, int slot); +BOOL HandleMenu_ChooseTeam(IReGameHook_HandleMenu_ChooseTeam *chain, CBasePlayer *pPlayer, int slot); +void ShowMenu(IReGameHook_ShowMenu *chain, CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText); +void ShowVGUIMenu(IReGameHook_ShowVGUIMenu *chain, CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu); +bool BuyGunAmmo(IReGameHook_BuyGunAmmo *chain, CBasePlayer *player, CBasePlayerItem *weapon, bool bBlinkMoney); +CBaseEntity *BuyWeaponByWeaponID(IReGameHook_BuyWeaponByWeaponID *chain, CBasePlayer *pPlayer, WeaponIdType weaponID); +// TODO: pending InternalCommand BOOL CSGameRules_FShouldSwitchWeapon(IReGameHook_CSGameRules_FShouldSwitchWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon); BOOL CSGameRules_GetNextBestWeapon(IReGameHook_CSGameRules_GetNextBestWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon); @@ -507,33 +480,69 @@ void CSGameRules_ChangeLevel(IReGameHook_CSGameRules_ChangeLevel *chain); void CSGameRules_GoToIntermission(IReGameHook_CSGameRules_GoToIntermission *chain); void CSGameRules_BalanceTeams(IReGameHook_CSGameRules_BalanceTeams *chain); void CSGameRules_OnRoundFreezeEnd(IReGameHook_CSGameRules_OnRoundFreezeEnd *chain); +// TODO: pending PM_UpdateStepSound +void CBasePlayer_StartDeathCam(IReGameHook_CBasePlayer_StartDeathCam *chain, CBasePlayer *pthis); +void CBasePlayer_SwitchTeam(IReGameHook_CBasePlayer_SwitchTeam *chain, CBasePlayer *pthis); +bool CBasePlayer_CanSwitchTeam(IReGameHook_CBasePlayer_CanSwitchTeam *chain, CBasePlayer *pthis, TeamName teamToSwap); +CGrenade *CBasePlayer_ThrowGrenade(IReGameHook_CBasePlayer_ThrowGrenade *chain, CBasePlayer *pthis, CBasePlayerWeapon *pWeapon, Vector &vecSrc, Vector &vecThrow, float time, unsigned short usEvent); bool CSGameRules_CanPlayerHearPlayer(IReGameHook_CSGameRules_CanPlayerHearPlayer *chain, CBasePlayer *pListener, CBasePlayer *pSender); - void CWeaponBox_SetModel(IReGameHook_CWeaponBox_SetModel *chain, CWeaponBox *pthis, const char *pszModelName); - void CGrenade_DefuseBombStart(IReGameHook_CGrenade_DefuseBombStart *chain, CGrenade *pthis, CBasePlayer *pPlayer); void CGrenade_DefuseBombEnd(IReGameHook_CGrenade_DefuseBombEnd *chain, CGrenade *pthis, CBasePlayer *pPlayer, bool bDefused); void CGrenade_ExplodeHeGrenade(IReGameHook_CGrenade_ExplodeHeGrenade *chain, CGrenade *pthis, TraceResult *ptr, int bitsDamageType); void CGrenade_ExplodeFlashbang(IReGameHook_CGrenade_ExplodeFlashbang *chain, CGrenade *pthis, TraceResult *ptr, int bitsDamageType); void CGrenade_ExplodeSmokeGrenade(IReGameHook_CGrenade_ExplodeSmokeGrenade *chain, CGrenade *pthis); void CGrenade_ExplodeBomb(IReGameHook_CGrenade_ExplodeBomb *chain, CGrenade *pthis, TraceResult *ptr, int bitsDamageType); +CGrenade *ThrowHeGrenade(IReGameHook_ThrowHeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, int iTeam, unsigned short usEvent); +CGrenade *ThrowFlashbang(IReGameHook_ThrowFlashbang *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time); +CGrenade *ThrowSmokeGrenade(IReGameHook_ThrowSmokeGrenade *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity, float time, unsigned short usEvent); +CGrenade *PlantBomb(IReGameHook_PlantBomb *chain, entvars_t *pevOwner, Vector &vecStart, Vector &vecVelocity); +void CBasePlayer_RemoveSpawnProtection(IReGameHook_CBasePlayer_RemoveSpawnProtection *chain, CBasePlayer *pthis); +void CBasePlayer_SetSpawnProtection(IReGameHook_CBasePlayer_SetSpawnProtection *chain, CBasePlayer *pthis, float flProtectionTime); +bool IsPenetrableEntity(IReGameHook_IsPenetrableEntity *chain, Vector &vecSrc, Vector &vecEnd, entvars_t *pevAttacker, edict_t *pHit); +bool CBasePlayer_HintMessageEx(IReGameHook_CBasePlayer_HintMessageEx *chain, CBasePlayer *pthis, const char *pMessage, float duration, bool bDisplayIfPlayerDead, bool bOverride); +void CBasePlayer_UseEmpty(IReGameHook_CBasePlayer_UseEmpty *chain, CBasePlayer *pthis); +BOOL CBasePlayerWeapon_CanDeploy(IReGameHook_CBasePlayerWeapon_CanDeploy *chain, CBasePlayerWeapon *pthis); +BOOL CBasePlayerWeapon_DefaultDeploy(IReGameHook_CBasePlayerWeapon_DefaultDeploy *chain, CBasePlayerWeapon *pthis, char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal); +int CBasePlayerWeapon_DefaultReload(IReGameHook_CBasePlayerWeapon_DefaultReload *chain, CBasePlayerWeapon *pthis, int iClipSize, int iAnim, float fDelay); +bool CBasePlayerWeapon_DefaultShotgunReload(IReGameHook_CBasePlayerWeapon_DefaultShotgunReload *chain, CBasePlayerWeapon *pthis, int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1, const char *pszReloadSound2); +void CBasePlayer_DropIdlePlayer(IReGameHook_CBasePlayer_DropIdlePlayer *chain, CBasePlayer *pthis, const char *reason); +CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo); -// regamedll functions - gib +CGib *SpawnHeadGib(IReGameHook_SpawnHeadGib *chain, entvars_t *pevVictim); +void SpawnRandomGibs(IReGameHook_SpawnRandomGibs *chain, entvars_t *pevVictim, int cGibs, int human); void CGib_Spawn(IReGameHook_CGib_Spawn *chain, CGib *pthis, const char *szGibModel); 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); +void CBasePlayer_Observer_SetMode(IReGameHook_CBasePlayer_Observer_SetMode *chain, CBasePlayer *pthis, int iMode); +void CBasePlayer_Observer_FindNextPlayer(IReGameHook_CBasePlayer_Observer_FindNextPlayer *chain, CBasePlayer *pthis, bool bReverse, const char *name); + +void CBasePlayer_Pain(IReGameHook_CBasePlayer_Pain *chain, CBasePlayer *pthis, int iLastHitGroup, bool bHasArmour); +void CBasePlayer_DeathSound(IReGameHook_CBasePlayer_DeathSound *chain, CBasePlayer *pthis); +void CBasePlayer_JoiningThink(IReGameHook_CBasePlayer_JoiningThink *chain, CBasePlayer *pthis); + +// TODO: pending FreeGameRules +void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex); +void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder); + +/* +* VTC functions +*/ extern int g_iClientStartSpeak; extern int g_iClientStopSpeak; void OnClientStartSpeak(size_t clientIndex); void OnClientStopSpeak(size_t clientIndex); +/* +* ReChecker functions +*/ + using CmdExec_t = hookdata_t; void CmdExec_AMXX(CmdExec_t *chain, IGameClient *cl, const char *filename, char *cmd, uint32 responseHash); void CmdExec(IRecheckerHook_CmdExec *chain, IGameClient *cl, IResourceBuffer *res, char *cmd, uint32 responseHash); diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index 7bfca903..becae619 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -760,6 +760,8 @@ member_t memberlist_csplayer[] = { CSPL_MEMBERS(m_bGameForcingRespawn), CSPL_MEMBERS(m_bAutoBunnyHopping), CSPL_MEMBERS(m_bMegaBunnyJumping), + CSPL_MEMBERS(m_bPlantC4Anywhere), + CSPL_MEMBERS(m_bSpawnProtectionEffects), }; member_t memberlist_baseitem[] = { @@ -1002,6 +1004,7 @@ member_t memberlist_knife[] = { KNIFE_MEMBERS(flSwingBaseDamage_Fast), KNIFE_MEMBERS(flStabDistance), KNIFE_MEMBERS(flSwingDistance), + KNIFE_MEMBERS(flBackStabMultiplier), }; member_t memberlist_p90[] = { diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index b2947853..30c9908d 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -749,6 +749,8 @@ enum CSPlayer_Members m_bGameForcingRespawn, m_bAutoBunnyHopping, m_bMegaBunnyJumping, + m_bPlantC4Anywhere, + m_bSpawnProtectionEffects, }; enum CBasePlayerItem_Members @@ -1023,6 +1025,7 @@ enum CKnife_Members m_Knife_flSwingBaseDamage_Fast, m_Knife_flStabDistance, m_Knife_flSwingDistance, + m_Knife_flBackStabMultiplier, }; enum CP90_Members From 28fe32e5144ed8bbcd64c843bbafecd337abdc65 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Thu, 24 Aug 2023 17:22:10 +0700 Subject: [PATCH 23/50] Update CSSDK --- reapi/include/cssdk/dlls/API/CSEntity.h | 20 +++++++++++++++----- reapi/include/cssdk/dlls/cbase.h | 6 ++++++ reapi/src/mods/mod_regamedll_api.cpp | 6 ++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/reapi/include/cssdk/dlls/API/CSEntity.h b/reapi/include/cssdk/dlls/API/CSEntity.h index 1e9ca2b9..8f03b7c2 100644 --- a/reapi/include/cssdk/dlls/API/CSEntity.h +++ b/reapi/include/cssdk/dlls/API/CSEntity.h @@ -43,9 +43,14 @@ class CCSEntity virtual void FireBuckshots(ULONG cShots, Vector &vecSrc, Vector &vecDirShooting, Vector &vecSpread, float flDistance, int iTracerFreq, int iDamage, entvars_t *pevAttacker) = 0; virtual Vector FireBullets3(Vector &vecSrc, Vector &vecDirShooting, float vecSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand) = 0; +public: + CBaseEntity *m_pContainingEntity; + +private: #if defined(_MSC_VER) -#pragma region reserve_vfuncs_Region +#pragma region reserve_data_Region #endif + int CCSEntity_Reserve[0x1000]; virtual void func_reserve1() {}; virtual void func_reserve2() {}; virtual void func_reserve3() {}; @@ -79,9 +84,6 @@ class CCSEntity #if defined(_MSC_VER) #pragma endregion #endif - -public: - CBaseEntity *m_pContainingEntity; }; class CCSDelay: public CCSEntity @@ -89,6 +91,8 @@ class CCSDelay: public CCSEntity DECLARE_CLASS_TYPES(CCSDelay, CCSEntity); public: +private: + int CCSDelay_Reserve[0x100]; }; class CCSAnimating: public CCSDelay @@ -96,6 +100,8 @@ class CCSAnimating: public CCSDelay DECLARE_CLASS_TYPES(CCSAnimating, CCSDelay); public: +private: + int CCSAnimating_Reserve[0x100]; }; class CCSToggle: public CCSAnimating @@ -103,6 +109,8 @@ class CCSToggle: public CCSAnimating DECLARE_CLASS_TYPES(CCSToggle, CCSAnimating); public: +private: + int CCSToggle_Reserve[0x100]; }; class CCSMonster: public CCSToggle @@ -110,6 +118,8 @@ class CCSMonster: public CCSToggle DECLARE_CLASS_TYPES(CCSMonster, CCSToggle); public: +private: + int CCSMonster_Reserve[0x100]; }; -#define CSENTITY_API_INTERFACE_VERSION "CSENTITY_API_INTERFACE_VERSION002" +#define CSENTITY_API_INTERFACE_VERSION "CSENTITY_API_INTERFACE_VERSION003" diff --git a/reapi/include/cssdk/dlls/cbase.h b/reapi/include/cssdk/dlls/cbase.h index 53d4a031..96731bbd 100644 --- a/reapi/include/cssdk/dlls/cbase.h +++ b/reapi/include/cssdk/dlls/cbase.h @@ -173,6 +173,7 @@ class CBaseEntity public: CCSEntity *m_pEntity; // NOTE: it was replaced on member "int *current_ammo" because it is useless. + CCSEntity *CSEntity() const; // We use this variables to store each ammo count. float currentammo; @@ -253,6 +254,11 @@ inline void CBaseEntity::SetBlocked(std::nullptr_t) m_pfnBlocked = nullptr; } +inline CCSEntity *CBaseEntity::CSEntity() const +{ + return m_pEntity; +} + class CPointEntity: public CBaseEntity { DECLARE_CLASS_TYPES(CPointEntity, CBaseEntity); diff --git a/reapi/src/mods/mod_regamedll_api.cpp b/reapi/src/mods/mod_regamedll_api.cpp index c7810f78..bd7051e2 100644 --- a/reapi/src/mods/mod_regamedll_api.cpp +++ b/reapi/src/mods/mod_regamedll_api.cpp @@ -62,6 +62,12 @@ bool RegamedllApi_Init() if (!g_ReGameApi->BGetICSEntity(CSENTITY_API_INTERFACE_VERSION)) { UTIL_ServerPrint("[%s]: Interface CCSEntity API version '%s' not found.\n", Plugin_info.logtag, CSENTITY_API_INTERFACE_VERSION); + + if (g_ReGameApi->BGetICSEntity("CSENTITY_API_INTERFACE_VERSION002")) + UTIL_ServerPrint("[%s]: Please update ReGameDLL to the latest version.\n", Plugin_info.logtag); + else + UTIL_ServerPrint("[%s]: Please update ReAPI to the latest version.\n", Plugin_info.logtag); + return false; } From a60e2b51e2c9d06e9df18ae5ccd95289ee04b012 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 26 Aug 2023 18:29:56 +0700 Subject: [PATCH 24/50] Disable fixes angles for natives GetBonePosition/GetAttachment if ReGameDLL is running --- reapi/src/reapi_utils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 5fc7f6e6..2a426447 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -175,7 +175,8 @@ void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector GET_BONE_POSITION(pEdict, iBone, vecOrigin, vecAngles); pEntity->pev->angles.x = -pEntity->pev->angles.x; - if (!pEntity->IsPlayer()) { + // ReGameDLL already have fixes angles for non-players entities + if (!g_ReGameApi && !pEntity->IsPlayer()) { FixupAngles(pEdict, vecOrigin); } @@ -208,7 +209,8 @@ void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Ve GET_ATTACHMENT(pEdict, iAttachment, vecOrigin, vecAngles); - if (!pEntity->IsPlayer()) { + // ReGameDLL already have fixes angles for non-players entities + if (!g_ReGameApi && !pEntity->IsPlayer()) { FixupAngles(pEdict, vecOrigin); } From 2bceff94cf901ff10eb3d8d37bc58bf9711ef826 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Sep 2023 09:06:27 +0700 Subject: [PATCH 25/50] Reworked entity callback dispatcher Fixed crash when callback was deleted in middle callback dispatcher --- reapi/src/amx_hook.h | 26 --- reapi/src/entity_callback.cpp | 179 ----------------- reapi/src/entity_callback.h | 78 -------- reapi/src/entity_callback_dispatcher.cpp | 234 +++++++++++++++++++++++ reapi/src/entity_callback_dispatcher.h | 172 +++++++++++++++++ reapi/src/main.cpp | 4 +- reapi/src/natives/natives_common.cpp | 20 +- reapi/src/precompiled.h | 3 +- 8 files changed, 420 insertions(+), 296 deletions(-) delete mode 100644 reapi/src/entity_callback.cpp delete mode 100644 reapi/src/entity_callback.h create mode 100644 reapi/src/entity_callback_dispatcher.cpp create mode 100644 reapi/src/entity_callback_dispatcher.h diff --git a/reapi/src/amx_hook.h b/reapi/src/amx_hook.h index 8b84a356..68e7c6ed 100644 --- a/reapi/src/amx_hook.h +++ b/reapi/src/amx_hook.h @@ -29,29 +29,3 @@ class CAmxxHookBase fwdstate m_state; AMX *m_amx; }; - -template -class CAmxxHookUnique: public CAmxxHookBase -{ -public: - ~CAmxxHookUnique() - { - if (m_uniqueData) - { - delete m_uniqueData; - m_uniqueData = nullptr; - } - } - - CAmxxHookUnique(AMX *amx, const char *funcname, int index, T *data = nullptr) : - CAmxxHookBase(amx, funcname, index, -1), - m_uniqueData(data) - { - - } - - T *GetUnique() const { return m_uniqueData; } - -private: - T *m_uniqueData; -}; diff --git a/reapi/src/entity_callback.cpp b/reapi/src/entity_callback.cpp deleted file mode 100644 index a11b59d3..00000000 --- a/reapi/src/entity_callback.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "precompiled.h" - -CEntityCallback g_entCallback; - -void CEntityCallback::PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type) -{ - auto it = m_callbacks.begin(); - while (it != m_callbacks.end()) - { - eCallback_t *pUnique = (*it)->GetUnique(); - - // this callback was already sets, need to unregister the current forward - if (pUnique->m_callbackType == type && pUnique->m_entity == pEntity) { - delete (*it); - it = m_callbacks.erase(it); - } else { - it++; - } - } -} - -void CEntityCallback::Clear(CBaseEntity *pEntity) -{ - if (pEntity) - { - auto it = m_callbacks.begin(); - while (it != m_callbacks.end()) - { - eCallback_t *pUnique = (*it)->GetUnique(); - if (pUnique->m_entity == pEntity) { - delete (*it); - it = m_callbacks.erase(it); - } else { - it++; - } - } - } - else - { - for (auto h : m_callbacks) { - delete h; - } - - m_callbacks.clear(); - } -} - -bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) -{ - PurgeCallbacks(pEntity, CType_Think); - - int fwdid; - if (iParamsLen > 0) { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); - } else { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); - } - - if (fwdid == -1) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); - return false; - } - - m_callbacks.push_back(new CAmxxHookUnique(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Think))); - pEntity->SetThink(&CBaseEntity::SUB_Think); - return true; -} - -bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) -{ - PurgeCallbacks(pEntity, CType_Touch); - - int fwdid; - if (iParamsLen > 0) { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); - } else { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); - } - - if (fwdid == -1) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); - return false; - } - - m_callbacks.push_back(new CAmxxHookUnique(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Touch))); - pEntity->SetTouch(&CBaseEntity::SUB_Touch); - return true; -} - -bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) -{ - PurgeCallbacks(pEntity, CType_Use); - - int fwdid; - if (iParamsLen > 0) { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_DONE); - } else { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE); - } - - if (fwdid == -1) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); - return false; - } - - m_callbacks.push_back(new CAmxxHookUnique(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Use))); - pEntity->SetUse(&CBaseEntity::SUB_Use); - return true; -} - -bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) -{ - PurgeCallbacks(pEntity, CType_Blocked); - - int fwdid; - if (iParamsLen > 0) { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); - } else { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); - } - - if (fwdid == -1) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); - return false; - } - - m_callbacks.push_back(new CAmxxHookUnique(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Blocked))); - pEntity->SetBlocked(&CBaseEntity::SUB_Blocked); - return true; -} - -bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) -{ - PurgeCallbacks(pEntity, CType_MoveDone); - - int fwdid; - if (iParamsLen > 0) { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); - } else { - fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); - } - - if (fwdid == -1) { - AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); - return false; - } - - m_callbacks.push_back(new CAmxxHookUnique(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_MoveDone))); - - // TODO: Make sure that the entity actually inherited from CBaseToggle - ((CBaseToggle *)pEntity)->SetMoveDone(&CBaseToggle::SUB_MoveDone); - return true; -} - -// Fundamental callbacks -void CBaseEntity::SUB_Think() -{ - g_entCallback.FireCallbacks(this, CEntityCallback::CType_Think, indexOfEdict(pev)); -} - -void CBaseEntity::SUB_Touch(CBaseEntity *pOther) -{ - g_entCallback.FireCallbacks(this, CEntityCallback::CType_Touch, indexOfEdict(pev), indexOfEdict(pOther->pev)); -} - -void CBaseEntity::SUB_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - g_entCallback.FireCallbacks(this, CEntityCallback::CType_Use, indexOfEdict(pev), indexOfEdict(pActivator->pev), indexOfEdict(pCaller->pev), useType, value); -} - -void CBaseEntity::SUB_Blocked(CBaseEntity *pOther) -{ - g_entCallback.FireCallbacks(this, CEntityCallback::CType_Blocked, indexOfEdict(pev), indexOfEdict(pOther->pev)); -} - -void CBaseToggle::SUB_MoveDone() -{ - g_entCallback.FireCallbacks(this, CEntityCallback::CType_MoveDone, indexOfEdict(pev)); -} diff --git a/reapi/src/entity_callback.h b/reapi/src/entity_callback.h deleted file mode 100644 index 62202591..00000000 --- a/reapi/src/entity_callback.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include "amx_hook.h" - -class CEntityCallback -{ -public: - void Clear(CBaseEntity *pEntity = nullptr); - - bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); - bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); - bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); - bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); - bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); - - enum CallbackType_e - { - CType_Think, - CType_Touch, - CType_Use, - CType_Blocked, - CType_MoveDone, - }; - - template - void FireCallbacks(CBaseEntity *pEntity, CallbackType_e type, volatile f_args... args) - { - for (auto fwd : m_callbacks) { - auto data = fwd->GetUnique(); - if (data->m_entity == pEntity && data->m_callbackType == type) - { - if (data->m_iParamLen > 0) { - g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), args..., g_amxxapi.PrepareCellArrayA(data->m_pParams, data->m_iParamLen, true)); - } else { - g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), args...); - } - } - } - } - -private: - void PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type); - struct eCallback_t - { - eCallback_t(CBaseEntity *pEntity, const cell *pParams, size_t iParamsLen, CallbackType_e type) : - m_entity(pEntity), m_callbackType(type) - { - if (iParamsLen > 0) { - m_iParamLen = iParamsLen + 1; - m_pParams = new cell[m_iParamLen]; - Q_memcpy(m_pParams, pParams, sizeof(cell) * iParamsLen); - m_pParams[iParamsLen] = 0; - } else { - m_iParamLen = 0; - m_pParams = nullptr; - } - }; - - ~eCallback_t() - { - if (m_pParams) { - delete[] m_pParams; - m_pParams = nullptr; - } - - m_iParamLen = 0; - } - - CBaseEntity *m_entity; - CallbackType_e m_callbackType; - cell *m_pParams; - size_t m_iParamLen; - }; - - std::vector *> m_callbacks; -}; - -extern CEntityCallback g_entCallback; diff --git a/reapi/src/entity_callback_dispatcher.cpp b/reapi/src/entity_callback_dispatcher.cpp new file mode 100644 index 00000000..54fdbb99 --- /dev/null +++ b/reapi/src/entity_callback_dispatcher.cpp @@ -0,0 +1,234 @@ +#include "precompiled.h" + +// Deletes all registered callbacks for the specified entity, or all entities if pEntity is nullptr +void CEntityCallbackDispatcher::DeleteExistingCallbacks(CBaseEntity *pEntity, CallbackType type) +{ + for (std::list::const_iterator it = m_callbacks.begin(); + it != m_callbacks.end(); ) + { + EntityCallback *callback = (*it); + + // This callback was already sets, need to unregister the current forward + if (!pEntity || (callback->m_pEntity == pEntity && (callback->m_callbackType == type || None == type))) + { + // Are we in the middle of processing callbacks? + if (IsProcessingCallbacks()) + { + // Sets the mark for the object to be deleted later + const std::list::const_iterator callbackIt = + std::find(m_callbacksMarkForDeletion.begin(), m_callbacksMarkForDeletion.end(), callback); + + if (callbackIt == m_callbacksMarkForDeletion.end()) + m_callbacksMarkForDeletion.push_back(callback); + + it++; + } + else + { + it = m_callbacks.erase(it); + delete callback; + } + } + else + { + it++; + } + } + + if (!pEntity && !IsProcessingCallbacks()) + m_callbacks.clear(); +} + +// Deletes all registered callbacks +void CEntityCallbackDispatcher::DeleteAllCallbacks() +{ + DeleteExistingCallbacks(nullptr); +} + +bool CEntityCallbackDispatcher::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) +{ + DeleteExistingCallbacks(pEntity, Think); + + int fwdid; + if (iParamsLen > 0) + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); + else + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + + if (fwdid == -1) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); + return false; + } + + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, Think)); + pEntity->SetThink(&CBaseEntity::SUB_Think); + return true; +} + +bool CEntityCallbackDispatcher::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) +{ + DeleteExistingCallbacks(pEntity, Touch); + + int fwdid; + if (iParamsLen > 0) + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); + else + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + + if (fwdid == -1) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); + return false; + } + + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, Touch)); + pEntity->SetTouch(&CBaseEntity::SUB_Touch); + return true; +} + +bool CEntityCallbackDispatcher::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) +{ + DeleteExistingCallbacks(pEntity, Use); + + int fwdid; + if (iParamsLen > 0) + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_DONE); + else + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE); + + if (fwdid == -1) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); + return false; + } + + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, Use)); + pEntity->SetUse(&CBaseEntity::SUB_Use); + return true; +} + +bool CEntityCallbackDispatcher::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) +{ + DeleteExistingCallbacks(pEntity, Blocked); + + int fwdid; + if (iParamsLen > 0) + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); + else + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + + if (fwdid == -1) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); + return false; + } + + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, Blocked)); + pEntity->SetBlocked(&CBaseEntity::SUB_Blocked); + return true; +} + +bool CEntityCallbackDispatcher::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) +{ + DeleteExistingCallbacks(pEntity, MoveDone); + + int fwdid; + if (iParamsLen > 0) + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); + else + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + + if (fwdid == -1) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); + return false; + } + + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, MoveDone)); + + // Make sure that the entity actually inherited from CBaseToggle + CBaseToggle *pEntityToggle = dynamic_cast(pEntity); + if (!pEntityToggle) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: '%s' has no refs to the base class of an entity 'CBaseToggle'", __FUNCTION__, STRING(pEntity->pev->classname)); + return false; + } + + // TODO: Make sure that the entity actually inherited from CBaseToggle + pEntityToggle->SetMoveDone(&CBaseToggle::SUB_MoveDone); + return true; +} + +void CEntityCallbackDispatcher::UnsetThink(AMX *amx, CBaseEntity *pEntity) +{ + pEntity->SetThink(nullptr); + DeleteExistingCallbacks(pEntity, Think); +} + +void CEntityCallbackDispatcher::UnsetTouch(AMX *amx, CBaseEntity *pEntity) +{ + pEntity->SetTouch(nullptr); + DeleteExistingCallbacks(pEntity, Touch); +} + +void CEntityCallbackDispatcher::UnsetUse(AMX *amx, CBaseEntity *pEntity) +{ + pEntity->SetUse(nullptr); + DeleteExistingCallbacks(pEntity, Use); +} + +void CEntityCallbackDispatcher::UnsetBlocked(AMX *amx, CBaseEntity *pEntity) +{ + pEntity->SetBlocked(nullptr); + DeleteExistingCallbacks(pEntity, Blocked); +} + +void CEntityCallbackDispatcher::UnsetMoveDone(AMX *amx, CBaseEntity *pEntity) +{ + // Make sure that the entity actually inherited from CBaseToggle + CBaseToggle *pEntityToggle = dynamic_cast(pEntity); + if (!pEntityToggle) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: '%s' has no refs to the base class of an entity 'CBaseToggle'", __FUNCTION__, STRING(pEntity->pev->classname)); + return; + } + + pEntityToggle->SetMoveDone(nullptr); + DeleteExistingCallbacks(pEntity, MoveDone); +} + +// Fundamental callbacks +void CBaseEntity::SUB_Think() +{ + EntityCallbackDispatcher().DispatchCallbacks(this, CEntityCallbackDispatcher::Think, indexOfEdict(pev)); +} + +void CBaseEntity::SUB_Touch(CBaseEntity *pOther) +{ + EntityCallbackDispatcher().DispatchCallbacks(this, CEntityCallbackDispatcher::Touch, indexOfEdict(pev), indexOfEdict(pOther->pev)); +} + +void CBaseEntity::SUB_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) +{ + EntityCallbackDispatcher().DispatchCallbacks(this, CEntityCallbackDispatcher::Use, indexOfEdict(pev), indexOfEdict(pActivator->pev), indexOfEdict(pCaller->pev), useType, value); +} + +void CBaseEntity::SUB_Blocked(CBaseEntity *pOther) +{ + EntityCallbackDispatcher().DispatchCallbacks(this, CEntityCallbackDispatcher::Blocked, indexOfEdict(pev), indexOfEdict(pOther->pev)); +} + +void CBaseToggle::SUB_MoveDone() +{ + EntityCallbackDispatcher().DispatchCallbacks(this, CEntityCallbackDispatcher::MoveDone, indexOfEdict(pev)); +} + +// Instance of the callback dispatcher +static CEntityCallbackDispatcher s_EntityCallbackDispatcher = {}; + +// Returns the instance of the callback dispatcher +CEntityCallbackDispatcher &EntityCallbackDispatcher() +{ + return s_EntityCallbackDispatcher; +} diff --git a/reapi/src/entity_callback_dispatcher.h b/reapi/src/entity_callback_dispatcher.h new file mode 100644 index 00000000..7a701392 --- /dev/null +++ b/reapi/src/entity_callback_dispatcher.h @@ -0,0 +1,172 @@ +#pragma once + +#include "amx_hook.h" + +// Manages entity member functions such as (m_pfnThink, m_pfnTouch, m_pfnUse) and dispatches callbacks to AMXX plugins +class CEntityCallbackDispatcher +{ +public: + bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetMoveDone (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + + void UnsetThink (AMX *amx, CBaseEntity *pEntity); + void UnsetTouch (AMX *amx, CBaseEntity *pEntity); + void UnsetUse (AMX *amx, CBaseEntity *pEntity); + void UnsetBlocked (AMX *amx, CBaseEntity *pEntity); + void UnsetMoveDone(AMX *amx, CBaseEntity *pEntity); + + // Enumeration of possible callback types for entity events + enum CallbackType + { + None, // No specific callback type, means unset + Think, + Touch, + Use, + Blocked, + MoveDone, + }; + + // + // @brief Deletes all registered callbacks + void DeleteAllCallbacks(); + + // + // @brief Deletes existing callbacks of the specified type associated with the given entity + // + // @param pEntity Pointer to the entity for which callbacks should be deleted. + // @param type Type of callback to delete (default:None to delete all types) + // + void DeleteExistingCallbacks(CBaseEntity *pEntity, CallbackType type = None); + + // Are we in the middle of processing callbacks? + bool IsProcessingCallbacks() const { return m_bIsProcessingCallbacks; } + + // + // @brief Dispatches callbacks associated with the specified entity and callback type + // + // This function iterates through registered callbacks and executes them for the + // given entity and callback type + // + // + // @param pEntity Pointer to the entity for which callbacks should be dispatched + // @param type Type of callback to dispatch + // @param args Arguments to pass to the callbacks + // + template + void DispatchCallbacks(CBaseEntity *pEntity, CallbackType type, volatile f_args... args) + { + // Flag to indicate that callback processing is currently active. + // This flag is set to true while callback processing to prevent immediate deletion + // of registered callbacks that may be involved in caused AMXX plugin callbacks + // Callbacks marked for deletion are prune after callback processing is complete + m_bIsProcessingCallbacks = true; + + // Iterate through the list of registered callbacks + for (std::list::const_iterator it = m_callbacks.begin(); + it != m_callbacks.end(); it++) + { + const EntityCallback *callback = (*it); + + // Check if the callback is associated with the specified entity and callback type + if (callback->m_pEntity == pEntity && callback->m_callbackType == type) + { + // Check if user parameters provided for this callback + if (callback->m_nUserParamBlockSize > 0) + { + // Execute the callback with the provided arguments and user parameters + g_amxxapi.ExecuteForward(callback->GetFwdIndex(), args..., g_amxxapi.PrepareCellArrayA(callback->m_pUserParams, callback->m_nUserParamBlockSize, true)); + } + else + { + // Execute the callback with the provided arguments + g_amxxapi.ExecuteForward(callback->GetFwdIndex(), args...); + } + } + } + + // Reset the flag to indicate that callback processing has concluded + // From this point onward, entity callbacks will be immediately deleted on the spot as it is, + // without any deferred removals or processing + m_bIsProcessingCallbacks = false; + + // Is there at least one candidate marked for deletion? + if (!m_callbacksMarkForDeletion.empty()) + { + for (std::list::const_iterator it = m_callbacksMarkForDeletion.begin(); + it != m_callbacksMarkForDeletion.end(); it++) + { + const EntityCallback *toDelete = (*it); + + const std::list::const_iterator callbackIt = + std::find(m_callbacks.begin(), m_callbacks.end(), toDelete); + + // Check if the marked for deletion callback + // was found in the list of registered callbacks + if (callbackIt != m_callbacks.end()) + { + m_callbacks.erase(callbackIt); + delete toDelete; + } + } + + m_callbacksMarkForDeletion.clear(); + } + } + +private: + // EntityCallback - a class representing a registered callback for an entity + class EntityCallback: public CAmxxHookBase + { + public: + EntityCallback(AMX *amx, const char *funcname, int index, + CBaseEntity *pEntity, const cell *pParams, size_t iParamsLen, CallbackType type + ) : + CAmxxHookBase(amx, funcname, index, -1), + m_pEntity(pEntity), m_callbackType(type) + { + if (iParamsLen > 0) { + m_nUserParamBlockSize = iParamsLen + 1; + m_pUserParams = new cell[m_nUserParamBlockSize]; + Q_memcpy(m_pUserParams, pParams, sizeof(cell) * iParamsLen); + m_pUserParams[iParamsLen] = 0; + } else { + m_nUserParamBlockSize = 0; + m_pUserParams = nullptr; + } + } + + ~EntityCallback() + { + if (m_pUserParams) + delete[] m_pUserParams; + m_pUserParams = nullptr; + m_nUserParamBlockSize = 0; + } + + // Pointer to the entity for which the callback is registered + CBaseEntity *m_pEntity; + + // Type of the callback (e.g., Think, Touch, Use, and so on) + CallbackType m_callbackType; + + // User-provided data to be passed to their callback function + cell *m_pUserParams; + + // The length of user-provided parameters to be passed to their callback function + size_t m_nUserParamBlockSize; + }; + + // Flag indicating that callback processing is currently in progress + bool m_bIsProcessingCallbacks; + + // List of registered callbacks + std::list m_callbacks; + + // List of callbacks marked for deletion after dispatching callbacks is complete + std::list m_callbacksMarkForDeletion; +}; + +CEntityCallbackDispatcher &EntityCallbackDispatcher(); diff --git a/reapi/src/main.cpp b/reapi/src/main.cpp index 263786b6..d82b4252 100644 --- a/reapi/src/main.cpp +++ b/reapi/src/main.cpp @@ -69,7 +69,7 @@ void ServerDeactivate_Post() api_cfg.ServerDeactivate(); g_hookManager.Clear(); g_queryFileManager.Clear(); - g_entCallback.Clear(); + EntityCallbackDispatcher().DeleteAllCallbacks(); g_pFunctionTable->pfnSpawn = DispatchSpawn; g_pFunctionTable->pfnKeyValue = KeyValue; @@ -140,6 +140,6 @@ void OnFreeEntPrivateData(edict_t *pEdict) return; } - g_entCallback.Clear(pEntity); + EntityCallbackDispatcher().DeleteExistingCallbacks(pEntity); SET_META_RESULT(MRES_IGNORED); } diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index 8b2b8508..fff90643 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -287,7 +287,7 @@ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params) char namebuf[256]; const char *funcname = getAmxString(amx, params[arg_handler], namebuf); if (unlikely(funcname == nullptr || funcname[0] == '\0')) { - pEntity->SetThink(nullptr); + EntityCallbackDispatcher().UnsetThink(amx, pEntity); return TRUE; } @@ -298,7 +298,7 @@ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params) } cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; - return (cell)g_entCallback.SetThink(amx, pEntity, funcname, pParams, params[arg_len]); + return (cell)EntityCallbackDispatcher().SetThink(amx, pEntity, funcname, pParams, params[arg_len]); } /* @@ -331,7 +331,7 @@ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params) char namebuf[256]; const char *funcname = getAmxString(amx, params[arg_handler], namebuf); if (unlikely(funcname == nullptr || funcname[0] == '\0')) { - pEntity->SetTouch(nullptr); + EntityCallbackDispatcher().UnsetTouch(amx, pEntity); return TRUE; } @@ -342,7 +342,7 @@ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params) } cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; - return (cell)g_entCallback.SetTouch(amx, pEntity, funcname, pParams, params[arg_len]); + return (cell)EntityCallbackDispatcher().SetTouch(amx, pEntity, funcname, pParams, params[arg_len]); } /* @@ -375,7 +375,7 @@ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params) char namebuf[256]; const char *funcname = getAmxString(amx, params[arg_handler], namebuf); if (unlikely(funcname == nullptr || funcname[0] == '\0')) { - pEntity->SetUse(nullptr); + EntityCallbackDispatcher().UnsetUse(amx, pEntity); return TRUE; } @@ -386,7 +386,7 @@ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params) } cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; - return (cell)g_entCallback.SetUse(amx, pEntity, funcname, pParams, params[arg_len]); + return (cell)EntityCallbackDispatcher().SetUse(amx, pEntity, funcname, pParams, params[arg_len]); } /* @@ -419,7 +419,7 @@ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params) char namebuf[256]; const char *funcname = getAmxString(amx, params[arg_handler], namebuf); if (unlikely(funcname == nullptr || funcname[0] == '\0')) { - pEntity->SetBlocked(nullptr); + EntityCallbackDispatcher().UnsetBlocked(amx, pEntity); return TRUE; } @@ -430,7 +430,7 @@ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params) } cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; - return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname, pParams, params[arg_len]); + return (cell)EntityCallbackDispatcher().SetBlocked(amx, pEntity, funcname, pParams, params[arg_len]); } /* @@ -464,7 +464,7 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) char namebuf[256]; const char *funcname = getAmxString(amx, params[arg_handler], namebuf); if (unlikely(funcname == nullptr || funcname[0] == '\0')) { - ((CBaseToggle *)pEntity)->SetMoveDone(nullptr); + EntityCallbackDispatcher().UnsetMoveDone(amx, pEntity); return TRUE; } @@ -475,7 +475,7 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) } cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; - return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname, pParams, params[arg_len]); + return (cell)EntityCallbackDispatcher().SetMoveDone(amx, pEntity, funcname, pParams, params[arg_len]); } AMX_NATIVE_INFO Natives_Common[] = diff --git a/reapi/src/precompiled.h b/reapi/src/precompiled.h index 742ef8c9..e9a4ae4d 100644 --- a/reapi/src/precompiled.h +++ b/reapi/src/precompiled.h @@ -9,6 +9,7 @@ // C++ #include // std::vector +#include // std::list // platform defs #include "platform.h" @@ -60,7 +61,7 @@ #include "api_config.h" #include "hook_manager.h" #include "hook_callback.h" -#include "entity_callback.h" +#include "entity_callback_dispatcher.h" #include "member_list.h" // natives From 30c1964df17cc620f7e749490356d39806421549 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Sep 2023 09:13:44 +0700 Subject: [PATCH 26/50] Add an important clarification to the native rg_create_entity comment about cannot use a hash table for an entity with mutable class name otherwise, it will cause a memory leak --- .../amxmodx/scripting/include/reapi_gamedll.inc | 5 +++-- reapi/src/natives/natives_misc.cpp | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 984fb563..38df2034 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -419,8 +419,9 @@ native rg_update_teamscores(const iCtsWins = 0, const iTsWins = 0, const bool:bA * * @param classname Entity classname * @param useHashTable Use this only for known game entities -* -* @note: Do not use this if you use a custom classname +* @note: Do not use this if you plan to change custom classname an entity after creation, +* otherwise it will never be release from hash table even if an entity was destroyed, +* and that to lead table to inflate/memory leaks * * @return Index of the created entity or 0 otherwise */ diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 24b19f04..837907fd 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -542,8 +542,9 @@ cell AMX_NATIVE_CALL rg_update_teamscores(AMX *amx, cell *params) * * @param classname Entity classname * @param useHashTable Use this only for known game entities -* -* @note: Do not use this if you use a custom classname +* @note: Do not use this if you plan to change custom classname an entity after creation, +* otherwise it will never be release from hash table even if an entity was destroyed, +* and that to lead table to inflate/memory leaks * * @return Index of the created entity or 0 otherwise * @@ -1259,7 +1260,7 @@ cell AMX_NATIVE_CALL rg_give_defusekit(AMX *amx, cell *params) if (CSGameRules() != nullptr && !CSGameRules()->m_bMapHasBombTarget && !CSGameRules()->m_bMapHasBombZone) { return FALSE; } - + if (pPlayer->m_iTeam != CT) { return FALSE; } @@ -2734,7 +2735,7 @@ cell AMX_NATIVE_CALL rh_drop_client(AMX *amx, cell *params) * * @param output Buffer to copy the ip address * @param len Maximum buffer size -* +* * @noreturn * * native rh_get_net_from(output[], len); @@ -2747,7 +2748,7 @@ cell AMX_NATIVE_CALL rh_get_net_from(AMX* amx, cell* params) char *addr = NET_AdrToString(*g_RehldsData->GetNetFrom()); setAmxString(dest, addr, params[arg_maxlen]); - + return TRUE; } @@ -2772,7 +2773,7 @@ cell AMX_NATIVE_CALL rh_get_client_connect_time(AMX *amx, cell *params) AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[arg_index]); return FALSE; } - + return (cell)(g_RehldsFuncs->GetRealTime() - pClient->netchan.connect_time); } From 20d81334f8f50cb3ebd6ec2cd23c1de07a230a76 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Sep 2023 09:26:22 +0700 Subject: [PATCH 27/50] Update cmake/project files --- reapi/CMakeLists.txt | 2 +- reapi/msvc/reapi.vcxproj | 4 ++-- reapi/msvc/reapi.vcxproj.filters | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/reapi/CMakeLists.txt b/reapi/CMakeLists.txt index 5e064074..cfe8f930 100644 --- a/reapi/CMakeLists.txt +++ b/reapi/CMakeLists.txt @@ -111,7 +111,7 @@ set(REAPI_SRCS "src/amxxmodule.cpp" "src/h_export.cpp" "src/dllapi.cpp" - "src/entity_callback.cpp" + "src/entity_callback_dispatcher.cpp" "src/hook_callback.cpp" "src/hook_list.cpp" "src/hook_manager.cpp" diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index 5fdef54e..4573b111 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -210,7 +210,7 @@ - + @@ -255,7 +255,7 @@ - + diff --git a/reapi/msvc/reapi.vcxproj.filters b/reapi/msvc/reapi.vcxproj.filters index 99cf6ff6..41448a5c 100644 --- a/reapi/msvc/reapi.vcxproj.filters +++ b/reapi/msvc/reapi.vcxproj.filters @@ -699,7 +699,7 @@ common - + src @@ -821,7 +821,7 @@ common - + src From 2b8ae61f1e44fce3bcde37fab8293831f6358c2d Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Sep 2023 10:25:01 +0700 Subject: [PATCH 28/50] Fix comment --- reapi/src/entity_callback_dispatcher.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/reapi/src/entity_callback_dispatcher.cpp b/reapi/src/entity_callback_dispatcher.cpp index 54fdbb99..18d574e3 100644 --- a/reapi/src/entity_callback_dispatcher.cpp +++ b/reapi/src/entity_callback_dispatcher.cpp @@ -155,7 +155,6 @@ bool CEntityCallbackDispatcher::SetMoveDone(AMX *amx, CBaseEntity *pEntity, cons return false; } - // TODO: Make sure that the entity actually inherited from CBaseToggle pEntityToggle->SetMoveDone(&CBaseToggle::SUB_MoveDone); return true; } From eab165880efcc5dad3ec83dd9a89d85d0aa12dfe Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Sep 2023 15:26:17 +0700 Subject: [PATCH 29/50] Fix SetMoveDone callback dispatcher --- reapi/src/entity_callback_dispatcher.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reapi/src/entity_callback_dispatcher.cpp b/reapi/src/entity_callback_dispatcher.cpp index 18d574e3..71279336 100644 --- a/reapi/src/entity_callback_dispatcher.cpp +++ b/reapi/src/entity_callback_dispatcher.cpp @@ -145,8 +145,6 @@ bool CEntityCallbackDispatcher::SetMoveDone(AMX *amx, CBaseEntity *pEntity, cons return false; } - m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, MoveDone)); - // Make sure that the entity actually inherited from CBaseToggle CBaseToggle *pEntityToggle = dynamic_cast(pEntity); if (!pEntityToggle) @@ -155,6 +153,7 @@ bool CEntityCallbackDispatcher::SetMoveDone(AMX *amx, CBaseEntity *pEntity, cons return false; } + m_callbacks.push_back(new EntityCallback(amx, pszCallback, fwdid, pEntity, pParams, iParamsLen, MoveDone)); pEntityToggle->SetMoveDone(&CBaseToggle::SUB_MoveDone); return true; } From da81fe511d2efe4e2c898b68f7a2c8d46922a13b Mon Sep 17 00:00:00 2001 From: s1lentq Date: Tue, 5 Sep 2023 20:08:20 +0700 Subject: [PATCH 30/50] Update workflows/build.yml --- .github/workflows/build.yml | 61 ++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b191a309..2f8746ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,12 +23,14 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v1.1.3 + with: + vs-version: '16.8' - name: Build run: | @@ -43,7 +45,7 @@ jobs: move msvc\${{ env.buildRelease }}\reapi_amxx.pdb publish\debug\reapi_amxx.pdb - name: Deploy artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3.1.1 with: name: win32 path: publish/* @@ -52,10 +54,12 @@ jobs: name: 'Linux' runs-on: ubuntu-latest container: s1lentq/linux86buildtools:latest + outputs: + app-version: ${{ steps.app-version.outputs.version }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 @@ -63,6 +67,21 @@ jobs: run: | rm -rf build && CC=icc CXX=icpc cmake -B build && cmake --build build -j8 + - name: Reading appversion.h + id: app-version + run: | + if [ -e "reapi/version/appversion.h" ]; then + APP_VERSION=$(cat "reapi/version/appversion.h" | grep -wi '#define APP_VERSION_STRD' | sed -e 's/#define APP_VERSION_STRD[ \t\r\n\v\f]\+\(.*\)/\1/i' -e 's/\r//g') + if [ $? -ne 0 ]; then + APP_VERSION="" + else + # Remove quotes + APP_VERSION=$(echo $APP_VERSION | xargs) + fi + fi + echo "version=${APP_VERSION}" >> "$GITHUB_OUTPUT" + shell: bash + - name: Prepare AMXX run: | mkdir -p publish/addons/amxmodx/modules @@ -72,7 +91,6 @@ jobs: - name: Move files run: | mv build/reapi/reapi_amxx_i386.so publish/addons/amxmodx/modules/reapi_amxx_i386.so - mv reapi/version/appversion.h publish/appversion.h - name: Run GLIBC/ABI version compat test run: | @@ -86,17 +104,12 @@ jobs: shell: bash - name: Deploy artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3.1.1 id: upload-job with: name: linux32 path: publish/* - - name: Cleanup temporary artifacts - if: success() && steps.upload-job.outcome == 'success' - run: | - rm -f appversion.h - publish: name: 'Publish' runs-on: ubuntu-latest @@ -104,29 +117,15 @@ jobs: steps: - name: Deploying linux artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: linux32 - name: Deploying windows artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: win32 - - name: Reading appversion.h - run: | - if [ -e appversion.h ]; then - APP_VERSION=$(cat appversion.h | grep -wi '#define APP_VERSION_STRD' | sed -e 's/#define APP_VERSION_STRD[ \t\r\n\v\f]\+\(.*\)/\1/i' -e 's/\r//g') - if [ $? -ne 0 ]; then - APP_VERSION="" - else - # Remove quotes - APP_VERSION=$(echo $APP_VERSION | xargs) - echo "APP_VERSION=${APP_VERSION}" >> $GITHUB_ENV - fi - fi - rm -f appversion.h - - name: Packaging binaries id: packaging-job if: | @@ -134,7 +133,7 @@ jobs: github.event.action == 'published' && startsWith(github.ref, 'refs/tags/') run: | - 7z a -tzip reapi-bin-${{ env.APP_VERSION }}.zip addons/ + 7z a -tzip reapi-bin-${{ needs.linux.outputs.app-version }}.zip addons/ - name: Publish artifacts uses: softprops/action-gh-release@v1 @@ -147,9 +146,3 @@ jobs: *.zip env: GITHUB_TOKEN: ${{ secrets.API_TOKEN }} - - - name: Cleanup temporary artifacts - if: success() && steps.publish-job.outcome == 'success' - run: | - rm -rf addons debug - rm -f *.zip appversion.h From 463799748e9b62155f9e07c7cb33b58c033c71b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Tue, 5 Sep 2023 10:33:21 -0300 Subject: [PATCH 31/50] `API`: Added rg_set/get_global_iteminfo natives (#279) --- .../scripting/include/reapi_gamedll.inc | 22 +++ .../scripting/include/reapi_gamedll_const.inc | 2 +- reapi/src/natives/natives_misc.cpp | 132 ++++++++++++++++++ 3 files changed, 155 insertions(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 38df2034..f454e988 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -896,6 +896,28 @@ native rg_set_iteminfo(const entity, ItemInfo:type, any:...); */ native rg_get_iteminfo(const ent, ItemInfo:type, any:...); +/** +* Sets a parameter of the global CBasePlayerItem::m_ItemInfoArray array +* @note To have effect on client side (i.g. ammo size on HUD) you should +* alter this value BEFORE WeaponList message is sent to client, or +* force it's alteration by sending again to the specific client. +* Hooking WeaponList message with AMXX's register_message is a choice. +* +* @param weapon_id Weapon id, see WEAPON_* constants +* @param type Item info type. See ItemInfo constants. +* +*/ +native rg_set_global_iteminfo(const {WeaponIdType,_}:weapon_id, ItemInfo:type, any:...); + +/** +* Gets a parameter of the global CBasePlayerItem::m_ItemInfoArray array +* +* @param weapon_id Weapon id, see WEAPON_* constants +* @param type Item info type. See ItemInfo constants. +* +*/ +native rg_get_global_iteminfo(const {WeaponIdType,_}:weapon_id, ItemInfo:type, any:...); + /* * Adds hint message to the queue. * diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index df3ebb7e..ce31aa34 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -138,7 +138,7 @@ enum WpnInfo }; /** -* Item's info types for use with rg_set_iteminfo/rg_get_iteminfo() +* Item's info types for use with rg_set_[global_]iteminfo/rg_get_[global_]iteminfo() */ enum ItemInfo { diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 837907fd..a9170846 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -2244,6 +2244,136 @@ cell AMX_NATIVE_CALL rg_get_iteminfo(AMX *amx, cell *params) return TRUE; } +/** +* Sets a parameter of the global CBasePlayerItem::m_ItemInfoArray array +* @note To have effect on client side (i.g. ammo size on HUD) you should +* alter this value BEFORE WeaponList message is sent to client, or +* force it's alteration by sending again to the specific client. +* Hooking WeaponList message with AMXX's register_message is a choice. +* +* @param weapon_id Weapon id, see WEAPON_* constants +* @param type Item info type. See ItemInfo constants. +* +* native rg_set_global_iteminfo(const {WeaponIdType,_}:weapon_id, ItemInfo:type, any:...); +*/ +cell AMX_NATIVE_CALL rg_set_global_iteminfo(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_weapon_id, arg_type, arg_value }; + + WeaponIdType weaponId = static_cast(params[arg_weapon_id]); + if (!GetWeaponInfoRange(weaponId, false)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid weapon id %i", __FUNCTION__, weaponId); + return FALSE; + } + + ItemInfo* II = g_ReGameApi->GetItemInfo(weaponId); + + char itembuf[256]; + cell *ptr = getAmxAddr(amx, params[arg_value]); + + ItemInfo_e type = static_cast(params[arg_type]); + switch (type) + { + case ItemInfo_iSlot: II->iSlot = *ptr; break; + case ItemInfo_iPosition: II->iPosition = *ptr; break; + case ItemInfo_iMaxAmmo1: II->iMaxAmmo1 = *ptr; break; + case ItemInfo_iMaxAmmo2: II->iMaxAmmo2 = *ptr; break; + case ItemInfo_iMaxClip: II->iMaxClip = *ptr; break; + case ItemInfo_iId: II->iId = *ptr; break; + case ItemInfo_iFlags: II->iFlags = *ptr; break; + case ItemInfo_iWeight: II->iWeight = *ptr; break; + case ItemInfo_pszAmmo1: II->pszAmmo1 = STRING(getAmxStringAlloc(amx, params[arg_value], itembuf)); break; + case ItemInfo_pszAmmo2: II->pszAmmo2 = STRING(getAmxStringAlloc(amx, params[arg_value], itembuf)); break; + case ItemInfo_pszName: II->pszName = STRING(getAmxStringAlloc(amx, params[arg_value], itembuf)); break; + + default: + AMXX_LogError(amx, AMX_ERR_NATIVE, "Unknown ItemInfo type %d", type); + return FALSE; + } + + return TRUE; +} + +/** +* Gets a parameter of the global CBasePlayerItem::m_ItemInfoArray array +* +* @param weapon_id Weapon id, see WEAPON_* constants +* @param type Item info type. See ItemInfo constants. +* +* native rg_get_global_iteminfo(const {WeaponIdType,_}:weapon_id, ItemInfo:type, any:...); +*/ +cell AMX_NATIVE_CALL rg_get_global_iteminfo(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_weapon_id, arg_type, arg_output, arg_length }; + + WeaponIdType weaponId = static_cast(params[arg_weapon_id]); + if (!GetWeaponInfoRange(weaponId, false)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid weapon id %i", __FUNCTION__, weaponId); + return FALSE; + } + + ItemInfo_e type = static_cast(params[arg_type]); + if ((type == ItemInfo_pszAmmo1 || type == ItemInfo_pszAmmo2 || type == ItemInfo_pszName) && PARAMS_COUNT != 4) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "Bad arg count. Expected %d, got %d.", 4, PARAMS_COUNT); + return FALSE; + } + + ItemInfo* II = g_ReGameApi->GetItemInfo(weaponId); + + cell *dest = getAmxAddr(amx, params[arg_output]); + size_t length = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_length]) : 0; + + switch (type) + { + case ItemInfo_iSlot: return II->iSlot; + case ItemInfo_iPosition: return II->iPosition; + case ItemInfo_iMaxAmmo1: return II->iMaxAmmo1; + case ItemInfo_iMaxAmmo2: return II->iMaxAmmo2; + case ItemInfo_iMaxClip: return II->iMaxClip; + case ItemInfo_iId: return II->iId; + case ItemInfo_iFlags: return II->iFlags; + case ItemInfo_iWeight: return II->iWeight; + case ItemInfo_pszAmmo1: + { + if (II->pszAmmo1 == nullptr) { + setAmxString(dest, "", 1); + break; + } + + setAmxString(dest, II->pszAmmo1, length); + break; + } + case ItemInfo_pszAmmo2: + { + if (II->pszAmmo2 == nullptr) { + setAmxString(dest, "", 1); + break; + } + + setAmxString(dest, II->pszAmmo2, length); + break; + } + case ItemInfo_pszName: + { + if (II->pszName == nullptr) { + setAmxString(dest, "", 1); + break; + } + + setAmxString(dest, II->pszName, length); + break; + } + default: + AMXX_LogError(amx, AMX_ERR_NATIVE, "Unknown ItemInfo type %d", type); + return FALSE; + } + + return TRUE; +} + /* * Adds hint message to the queue. * @@ -2555,6 +2685,8 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_set_iteminfo", rg_set_iteminfo }, { "rg_get_iteminfo", rg_get_iteminfo }, + { "rg_set_global_iteminfo", rg_set_global_iteminfo }, + { "rg_get_global_iteminfo", rg_get_global_iteminfo }, { "rg_hint_message", rg_hint_message }, From 4ef19557c96a8262c4798587b7dcdf2d12eee462 Mon Sep 17 00:00:00 2001 From: Javekson <132286351+Javekson@users.noreply.github.com> Date: Tue, 5 Sep 2023 18:11:49 +0400 Subject: [PATCH 32/50] Added a new argument removeAmmo to the rg_remove_items_by_slot native (#283) --- .../scripting/include/reapi_gamedll.inc | 9 +++++---- reapi/src/natives/natives_misc.cpp | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index f454e988..3ea2a44c 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -496,12 +496,13 @@ native rg_set_weapon_info(const {WeaponIdType,_}:weapon_id, WpnInfo:type, any:.. /* * Remove all the player's stuff in a specific slot. * -* @param index Client index -* @param slot The slot that will be emptied +* @param index Client index +* @param slot The slot that will be emptied +* @param removeAmmo Remove ammunition * -* @return 1 on success, 0 otherwise +* @return 1 on success, 0 otherwise */ -native rg_remove_items_by_slot(const index, const InventorySlotType:slot); +native rg_remove_items_by_slot(const index, const InventorySlotType:slot, const bool:removeAmmo = true); /* * Drop to floor all the player's stuff by specific slot. diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index a9170846..8d1bcb6e 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -905,16 +905,17 @@ cell AMX_NATIVE_CALL rg_set_weapon_info(AMX *amx, cell *params) /* * Remove all the player's stuff in a specific slot. * -* @param index Client index -* @param slot The slot that will be emptied +* @param index Client index +* @param slot The slot that will be emptied +* @param removeAmmo Remove ammunition * -* @return 1 on success, 0 otherwise +* @return 1 on success, 0 otherwise * -* native rg_remove_items_by_slot(const index, const InventorySlotType:slot); +* native rg_remove_items_by_slot(const index, const InventorySlotType:slot, const bool:removeAmmo = true); */ cell AMX_NATIVE_CALL rg_remove_items_by_slot(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_slot }; + enum args_e { arg_count, arg_index, arg_slot, arg_remammo }; CHECK_ISPLAYER(arg_index); @@ -927,14 +928,18 @@ cell AMX_NATIVE_CALL rg_remove_items_by_slot(AMX *amx, cell *params) } else { - pPlayer->ForEachItem(params[arg_slot], [pPlayer](CBasePlayerItem *pItem) + pPlayer->ForEachItem(params[arg_slot], [pPlayer, params](CBasePlayerItem *pItem) { if (pItem->IsWeapon()) { if (pItem == pPlayer->m_pActiveItem) { ((CBasePlayerWeapon *)pItem)->RetireWeapon(); } - pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ] = 0; + // Compatible with older versions of the plugin, + // which still only pass two parameters + if (PARAMS_COUNT < 3 || params[arg_remammo]) { + pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ] = 0; + } } if (pPlayer->RemovePlayerItem(pItem)) { From 2142208e77a118dabd3a4e596c18cf772b0f4bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Tue, 5 Sep 2023 20:33:11 -0300 Subject: [PATCH 33/50] `API`: New gamedll hookchains (#280) --- .../amxmodx/scripting/include/cssdk_const.inc | 117 +++++++- .../extra/amxmodx/scripting/include/reapi.inc | 9 +- .../scripting/include/reapi_gamedll_const.inc | 144 ++++++++++ reapi/include/cssdk/dlls/regamedll_api.h | 120 ++++++++- reapi/src/hook_callback.cpp | 249 ++++++++++++++++++ reapi/src/hook_callback.h | 29 ++ reapi/src/hook_list.cpp | 31 ++- reapi/src/hook_list.h | 31 +++ 8 files changed, 719 insertions(+), 11 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 8aa09a01..149baeed 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -75,9 +75,9 @@ * global_get(glb_trace_flags) values * @note Custom flags that we can retrieve in pfnShouldCollide/TraceLine/TraceHull */ -#define FTRACE_BULLET (1<<16) -#define FTRACE_FLASH (1<<17) -#define FTRACE_KNIFE (1<<18) +#define FTRACE_BULLET (1<<16) +#define FTRACE_FLASH (1<<17) +#define FTRACE_KNIFE (1<<18) /** * get_entvar(entity, var_movetype) values @@ -1368,3 +1368,114 @@ enum InfoMapBuyParam #define SCORE_STATUS_BOMB (1<<1) #define SCORE_STATUS_VIP (1<<2) #define SCORE_STATUS_DEFKIT (1<<3) + +/** +* For RG_CBotManager_OnEvent +*/ +enum GameEventType +{ + EVENT_INVALID = 0, + EVENT_WEAPON_FIRED, // tell bots the player is attack (argumens: 1 = attacker, 2 = NULL) + EVENT_WEAPON_FIRED_ON_EMPTY, // tell bots the player is attack without clip ammo (argumens: 1 = attacker, 2 = NULL) + EVENT_WEAPON_RELOADED, // tell bots the player is reloading his weapon (argumens: 1 = reloader, 2 = NULL) + + EVENT_HE_GRENADE_EXPLODED, // tell bots the HE grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) + EVENT_FLASHBANG_GRENADE_EXPLODED, // tell bots the flashbang grenade is exploded (argumens: 1 = grenade thrower, 2 = explosion origin) + EVENT_SMOKE_GRENADE_EXPLODED, // tell bots the smoke grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) + EVENT_GRENADE_BOUNCED, + + EVENT_BEING_SHOT_AT, + EVENT_PLAYER_BLINDED_BY_FLASHBANG, // tell bots the player is flashed (argumens: 1 = flashed player, 2 = NULL) + EVENT_PLAYER_FOOTSTEP, // tell bots the player is running (argumens: 1 = runner, 2 = NULL) + EVENT_PLAYER_JUMPED, // tell bots the player is jumped (argumens: 1 = jumper, 2 = NULL) + EVENT_PLAYER_DIED, // tell bots the player is killed (argumens: 1 = victim, 2 = killer) + EVENT_PLAYER_LANDED_FROM_HEIGHT, // tell bots the player is fell with some damage (argumens: 1 = felled player, 2 = NULL) + EVENT_PLAYER_TOOK_DAMAGE, // tell bots the player is take damage (argumens: 1 = victim, 2 = attacker) + EVENT_HOSTAGE_DAMAGED, // tell bots the player has injured a hostage (argumens: 1 = hostage, 2 = injurer) + EVENT_HOSTAGE_KILLED, // tell bots the player has killed a hostage (argumens: 1 = hostage, 2 = killer) + + EVENT_DOOR, // tell bots the door is moving (argumens: 1 = door, 2 = NULL) + EVENT_BREAK_GLASS, // tell bots the glass has break (argumens: 1 = glass, 2 = NULL) + EVENT_BREAK_WOOD, // tell bots the wood has break (argumens: 1 = wood, 2 = NULL) + EVENT_BREAK_METAL, // tell bots the metal/computer has break (argumens: 1 = metal/computer, 2 = NULL) + EVENT_BREAK_FLESH, // tell bots the flesh has break (argumens: 1 = flesh, 2 = NULL) + EVENT_BREAK_CONCRETE, // tell bots the concrete has break (argumens: 1 = concrete, 2 = NULL) + + EVENT_BOMB_PLANTED, // tell bots the bomb has been planted (argumens: 1 = planter, 2 = NULL) + EVENT_BOMB_DROPPED, // tell bots the bomb has been dropped (argumens: 1 = NULL, 2 = NULL) + EVENT_BOMB_PICKED_UP, // let the bots hear the bomb pickup (argumens: 1 = player that pickup c4, 2 = NULL) + EVENT_BOMB_BEEP, // let the bots hear the bomb beeping (argumens: 1 = c4, 2 = NULL) + EVENT_BOMB_DEFUSING, // tell the bots someone has started defusing (argumens: 1 = defuser, 2 = NULL) + EVENT_BOMB_DEFUSE_ABORTED, // tell the bots someone has aborted defusing (argumens: 1 = NULL, 2 = NULL) + EVENT_BOMB_DEFUSED, // tell the bots the bomb is defused (argumens: 1 = defuser, 2 = NULL) + EVENT_BOMB_EXPLODED, // let the bots hear the bomb exploding (argumens: 1 = NULL, 2 = NULL) + + EVENT_HOSTAGE_USED, // tell bots the hostage is used (argumens: 1 = user, 2 = NULL) + EVENT_HOSTAGE_RESCUED, // tell bots the hostage is rescued (argumens: 1 = rescuer (CBasePlayer *), 2 = hostage (CHostage *)) + EVENT_ALL_HOSTAGES_RESCUED, // tell bots the all hostages are rescued (argumens: 1 = NULL, 2 = NULL) + + EVENT_VIP_ESCAPED, // tell bots the VIP is escaped (argumens: 1 = NULL, 2 = NULL) + EVENT_VIP_ASSASSINATED, // tell bots the VIP is assassinated (argumens: 1 = NULL, 2 = NULL) + EVENT_TERRORISTS_WIN, // tell bots the terrorists won the round (argumens: 1 = NULL, 2 = NULL) + EVENT_CTS_WIN, // tell bots the CTs won the round (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_DRAW, // tell bots the round was a draw (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_WIN, // tell carreer the round was a win (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_LOSS, // tell carreer the round was a loss (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_START, // tell bots the round was started (when freeze period is expired) (argumens: 1 = NULL, 2 = NULL) + EVENT_PLAYER_SPAWNED, // tell bots the player is spawned (argumens: 1 = spawned player, 2 = NULL) + EVENT_CLIENT_CORPSE_SPAWNED, + EVENT_BUY_TIME_START, + EVENT_PLAYER_LEFT_BUY_ZONE, + EVENT_DEATH_CAMERA_START, + EVENT_KILL_ALL, + EVENT_ROUND_TIME, + EVENT_DIE, + EVENT_KILL, + EVENT_HEADSHOT, + EVENT_KILL_FLASHBANGED, + EVENT_TUTOR_BUY_MENU_OPENNED, + EVENT_TUTOR_AUTOBUY, + EVENT_PLAYER_BOUGHT_SOMETHING, + EVENT_TUTOR_NOT_BUYING_ANYTHING, + EVENT_TUTOR_NEED_TO_BUY_PRIMARY_WEAPON, + EVENT_TUTOR_NEED_TO_BUY_PRIMARY_AMMO, + EVENT_TUTOR_NEED_TO_BUY_SECONDARY_AMMO, + EVENT_TUTOR_NEED_TO_BUY_ARMOR, + EVENT_TUTOR_NEED_TO_BUY_DEFUSE_KIT, + EVENT_TUTOR_NEED_TO_BUY_GRENADE, + EVENT_CAREER_TASK_DONE, + + EVENT_START_RADIO_1, + EVENT_RADIO_COVER_ME, + EVENT_RADIO_YOU_TAKE_THE_POINT, + EVENT_RADIO_HOLD_THIS_POSITION, + EVENT_RADIO_REGROUP_TEAM, + EVENT_RADIO_FOLLOW_ME, + EVENT_RADIO_TAKING_FIRE, + EVENT_START_RADIO_2, + EVENT_RADIO_GO_GO_GO, + EVENT_RADIO_TEAM_FALL_BACK, + EVENT_RADIO_STICK_TOGETHER_TEAM, + EVENT_RADIO_GET_IN_POSITION_AND_WAIT, + EVENT_RADIO_STORM_THE_FRONT, + EVENT_RADIO_REPORT_IN_TEAM, + EVENT_START_RADIO_3, + EVENT_RADIO_AFFIRMATIVE, + EVENT_RADIO_ENEMY_SPOTTED, + EVENT_RADIO_NEED_BACKUP, + EVENT_RADIO_SECTOR_CLEAR, + EVENT_RADIO_IN_POSITION, + EVENT_RADIO_REPORTING_IN, + EVENT_RADIO_GET_OUT_OF_THERE, + EVENT_RADIO_NEGATIVE, + EVENT_RADIO_ENEMY_DOWN, + EVENT_END_RADIO, + + EVENT_NEW_MATCH, // tell bots the game is new (argumens: 1 = NULL, 2 = NULL) + EVENT_PLAYER_CHANGED_TEAM, // tell bots the player is switch his team (also called from ClientPutInServer()) (argumens: 1 = switcher, 2 = NULL) + EVENT_BULLET_IMPACT, // tell bots the player is shoot at wall (argumens: 1 = shooter, 2 = shoot trace end position) + EVENT_GAME_COMMENCE, // tell bots the game is commencing (argumens: 1 = NULL, 2 = NULL) + EVENT_WEAPON_ZOOMED, // tell bots the player is switch weapon zoom (argumens: 1 = zoom switcher, 2 = NULL) + EVENT_HOSTAGE_CALLED_FOR_HELP, // tell bots the hostage is talking (argumens: 1 = listener, 2 = NULL) + NUM_GAME_EVENTS, +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi.inc b/reapi/extra/amxmodx/scripting/include/reapi.inc index aac39c33..2b95782d 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi.inc @@ -25,7 +25,8 @@ enum hooks_tables_e ht_weaponbox, ht_weapon, ht_gib, - ht_cbaseentity + ht_cbaseentity, + ht_botmanager }; enum members_tables_e @@ -81,6 +82,8 @@ enum members_tables_e mt_gib }; +#define ReAPIFunc {EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib, GamedllFunc_CBaseEntity, GamedllFunc_CBotManager} + // Is like FNullEnt #define is_nullent(%0) (%0 == 0 || is_entity(%0) == false) @@ -149,7 +152,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, GamedllFunc_CBaseEntity}:function_id, const callback[], post = 0); +native HookChain:RegisterHookChain(ReAPIFunc:function_id, const callback[], post = 0); /* * Stops a hook from triggering. @@ -210,7 +213,7 @@ native SetHookChainArg(number, AType:type, any:...); * * @return Returns true if the original function was called, otherwise false */ -native bool:IsReapiHookOriginalWasCalled({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib}:function_id); +native bool:IsReapiHookOriginalWasCalled(ReAPIFunc:function_id); /* * Returns the current hookchain handle. diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index ce31aa34..2bc7f000 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -413,6 +413,72 @@ enum GamedllFunc * Params: (const pLadder, const playerIndex) */ RG_PM_LadderMove, + + /* + * Description: Called on every frame after a player jumps on water for a short period of time + * Params: (const playerIndex) + */ + RG_PM_WaterJump, + + /* + * Description: Called when a player jumps on water for the first time + * Params: (const playerIndex) + */ + RG_PM_CheckWaterJump, + + /* + * Description: Called on every frame while player presses jump button + * Params: (const playerIndex) + */ + RG_PM_Jump, + + /* + * Description: Called on every frame to check player ducking + * Params: (const playerIndex) + */ + RG_PM_Duck, + + /* + * Description: Called whenever player tries to unduck + * Params: (const playerIndex) + */ + RG_PM_UnDuck, + + /* + * Description: Called whenever player emits an step sound + * Params: (step, Float:fvol, const playerIndex) + */ + RG_PM_PlayStepSound, + + /* + * Description: Called whenever player is on air (not touching floor) + * Params: (Float:wishdir[3], Float:wishspeed, Float:accel, const playerIndex) + */ + RG_PM_AirAccelerate, + + /* + * Description: Called when game clears multidamage data (before TraceAttack) + * Params: () + */ + RG_ClearMultiDamage, + + /* + * Description: Called inside TraceAttack to store entity damage to multidamage data + * Params: (const pevInflictor, const pEntity, Float:flDamage, bitsDamageType) + */ + RG_AddMultiDamage, + + /* + * Description: Called after game finished a bullet tracing for applying damage cached on multidamage data + * Params: (const pevInflictor, const pevAttacker) + */ + RG_ApplyMultiDamage, + + /* + * Description: Called when player buys an item from buy menu (Nightvision, Kevlar, etc.) + * Params: (const pPlayer, iSlot) + */ + RG_BuyItem, }; /** @@ -834,6 +900,20 @@ enum GamedllFunc_CBasePlayer * Params: (const this) */ RG_CBasePlayer_JoiningThink, + + /* + * Description: Called every client frame to check time based damage + * Return type: void + * Params: (const this) + */ + RG_CBasePlayer_CheckTimeBasedDamage, + + /* + * Description: Called when game selects a spawn point (info_player_start/deathmatch) to position the player + * Return type: edict_t * (Entity index of selected spawn point) + * Params: (const this) + */ + RG_CBasePlayer_EntSelectSpawnPoint, }; /** @@ -868,6 +948,29 @@ enum GamedllFunc_CBasePlayerWeapon * Params: (const this, iAnim, iStartAnim, Float:fDelay, Float:fStartDelay, const pszReloadSound1[], const pszReloadSound2[]) */ RG_CBasePlayerWeapon_DefaultShotgunReload, + + /* + * Description: Called every client frame (PlayerPostThink) for the player's active weapon + * Return type: void + * Params: (const this) + */ + RG_CBasePlayerWeapon_ItemPostFrame, + + /* + * Description: Called whenever player fires a weapon and shakes player screen (punchangles altering) + * @note Weapons that use KickBack: AK47, AUG, FAMAS, GALIL, M249, M4A1, MAC10, MP5NAVY, P90, SG552, TMP, UMP45 + * Return type: void + * Params: (const this, Float:up_base, Float:lateral_base, Float:up_modifier, Float:lateral_modifier, Float:p_max, Float:lateral_max, direction_change) + */ + RG_CBasePlayerWeapon_KickBack, + + /* + * Description: Called whenever game sends an animation to his current holder (player) + * @note This is often called for all animations in exception of "fire" and "idle" sequences (both called via client prediction) + * Return type: void + * Params: (const this, iAnim, skiplocal) + */ + RG_CBasePlayerWeapon_SendWeaponAnim, }; /** @@ -922,6 +1025,21 @@ enum GamedllFunc_CBaseEntity RG_CBaseEntity_FireBullets3, }; +/** +* GamedllFunc CBotManager +*/ +enum GamedllFunc_CBotManager +{ + /* + * Description: Called on each improved bot event + * Return type: void + * Params: (GameEventType:event, const pEntity, const pOther) + + */ + RG_CBotManager_OnEvent = BEGIN_FUNC_REGION(botmanager), +} + + /** * GamedllFunc CSGameRules */ @@ -1081,6 +1199,32 @@ enum GamedllFunc_CSGameRules * Params: (const listener, const sender) */ RG_CSGameRules_CanPlayerHearPlayer, + + /* + * Description: Called every server frame to process game rules + * Params: () + */ + RG_CSGameRules_Think, + + /* + * Description: Called each time player tries to join a team to ensure availability + * Return type: bool + * Params: (team_id) + */ + RG_CSGameRules_TeamFull, + + /* + * Description: Called each time player tries to join a team to ensure a fair distribution of players (based on mp_limitteams cvar) + * Return type: bool + * Params: (newTeam_id, curTeam_id) + */ + RG_CSGameRules_TeamStacked, + + /* + * Description: Called each time player gets a weapon linked to his inventory + * Params: (const pPlayer, const pWeapon) + */ + RG_CSGameRules_PlayerGotWeapon, }; /** diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index e971ef56..d3531fec 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #define REGAMEDLL_API_VERSION_MAJOR 5 @@ -237,10 +238,6 @@ typedef IHookChainRegistry IReGameHookRegistry typedef IHookChain IReGameHook_PM_AirMove; typedef IHookChainRegistry IReGameHookRegistry_PM_AirMove; -// PM_LadderMove hook -typedef IHookChain IReGameHook_PM_LadderMove; -typedef IHookChainRegistry IReGameHookRegistry_PM_LadderMove; - // HandleMenu_ChooseAppearance hook typedef IHookChain IReGameHook_HandleMenu_ChooseAppearance; typedef IHookChainRegistry IReGameHookRegistry_HandleMenu_ChooseAppearance; @@ -529,6 +526,94 @@ typedef IHookChainRegistryClass IReGameHookRegistry_CBa typedef IHookChain IReGameHook_FreeGameRules; typedef IHookChainRegistry IReGameHookRegistry_FreeGameRules; +// PM_LadderMove hook +typedef IHookChain IReGameHook_PM_LadderMove; +typedef IHookChainRegistry IReGameHookRegistry_PM_LadderMove; + +// PM_WaterJump hook +typedef IHookChain IReGameHook_PM_WaterJump; +typedef IHookChainRegistry IReGameHookRegistry_PM_WaterJump; + +// PM_CheckWaterJump hook +typedef IHookChain IReGameHook_PM_CheckWaterJump; +typedef IHookChainRegistry IReGameHookRegistry_PM_CheckWaterJump; + +// PM_Jump hook +typedef IHookChain IReGameHook_PM_Jump; +typedef IHookChainRegistry IReGameHookRegistry_PM_Jump; + +// PM_Duck hook +typedef IHookChain IReGameHook_PM_Duck; +typedef IHookChainRegistry IReGameHookRegistry_PM_Duck; + +// PM_UnDuck hook +typedef IHookChain IReGameHook_PM_UnDuck; +typedef IHookChainRegistry IReGameHookRegistry_PM_UnDuck; + +// PM_PlayStepSound hook +typedef IHookChain IReGameHook_PM_PlayStepSound; +typedef IHookChainRegistry IReGameHookRegistry_PM_PlayStepSound; + +// PM_AirAccelerate hook +typedef IHookChain IReGameHook_PM_AirAccelerate; +typedef IHookChainRegistry IReGameHookRegistry_PM_AirAccelerate; + +// ClearMultiDamage hook +typedef IHookChain IReGameHook_ClearMultiDamage; +typedef IHookChainRegistry IReGameHookRegistry_ClearMultiDamage; + +// AddMultiDamage hook +typedef IHookChain IReGameHook_AddMultiDamage; +typedef IHookChainRegistry IReGameHookRegistry_AddMultiDamage; + +// ApplyMultiDamage hook +typedef IHookChain IReGameHook_ApplyMultiDamage; +typedef IHookChainRegistry IReGameHookRegistry_ApplyMultiDamage; + +// BuyItem hook +typedef IHookChain IReGameHook_BuyItem; +typedef IHookChainRegistry IReGameHookRegistry_BuyItem; + +// CHalfLifeMultiplay::Think hook +typedef IHookChain IReGameHook_CSGameRules_Think; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_Think; + +// CHalfLifeMultiplay::TeamFull hook +typedef IHookChain IReGameHook_CSGameRules_TeamFull; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_TeamFull; + +// CHalfLifeMultiplay::TeamStacked hook +typedef IHookChain IReGameHook_CSGameRules_TeamStacked; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_TeamStacked; + +// CHalfLifeMultiplay::PlayerGotWeapon hook +typedef IHookChain IReGameHook_CSGameRules_PlayerGotWeapon; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_PlayerGotWeapon; + +// CBotManager::OnEvent hook +typedef IHookChain IReGameHook_CBotManager_OnEvent; +typedef IHookChainRegistry IReGameHookRegistry_CBotManager_OnEvent; + +// CBasePlayer::CheckTimeBasedDamage hook +typedef IHookChainClass IReGameHook_CBasePlayer_CheckTimeBasedDamage; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage; + +// CBasePlayer::EntSelectSpawnPoint hook +typedef IHookChainClass IReGameHook_CBasePlayer_EntSelectSpawnPoint; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint; + +// CBasePlayerWeapon::ItemPostFrame hook +typedef IHookChainClass IReGameHook_CBasePlayerWeapon_ItemPostFrame; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame; + +// CBasePlayerWeapon::KickBack hook +typedef IHookChainClass IReGameHook_CBasePlayerWeapon_KickBack; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_KickBack; + +// CBasePlayerWeapon::SendWeaponAnim hook +typedef IHookChainClass IReGameHook_CBasePlayerWeapon_SendWeaponAnim; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim; + class IReGameHookchains { public: virtual ~IReGameHookchains() {} @@ -665,6 +750,27 @@ class IReGameHookchains { virtual IReGameHookRegistry_FreeGameRules *FreeGameRules() = 0; virtual IReGameHookRegistry_PM_LadderMove *PM_LadderMove() = 0; + virtual IReGameHookRegistry_PM_WaterJump *PM_WaterJump() = 0; + virtual IReGameHookRegistry_PM_CheckWaterJump *PM_CheckWaterJump() = 0; + virtual IReGameHookRegistry_PM_Jump *PM_Jump() = 0; + virtual IReGameHookRegistry_PM_Duck *PM_Duck() = 0; + virtual IReGameHookRegistry_PM_UnDuck *PM_UnDuck() = 0; + virtual IReGameHookRegistry_PM_PlayStepSound *PM_PlayStepSound() = 0; + virtual IReGameHookRegistry_PM_AirAccelerate *PM_AirAccelerate() = 0; + virtual IReGameHookRegistry_ClearMultiDamage *ClearMultiDamage() = 0; + virtual IReGameHookRegistry_AddMultiDamage *AddMultiDamage() = 0; + virtual IReGameHookRegistry_ApplyMultiDamage *ApplyMultiDamage() = 0; + virtual IReGameHookRegistry_BuyItem *BuyItem() = 0; + virtual IReGameHookRegistry_CSGameRules_Think *CSGameRules_Think() = 0; + virtual IReGameHookRegistry_CSGameRules_TeamFull *CSGameRules_TeamFull() = 0; + virtual IReGameHookRegistry_CSGameRules_TeamStacked *CSGameRules_TeamStacked() = 0; + virtual IReGameHookRegistry_CSGameRules_PlayerGotWeapon *CSGameRules_PlayerGotWeapon() = 0; + virtual IReGameHookRegistry_CBotManager_OnEvent *CBotManager_OnEvent() = 0; + virtual IReGameHookRegistry_CBasePlayer_CheckTimeBasedDamage *CBasePlayer_CheckTimeBasedDamage() = 0; + virtual IReGameHookRegistry_CBasePlayer_EntSelectSpawnPoint *CBasePlayer_EntSelectSpawnPoint() = 0; + virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0; + virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0; + virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0; }; struct ReGameFuncs_t { @@ -685,6 +791,12 @@ struct ReGameFuncs_t { void (*UTIL_RestartOther)(const char *szClassname); void (*UTIL_ResetEntities)(); void (*UTIL_RemoveOther)(const char *szClassname, int nCount); + void (*UTIL_DecalTrace)(TraceResult *pTrace, int decalNumber); + void (*UTIL_Remove)(CBaseEntity *pEntity); + int (*AddAmmoNameToAmmoRegistry)(const char *szAmmoname); + void (*TextureTypePlaySound)(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType); + class CWeaponBox *(*CreateWeaponBox)(CBasePlayerItem *pItem, CBasePlayer *pPlayerOwner, const char *modelName, Vector &origin, Vector &angles, Vector &velocity, float lifeTime, bool packAmmo); + class CGrenade *(*SpawnGrenade)(WeaponIdType weaponId, entvars_t *pevOwner, Vector &vecSrc, Vector &vecThrow, float time, int iTeam, unsigned short usEvent); }; class IReGameApi { diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index bd43ff7b..36486caa 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -1458,6 +1458,254 @@ void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder) PM_LadderMove_AMXX(chain, pLadder, pLadder->player + 1); } +void PM_WaterJump_AMXX(IReGameHook_PM_WaterJump *chain, int playerIndex) +{ + auto original = [chain](int _playerIndex) + { + chain->callNext(); + }; + + callVoidForward(RG_PM_WaterJump, original, playerIndex); +} + +void PM_WaterJump(IReGameHook_PM_WaterJump *chain) +{ + PM_WaterJump_AMXX(chain, g_pMove->player_index + 1); +} + +void PM_CheckWaterJump_AMXX(IReGameHook_PM_CheckWaterJump *chain, int playerIndex) +{ + auto original = [chain](int _playerIndex) + { + chain->callNext(); + }; + + callVoidForward(RG_PM_CheckWaterJump, original, playerIndex); +} + +void PM_CheckWaterJump(IReGameHook_PM_CheckWaterJump *chain) +{ + PM_CheckWaterJump_AMXX(chain, g_pMove->player_index + 1); +} + +void PM_Jump_AMXX(IReGameHook_PM_Jump *chain, int playerIndex) +{ + auto original = [chain](int _playerIndex) + { + chain->callNext(); + }; + + callVoidForward(RG_PM_Jump, original, playerIndex); +} + +void PM_Jump(IReGameHook_PM_Jump *chain) +{ + PM_Jump_AMXX(chain, g_pMove->player_index + 1); +} + +void PM_Duck_AMXX(IReGameHook_PM_Duck *chain, int playerIndex) +{ + auto original = [chain](int _playerIndex) + { + chain->callNext(); + }; + + callVoidForward(RG_PM_Duck, original, playerIndex); +} + +void PM_Duck(IReGameHook_PM_Duck *chain) +{ + PM_Duck_AMXX(chain, g_pMove->player_index + 1); +} + +void PM_UnDuck_AMXX(IReGameHook_PM_UnDuck *chain, int playerIndex) +{ + auto original = [chain](int _playerIndex) + { + chain->callNext(); + }; + + callVoidForward(RG_PM_UnDuck, original, playerIndex); +} + +void PM_UnDuck(IReGameHook_PM_UnDuck *chain) +{ + PM_UnDuck_AMXX(chain, g_pMove->player_index + 1); +} + +void PM_PlayStepSound_AMXX(IReGameHook_PM_PlayStepSound *chain, int step, float fvol, int playerIndex) +{ + auto original = [chain](int _step, float _fvol, int _playerIndex) + { + chain->callNext(_step, _fvol); + }; + + callVoidForward(RG_PM_PlayStepSound, original, step, fvol, playerIndex); +} + +void PM_PlayStepSound(IReGameHook_PM_PlayStepSound *chain, int step, float fvol) +{ + PM_PlayStepSound_AMXX(chain, step, fvol, g_pMove->player_index + 1); +} + +void PM_AirAccelerate_AMXX(IReGameHook_PM_AirAccelerate *chain, vec_t *wishdir, float wishspeed, float accel, int playerIndex) +{ + Vector wishdirCopy(wishdir); + + auto original = [chain, &wishdirCopy](cell _wishdir, float _wishspeed, float _accel, int _playerIndex) + { + chain->callNext(wishdirCopy, _wishspeed, _accel); + }; + + callVoidForward(RG_PM_AirAccelerate, original, getAmxVector(wishdirCopy), wishspeed, accel, playerIndex); +} + +void PM_AirAccelerate(IReGameHook_PM_AirAccelerate *chain, vec_t *wishdir, float wishspeed, float accel) +{ + PM_AirAccelerate_AMXX(chain, wishdir, wishspeed, accel, g_pMove->player_index + 1); +} + +void ClearMultiDamage(IReGameHook_ClearMultiDamage *chain) +{ + auto original = [chain]() + { + chain->callNext(); + }; + + callVoidForward(RG_ClearMultiDamage, original); +} + +void AddMultiDamage(IReGameHook_AddMultiDamage *chain, entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType) +{ + auto original = [chain](int _pevInflictor, int _pEntity, float _flDamage, int _bitsDamageType) + { + chain->callNext(PEV(_pevInflictor), getPrivate(_pEntity), _flDamage, _bitsDamageType); + }; + + callVoidForward(RG_AddMultiDamage, original, indexOfEdict(pevInflictor), indexOfEdict(pEntity->pev), flDamage, bitsDamageType); +} + +void ApplyMultiDamage(IReGameHook_ApplyMultiDamage *chain, entvars_t *pevInflictor, entvars_t *pevAttacker) +{ + auto original = [chain](int _pevInflictor, int _pevAttacker) + { + chain->callNext(PEV(_pevInflictor), PEV(_pevAttacker)); + }; + + callVoidForward(RG_ApplyMultiDamage, original, indexOfEdict(pevInflictor), indexOfEdict(pevAttacker)); +} + +void BuyItem(IReGameHook_BuyItem *chain, CBasePlayer *pPlayer, int iSlot) +{ + auto original = [chain](int _pPlayer, int _iSlot) + { + chain->callNext(getPrivate(_pPlayer), _iSlot); + }; + + callVoidForward(RG_AddMultiDamage, original, indexOfEdict(pPlayer->pev), iSlot); +} + +void CSGameRules_Think(IReGameHook_CSGameRules_Think *chain) +{ + auto original = [chain]() + { + chain->callNext(); + }; + + callVoidForward(RG_CSGameRules_Think, original); +} + +BOOL CSGameRules_TeamFull(IReGameHook_CSGameRules_TeamFull *chain, int team_id) +{ + auto original = [chain](int _team_id) + { + return chain->callNext(_team_id); + }; + + return callForward(RG_CSGameRules_TeamFull, original, team_id); +} + +BOOL CSGameRules_TeamStacked(IReGameHook_CSGameRules_TeamStacked *chain, int newTeam_id, int curTeam_id) +{ + auto original = [chain](int _newTeam_id, int _curTeam_id) + { + return chain->callNext(_newTeam_id, _curTeam_id); + }; + + return callForward(RG_CSGameRules_TeamStacked, original, newTeam_id, curTeam_id); +} + +void CSGameRules_PlayerGotWeapon(IReGameHook_CSGameRules_PlayerGotWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon) +{ + auto original = [chain](int _pPlayer, int _pWeapon) + { + chain->callNext(getPrivate(_pPlayer), getPrivate(_pWeapon)); + }; + + callVoidForward(RG_CSGameRules_PlayerGotWeapon, original, indexOfEdict(pPlayer->pev), indexOfEdict(pWeapon->pev)); +} + +void CBotManager_OnEvent(IReGameHook_CBotManager_OnEvent *chain, GameEventType event, CBaseEntity* pEntity, CBaseEntity* pOther) +{ + auto original = [chain](GameEventType _event, int _pEntity, int _pOther) + { + chain->callNext(_event, getPrivate(_pEntity), getPrivate(_pOther)); + }; + + callVoidForward(RG_CBotManager_OnEvent, original, event, indexOfEdict(pEntity->pev), indexOfEdict(pOther->pev)); +} + +void CBasePlayer_CheckTimeBasedDamage(IReGameHook_CBasePlayer_CheckTimeBasedDamage *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_CheckTimeBasedDamage, original, indexOfEdict(pthis->pev)); +} + +edict_t *CBasePlayer_EntSelectSpawnPoint(IReGameHook_CBasePlayer_EntSelectSpawnPoint *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + return indexOfEdict(chain->callNext(getPrivate(_pthis))); + }; + + return edictByIndexAmx(callForward(RG_CBasePlayer_EntSelectSpawnPoint, original, indexOfEdict(pthis->pev))); +} + +void CBasePlayerWeapon_ItemPostFrame(IReGameHook_CBasePlayerWeapon_ItemPostFrame *chain, CBasePlayerWeapon *pthis) +{ + auto original = [chain](int _pthis) + { + chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayerWeapon_ItemPostFrame, original, indexOfEdict(pthis->pev)); +} + +void CBasePlayerWeapon_KickBack(IReGameHook_CBasePlayerWeapon_KickBack *chain, CBasePlayerWeapon *pthis, float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change) +{ + auto original = [chain](int _pthis, float _up_base, float _lateral_base, float _up_modifier, float _lateral_modifier, float _up_max, float _lateral_max, int _direction_change) + { + chain->callNext(getPrivate(_pthis), _up_base, _lateral_base, _up_modifier, _lateral_modifier, _up_max, _lateral_max, _direction_change); + }; + + callVoidForward(RG_CBasePlayerWeapon_KickBack, original, indexOfEdict(pthis->pev), up_base, lateral_base, up_modifier, lateral_modifier, up_max, lateral_max, direction_change); +} + +void CBasePlayerWeapon_SendWeaponAnim(IReGameHook_CBasePlayerWeapon_SendWeaponAnim *chain, CBasePlayerWeapon *pthis, int iAnim, int skiplocal) +{ + auto original = [chain](int _pthis, int _iAnim, int _skiplocal) + { + chain->callNext(getPrivate(_pthis), _iAnim, _skiplocal); + }; + + callVoidForward(RG_CBasePlayerWeapon_SendWeaponAnim, original, indexOfEdict(pthis->pev), iAnim, skiplocal); +} + + /* * VTC functions */ @@ -1527,3 +1775,4 @@ void CmdExec(IRecheckerHook_CmdExec *chain, IGameClient *cl, IResourceBuffer *re CmdExec_t data(chain, res); CmdExec_AMXX(&data, cl, res->GetFileName(), cmdExec, responseHash); } + diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 49457023..cec30399 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -529,6 +529,34 @@ void CBasePlayer_JoiningThink(IReGameHook_CBasePlayer_JoiningThink *chain, CBase // TODO: pending FreeGameRules void PM_LadderMove_AMXX(IReGameHook_PM_LadderMove *chain, physent_t *pLadder, int playerIndex); void PM_LadderMove(IReGameHook_PM_LadderMove *chain, physent_t *pLadder); +void PM_WaterJump_AMXX(IReGameHook_PM_WaterJump *chain, int playerIndex); +void PM_WaterJump(IReGameHook_PM_WaterJump *chain); +void PM_CheckWaterJump_AMXX(IReGameHook_PM_CheckWaterJump *chain, int playerIndex); +void PM_CheckWaterJump(IReGameHook_PM_CheckWaterJump *chain); +void PM_Jump_AMXX(IReGameHook_PM_Jump *chain, int playerIndex); +void PM_Jump(IReGameHook_PM_Jump *chain); +void PM_Duck_AMXX(IReGameHook_PM_Duck *chain, int playerIndex); +void PM_Duck(IReGameHook_PM_Duck *chain); +void PM_UnDuck_AMXX(IReGameHook_PM_UnDuck *chain, int playerIndex); +void PM_UnDuck(IReGameHook_PM_UnDuck *chain); +void PM_PlayStepSound_AMXX(IReGameHook_PM_PlayStepSound *chain, int step, float fvol, int playerIndex); +void PM_PlayStepSound(IReGameHook_PM_PlayStepSound *chain, int step, float fvol); +void PM_AirAccelerate_AMXX(IReGameHook_PM_AirAccelerate *chain, vec_t *wishdir, float wishspeed, float accel, int playerIndex); +void PM_AirAccelerate(IReGameHook_PM_AirAccelerate *chain, vec_t *wishdir, float wishspeed, float accel); +void ClearMultiDamage(IReGameHook_ClearMultiDamage *chain); +void AddMultiDamage(IReGameHook_AddMultiDamage *chain, entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType); +void ApplyMultiDamage(IReGameHook_ApplyMultiDamage *chain, entvars_t *pevInflictor, entvars_t *pevAttacker); +void BuyItem(IReGameHook_BuyItem *chain, CBasePlayer *pPlayer, int iSlot); +void CSGameRules_Think(IReGameHook_CSGameRules_Think *chain); +BOOL CSGameRules_TeamFull(IReGameHook_CSGameRules_TeamFull *chain, int team_id); +BOOL CSGameRules_TeamStacked(IReGameHook_CSGameRules_TeamStacked *chain, int newTeam_id, int curTeam_id); +void CSGameRules_PlayerGotWeapon(IReGameHook_CSGameRules_PlayerGotWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon); +void CBotManager_OnEvent(IReGameHook_CBotManager_OnEvent *chain, GameEventType event, CBaseEntity* pEntity, CBaseEntity* pOther); +void CBasePlayer_CheckTimeBasedDamage(IReGameHook_CBasePlayer_CheckTimeBasedDamage *chain, CBasePlayer *pthis); +edict_t *CBasePlayer_EntSelectSpawnPoint(IReGameHook_CBasePlayer_EntSelectSpawnPoint *chain, CBasePlayer *pthis); +void CBasePlayerWeapon_ItemPostFrame(IReGameHook_CBasePlayerWeapon_ItemPostFrame *chain, CBasePlayerWeapon *pthis); +void CBasePlayerWeapon_KickBack(IReGameHook_CBasePlayerWeapon_KickBack *chain, CBasePlayerWeapon *pthis, float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change); +void CBasePlayerWeapon_SendWeaponAnim(IReGameHook_CBasePlayerWeapon_SendWeaponAnim *chain, CBasePlayerWeapon *pthis, int iAnim, int skiplocal); /* * VTC functions @@ -552,3 +580,4 @@ void FileConsistencyProcess_AMXX(FileConsistencyProcess_t *data, IGameClient *cl void FileConsistencyProcess(IRecheckerHook_FileConsistencyProcess *chain, IGameClient *cl, IResourceBuffer *res, ResourceType_e typeFind, uint32 responseHash); void FileConsistencyFinal(IRecheckerHook_FileConsistencyFinal *chain, IGameClient *cl); + diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index bd44eba8..6e77e20a 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -23,6 +23,8 @@ inline size_t getFwdParamType(void(*)(IResourceBuffer*)) { return FP_CELL inline size_t getFwdParamType(void(*)(unsigned char)) { return FP_CELL; } inline size_t getFwdParamType(void(*)(resourcetype_t)) { return FP_CELL; } inline size_t getFwdParamType(void(*)(cmd_source_t)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(GameEventType)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(float*)) { return FP_ARRAY; } template inline size_t getFwdParamType(void(*)(T *)) { return FP_CELL; } @@ -131,7 +133,18 @@ hook_t hooklist_gamedll[] = { DLL(SpawnHeadGib), DLL(SpawnRandomGibs), DLL(CreateWeaponBox), - DLL(PM_LadderMove), + DLL(PM_LadderMove, _AMXX), + DLL(PM_WaterJump, _AMXX), + DLL(PM_CheckWaterJump, _AMXX), + DLL(PM_Jump, _AMXX), + DLL(PM_Duck, _AMXX), + DLL(PM_UnDuck, _AMXX), + DLL(PM_PlayStepSound, _AMXX), + DLL(PM_AirAccelerate, _AMXX), + DLL(ClearMultiDamage), + DLL(AddMultiDamage), + DLL(ApplyMultiDamage), + DLL(BuyItem), }; hook_t hooklist_animating[] = { @@ -196,6 +209,9 @@ hook_t hooklist_player[] = { DLL(CBasePlayer_Pain), DLL(CBasePlayer_DeathSound), DLL(CBasePlayer_JoiningThink), + + DLL(CBasePlayer_CheckTimeBasedDamage), + DLL(CBasePlayer_EntSelectSpawnPoint), }; hook_t hooklist_gamerules[] = { @@ -223,6 +239,10 @@ hook_t hooklist_gamerules[] = { DLL(CSGameRules_BalanceTeams), DLL(CSGameRules_OnRoundFreezeEnd), DLL(CSGameRules_CanPlayerHearPlayer), + DLL(CSGameRules_Think), + DLL(CSGameRules_TeamFull), + DLL(CSGameRules_TeamStacked), + DLL(CSGameRules_PlayerGotWeapon), }; hook_t hooklist_grenade[] = { @@ -243,6 +263,9 @@ hook_t hooklist_weapon[] = { DLL(CBasePlayerWeapon_DefaultDeploy), DLL(CBasePlayerWeapon_DefaultReload), DLL(CBasePlayerWeapon_DefaultShotgunReload), + DLL(CBasePlayerWeapon_ItemPostFrame), + DLL(CBasePlayerWeapon_KickBack), + DLL(CBasePlayerWeapon_SendWeaponAnim), }; hook_t hooklist_gib[] = { @@ -257,6 +280,10 @@ hook_t hooklist_cbaseentity[] = { DLL(CBaseEntity_FireBullets3), }; +hook_t hooklist_botmanager[] = { + DLL(CBotManager_OnEvent), +}; + #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), @@ -283,6 +310,7 @@ hook_t* hooklist_t::getHookSafe(size_t hook) CASE(weapon) CASE(gib) CASE(cbaseentity) + CASE(botmanager) } return nullptr; @@ -303,6 +331,7 @@ void hooklist_t::clear() FOREACH_CLEAR(weapon); FOREACH_CLEAR(gib); FOREACH_CLEAR(cbaseentity); + FOREACH_CLEAR(botmanager); } void hook_t::clear() diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 352472cf..18483eb2 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -38,6 +38,7 @@ extern hook_t hooklist_weaponbox[]; extern hook_t hooklist_weapon[]; extern hook_t hooklist_gib[]; extern hook_t hooklist_cbaseentity[]; +extern hook_t hooklist_botmanager[]; enum { @@ -65,6 +66,7 @@ struct hooklist_t CASE(weapon) CASE(gib) CASE(cbaseentity) + CASE(botmanager) } #undef CASE @@ -88,6 +90,7 @@ struct hooklist_t ht_weapon, ht_gib, ht_cbaseentity, + ht_botmanager, }; }; @@ -146,6 +149,17 @@ enum GamedllFunc RG_CreateWeaponBox, RG_PM_LadderMove, + RG_PM_WaterJump, + RG_PM_CheckWaterJump, + RG_PM_Jump, + RG_PM_Duck, + RG_PM_UnDuck, + RG_PM_PlayStepSound, + RG_PM_AirAccelerate, + RG_ClearMultiDamage, + RG_AddMultiDamage, + RG_ApplyMultiDamage, + RG_BuyItem, // [...] }; @@ -219,6 +233,9 @@ enum GamedllFunc_CBasePlayer RG_CBasePlayer_DeathSound, RG_CBasePlayer_JoiningThink, + RG_CBasePlayer_CheckTimeBasedDamage, + RG_CBasePlayer_EntSelectSpawnPoint, + // [...] }; @@ -247,6 +264,9 @@ enum GamedllFunc_CBasePlayerWeapon RG_CBasePlayerWeapon_DefaultDeploy, RG_CBasePlayerWeapon_DefaultReload, RG_CBasePlayerWeapon_DefaultShotgunReload, + RG_CBasePlayerWeapon_ItemPostFrame, + RG_CBasePlayerWeapon_KickBack, + RG_CBasePlayerWeapon_SendWeaponAnim, // [...] }; @@ -278,6 +298,10 @@ enum GamedllFunc_CSGameRules RG_CSGameRules_BalanceTeams, RG_CSGameRules_OnRoundFreezeEnd, RG_CSGameRules_CanPlayerHearPlayer, + RG_CSGameRules_Think, + RG_CSGameRules_TeamFull, + RG_CSGameRules_TeamStacked, + RG_CSGameRules_PlayerGotWeapon, // [...] }; @@ -300,6 +324,13 @@ enum GamedllFunc_CBaseEntity // [...] }; +enum GamedllFunc_CBotManager +{ + RG_CBotManager_OnEvent = BEGIN_FUNC_REGION(botmanager), + + // [...] +}; + enum ReCheckerFunc { RC_FileConsistencyProcess = BEGIN_FUNC_REGION(rechecker), From fcca39b87ba8d975c75ea4505aa78f400a201d39 Mon Sep 17 00:00:00 2001 From: Javekson <132286351+Javekson@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:00:10 +0400 Subject: [PATCH 34/50] Fix error 029: invalid expression for IsRoundExpireEvent (#286) --- reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 2bc7f000..8994cfdf 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -9,7 +9,7 @@ * * @note Use this for hookchain RG_RoundEnd with the parameter ScenarioEventEndRound:event */ -#define IsRoundExpireEvent(%0) (((1<<_:(%0) + ScenarioEventEndRound:0)) & ((1<<_:ROUND_TARGET_SAVED) | (1<<_:ROUND_HOSTAGE_NOT_RESCUED) | (1<<_:ROUND_TERRORISTS_NOT_ESCAPED) | (1<<_:ROUND_VIP_NOT_ESCAPED) | (1<<_:ROUND_GAME_OVER))) != 0) +#define IsRoundExpireEvent(%0) (((1 << _:(%0) + _:ScenarioEventEndRound:0) & ((1 << _:ROUND_TARGET_SAVED) | (1 << _:ROUND_HOSTAGE_NOT_RESCUED) | (1 << _:ROUND_TERRORISTS_NOT_ESCAPED) | (1 << _:ROUND_VIP_NOT_ESCAPED) | (1 << _:ROUND_GAME_OVER))) != 0) /** * suppress warning: 200 on amxmodx 1.8.2 From 2077022a43d2ae3dd43ef8799a1e5747e616826e Mon Sep 17 00:00:00 2001 From: Javekson <132286351+Javekson@users.noreply.github.com> Date: Sat, 7 Oct 2023 13:23:19 +0400 Subject: [PATCH 35/50] Refactored rg_remove_items_by_slot and updated the return logic (#288) --- .../scripting/include/reapi_gamedll.inc | 3 +- reapi/src/natives/natives_misc.cpp | 50 ++++--------------- 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 3ea2a44c..bb3c7066 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -500,7 +500,8 @@ native rg_set_weapon_info(const {WeaponIdType,_}:weapon_id, WpnInfo:type, any:.. * @param slot The slot that will be emptied * @param removeAmmo Remove ammunition * -* @return 1 on success, 0 otherwise +* @return 1 - successful removal of all items in the slot or the slot is empty +* 0 - if at least one item failed to remove */ native rg_remove_items_by_slot(const index, const InventorySlotType:slot, const bool:removeAmmo = true); diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 8d1bcb6e..ccae232c 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -909,7 +909,8 @@ cell AMX_NATIVE_CALL rg_set_weapon_info(AMX *amx, cell *params) * @param slot The slot that will be emptied * @param removeAmmo Remove ammunition * -* @return 1 on success, 0 otherwise +* @return 1 - successful removal of all items in the slot or the slot is empty +* 0 - if at least one item failed to remove * * native rg_remove_items_by_slot(const index, const InventorySlotType:slot, const bool:removeAmmo = true); */ @@ -922,46 +923,17 @@ cell AMX_NATIVE_CALL rg_remove_items_by_slot(AMX *amx, cell *params) CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); CHECK_CONNECTED(pPlayer, arg_index); - if (params[arg_slot] == C4_SLOT) - { - pPlayer->CSPlayer()->RemovePlayerItemEx("weapon_c4", true); - } - else - { - pPlayer->ForEachItem(params[arg_slot], [pPlayer, params](CBasePlayerItem *pItem) - { - if (pItem->IsWeapon()) { - if (pItem == pPlayer->m_pActiveItem) { - ((CBasePlayerWeapon *)pItem)->RetireWeapon(); - } - - // Compatible with older versions of the plugin, - // which still only pass two parameters - if (PARAMS_COUNT < 3 || params[arg_remammo]) { - pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ] = 0; - } - } - - if (pPlayer->RemovePlayerItem(pItem)) { - pPlayer->pev->weapons &= ~(1 << pItem->m_iId); + bool success = true; - // No more weapon - if ((pPlayer->pev->weapons & ~(1 << WEAPON_SUIT)) == 0) { - pPlayer->m_iHideHUD |= HIDEHUD_WEAPONS; - } - - pItem->Kill(); - } - - return false; - }); - - if (!pPlayer->m_rgpPlayerItems[PRIMARY_WEAPON_SLOT]) { - pPlayer->m_bHasPrimary = false; - } - } + pPlayer->ForEachItem(params[arg_slot], [&](CBasePlayerItem *pItem) + { + // Compatible with older versions of the plugin, + // which still only pass two parameters + success &= pPlayer->CSPlayer()->RemovePlayerItemEx(STRING(pItem->pev->classname), (PARAMS_COUNT < 3 || params[arg_remammo] != 0)) ? true : false; + return false; + }); - return TRUE; + return success ? TRUE : FALSE; } /* From e36a40c3e5d36ec90cfc17beb4eda1bf778b5f29 Mon Sep 17 00:00:00 2001 From: Javekson <132286351+Javekson@users.noreply.github.com> Date: Sat, 7 Oct 2023 13:23:40 +0400 Subject: [PATCH 36/50] Updated the return logic of rg_drop_item and rg_drop_items_by_slot (#289) --- .../scripting/include/reapi_gamedll.inc | 7 +++--- reapi/include/cssdk/dlls/API/CSPlayer.h | 4 ++-- reapi/src/natives/natives_misc.cpp | 23 ++++++++++++------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index bb3c7066..edf31f99 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -511,7 +511,8 @@ native rg_remove_items_by_slot(const index, const InventorySlotType:slot, const * @param index Client index * @param slot Specific slot for remove of each item. * -* @return 1 on success, 0 otherwise +* @return 1 - successful drop of all items in the slot or the slot is empty +* 0 - if at least one item failed to drop */ native rg_drop_items_by_slot(const index, const InventorySlotType:slot); @@ -529,9 +530,9 @@ native rg_remove_all_items(const index, const bool:removeSuit = false); * Forces the player to drop the specified item classname. * * @param index Client index -* @param item_name Item classname +* @param item_name Item classname, if no name, the active item classname * -* @return 1 on success, 0 otherwise +* @return Entity index of weaponbox, AMX_NULLENT (-1) otherwise * */ native rg_drop_item(const index, const item_name[]); diff --git a/reapi/include/cssdk/dlls/API/CSPlayer.h b/reapi/include/cssdk/dlls/API/CSPlayer.h index 3f63d5c3..b12aa230 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayer.h +++ b/reapi/include/cssdk/dlls/API/CSPlayer.h @@ -64,8 +64,8 @@ class CCSPlayer: public CCSMonster virtual CBaseEntity *GiveNamedItemEx(const char *pszName) = 0; virtual void GiveDefaultItems() = 0; virtual void GiveShield(bool bDeploy = true) = 0; - virtual void DropShield(bool bDeploy = true) = 0; - virtual void DropPlayerItem(const char *pszItemName) = 0; + virtual CBaseEntity *DropShield(bool bDeploy = true) = 0; + virtual CBaseEntity *DropPlayerItem(const char *pszItemName) = 0; virtual bool RemoveShield() = 0; virtual void RemoveAllItems(bool bRemoveSuit) = 0; virtual bool RemovePlayerItem(const char* pszItemName) = 0; diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index ccae232c..ea276784 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -942,7 +942,8 @@ cell AMX_NATIVE_CALL rg_remove_items_by_slot(AMX *amx, cell *params) * @param index Client index * @param slot Specific slot for remove of each item. * -* @return 1 on success, 0 otherwise +* @return 1 - successful drop of all items in the slot or the slot is empty +* 0 - if at least one item failed to drop * * native rg_drop_items_by_slot(const index, const InventorySlotType:slot); */ @@ -955,12 +956,14 @@ cell AMX_NATIVE_CALL rg_drop_items_by_slot(AMX *amx, cell *params) CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); CHECK_CONNECTED(pPlayer, arg_index); - pPlayer->ForEachItem(params[arg_slot], [pPlayer](CBasePlayerItem *pItem) { - pPlayer->CSPlayer()->DropPlayerItem(STRING(pItem->pev->classname)); + bool success = true; + + pPlayer->ForEachItem(params[arg_slot], [&](CBasePlayerItem *pItem) { + success &= pPlayer->CSPlayer()->DropPlayerItem(STRING(pItem->pev->classname)) ? true : false; return false; }); - return TRUE; + return success ? TRUE : FALSE; } /* @@ -990,9 +993,9 @@ cell AMX_NATIVE_CALL rg_remove_all_items(AMX *amx, cell *params) * Forces the player to drop the specified item classname. * * @param index Client index -* @param item_name Item classname +* @param item_name Item classname, if no name, the active item classname * -* @return 1 on success, 0 otherwise +* @return Entity index of weaponbox, AMX_NULLENT (-1) otherwise * * native rg_drop_item(const index, const item_name[]); */ @@ -1006,8 +1009,12 @@ cell AMX_NATIVE_CALL rg_drop_item(AMX *amx, cell *params) CHECK_CONNECTED(pPlayer, arg_index); char item[256]; - pPlayer->CSPlayer()->DropPlayerItem(getAmxString(amx, params[arg_item_name], item)); - return TRUE; + auto pEntity = pPlayer->CSPlayer()->DropPlayerItem(getAmxString(amx, params[arg_item_name], item)); + + if (pEntity) + return indexOfPDataAmx(pEntity); + + return AMX_NULLENT; } /* From 08210bec75baf7a0d82d5bea70dfe61b19b4d16f Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 7 Oct 2023 16:28:07 +0700 Subject: [PATCH 37/50] Info_SetValueForStarKey allow a colon in playername --- reapi/common/info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reapi/common/info.cpp b/reapi/common/info.cpp index 5e0f096c..8ebcfcf3 100644 --- a/reapi/common/info.cpp +++ b/reapi/common/info.cpp @@ -282,7 +282,7 @@ void Info_SetValueForStarKey(char *s, const char *key, const char *value, int ma return; } - if (Q_strstr(key, "..") || Q_strstr(value, "..")) + if (Q_strstr(key, "..") || (Q_strcmp(key, "name") != 0 && Q_strstr(value, ".."))) { // TODO: Why silently return? //UTIL_ServerPrint("Can't use keys or values with a ..\n"); From ed57d7b309ed12ac89c882ec8d47d9b3f9abfbee Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 7 Oct 2023 21:21:32 +0700 Subject: [PATCH 38/50] SV_CheckUserInfo: Refer to 'userinfo' argument as a pointer instead of an AMX string buffer Added natives: - set_netadr/get_netaddr - set_key_value_buffer(buffer, "\\name\\ololo") overwrite a entire buffer - get_key_value_buffer(buffer, userinfo, charsmax(userinfo)) get userinfo as AMX string presentation Minor cleanup Bump minor --- .../extra/amxmodx/scripting/include/reapi.inc | 3 +- .../scripting/include/reapi_engine.inc | 42 ++++++++- .../scripting/include/reapi_engine_const.inc | 53 +++++++++-- .../scripting/include/reapi_gamedll_const.inc | 2 +- reapi/src/hook_callback.cpp | 15 ++- reapi/src/hook_callback.h | 7 +- reapi/src/hook_list.cpp | 2 +- reapi/src/member_list.cpp | 9 ++ reapi/src/member_list.h | 8 ++ reapi/src/natives/natives_common.cpp | 83 ++++++++++++++--- reapi/src/natives/natives_members.cpp | 93 +++++++++++++++++++ reapi/src/natives/natives_misc.cpp | 8 +- reapi/src/reapi_utils.cpp | 10 +- reapi/src/reapi_utils.h | 2 +- reapi/version/version.h | 2 +- 15 files changed, 298 insertions(+), 41 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi.inc b/reapi/extra/amxmodx/scripting/include/reapi.inc index 2b95782d..fdfb9c84 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi.inc @@ -79,7 +79,8 @@ enum members_tables_e mt_rebuystruct, mt_mapinfo, mt_csplayerweapon, - mt_gib + mt_gib, + mt_netadr }; #define ReAPIFunc {EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib, GamedllFunc_CBaseEntity, GamedllFunc_CBotManager} diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index a98f50b4..f3cedd0a 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -30,6 +30,24 @@ native set_ucmd(const ucmd, const UCmd:var, any:...); */ native any:get_ucmd(const ucmd, const UCmd:var, any:...); +/* +* Sets a NetAdr var. +* +* @param var The specified mvar, look at the enum NetAdrVars +* +* @return 1 on success. +*/ +native set_netadr(const adr, const NetAdrVars:var, any:...); + +/* +* Returns a NetAdr var +* +* @param var The specified mvar, look at the enum NetAdrVars +* +* @return If an integer or boolean or one byte, array or everything else is passed via the 3rd argument and more, look at the argument list for the specified mvar +*/ +native any:get_netadr(const adr, const NetAdrVars:var, any:...); + /* * Gets value for key in buffer * @@ -55,6 +73,28 @@ native get_key_value(const pbuffer, const key[], const value[], const maxlen); */ native set_key_value(const pbuffer, const key[], const value[]); +/* +* Gets an AMXX string buffer from a infobuffer pointer +* +* @param buffer Info string pointer +* @param value String to copy value to +* @param maxlen Maximum size of the output buffer +* +* @return Returns a string buffer on infobuffer pointer +*/ +native get_key_value_buffer(const pbuffer, const output[], const maxlen); + +/* +* Sets value string to entire buffer +* +* @param buffer Pointer to buffer +* @param value Value to set +* @param maxlen Maximum size of the value buffer to set, -1 means copy all characters +* +* @return 1 on success, 0 otherwise +*/ +native set_key_value_buffer(const pbuffer, const value[], const maxlen = -1); + /* * Gets the position of the bone * @@ -156,7 +196,7 @@ native rh_drop_client(const index, const message[] = ""); * @param len Maximum buffer size * * @noreturn -* +* */ native rh_get_net_from(output[], len); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc index 81c4c16b..d1b114e9 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc @@ -115,53 +115,53 @@ enum EngineFunc /* * Description: Called when a player's userinfo is being checked. - * Params: (adr, userinfo[], bool:reconnect, reconnectSlot, name[]) + * Params: (adr, buffer, bool:reconnect, reconnectSlot, name[]) * * @note Param adr is unused, guaranteed to return nothing also, don't send anything through it. * @note In order for param name work, hook needs to be registered as Post. */ RH_SV_CheckUserInfo, - + /* * Description: Called when a generic resource is being added to generic precache list. * Return type: int * Params: (const string[]) */ RH_PF_precache_generic_I, - + /* * Description: Called when a model is being added to model precache list. * Return type: int * Params: (const string[]) */ RH_PF_precache_model_I, - + /* * Description: Called when a sound is being added to sound precache list. * Return type: int * Params: (const string[]) */ RH_PF_precache_sound_I, - + /* * Description: Called when an event is being added to event precache list. * Return type: int * Params: (const string[]) */ RH_EV_Precache, - + /* * Description: Called when a resource is being added to resource list. * Params: (ResourceType_t:type, const filename[], size, flags, index) */ RH_SV_AddResource, - + /* * Description: Called when message is being printed to client console. * Params: (const string[]) */ RH_SV_ClientPrintf, - + /* * Description: Called when a command is being sent to server. * Params: (const cmd[], source, id) @@ -1268,3 +1268,40 @@ enum UCmd */ ucmd_impact_position }; + +enum NetAdrType +{ + NA_NULL = 0, + NA_LOOPBACK, + NA_BROADCAST, + NA_IP, + NA_IPX, // Deprecated: GoldSrc + NA_BROADCAST_IPX, // Deprecated: GoldSrc +}; + +enum NetAdrVars +{ + /* + * Description: - + * Member type: NetAdrType + * Get params: get_netadr(const NetAdr:adr, const NetAdrVars:var); + * Set params: set_netadr(const NetAdr:adr, const NetAdrVars:var, const value); + */ + netadr_type = BEGIN_MEMBER_REGION(netadr), + + /* + * Description: - + * Member type: unsigned char [4] + * Get params: get_netadr(const NetAdr:adr, const NetAdrVars:var, dest[], const lenght); // Also returns a iplong value + * Set params: set_netadr(const NetAdr:adr, const NetAdrVars:var, const iplong_value); // Only iplong can to set + */ + netadr_ip, + + /* + * Description: - + * Member type: unsigned short + * Get params: get_netadr(const NetAdr:adr, const NetAdrVars:var); + * Set params: set_netadr(const NetAdr:adr, const NetAdrVars:var, const value); + */ + netadr_port +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 8994cfdf..a4a34e8e 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -475,7 +475,7 @@ enum GamedllFunc RG_ApplyMultiDamage, /* - * Description: Called when player buys an item from buy menu (Nightvision, Kevlar, etc.) + * Description: Called when player buys an item from buy menu (Nightvision, Kevlar, etc.) * Params: (const pPlayer, iSlot) */ RG_BuyItem, diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 36486caa..918c0550 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -150,14 +150,19 @@ bool SV_AllowPhysent(IRehldsHook_SV_AllowPhysent* chain, edict_t* check, edict_t return callForward(RH_SV_AllowPhysent, original, indexOfEdict(check), indexOfEdict(sv_player)); } -int SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name) +BOOL SV_CheckUserInfo_AMXX(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, size_t userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name) { - auto original = [chain](netadr_t *_adr, char *_userinfo, qboolean _bIsReconnecting, int _iReconnectSlot, char *_name) + auto original = [chain](netadr_t *_adr, cell _userinfo, qboolean _bIsReconnecting, int _iReconnectSlot, char *_name) { - return chain->callNext(_adr, _userinfo, _bIsReconnecting, _iReconnectSlot, _name); + return chain->callNext(_adr, (char *)_userinfo, _bIsReconnecting, _iReconnectSlot, _name); }; - return callForward(RH_SV_CheckUserInfo, original, adr, userinfo, bIsReconnecting, iReconnectSlot, name); + return callForward(RH_SV_CheckUserInfo, original, adr, userinfo, bIsReconnecting, iReconnectSlot, name); +} + +BOOL SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name) +{ + return SV_CheckUserInfo_AMXX(chain, adr, (size_t)userinfo, bIsReconnecting, iReconnectSlot, name); } int PF_precache_generic_I(IRehldsHook_PF_precache_generic_I *chain, const char *s) @@ -1614,7 +1619,7 @@ void CSGameRules_Think(IReGameHook_CSGameRules_Think *chain) callVoidForward(RG_CSGameRules_Think, original); } - + BOOL CSGameRules_TeamFull(IReGameHook_CSGameRules_TeamFull *chain, int team_id) { auto original = [chain](int _team_id) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index cec30399..089299d6 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -338,7 +338,8 @@ void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics); void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value); void ClientConnected(IRehldsHook_ClientConnected* chain, IGameClient* cl); void SV_ConnectClient(IRehldsHook_SV_ConnectClient* chain); -int SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo* chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name); +BOOL SV_CheckUserInfo(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name); +BOOL SV_CheckUserInfo_AMXX(IRehldsHook_SV_CheckUserInfo *chain, netadr_t *adr, size_t userinfo, qboolean bIsReconnecting, int iReconnectSlot, char *name); struct SV_WriteFullClientUpdate_args_t { @@ -547,14 +548,14 @@ void ClearMultiDamage(IReGameHook_ClearMultiDamage *chain); void AddMultiDamage(IReGameHook_AddMultiDamage *chain, entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType); void ApplyMultiDamage(IReGameHook_ApplyMultiDamage *chain, entvars_t *pevInflictor, entvars_t *pevAttacker); void BuyItem(IReGameHook_BuyItem *chain, CBasePlayer *pPlayer, int iSlot); -void CSGameRules_Think(IReGameHook_CSGameRules_Think *chain); +void CSGameRules_Think(IReGameHook_CSGameRules_Think *chain); BOOL CSGameRules_TeamFull(IReGameHook_CSGameRules_TeamFull *chain, int team_id); BOOL CSGameRules_TeamStacked(IReGameHook_CSGameRules_TeamStacked *chain, int newTeam_id, int curTeam_id); void CSGameRules_PlayerGotWeapon(IReGameHook_CSGameRules_PlayerGotWeapon *chain, CBasePlayer *pPlayer, CBasePlayerItem *pWeapon); void CBotManager_OnEvent(IReGameHook_CBotManager_OnEvent *chain, GameEventType event, CBaseEntity* pEntity, CBaseEntity* pOther); void CBasePlayer_CheckTimeBasedDamage(IReGameHook_CBasePlayer_CheckTimeBasedDamage *chain, CBasePlayer *pthis); edict_t *CBasePlayer_EntSelectSpawnPoint(IReGameHook_CBasePlayer_EntSelectSpawnPoint *chain, CBasePlayer *pthis); -void CBasePlayerWeapon_ItemPostFrame(IReGameHook_CBasePlayerWeapon_ItemPostFrame *chain, CBasePlayerWeapon *pthis); +void CBasePlayerWeapon_ItemPostFrame(IReGameHook_CBasePlayerWeapon_ItemPostFrame *chain, CBasePlayerWeapon *pthis); void CBasePlayerWeapon_KickBack(IReGameHook_CBasePlayerWeapon_KickBack *chain, CBasePlayerWeapon *pthis, float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change); void CBasePlayerWeapon_SendWeaponAnim(IReGameHook_CBasePlayerWeapon_SendWeaponAnim *chain, CBasePlayerWeapon *pthis, int iAnim, int skiplocal); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 6e77e20a..870c95c1 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -99,7 +99,7 @@ hook_t hooklist_engine[] = { ENG(ED_Alloc), ENG(ED_Free), ENG(Con_Printf), - ENG(SV_CheckUserInfo), + ENG(SV_CheckUserInfo, _AMXX), ENG(PF_precache_generic_I), ENG(PF_precache_model_I), ENG(PF_precache_sound_I), diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index becae619..b7777ad6 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -30,6 +30,7 @@ #define MOVEVAR_MEMBERS(mx) STRUCT_MEMBERS(movevars_t, mx, mv_##mx) #define UCMD_MEMBERS(mx) STRUCT_MEMBERS(usercmd_s, mx, ucmd_##mx) #define PMTRACE_MEMBERS(mx) STRUCT_MEMBERS(pmtrace_s, mx, pmt_##mx) +#define NETADR_MEMBERS(mx) STRUCT_MEMBERS(netadr_t, mx, netadr_##mx) #define CSPL_MEMBERS(mx) CLASS_MEMBERS(CCSPlayer, mx, mx) #define BASEITEM_MEMBERS(mx) CLASS_MEMBERS(CBasePlayerItem, mx, mx) #define BASEWPN_MEMBERS(mx) CLASS_MEMBERS_PREF(CBasePlayerWeapon, mx, m_Weapon_##mx, m_) @@ -111,6 +112,7 @@ inline MType getMemberType(MONSTERSTATE) { return MEMBER_INTEGER; } inline MType getMemberType(ArmorType) { return MEMBER_INTEGER; } inline MType getMemberType(ArmouryItemPack) { return MEMBER_INTEGER; } inline MType getMemberType(InfoMapBuyParam) { return MEMBER_INTEGER; } +inline MType getMemberType(netadrtype_t) { return MEMBER_INTEGER; } inline MType getMemberType(TraceResult) { return MEMBER_TRACERESULT; } @@ -1048,6 +1050,12 @@ member_t memberlist_gib[] = { GIB_MEMBERS(lifeTime), }; +member_t memberlist_netadr[] = { + NETADR_MEMBERS(type), + NETADR_MEMBERS(ip), + NETADR_MEMBERS(port) +}; + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // #ifdef __GNUC__ @@ -1111,6 +1119,7 @@ member_t *memberlist_t::operator[](size_t members) const CASE(mapinfo) CASE(csplayerweapon) CASE(gib) + CASE(netadr) } #undef CASE diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index 30c9908d..d54c6aad 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -83,6 +83,7 @@ struct memberlist_t mt_mapinfo, mt_csplayerweapon, mt_gib, + mt_netadr }; }; @@ -735,6 +736,13 @@ enum PMTrace pmt_hitgroup }; +enum NetAdr +{ + netadr_type = BEGIN_MEMBER_REGION(netadr), + netadr_ip, + netadr_port +}; + // CCSPlayer enum CSPlayer_Members { diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index fff90643..e36c465f 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -113,6 +113,61 @@ cell AMX_NATIVE_CALL amx_get_viewent(AMX *amx, cell *params) return indexOfEdictAmx(pClient->pViewEntity); } +/* +* Sets value string to entire buffer +* +* @param buffer Pointer to buffer +* @param value Value to set +* @param maxlen Maximum size of the value buffer to set, -1 means copy all characters +* +* @return 1 on success, 0 otherwise +* +* native set_key_value_buffer(const pbuffer, const value[], const maxlen = -1); +*/ +cell AMX_NATIVE_CALL amx_set_key_value_buffer(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_buffer, arg_value, arg_maxlen }; + + char *buffer = reinterpret_cast(params[arg_buffer]); + if (!buffer) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid buffer", __FUNCTION__); + return FALSE; + } + + size_t maxlen = (params[arg_maxlen] > 0) ? min(params[arg_maxlen], MAX_INFO_STRING) : MAX_INFO_STRING; + char infobuf[MAX_INFO_STRING]; + const char *value = getAmxString(amx, params[arg_value], infobuf); + size_t len = min(Q_strlen(value) + 1, maxlen); + Q_strnlcpy(buffer, value, len); + return TRUE; +} + +/* +* Gets an AMXX string buffer from a infobuffer pointer +* +* @param buffer Info string pointer +* @param value String to copy value to +* @param maxlen Maximum size of the output buffer +* +* @return Returns a string buffer on infobuffer pointer +* +* native get_key_value_buffer(const pbuffer, const output[], const maxlen); +*/ +cell AMX_NATIVE_CALL amx_get_key_value_buffer(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_buffer, arg_output, arg_maxlen }; + + char *buffer = reinterpret_cast(params[arg_buffer]); + if (!buffer) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid buffer", __FUNCTION__); + return FALSE; + } + + return g_amxxapi.SetAmxString(amx, params[arg_output], buffer, params[arg_maxlen]); +} + /* * Gets value for key in buffer * @@ -480,19 +535,21 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) AMX_NATIVE_INFO Natives_Common[] = { - { "FClassnameIs", amx_FClassnameIs }, - { "GetGrenadeType", amx_GetGrenadeType }, - { "engset_view", amx_engset_view }, - { "get_viewent", amx_get_viewent }, - { "get_key_value", amx_get_key_value }, - { "set_key_value", amx_set_key_value }, - { "GetBonePosition", amx_GetBonePosition }, - { "GetAttachment", amx_GetAttachment }, - { "SetThink", amx_SetThink }, - { "SetTouch", amx_SetTouch }, - { "SetUse", amx_SetUse }, - { "SetBlocked", amx_SetBlocked }, - { "SetMoveDone", amx_SetMoveDone }, + { "FClassnameIs", amx_FClassnameIs }, + { "GetGrenadeType", amx_GetGrenadeType }, + { "engset_view", amx_engset_view }, + { "get_viewent", amx_get_viewent }, + { "get_key_value", amx_get_key_value }, + { "set_key_value", amx_set_key_value }, + { "get_key_value_buffer", amx_get_key_value_buffer }, + { "set_key_value_buffer", amx_set_key_value_buffer }, + { "GetBonePosition", amx_GetBonePosition }, + { "GetAttachment", amx_GetAttachment }, + { "SetThink", amx_SetThink }, + { "SetTouch", amx_SetTouch }, + { "SetUse", amx_SetUse }, + { "SetBlocked", amx_SetBlocked }, + { "SetMoveDone", amx_SetMoveDone }, { nullptr, nullptr } }; diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index a356f8a6..9c2daa12 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -667,6 +667,96 @@ cell AMX_NATIVE_CALL get_pmtrace(AMX *amx, cell *params) return get_member(tr, member, dest, element); } +/* +* Sets a NetAdr var. +* +* @param var The specified mvar, look at the enum NetAdrVars +* +* @return 1 on success. +* +* native set_netadr(const adr, const NetAdrVars:var, any:...); +*/ +cell AMX_NATIVE_CALL set_netadr(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_adr, arg_var, arg_value }; + member_t *member = memberlist[params[arg_var]]; + + if (unlikely(member == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: unknown member id %i", __FUNCTION__, params[arg_var]); + return FALSE; + } + + netadr_t *adr = (netadr_t *)params[arg_adr]; + if (unlikely(adr == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid network address", __FUNCTION__); + return FALSE; + } + + switch (params[arg_var]) + { + case netadr_type: + adr->type = (netadrtype_t)params[arg_value]; + break; + case netadr_port: + adr->port = ntohs(params[arg_value] & 0xFFFF); // cap short + break; + case netadr_ip: + *(size_t *)adr->ip = htonl(params[arg_value] & 0xFFFFFFFF); // cap int + break; + default: + return FALSE; + } + + return TRUE; +} + +/* +* Returns a NetAdr var +* +* @param var The specified mvar, look at the enum NetAdrVars +* +* @return If an integer or boolean or one byte, array or everything else is passed via the 3rd argument and more, look at the argument list for the specified mvar +* +* native any:get_netadr(const adr, const NetAdrVars:var, any:...); +*/ +cell AMX_NATIVE_CALL get_netadr(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_adr, arg_var, arg_3, arg_4 }; + member_t *member = memberlist[params[arg_var]]; + + if (unlikely(member == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: unknown member id %i", __FUNCTION__, params[arg_var]); + return FALSE; + } + + netadr_t *adr = (netadr_t *)params[arg_adr]; + if (unlikely(adr == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid network address", __FUNCTION__); + return FALSE; + } + + switch (params[arg_var]) + { + case netadr_type: return adr->type; + case netadr_port: return ntohs(adr->port); + case netadr_ip: + { + if (PARAMS_COUNT == 4) + { + cell *dest = getAmxAddr(amx, params[arg_3]); + size_t length = *getAmxAddr(amx, params[arg_4]); + setAmxString(dest, NET_AdrToString(*adr, true /*no port*/), length); + } + + return htonl(*(size_t *)adr->ip); + } + default: + break; + } + + return FALSE; +} + /* * Sets a RebuyStruct member. * @@ -757,6 +847,9 @@ AMX_NATIVE_INFO ReGameVars_Natives[] = { "set_pmtrace", set_pmtrace }, { "get_pmtrace", get_pmtrace }, + { "set_netadr", set_netadr }, + { "get_netadr", get_netadr }, + { nullptr, nullptr } }; diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index ea276784..15f85ea7 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -1010,7 +1010,7 @@ cell AMX_NATIVE_CALL rg_drop_item(AMX *amx, cell *params) char item[256]; auto pEntity = pPlayer->CSPlayer()->DropPlayerItem(getAmxString(amx, params[arg_item_name], item)); - + if (pEntity) return indexOfPDataAmx(pEntity); @@ -2230,7 +2230,7 @@ cell AMX_NATIVE_CALL rg_get_iteminfo(AMX *amx, cell *params) /** * Sets a parameter of the global CBasePlayerItem::m_ItemInfoArray array -* @note To have effect on client side (i.g. ammo size on HUD) you should +* @note To have effect on client side (i.g. ammo size on HUD) you should * alter this value BEFORE WeaponList message is sent to client, or * force it's alteration by sending again to the specific client. * Hooking WeaponList message with AMXX's register_message is a choice. @@ -2299,7 +2299,7 @@ cell AMX_NATIVE_CALL rg_get_global_iteminfo(AMX *amx, cell *params) } ItemInfo_e type = static_cast(params[arg_type]); - if ((type == ItemInfo_pszAmmo1 || type == ItemInfo_pszAmmo2 || type == ItemInfo_pszName) && PARAMS_COUNT != 4) + if ((type == ItemInfo_pszAmmo1 || type == ItemInfo_pszAmmo2 || type == ItemInfo_pszName) && PARAMS_COUNT != 4) { AMXX_LogError(amx, AMX_ERR_NATIVE, "Bad arg count. Expected %d, got %d.", 4, PARAMS_COUNT); return FALSE; @@ -2861,7 +2861,7 @@ cell AMX_NATIVE_CALL rh_get_net_from(AMX* amx, cell* params) enum args_e { arg_count, arg_output, arg_maxlen }; cell *dest = getAmxAddr(amx, params[arg_output]); - char *addr = NET_AdrToString(*g_RehldsData->GetNetFrom()); + const char *addr = NET_AdrToString(*g_RehldsData->GetNetFrom()); setAmxString(dest, addr, params[arg_maxlen]); diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 2a426447..d285b347 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -262,7 +262,7 @@ const char *getATypeStr(AType type) return s_ATypes[type]; } -char* NET_AdrToString(const netadr_t& a) +const char *NET_AdrToString(const netadr_t &a, bool onlyBase) { static char s[64]; @@ -270,8 +270,14 @@ char* NET_AdrToString(const netadr_t& a) if (a.type == NA_LOOPBACK) Q_snprintf(s, sizeof(s), "loopback"); + else if (a.type == NA_IP) - Q_snprintf(s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); + { + if (onlyBase) + Q_snprintf(s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); + else + Q_snprintf(s, sizeof(s), "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ntohs(a.port)); + } #ifdef _WIN32 else // NA_IPX Q_snprintf(s, sizeof(s), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], ntohs(a.port)); diff --git a/reapi/src/reapi_utils.h b/reapi/src/reapi_utils.h index 7f261457..bad3c0f0 100644 --- a/reapi/src/reapi_utils.h +++ b/reapi/src/reapi_utils.h @@ -59,6 +59,6 @@ void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType typ const char *getATypeStr(AType type); -char *NET_AdrToString(const netadr_t& a); +const char *NET_AdrToString(const netadr_t &a, bool onlyBase = false); extern void NORETURN UTIL_SysError(const char *fmt, ...); diff --git a/reapi/version/version.h b/reapi/version/version.h index 554ac429..721f2b48 100644 --- a/reapi/version/version.h +++ b/reapi/version/version.h @@ -6,5 +6,5 @@ #pragma once #define VERSION_MAJOR 5 -#define VERSION_MINOR 23 +#define VERSION_MINOR 24 #define VERSION_MAINTENANCE 0 From 1a72c8a45cd70d111464ba5a2cb0c53f6b2b5614 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Tue, 10 Oct 2023 06:31:48 +0700 Subject: [PATCH 39/50] Improved initialization of rehlds api Prefer Sys_GetModuleHandle over Sys_LoadModule to avoid unnecessary reference count increase --- reapi/include/cssdk/public/interface.cpp | 8 ++++++++ reapi/include/cssdk/public/interface.h | 2 ++ reapi/src/mods/mod_regamedll_api.cpp | 2 +- reapi/src/mods/mod_rehlds_api.cpp | 19 ++++++++++++++----- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/reapi/include/cssdk/public/interface.cpp b/reapi/include/cssdk/public/interface.cpp index e6de1bef..de0a1848 100644 --- a/reapi/include/cssdk/public/interface.cpp +++ b/reapi/include/cssdk/public/interface.cpp @@ -121,6 +121,14 @@ void *Sys_GetProcAddress(void *pModuleHandle, const char *pName) return GetProcAddress((HMODULE)pModuleHandle, pName); } +// Purpose: Returns a module handle by its name. +// Input : pModuleName - module name +// Output : the module handle or NULL in case of an error +CSysModule *Sys_GetModuleHandle(const char *pModuleName) +{ + return reinterpret_cast(GetModuleHandle(pModuleName)); +} + // Purpose: Loads a DLL/component from disk and returns a handle to it // Input : *pModuleName - filename of the component // Output : opaque handle to the module (hides system dependency) diff --git a/reapi/include/cssdk/public/interface.h b/reapi/include/cssdk/public/interface.h index 0aeaca48..abe45b54 100644 --- a/reapi/include/cssdk/public/interface.h +++ b/reapi/include/cssdk/public/interface.h @@ -114,6 +114,8 @@ extern CreateInterfaceFn Sys_GetFactory(const char *pModuleName); // load/unload components class CSysModule; +extern CSysModule *Sys_GetModuleHandle(const char *pModuleName); + // Load & Unload should be called in exactly one place for each module // The factory for that module should be passed on to dependent components for // proper versioning. diff --git a/reapi/src/mods/mod_regamedll_api.cpp b/reapi/src/mods/mod_regamedll_api.cpp index bd7051e2..22dfcbd4 100644 --- a/reapi/src/mods/mod_regamedll_api.cpp +++ b/reapi/src/mods/mod_regamedll_api.cpp @@ -11,7 +11,7 @@ bool RegamedllApi_Init() if (!szGameDLLModule) return false; - CSysModule *gameModule = Sys_LoadModule(szGameDLLModule); + CSysModule *gameModule = Sys_GetModuleHandle(szGameDLLModule); if (!gameModule) return false; diff --git a/reapi/src/mods/mod_rehlds_api.cpp b/reapi/src/mods/mod_rehlds_api.cpp index 7dedb302..109c582f 100644 --- a/reapi/src/mods/mod_rehlds_api.cpp +++ b/reapi/src/mods/mod_rehlds_api.cpp @@ -8,15 +8,24 @@ IRehldsServerStatic* g_RehldsSvs; bool RehldsApi_Init() { - if (!IS_DEDICATED_SERVER()) +#ifdef WIN32 + // Find the most appropriate module handle from a list of DLL candidates + // Notes: + // - "swds.dll" is the library Dedicated Server + // + // Let's also attempt to locate the ReHLDS API in the client's library + // - "sw.dll" is the client library for Software render, with a built-in listenserver + // - "hw.dll" is the client library for Hardware render, with a built-in listenserver + const char *dllNames[] = { "swds.dll", "sw.dll", "hw.dll" }; // List of DLL candidates to lookup for the ReHLDS API + CSysModule *engineModule = NULL; // The module handle of the selected DLL + for (const char *dllName : dllNames) { - return false; + if (engineModule = Sys_GetModuleHandle(dllName)) + break; // gotcha } -#ifdef WIN32 - CSysModule* engineModule = Sys_LoadModule("swds.dll"); #else - CSysModule* engineModule = Sys_LoadModule("engine_i486.so"); + CSysModule *engineModule = Sys_GetModuleHandle("engine_i486.so"); #endif if (!engineModule) From 11ead5d3b6b617250643d5ea5408a322e950b528 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Wed, 22 Nov 2023 10:19:59 +0700 Subject: [PATCH 40/50] Fixed startPercent argument type for native rg_send_bartime2 --- reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc | 4 ++-- reapi/src/natives/natives_misc.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index edf31f99..198c3a79 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -868,7 +868,7 @@ native rg_send_bartime(const index, const duration, const bool:observer = true); * * @noreturn */ -native rg_send_bartime2(const index, const duration, const startPercent, const bool:observer = true); +native rg_send_bartime2(const index, const duration, const Float:startPercent, const bool:observer = true); /* * Sends the SendAudio message - plays the specified audio. @@ -901,7 +901,7 @@ native rg_get_iteminfo(const ent, ItemInfo:type, any:...); /** * Sets a parameter of the global CBasePlayerItem::m_ItemInfoArray array -* @note To have effect on client side (i.g. ammo size on HUD) you should +* @note To have effect on client side (i.g. ammo size on HUD) you should * alter this value BEFORE WeaponList message is sent to client, or * force it's alteration by sending again to the specific client. * Hooking WeaponList message with AMXX's register_message is a choice. diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 15f85ea7..3b53665f 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -2014,7 +2014,7 @@ cell AMX_NATIVE_CALL rg_send_bartime(AMX *amx, cell *params) * * @noreturn * -* native rg_send_bartime2(const index, const duration, const startPercent, const bool:observer = true); +* native rg_send_bartime2(const index, const duration, const Float:startPercent, const bool:observer = true); */ cell AMX_NATIVE_CALL rg_send_bartime2(AMX *amx, cell *params) { @@ -2024,15 +2024,16 @@ cell AMX_NATIVE_CALL rg_send_bartime2(AMX *amx, cell *params) CHECK_CONNECTED(pPlayer, arg_index); CAmxArgs args(amx, params); + float startPercent = args[arg_start_percent]; if (!args[arg_observer]) { EMESSAGE_BEGIN(MSG_ONE_UNRELIABLE, gmsgBarTime2, nullptr, pPlayer->edict()); EWRITE_SHORT(args[arg_time]); - EWRITE_SHORT(args[arg_start_percent]); + EWRITE_SHORT(startPercent); EMESSAGE_END(); return TRUE; } - pPlayer->CSPlayer()->SetProgressBarTime2(args[arg_time], args[arg_start_percent]); + pPlayer->CSPlayer()->SetProgressBarTime2(args[arg_time], startPercent); return TRUE; } From cf757aa832a28cd2b391294038963c7e8c50aa33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sun, 26 Nov 2023 00:38:49 -0300 Subject: [PATCH 41/50] Added GetBodygroup, SetBodygroup, GetSequenceInfo natives (#294) --- .../scripting/include/reapi_engine.inc | 42 +++++++ reapi/src/natives/natives_common.cpp | 104 ++++++++++++++++++ reapi/src/reapi_utils.cpp | 68 ++++++++++++ reapi/src/reapi_utils.h | 3 + 4 files changed, 217 insertions(+) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index f3cedd0a..ce3aabb8 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -123,6 +123,48 @@ native GetBonePosition(const entity, const bone, Float:vecOrigin[3], Float:vecAn */ native GetAttachment(const entity, const attachment, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0}); +/* +* Sets body group value based on entity's model group +* +* @param entity Entity index +* @param group Number of entity's model group index +* @param value Value to assign +* +* @return 1 on success, 0 otherwise +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +native SetBodygroup(const entity, const group, const value); + +/* +* Gets body group value based on entity's model group +* +* @param entity Entity index +* @param group Number of entity's model group index +* +* @return Body group value +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +native GetBodygroup(const entity, const group); + +/* +* Gets sequence information based on entity's model current sequence index +* +* @param entity Entity index +* @param piFlags Sequence flags (1 = sequence loops) +* @param pflFrameRate Sequence framerate +* @param pflGroundSpeed Sequence ground speed +* +* @return True on success, false otherwise +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +native bool:GetSequenceInfo(const entity, &piFlags, &Float:pflFrameRate, &Float:pflGroundSpeed); + /* * Sets the name of the map. * diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index e36c465f..416521a7 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -312,6 +312,107 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params) return TRUE; } +/* +* Sets body group value based on entity's model group +* +* @param entity Entity index +* @param group Number of entity's model group index +* @param value Value to assign +* +* @return 1 on success, 0 otherwise +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +cell AMX_NATIVE_CALL amx_GetBodygroup(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_group }; + + CHECK_ISENTITY(arg_index); + + CBaseEntity *pEntity = getPrivate(params[arg_index]); + if (unlikely(pEntity == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return 0; + } + + if (FNullEnt(params[arg_index])) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__); + return 0; + } + + return (cell)GetBodygroup(pEntity, params[arg_group]); +} + +/* +* Gets body group value based on entity's model group +* +* @param entity Entity index +* @param group Number of entity's model group index +* +* @return Body group value +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +cell AMX_NATIVE_CALL amx_SetBodygroup(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_group, arg_value }; + + CHECK_ISENTITY(arg_index); + + CBaseEntity *pEntity = getPrivate(params[arg_index]); + if (unlikely(pEntity == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (FNullEnt(params[arg_index])) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__); + return FALSE; + } + + SetBodygroup(pEntity, params[arg_group], params[arg_value]); + return TRUE; +} + +/* +* Gets sequence information based on entity's model current sequence index +* +* @param entity Entity index +* @param piFlags Sequence flags (1 = sequence loops) +* @param pflFrameRate Sequence framerate +* @param pflGroundSpeed Sequence ground speed +* +* @return True on success, false otherwise +* @error If the index is not within the range of 1 to maxEntities or +* the entity is not valid, an error will be thrown. +* +*/ +cell AMX_NATIVE_CALL amx_GetSequenceInfo(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_flags, arg_framerate, arg_groundspeed }; + + CHECK_ISENTITY(arg_index); + + CBaseEntity *pEntity = getPrivate(params[arg_index]); + if (unlikely(pEntity == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (FNullEnt(params[arg_index])) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__); + return FALSE; + } + + int* pflags = reinterpret_cast(getAmxAddr(amx, params[arg_flags])); + float* pframerate = reinterpret_cast(getAmxAddr(amx, params[arg_framerate])); + float* pgroundspeed = reinterpret_cast(getAmxAddr(amx, params[arg_groundspeed])); + + return (cell)GetSequenceInfo2(pEntity, pflags, pframerate, pgroundspeed); +} + /* * Sets Think callback for entity * @@ -545,6 +646,9 @@ AMX_NATIVE_INFO Natives_Common[] = { "set_key_value_buffer", amx_set_key_value_buffer }, { "GetBonePosition", amx_GetBonePosition }, { "GetAttachment", amx_GetAttachment }, + { "GetBodygroup", amx_GetBodygroup }, + { "SetBodygroup", amx_SetBodygroup }, + { "GetSequenceInfo", amx_GetSequenceInfo }, { "SetThink", amx_SetThink }, { "SetTouch", amx_SetTouch }, { "SetUse", amx_SetUse }, diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index d285b347..ade7779a 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -223,6 +223,74 @@ void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Ve } } +void SetBodygroup(CBaseEntity *pEntity, int iGroup, int iValue) +{ + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEntity->edict())); + if (!pstudiohdr || iGroup > pstudiohdr->numbodyparts) + { + return; + } + + mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup; + + if (iValue >= pbodypart->nummodels) + { + return; + } + + int iCurrent = (pEntity->pev->body / pbodypart->base) % pbodypart->nummodels; + pEntity->pev->body += (iValue - iCurrent) * pbodypart->base; +} + +int GetBodygroup(CBaseEntity *pEntity, int iGroup) +{ + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEntity->edict())); + + if (!pstudiohdr || iGroup > pstudiohdr->numbodyparts) + { + return 0; + } + + mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup; + + if (pbodypart->nummodels <= 1) + { + return 0; + } + + int iCurrent = (pEntity->pev->body / pbodypart->base) % pbodypart->nummodels; + return iCurrent; +} + +bool GetSequenceInfo2(CBaseEntity *pEntity, int *piFlags, float *pflFrameRate, float *pflGroundSpeed) +{ + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEntity->edict())); + + if (!pstudiohdr || pEntity->pev->sequence >= pstudiohdr->numseq) + { + *piFlags = 0; + *pflFrameRate = 0; + *pflGroundSpeed = 0; + return false; + } + + mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pEntity->pev->sequence); + *piFlags = pseqdesc->flags; + if (pseqdesc->numframes <= 1) + { + *pflFrameRate = 256.0f; + *pflGroundSpeed = 0.0f; + } + else + { + *pflFrameRate = pseqdesc->fps * 256.0f / (pseqdesc->numframes - 1); + *pflGroundSpeed = Q_sqrt(pseqdesc->linearmovement[0] * pseqdesc->linearmovement[0] + pseqdesc->linearmovement[1] * pseqdesc->linearmovement[1] + pseqdesc->linearmovement[2] * pseqdesc->linearmovement[2]); + *pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1); + } + + return true; +} + void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType type) { switch (type) diff --git a/reapi/src/reapi_utils.h b/reapi/src/reapi_utils.h index bad3c0f0..b8d3a4c0 100644 --- a/reapi/src/reapi_utils.h +++ b/reapi/src/reapi_utils.h @@ -55,6 +55,9 @@ CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *p void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles); void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Vector *pVecAngles); +void SetBodygroup(CBaseEntity *pEntity, int iGroup, int iValue); +int GetBodygroup(CBaseEntity *pEntity, int iGroup); +bool GetSequenceInfo2(CBaseEntity *pEntity, int *piFlags, float *pflFrameRate, float *pflGroundSpeed); void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType type); const char *getATypeStr(AType type); From b281588ddf8f68bba67498f9dc8a6cca1f7a44fb Mon Sep 17 00:00:00 2001 From: Javekson <132286351+Javekson@users.noreply.github.com> Date: Sun, 26 Nov 2023 07:54:11 +0400 Subject: [PATCH 42/50] fix(rg_transfer_c4): prevent C4 destruction on arg receiver = 0 (#291) --- .../scripting/include/reapi_gamedll.inc | 2 +- reapi/include/cssdk/dlls/gamerules.h | 2 +- reapi/src/natives/natives_misc.cpp | 46 ++++++++++++++----- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 198c3a79..47289600 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -697,7 +697,7 @@ native rg_get_user_footsteps(const index); * @param index Client index * @param receiver Receiver index, if 0 it will transfer to a random player * -* @return 1 on success, 0 otherwise +* @return Index of player entity if successfull, 0 otherwise */ native rg_transfer_c4(const index, const receiver = 0); diff --git a/reapi/include/cssdk/dlls/gamerules.h b/reapi/include/cssdk/dlls/gamerules.h index 6778601a..d0781beb 100644 --- a/reapi/include/cssdk/dlls/gamerules.h +++ b/reapi/include/cssdk/dlls/gamerules.h @@ -531,7 +531,7 @@ class CHalfLifeMultiplay: public CGameRules // check if the scenario has been won/lost virtual void CheckWinConditions() = 0; virtual void RemoveGuns() = 0; - virtual void GiveC4() = 0; + virtual CBasePlayer *GiveC4() = 0; virtual void ChangeLevel() = 0; virtual void GoToIntermission() = 0; diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 3b53665f..cf803a77 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -1575,10 +1575,11 @@ cell AMX_NATIVE_CALL rg_get_user_footsteps(AMX *amx, cell *params) * @param index Client index * @param receiver Receiver index, if 0 it will transfer to a random player * -* @return 1 on success, 0 otherwise +* @return Index of player entity if successfull, 0 otherwise * * native rg_transfer_c4(const index, const receiver = 0); */ + cell AMX_NATIVE_CALL rg_transfer_c4(AMX *amx, cell *params) { enum args_e { arg_count, arg_index, arg_receiver }; @@ -1589,29 +1590,50 @@ cell AMX_NATIVE_CALL rg_transfer_c4(AMX *amx, cell *params) CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); CHECK_CONNECTED(pPlayer, arg_index); - if (!pPlayer->m_bHasC4 || !pPlayer->CSPlayer()->RemovePlayerItem("weapon_c4")) + if (!pPlayer->m_bHasC4) { return FALSE; + } - pPlayer->pev->body = 0; - pPlayer->m_bHasC4 = false; - pPlayer->CSPlayer()->SetBombIcon(); - pPlayer->CSPlayer()->SetProgressBarTime(0); + CBasePlayer *pReceiver = nullptr; - if (params[arg_receiver] != 0 && params[arg_receiver] <= gpGlobals->maxClients) { - CBasePlayer *pReceiver = UTIL_PlayerByIndex(params[arg_receiver]); + if (params[arg_receiver] > 0 && params[arg_receiver] <= gpGlobals->maxClients) { + pReceiver = UTIL_PlayerByIndex(params[arg_receiver]); CHECK_CONNECTED(pReceiver, arg_receiver); - if (!pReceiver->CSPlayer()->MakeBomber()) + if (!pPlayer->CSPlayer()->RemovePlayerItemEx("weapon_c4", true)) { return FALSE; + } + + if (!pReceiver->CSPlayer()->MakeBomber()) { + return FALSE; + } + } + else { + int NumDeadCT, NumDeadTerrorist, NumAliveTerrorist, NumAliveCT; + CSGameRules()->InitializePlayerCounts(NumAliveTerrorist, NumAliveCT, NumDeadTerrorist, NumDeadCT); + + if (pPlayer->m_iTeam == CT && NumAliveTerrorist < 1) { + return FALSE; + } + + if (pPlayer->m_iTeam == TERRORIST && NumAliveTerrorist < 2) { + return FALSE; + } + + if (!pPlayer->CSPlayer()->RemovePlayerItemEx("weapon_c4", true)) { + return FALSE; + } - } else { auto flags = pPlayer->pev->flags; pPlayer->pev->flags |= FL_DORMANT; - CSGameRules()->GiveC4(); + pReceiver = CSGameRules()->GiveC4(); pPlayer->pev->flags = flags; } - return TRUE; + if (pReceiver) + return indexOfPDataAmx(pReceiver); + + return FALSE; } /* From 4c1932c2c957f35bbc85ed98de01164148d0156a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sun, 26 Nov 2023 01:12:14 -0300 Subject: [PATCH 43/50] Headers update, rename m_bHasSecondaryAttack, CSPlayer member additions (#293) * Update CSEntity.h, CSPlayer.h, CSPlayerItem.h, regamedll_api.h * SendDeathMessage interface to regamedll_api.h * Update CSPlayerWeapon class, rename m_bHasSecondaryAttack * Updated CSPlayerWeapon.h vfuncs and members * Renamed bHasSecondaryAttack member to iStateSecondaryAttack and added compat to AMXX includes * Added remaining CSPlayer members * Added overload method for bool[] --- .../amxmodx/scripting/include/cssdk_const.inc | 11 + .../scripting/include/reapi_gamedll_const.inc | 59 ++++- reapi/include/cssdk/dlls/API/CSEntity.h | 5 +- reapi/include/cssdk/dlls/API/CSPlayer.h | 37 ++- reapi/include/cssdk/dlls/API/CSPlayerItem.h | 1 + reapi/include/cssdk/dlls/API/CSPlayerWeapon.h | 18 +- reapi/include/cssdk/dlls/regamedll_api.h | 11 + reapi/include/cssdk/public/utlarray.h | 235 ++++++++++++++++++ reapi/msvc/reapi.vcxproj | 1 + reapi/msvc/reapi.vcxproj.filters | 3 + reapi/src/member_list.cpp | 10 +- reapi/src/member_list.h | 8 +- 12 files changed, 384 insertions(+), 15 deletions(-) create mode 100644 reapi/include/cssdk/public/utlarray.h diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 149baeed..17a0bf57 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -1479,3 +1479,14 @@ enum GameEventType EVENT_HOSTAGE_CALLED_FOR_HELP, // tell bots the hostage is talking (argumens: 1 = listener, 2 = NULL) NUM_GAME_EVENTS, }; + +/** +* Weapon secondary attack states +* For CCSPlayerWeapon::m_iStateSecondaryAttack +*/ +enum SecondaryAtkState +{ + WEAPON_SECONDARY_ATTACK_NONE = 0, + WEAPON_SECONDARY_ATTACK_SET, + WEAPON_SECONDARY_ATTACK_BLOCK +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index a4a34e8e..9749df4e 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -4816,6 +4816,54 @@ enum CCSPlayer_Members * Set params: set_member(index, member, bool:value); */ m_bSpawnProtectionEffects, + + /* + * Description: Player vertical jump height + * Member type: float + * Get params: Float:get_member(index, member); + * Set params: set_member(index, member, Float:value); + */ + m_flJumpHeight, + + /* + * Description: Player vertical jump height with longjump + * Member type: float + * Get params: Float:get_member(index, member); + * Set params: set_member(index, member, Float:value); + */ + m_flLongJumpHeight, + + /* + * Description: Player horizontal jump height with longjump + * Member type: float + * Get params: Float:get_member(index, member); + * Set params: set_member(index, member, Float:value); + */ + m_flLongJumpForce, + + /* + * Description: Player crouch maxspeed multiplier + * Member type: float + * Get params: Float:get_member(index, member); + * Set params: set_member(index, member, Float:value); + */ + m_flDuckSpeedMultiplier, + + /* + * Description: How many unanswered kills this player has been dealt by each other player (0-31) + * Member type: int [32] + * Get params: get_member(index, member, element); + * Set params: set_member(index, member, value, element); + */ + m_iNumKilledByUnanswered, + + /* + * Description: Array of state per other player whether player is dominating other players (0-31) + * Member type: bool [32] + * Get params: get_member(index, member, element); + * Set params: set_member(index, member, value, element); + */ + m_bPlayerDominated, }; /** @@ -6238,12 +6286,12 @@ enum CMapInfo_Members enum CCSPlayerWeapon_Members { /* - * Description: Can the weapon have secondary attack - * Member type: bool + * Description: Weapon secondary attack state + * Member type: enum SecondaryAtkState * Get params: get_member(index, member); - * Set params: set_member(index, member, bool:value); + * Set params: set_member(index, member, SecondaryAtkState:value); */ - m_Weapon_bHasSecondaryAttack = BEGIN_MEMBER_REGION(csplayerweapon), + m_Weapon_iStateSecondaryAttack = BEGIN_MEMBER_REGION(csplayerweapon), /* * Description: Basic damage that weapon deals before any multiplier, such as hitgroup, armor, distance and bullet penetration @@ -6254,6 +6302,9 @@ enum CCSPlayerWeapon_Members m_Weapon_flBaseDamage, }; +// API compatibility +#define m_Weapon_bHasSecondaryAttack m_Weapon_iStateSecondaryAttack + /** * CGib Members */ diff --git a/reapi/include/cssdk/dlls/API/CSEntity.h b/reapi/include/cssdk/dlls/API/CSEntity.h index 8f03b7c2..4f321515 100644 --- a/reapi/include/cssdk/dlls/API/CSEntity.h +++ b/reapi/include/cssdk/dlls/API/CSEntity.h @@ -36,6 +36,7 @@ class CCSEntity CCSEntity() : m_pContainingEntity(nullptr) { + m_ucDmgPenetrationLevel = 0; } virtual ~CCSEntity() {} @@ -45,12 +46,14 @@ class CCSEntity public: CBaseEntity *m_pContainingEntity; + unsigned char m_ucDmgPenetrationLevel; // penetration level of the damage caused by the inflictor private: #if defined(_MSC_VER) #pragma region reserve_data_Region #endif - int CCSEntity_Reserve[0x1000]; + char CCSEntity_Reserve[0x3FFF]; + virtual void func_reserve1() {}; virtual void func_reserve2() {}; virtual void func_reserve3() {}; diff --git a/reapi/include/cssdk/dlls/API/CSPlayer.h b/reapi/include/cssdk/dlls/API/CSPlayer.h index b12aa230..3495ee29 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayer.h +++ b/reapi/include/cssdk/dlls/API/CSPlayer.h @@ -30,6 +30,7 @@ #include #include +#include enum WeaponInfiniteAmmoMode { @@ -52,9 +53,21 @@ class CCSPlayer: public CCSMonster m_bAutoBunnyHopping(false), m_bMegaBunnyJumping(false), m_bPlantC4Anywhere(false), - m_bSpawnProtectionEffects(false) + m_bSpawnProtectionEffects(false), + m_flJumpHeight(0), + m_flLongJumpHeight(0), + m_flLongJumpForce(0), + m_flDuckSpeedMultiplier(0), + m_iUserID(-1) { m_szModel[0] = '\0'; + + // Resets the kill history for this player + for (int i = 0; i < MAX_CLIENTS; i++) + { + m_iNumKilledByUnanswered[i] = 0; + m_bPlayerDominated[i] = false; + } } virtual bool IsConnected() const = 0; @@ -106,11 +119,6 @@ class CCSPlayer: public CCSMonster virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true) = 0; virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr) = 0; - void ResetVars(); - - void OnSpawn(); - void OnKilled(); - CBasePlayer *BasePlayer() const; public: @@ -138,6 +146,23 @@ class CCSPlayer: public CCSMonster bool m_bMegaBunnyJumping; bool m_bPlantC4Anywhere; bool m_bSpawnProtectionEffects; + double m_flJumpHeight; + double m_flLongJumpHeight; + double m_flLongJumpForce; + double m_flDuckSpeedMultiplier; + + int m_iUserID; + struct CDamageRecord_t + { + float flDamage = 0.0f; + float flFlashDurationTime = 0.0f; + int userId = -1; + }; + using DamageList_t = CUtlArray; + DamageList_t m_DamageList; // A unified array of recorded damage that includes giver and taker in each entry + DamageList_t &GetDamageList() { return m_DamageList; } + int m_iNumKilledByUnanswered[MAX_CLIENTS]; // [0-31] how many unanswered kills this player has been dealt by each other player + bool m_bPlayerDominated[MAX_CLIENTS]; // [0-31] array of state per other player whether player is dominating other players }; // Inlines diff --git a/reapi/include/cssdk/dlls/API/CSPlayerItem.h b/reapi/include/cssdk/dlls/API/CSPlayerItem.h index 74abc0b2..e4bec454 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayerItem.h +++ b/reapi/include/cssdk/dlls/API/CSPlayerItem.h @@ -39,6 +39,7 @@ class CCSPlayerItem: public CCSAnimating } virtual void SetItemInfo(ItemInfo *pInfo) = 0; + virtual int GetItemInfo(ItemInfo *pInfo) = 0; CBasePlayerItem *BasePlayerItem() const; diff --git a/reapi/include/cssdk/dlls/API/CSPlayerWeapon.h b/reapi/include/cssdk/dlls/API/CSPlayerWeapon.h index 70317c93..837347c4 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayerWeapon.h +++ b/reapi/include/cssdk/dlls/API/CSPlayerWeapon.h @@ -28,19 +28,33 @@ #pragma once +enum SecondaryAtkState : uint8_t +{ + WEAPON_SECONDARY_ATTACK_NONE = 0, + WEAPON_SECONDARY_ATTACK_SET, + WEAPON_SECONDARY_ATTACK_BLOCK +}; + class CBasePlayerWeapon; class CCSPlayerWeapon: public CCSPlayerItem { + DECLARE_CLASS_TYPES(CCSPlayerWeapon, CCSPlayerItem); public: CCSPlayerWeapon() : - m_bHasSecondaryAttack(false) + m_iStateSecondaryAttack(WEAPON_SECONDARY_ATTACK_NONE) { } + virtual BOOL DefaultDeploy(char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal = 0) = 0; + virtual int DefaultReload(int iClipSize, int iAnim, float fDelay) = 0; + virtual bool DefaultShotgunReload(int iAnim, int iStartAnim, float fDelay, float fStartDelay, const char *pszReloadSound1 = nullptr, const char *pszReloadSound2 = nullptr) = 0; + virtual void KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change) = 0; + virtual void SendWeaponAnim(int iAnim, int skiplocal = 0) = 0; + CBasePlayerWeapon *BasePlayerWeapon() const; public: - bool m_bHasSecondaryAttack; + SecondaryAtkState m_iStateSecondaryAttack; float m_flBaseDamage; }; diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index d3531fec..5d5d4861 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -614,6 +614,14 @@ typedef IHookChainRegistryClass IReGameHook_CBasePlayerWeapon_SendWeaponAnim; typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim; +// CHalfLifeMultiplay::SendDeathMessage hook +typedef IHookChain IReGameHook_CSGameRules_SendDeathMessage; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_SendDeathMessage; + +// CBasePlayer::PlayerDeathThink hook +typedef IHookChainClass IReGameHook_CBasePlayer_PlayerDeathThink; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_PlayerDeathThink; + class IReGameHookchains { public: virtual ~IReGameHookchains() {} @@ -771,6 +779,9 @@ class IReGameHookchains { virtual IReGameHookRegistry_CBasePlayerWeapon_ItemPostFrame *CBasePlayerWeapon_ItemPostFrame() = 0; virtual IReGameHookRegistry_CBasePlayerWeapon_KickBack *CBasePlayerWeapon_KickBack() = 0; virtual IReGameHookRegistry_CBasePlayerWeapon_SendWeaponAnim *CBasePlayerWeapon_SendWeaponAnim() = 0; + virtual IReGameHookRegistry_CSGameRules_SendDeathMessage *CSGameRules_SendDeathMessage() = 0; + + virtual IReGameHookRegistry_CBasePlayer_PlayerDeathThink *CBasePlayer_PlayerDeathThink() = 0; }; struct ReGameFuncs_t { diff --git a/reapi/include/cssdk/public/utlarray.h b/reapi/include/cssdk/public/utlarray.h new file mode 100644 index 00000000..6bdb4136 --- /dev/null +++ b/reapi/include/cssdk/public/utlarray.h @@ -0,0 +1,235 @@ +/* +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +*/ + +#pragma once + +// A growable array class that maintains a free list and keeps elements +// in the same location +#include "tier0/platform.h" +#include "tier0/dbg.h" + +#define FOR_EACH_ARRAY(vecName, iteratorName)\ + for (int iteratorName = 0; (vecName).IsUtlArray && iteratorName < (vecName).Count(); iteratorName++) + +#define FOR_EACH_ARRAY_BACK(vecName, iteratorName)\ + for (int iteratorName = (vecName).Count() - 1; (vecName).IsUtlArray && iteratorName >= 0; iteratorName--) + +template +class CUtlArray +{ +public: + typedef T ElemType_t; + enum { IsUtlArray = true }; // Used to match this at compiletime + + CUtlArray(); + CUtlArray(T *pMemory, size_t count); + ~CUtlArray(); + + CUtlArray &operator=(const CUtlArray &other); + CUtlArray(CUtlArray const &vec); + + // element access + T &operator[](int i); + const T &operator[](int i) const; + T &Element(int i); + const T &Element(int i) const; + T &Random(); + const T &Random() const; + + T *Base(); + const T *Base() const; + + // Returns the number of elements in the array, NumAllocated() is included for consistency with UtlVector + int Count() const; + int NumAllocated() const; + + // Is element index valid? + bool IsValidIndex(int i) const; + static int InvalidIndex(); + + void CopyArray(const T *pArray, size_t count); + + void Clear(); + void RemoveAll(); + void Swap(CUtlArray< T, MAX_SIZE> &vec); + + // Finds an element (element needs operator== defined) + int Find(const T &src) const; + void FillWithValue(const T &src); + + bool HasElement(const T &src) const; + +protected: + T m_Memory[MAX_SIZE]; +}; + +// Constructor +template +inline CUtlArray::CUtlArray() +{ +} + +template +inline CUtlArray::CUtlArray(T *pMemory, size_t count) +{ + CopyArray(pMemory, count); +} + +// Destructor +template +inline CUtlArray::~CUtlArray() +{ +} + +template +inline CUtlArray &CUtlArray::operator=(const CUtlArray &other) +{ + if (this != &other) + { + for (size_t n = 0; n < MAX_SIZE; n++) + m_Memory[n] = other.m_Memory[n]; + } + + return *this; +} + +template +inline CUtlArray::CUtlArray(CUtlArray const &vec) +{ + for (size_t n = 0; n < MAX_SIZE; n++) + m_Memory[n] = vec.m_Memory[n]; +} + +template +inline T *CUtlArray::Base() +{ + return &m_Memory[0]; +} + +template +inline const T *CUtlArray::Base() const +{ + return &m_Memory[0]; +} + +// Element access +template +inline T &CUtlArray::operator[](int i) +{ + Assert(IsValidIndex(i)); + return m_Memory[i]; +} + +template +inline const T &CUtlArray::operator[](int i) const +{ + Assert(IsValidIndex(i)); + return m_Memory[i]; +} + +template +inline T &CUtlArray::Element(int i) +{ + Assert(IsValidIndex(i)); + return m_Memory[i]; +} + +template +inline const T &CUtlArray::Element(int i) const +{ + Assert(IsValidIndex(i)); + return m_Memory[i]; +} + +// Count +template +inline int CUtlArray::Count() const +{ + return (int)MAX_SIZE; +} + +template +inline int CUtlArray::NumAllocated() const +{ + return (int)MAX_SIZE; +} + +// Is element index valid? +template +inline bool CUtlArray::IsValidIndex(int i) const +{ + return (i >= 0) && (i < MAX_SIZE); +} + +// Returns in invalid index +template +inline int CUtlArray::InvalidIndex() +{ + return -1; +} + +template +void CUtlArray::CopyArray(const T *pArray, size_t count) +{ + Assert(count < MAX_SIZE); + + for (size_t n = 0; n < count; n++) + m_Memory[n] = pArray[n]; +} + +template +void CUtlArray::Clear() +{ + Q_memset(m_Memory, 0, MAX_SIZE * sizeof(T)); +} + +template +void CUtlArray::RemoveAll() +{ + Clear(); +} + +template +void CUtlArray::Swap(CUtlArray< T, MAX_SIZE> &vec) +{ + for (size_t n = 0; n < MAX_SIZE; n++) + SWAP(m_Memory[n], vec.m_Memory[n]); +} + +// Finds an element (element needs operator== defined) +template +int CUtlArray::Find(const T &src) const +{ + for (int i = 0; i < Count(); i++) + { + if (Element(i) == src) + return i; + } + + return -1; +} + +template +void CUtlArray::FillWithValue(const T &src) +{ + for (int i = 0; i < Count(); i++) + Element(i) = src; +} + +template +bool CUtlArray::HasElement(const T &src) const +{ + return (Find(src) >= 0); +} diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index 4573b111..41b87982 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -190,6 +190,7 @@ + diff --git a/reapi/msvc/reapi.vcxproj.filters b/reapi/msvc/reapi.vcxproj.filters index 41448a5c..501a60fc 100644 --- a/reapi/msvc/reapi.vcxproj.filters +++ b/reapi/msvc/reapi.vcxproj.filters @@ -582,6 +582,9 @@ include\cssdk\public + + include\cssdk\public + include\cssdk\public diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index b7777ad6..fb6ea887 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -112,6 +112,7 @@ inline MType getMemberType(MONSTERSTATE) { return MEMBER_INTEGER; } inline MType getMemberType(ArmorType) { return MEMBER_INTEGER; } inline MType getMemberType(ArmouryItemPack) { return MEMBER_INTEGER; } inline MType getMemberType(InfoMapBuyParam) { return MEMBER_INTEGER; } +inline MType getMemberType(SecondaryAtkState) { return MEMBER_INTEGER; } inline MType getMemberType(netadrtype_t) { return MEMBER_INTEGER; } inline MType getMemberType(TraceResult) { return MEMBER_TRACERESULT; } @@ -120,6 +121,7 @@ inline MType getMemberType(short) { return MEMBER_SHORT; } inline MType getMemberType(unsigned short) { return MEMBER_SHORT; } inline MType getMemberType(bool) { return MEMBER_BOOL; } +inline MType getMemberType(bool*) { return MEMBER_BOOL; } inline MType getMemberType(CUnifiedSignals) { return MEMBER_SIGNALS; } inline MType getMemberType(RebuyStruct) { return MEBMER_REBUYSTRUCT; } @@ -764,6 +766,12 @@ member_t memberlist_csplayer[] = { CSPL_MEMBERS(m_bMegaBunnyJumping), CSPL_MEMBERS(m_bPlantC4Anywhere), CSPL_MEMBERS(m_bSpawnProtectionEffects), + CSPL_MEMBERS(m_flJumpHeight), + CSPL_MEMBERS(m_flLongJumpHeight), + CSPL_MEMBERS(m_flLongJumpForce), + CSPL_MEMBERS(m_flDuckSpeedMultiplier), + CSPL_MEMBERS(m_iNumKilledByUnanswered), + CSPL_MEMBERS(m_bPlayerDominated), }; member_t memberlist_baseitem[] = { @@ -1039,7 +1047,7 @@ member_t memberlist_mapinfo[] = { }; member_t memberlist_csplayerweapon[] = { - CSPLWPN_MEMBERS(bHasSecondaryAttack), + CSPLWPN_MEMBERS(iStateSecondaryAttack), CSPLWPN_MEMBERS(flBaseDamage), }; diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index d54c6aad..017dadc0 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -759,6 +759,12 @@ enum CSPlayer_Members m_bMegaBunnyJumping, m_bPlantC4Anywhere, m_bSpawnProtectionEffects, + m_flJumpHeight, + m_flLongJumpHeight, + m_flLongJumpForce, + m_flDuckSpeedMultiplier, + m_iNumKilledByUnanswered, + m_bPlayerDominated, }; enum CBasePlayerItem_Members @@ -1071,7 +1077,7 @@ enum MapInfo_Members enum CSPlayerWeapon_Members { - m_Weapon_bHasSecondaryAttack = BEGIN_MEMBER_REGION(csplayerweapon), + m_Weapon_iStateSecondaryAttack = BEGIN_MEMBER_REGION(csplayerweapon), m_Weapon_flBaseDamage, }; From 5c38e6f5e446650062b3fb8a82aaf28df628e8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sun, 26 Nov 2023 06:45:39 -0300 Subject: [PATCH 44/50] Implemented CCSEntity members to export in AMXX headers (#296) --- .../extra/amxmodx/scripting/include/reapi.inc | 3 ++- .../scripting/include/reapi_gamedll_const.inc | 22 +++++++++++++++++++ reapi/include/cssdk/dlls/API/CSEntity.h | 3 ++- reapi/src/member_list.cpp | 7 ++++++ reapi/src/member_list.h | 9 +++++++- reapi/src/natives/natives_members.cpp | 1 + 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi.inc b/reapi/extra/amxmodx/scripting/include/reapi.inc index fdfb9c84..ba2ad484 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi.inc @@ -80,7 +80,8 @@ enum members_tables_e mt_mapinfo, mt_csplayerweapon, mt_gib, - mt_netadr + mt_netadr, + mt_csentity }; #define ReAPIFunc {EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib, GamedllFunc_CBaseEntity, GamedllFunc_CBotManager} diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 9749df4e..124b8e63 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -6342,3 +6342,25 @@ enum CGib_Members */ m_Gib_lifeTime, }; + +/** +* CCSEntity API Members +*/ +enum CCSEntity_Members +{ + /* + * Description: Penetration level of the damage caused by the inflictor + * Member type: unsigned char + * Get params: get_member(index, member); + * Set params: set_member(index, member, value); + */ + m_ucDmgPenetrationLevel = BEGIN_MEMBER_REGION(csplayerweapon), + + /* + * Description: Cached inflictor passed inside TakeDamage to retrieve in Killed + * Member type: entvars_t * + * Get params: get_member(index, member); + * Set params: set_member(index, member, value); + */ + m_pevLastInflictor, +}; diff --git a/reapi/include/cssdk/dlls/API/CSEntity.h b/reapi/include/cssdk/dlls/API/CSEntity.h index 4f321515..aa8de82e 100644 --- a/reapi/include/cssdk/dlls/API/CSEntity.h +++ b/reapi/include/cssdk/dlls/API/CSEntity.h @@ -47,12 +47,13 @@ class CCSEntity public: CBaseEntity *m_pContainingEntity; unsigned char m_ucDmgPenetrationLevel; // penetration level of the damage caused by the inflictor + entvars_t *m_pevLastInflictor; private: #if defined(_MSC_VER) #pragma region reserve_data_Region #endif - char CCSEntity_Reserve[0x3FFF]; + char CCSEntity_Reserve[0x3FF7]; virtual void func_reserve1() {}; virtual void func_reserve2() {}; diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index fb6ea887..bf3a90d3 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -70,6 +70,7 @@ #define MAPINFO_MEMBERS(mx) CLASS_MEMBERS_PREF(CMapInfo, mx, m_MapInfo_##mx, m_) #define CSPLWPN_MEMBERS(mx) CLASS_MEMBERS_PREF(CCSPlayerWeapon, mx, m_Weapon_##mx, m_) #define GIB_MEMBERS(mx) CLASS_MEMBERS_PREF(CGib, mx, m_Gib_##mx, m_) +#define CSENT_MEMBERS(mx) CLASS_MEMBERS(CCSEntity, mx, mx) inline MType getMemberType(float*) { return MEMBER_FLOAT; } inline MType getMemberType(float) { return MEMBER_FLOAT; } @@ -1064,6 +1065,11 @@ member_t memberlist_netadr[] = { NETADR_MEMBERS(port) }; +member_t memberlist_csentity[] = { + CSENT_MEMBERS(m_ucDmgPenetrationLevel), + CSENT_MEMBERS(m_pevLastInflictor), +}; + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // #ifdef __GNUC__ @@ -1128,6 +1134,7 @@ member_t *memberlist_t::operator[](size_t members) const CASE(csplayerweapon) CASE(gib) CASE(netadr) + CASE(csentity) } #undef CASE diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index 017dadc0..58969330 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -83,7 +83,8 @@ struct memberlist_t mt_mapinfo, mt_csplayerweapon, mt_gib, - mt_netadr + mt_netadr, + mt_csentity }; }; @@ -1088,3 +1089,9 @@ enum CGib_Members m_Gib_material, m_Gib_lifeTime, }; + +enum CSEntity_Members +{ + m_ucDmgPenetrationLevel = BEGIN_MEMBER_REGION(csentity), + m_pevLastInflictor, +}; diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index 9c2daa12..54ba699c 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -1122,6 +1122,7 @@ void *get_pdata_custom(CBaseEntity *pEntity, cell member) { const auto table = memberlist_t::members_tables_e(member / MAX_REGION_RANGE); switch (table) { + case memberlist_t::mt_csentity: case memberlist_t::mt_csplayer: case memberlist_t::mt_csplayerweapon: { if (unlikely(pEntity->m_pEntity == nullptr)) { From bf8b9bd48a5222e8cf5b70e7aa9eb68ecae69976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Sun, 26 Nov 2023 06:46:17 -0300 Subject: [PATCH 45/50] Fix GiveC4 hook callback return type (#295) * Fix GiveC4 hook callback return type --- .../extra/amxmodx/scripting/include/reapi_gamedll_const.inc | 1 + reapi/include/cssdk/dlls/regamedll_api.h | 4 ++-- reapi/src/hook_callback.cpp | 6 +++--- reapi/src/hook_callback.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 124b8e63..f1d1fbac 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -1165,6 +1165,7 @@ enum GamedllFunc_CSGameRules /* * Description: - + * Return type: CBasePlayer * (Entity index of player) * Params: () */ RG_CSGameRules_GiveC4, diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index 5d5d4861..762d06d6 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -339,8 +339,8 @@ typedef IHookChain IReGameHook_CSGameRules_RemoveGuns; typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_RemoveGuns; // CHalfLifeMultiplay::GiveC4 hook -typedef IHookChain IReGameHook_CSGameRules_GiveC4; -typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_GiveC4; +typedef IHookChain IReGameHook_CSGameRules_GiveC4; +typedef IHookChainRegistry IReGameHookRegistry_CSGameRules_GiveC4; // CHalfLifeMultiplay::ChangeLevel hook typedef IHookChain IReGameHook_CSGameRules_ChangeLevel; diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 918c0550..5962a26b 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -972,14 +972,14 @@ void CSGameRules_RemoveGuns(IReGameHook_CSGameRules_RemoveGuns *chain) callVoidForward(RG_CSGameRules_RemoveGuns, original); } -void CSGameRules_GiveC4(IReGameHook_CSGameRules_GiveC4 *chain) +CBasePlayer *CSGameRules_GiveC4(IReGameHook_CSGameRules_GiveC4 *chain) { auto original = [chain]() { - chain->callNext(); + return indexOfPDataAmx(chain->callNext()); }; - callVoidForward(RG_CSGameRules_GiveC4, original); + return getPrivate(callForward(RG_CSGameRules_GiveC4, original)); } void CSGameRules_ChangeLevel(IReGameHook_CSGameRules_ChangeLevel *chain) diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 089299d6..af39e6ad 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -476,7 +476,7 @@ void CSGameRules_CleanUpMap(IReGameHook_CSGameRules_CleanUpMap *chain); void CSGameRules_RestartRound(IReGameHook_CSGameRules_RestartRound *chain); void CSGameRules_CheckWinConditions(IReGameHook_CSGameRules_CheckWinConditions *chain); void CSGameRules_RemoveGuns(IReGameHook_CSGameRules_RemoveGuns *chain); -void CSGameRules_GiveC4(IReGameHook_CSGameRules_GiveC4 *chain); +CBasePlayer *CSGameRules_GiveC4(IReGameHook_CSGameRules_GiveC4 *chain); void CSGameRules_ChangeLevel(IReGameHook_CSGameRules_ChangeLevel *chain); void CSGameRules_GoToIntermission(IReGameHook_CSGameRules_GoToIntermission *chain); void CSGameRules_BalanceTeams(IReGameHook_CSGameRules_BalanceTeams *chain); From 4430205522b6781ff8b89a5f64b36797a7c26ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Mu=C3=B1oz?= Date: Tue, 28 Nov 2023 09:50:27 -0300 Subject: [PATCH 46/50] API upgrade: 15 new natives (#297) * 15 natives addition * Added DECAL_ indexes * Improve documentation * Added player null option on rg_create_weaponbox + code style fixes --- .../amxmodx/scripting/include/cssdk_const.inc | 149 +++-- .../scripting/include/reapi_gamedll.inc | 187 ++++++ reapi/src/natives/natives_helper.h | 12 + reapi/src/natives/natives_misc.cpp | 627 ++++++++++++++++++ 4 files changed, 925 insertions(+), 50 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 17a0bf57..a3bfc5e9 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -1375,54 +1375,54 @@ enum InfoMapBuyParam enum GameEventType { EVENT_INVALID = 0, - EVENT_WEAPON_FIRED, // tell bots the player is attack (argumens: 1 = attacker, 2 = NULL) - EVENT_WEAPON_FIRED_ON_EMPTY, // tell bots the player is attack without clip ammo (argumens: 1 = attacker, 2 = NULL) - EVENT_WEAPON_RELOADED, // tell bots the player is reloading his weapon (argumens: 1 = reloader, 2 = NULL) + EVENT_WEAPON_FIRED, // tell bots the player is attack (argumens: 1 = attacker, 2 = NULL) + EVENT_WEAPON_FIRED_ON_EMPTY, // tell bots the player is attack without clip ammo (argumens: 1 = attacker, 2 = NULL) + EVENT_WEAPON_RELOADED, // tell bots the player is reloading his weapon (argumens: 1 = reloader, 2 = NULL) - EVENT_HE_GRENADE_EXPLODED, // tell bots the HE grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) - EVENT_FLASHBANG_GRENADE_EXPLODED, // tell bots the flashbang grenade is exploded (argumens: 1 = grenade thrower, 2 = explosion origin) - EVENT_SMOKE_GRENADE_EXPLODED, // tell bots the smoke grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) + EVENT_HE_GRENADE_EXPLODED, // tell bots the HE grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) + EVENT_FLASHBANG_GRENADE_EXPLODED, // tell bots the flashbang grenade is exploded (argumens: 1 = grenade thrower, 2 = explosion origin) + EVENT_SMOKE_GRENADE_EXPLODED, // tell bots the smoke grenade is exploded (argumens: 1 = grenade thrower, 2 = NULL) EVENT_GRENADE_BOUNCED, EVENT_BEING_SHOT_AT, - EVENT_PLAYER_BLINDED_BY_FLASHBANG, // tell bots the player is flashed (argumens: 1 = flashed player, 2 = NULL) - EVENT_PLAYER_FOOTSTEP, // tell bots the player is running (argumens: 1 = runner, 2 = NULL) - EVENT_PLAYER_JUMPED, // tell bots the player is jumped (argumens: 1 = jumper, 2 = NULL) - EVENT_PLAYER_DIED, // tell bots the player is killed (argumens: 1 = victim, 2 = killer) - EVENT_PLAYER_LANDED_FROM_HEIGHT, // tell bots the player is fell with some damage (argumens: 1 = felled player, 2 = NULL) - EVENT_PLAYER_TOOK_DAMAGE, // tell bots the player is take damage (argumens: 1 = victim, 2 = attacker) - EVENT_HOSTAGE_DAMAGED, // tell bots the player has injured a hostage (argumens: 1 = hostage, 2 = injurer) - EVENT_HOSTAGE_KILLED, // tell bots the player has killed a hostage (argumens: 1 = hostage, 2 = killer) - - EVENT_DOOR, // tell bots the door is moving (argumens: 1 = door, 2 = NULL) - EVENT_BREAK_GLASS, // tell bots the glass has break (argumens: 1 = glass, 2 = NULL) - EVENT_BREAK_WOOD, // tell bots the wood has break (argumens: 1 = wood, 2 = NULL) - EVENT_BREAK_METAL, // tell bots the metal/computer has break (argumens: 1 = metal/computer, 2 = NULL) - EVENT_BREAK_FLESH, // tell bots the flesh has break (argumens: 1 = flesh, 2 = NULL) - EVENT_BREAK_CONCRETE, // tell bots the concrete has break (argumens: 1 = concrete, 2 = NULL) - - EVENT_BOMB_PLANTED, // tell bots the bomb has been planted (argumens: 1 = planter, 2 = NULL) - EVENT_BOMB_DROPPED, // tell bots the bomb has been dropped (argumens: 1 = NULL, 2 = NULL) - EVENT_BOMB_PICKED_UP, // let the bots hear the bomb pickup (argumens: 1 = player that pickup c4, 2 = NULL) - EVENT_BOMB_BEEP, // let the bots hear the bomb beeping (argumens: 1 = c4, 2 = NULL) - EVENT_BOMB_DEFUSING, // tell the bots someone has started defusing (argumens: 1 = defuser, 2 = NULL) - EVENT_BOMB_DEFUSE_ABORTED, // tell the bots someone has aborted defusing (argumens: 1 = NULL, 2 = NULL) - EVENT_BOMB_DEFUSED, // tell the bots the bomb is defused (argumens: 1 = defuser, 2 = NULL) - EVENT_BOMB_EXPLODED, // let the bots hear the bomb exploding (argumens: 1 = NULL, 2 = NULL) - - EVENT_HOSTAGE_USED, // tell bots the hostage is used (argumens: 1 = user, 2 = NULL) - EVENT_HOSTAGE_RESCUED, // tell bots the hostage is rescued (argumens: 1 = rescuer (CBasePlayer *), 2 = hostage (CHostage *)) - EVENT_ALL_HOSTAGES_RESCUED, // tell bots the all hostages are rescued (argumens: 1 = NULL, 2 = NULL) - - EVENT_VIP_ESCAPED, // tell bots the VIP is escaped (argumens: 1 = NULL, 2 = NULL) - EVENT_VIP_ASSASSINATED, // tell bots the VIP is assassinated (argumens: 1 = NULL, 2 = NULL) - EVENT_TERRORISTS_WIN, // tell bots the terrorists won the round (argumens: 1 = NULL, 2 = NULL) - EVENT_CTS_WIN, // tell bots the CTs won the round (argumens: 1 = NULL, 2 = NULL) - EVENT_ROUND_DRAW, // tell bots the round was a draw (argumens: 1 = NULL, 2 = NULL) - EVENT_ROUND_WIN, // tell carreer the round was a win (argumens: 1 = NULL, 2 = NULL) - EVENT_ROUND_LOSS, // tell carreer the round was a loss (argumens: 1 = NULL, 2 = NULL) - EVENT_ROUND_START, // tell bots the round was started (when freeze period is expired) (argumens: 1 = NULL, 2 = NULL) - EVENT_PLAYER_SPAWNED, // tell bots the player is spawned (argumens: 1 = spawned player, 2 = NULL) + EVENT_PLAYER_BLINDED_BY_FLASHBANG, // tell bots the player is flashed (argumens: 1 = flashed player, 2 = NULL) + EVENT_PLAYER_FOOTSTEP, // tell bots the player is running (argumens: 1 = runner, 2 = NULL) + EVENT_PLAYER_JUMPED, // tell bots the player is jumped (argumens: 1 = jumper, 2 = NULL) + EVENT_PLAYER_DIED, // tell bots the player is killed (argumens: 1 = victim, 2 = killer) + EVENT_PLAYER_LANDED_FROM_HEIGHT, // tell bots the player is fell with some damage (argumens: 1 = felled player, 2 = NULL) + EVENT_PLAYER_TOOK_DAMAGE, // tell bots the player is take damage (argumens: 1 = victim, 2 = attacker) + EVENT_HOSTAGE_DAMAGED, // tell bots the player has injured a hostage (argumens: 1 = hostage, 2 = injurer) + EVENT_HOSTAGE_KILLED, // tell bots the player has killed a hostage (argumens: 1 = hostage, 2 = killer) + + EVENT_DOOR, // tell bots the door is moving (argumens: 1 = door, 2 = NULL) + EVENT_BREAK_GLASS, // tell bots the glass has break (argumens: 1 = glass, 2 = NULL) + EVENT_BREAK_WOOD, // tell bots the wood has break (argumens: 1 = wood, 2 = NULL) + EVENT_BREAK_METAL, // tell bots the metal/computer has break (argumens: 1 = metal/computer, 2 = NULL) + EVENT_BREAK_FLESH, // tell bots the flesh has break (argumens: 1 = flesh, 2 = NULL) + EVENT_BREAK_CONCRETE, // tell bots the concrete has break (argumens: 1 = concrete, 2 = NULL) + + EVENT_BOMB_PLANTED, // tell bots the bomb has been planted (argumens: 1 = planter, 2 = NULL) + EVENT_BOMB_DROPPED, // tell bots the bomb has been dropped (argumens: 1 = NULL, 2 = NULL) + EVENT_BOMB_PICKED_UP, // let the bots hear the bomb pickup (argumens: 1 = player that pickup c4, 2 = NULL) + EVENT_BOMB_BEEP, // let the bots hear the bomb beeping (argumens: 1 = c4, 2 = NULL) + EVENT_BOMB_DEFUSING, // tell the bots someone has started defusing (argumens: 1 = defuser, 2 = NULL) + EVENT_BOMB_DEFUSE_ABORTED, // tell the bots someone has aborted defusing (argumens: 1 = NULL, 2 = NULL) + EVENT_BOMB_DEFUSED, // tell the bots the bomb is defused (argumens: 1 = defuser, 2 = NULL) + EVENT_BOMB_EXPLODED, // let the bots hear the bomb exploding (argumens: 1 = NULL, 2 = NULL) + + EVENT_HOSTAGE_USED, // tell bots the hostage is used (argumens: 1 = user, 2 = NULL) + EVENT_HOSTAGE_RESCUED, // tell bots the hostage is rescued (argumens: 1 = rescuer (CBasePlayer *), 2 = hostage (CHostage *)) + EVENT_ALL_HOSTAGES_RESCUED, // tell bots the all hostages are rescued (argumens: 1 = NULL, 2 = NULL) + + EVENT_VIP_ESCAPED, // tell bots the VIP is escaped (argumens: 1 = NULL, 2 = NULL) + EVENT_VIP_ASSASSINATED, // tell bots the VIP is assassinated (argumens: 1 = NULL, 2 = NULL) + EVENT_TERRORISTS_WIN, // tell bots the terrorists won the round (argumens: 1 = NULL, 2 = NULL) + EVENT_CTS_WIN, // tell bots the CTs won the round (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_DRAW, // tell bots the round was a draw (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_WIN, // tell carreer the round was a win (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_LOSS, // tell carreer the round was a loss (argumens: 1 = NULL, 2 = NULL) + EVENT_ROUND_START, // tell bots the round was started (when freeze period is expired) (argumens: 1 = NULL, 2 = NULL) + EVENT_PLAYER_SPAWNED, // tell bots the player is spawned (argumens: 1 = spawned player, 2 = NULL) EVENT_CLIENT_CORPSE_SPAWNED, EVENT_BUY_TIME_START, EVENT_PLAYER_LEFT_BUY_ZONE, @@ -1471,12 +1471,12 @@ enum GameEventType EVENT_RADIO_ENEMY_DOWN, EVENT_END_RADIO, - EVENT_NEW_MATCH, // tell bots the game is new (argumens: 1 = NULL, 2 = NULL) - EVENT_PLAYER_CHANGED_TEAM, // tell bots the player is switch his team (also called from ClientPutInServer()) (argumens: 1 = switcher, 2 = NULL) - EVENT_BULLET_IMPACT, // tell bots the player is shoot at wall (argumens: 1 = shooter, 2 = shoot trace end position) - EVENT_GAME_COMMENCE, // tell bots the game is commencing (argumens: 1 = NULL, 2 = NULL) - EVENT_WEAPON_ZOOMED, // tell bots the player is switch weapon zoom (argumens: 1 = zoom switcher, 2 = NULL) - EVENT_HOSTAGE_CALLED_FOR_HELP, // tell bots the hostage is talking (argumens: 1 = listener, 2 = NULL) + EVENT_NEW_MATCH, // tell bots the game is new (argumens: 1 = NULL, 2 = NULL) + EVENT_PLAYER_CHANGED_TEAM, // tell bots the player is switch his team (also called from ClientPutInServer()) (argumens: 1 = switcher, 2 = NULL) + EVENT_BULLET_IMPACT, // tell bots the player is shoot at wall (argumens: 1 = shooter, 2 = shoot trace end position) + EVENT_GAME_COMMENCE, // tell bots the game is commencing (argumens: 1 = NULL, 2 = NULL) + EVENT_WEAPON_ZOOMED, // tell bots the player is switch weapon zoom (argumens: 1 = zoom switcher, 2 = NULL) + EVENT_HOSTAGE_CALLED_FOR_HELP, // tell bots the hostage is talking (argumens: 1 = listener, 2 = NULL) NUM_GAME_EVENTS, }; @@ -1490,3 +1490,52 @@ enum SecondaryAtkState WEAPON_SECONDARY_ATTACK_SET, WEAPON_SECONDARY_ATTACK_BLOCK }; + +/** +* Decal list for rg_decal_trace +*/ +enum Decal +{ + DECAL_GUNSHOT1 = 0, + DECAL_GUNSHOT2, + DECAL_GUNSHOT3, + DECAL_GUNSHOT4, + DECAL_GUNSHOT5, + DECAL_LAMBDA1, + DECAL_LAMBDA2, + DECAL_LAMBDA3, + DECAL_LAMBDA4, + DECAL_LAMBDA5, + DECAL_LAMBDA6, + DECAL_SCORCH1, + DECAL_SCORCH2, + DECAL_BLOOD1, + DECAL_BLOOD2, + DECAL_BLOOD3, + DECAL_BLOOD4, + DECAL_BLOOD5, + DECAL_BLOOD6, + DECAL_YBLOOD1, + DECAL_YBLOOD2, + DECAL_YBLOOD3, + DECAL_YBLOOD4, + DECAL_YBLOOD5, + DECAL_YBLOOD6, + DECAL_GLASSBREAK1, + DECAL_GLASSBREAK2, + DECAL_GLASSBREAK3, + DECAL_BIGSHOT1, + DECAL_BIGSHOT2, + DECAL_BIGSHOT3, + DECAL_BIGSHOT4, + DECAL_BIGSHOT5, + DECAL_SPIT1, + DECAL_SPIT2, + DECAL_BPROOF1, // Bulletproof glass decal + DECAL_GARGSTOMP1, // Gargantua stomp crack + DECAL_SMALLSCORCH1, // Small scorch mark + DECAL_SMALLSCORCH2, // Small scorch mark + DECAL_SMALLSCORCH3, // Small scorch mark + DECAL_MOMMABIRTH, // Big momma birth splatter + DECAL_MOMMASPLAT, +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 47289600..a91bd509 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -1008,3 +1008,190 @@ native rg_spawn_head_gib(const index); * @noreturn */ native rg_spawn_random_gibs(const index, const cGibs, const bool:bHuman = true); + +/* +* Spawn a grenade (HEGrenade, Flashbang, SmokeGrenade, or C4) +* +* @param weaponId WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG or WEAPON_C4 +* @param pevOwner Grenade owner +* @param vecSrc Grenade spawn position +* @param vecThrow Grenade velocity vector +* @param time Grenade explosion time +* @param iTeam Grenade team, see TEAM_* constants +* @param usEvent Event index related to grenade (returned value of precache_event) +* +* @return Entity index on success, AMX_NULLENT (-1) otherwise +*/ +native rg_spawn_grenade(WeaponIdType:weaponId, pevOwner, Float:vecSrc[3], Float:vecThrow[3], Float:time, TeamName:iTeam, usEvent = 0); + +/* +* Spawn a weaponbox entity with its properties +* +* @param pItem Weapon entity index to attach +* @param pPlayerOwner Player index to remove pItem entity (0 = no weapon owner) +* @param modelName Model name ("models/w_*.mdl") +* @param origin Weaponbox origin position +* @param angles Weaponbox angles +* @param velocity Weaponbox initial velocity vector +* @param lifeTime Time to stay in world (< 0.0 = use mp_item_staytime cvar value) +* @param packAmmo Set if ammo should be removed from weapon owner +* +* @return Weaponbox ent index on success, AMX_NULLENT (-1) otherwise +*/ +native rg_create_weaponbox(const pItem, const pPlayerOwner, const modelName[], Float:origin[3], Float:angles[3], Float:velocity[3], Float:lifeTime, bool:packAmmo); + +/* +* Removes an entity using gamedll's UTIL_Remove function, which sets a frame delay to ensure its removal. +* +* @param pEntity Entity index to remove +* +* @return 1 on success, 0 otherwise +*/ +native rg_remove_entity(const pEntity); + +/* +* Creates a Decal in world based on a traceresult. +* +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param decalNumber Number of decal to spray, see DECAL_ constants on cssdk_const.inc +* +* @noreturn +*/ +native rg_decal_trace(const ptr, Decal:decalNumber); + +/* +* Emits a sound based on a traceresult simulating a bullet hit (metal, wood, concrete, etc.). +* @note Used mostly on trace attacks (bullets, knife). +* +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param vecSrc Start position +* @param vecEnd End position, must match ptr's vecEndPos member +* @param iBulletType Bullet type, see BULLET_* constants in cssdk_const.inc +* +* @noreturn +*/ +native rg_emit_texture_sound(const ptr, Float:vecSrc[3], Float:vecEnd[3], Bullet:iBulletType); + +/* +* Generates an ammo slot in game's logic +* @note To see a visual effect, WeaponList message should be sent using the custom ammo name, +* where ammo icon HUD will be the one listed in "sprites/weapon_.txt" file. +* +* @param szAmmoname Ammo name to create. +* +* @note Maximum ammo index is 31, after that every ammo instantiation will start from 1 overriding existing ones. +* @return New ammo index. If name already exists, will return the matched index from memory. +*/ +native rg_add_ammo_registry(const szAmmoname[]); + +/* +* Deploys a weapon attached to a player using the CBasePlayerWeapon::DefaultDeploy function. +* +* @param entity Weapon to deploy. Must be attached to a player. +* @param szViewModel Weapon view model name ("models/v_*.mdl") +* @param szWeaponModel Weapon world model bame ("models/p_*.mdl") +* @param iAnim Weapon view model animation to play (often "deploy", use HLMV to see anim index) +* @param szAnimExt Player anim extension name to assign. Examples: "carbine", "shotgun", "knife", etc. +* Use HLMV on a player model to see animext names. +* @param skiplocal If 0, weapon animation will be forced to play on client ignoring active client prediction. +* +* @return 1 on successful weapon deploy, 0 otherwise. +*/ +native rg_weapon_deploy(const entity, const szViewModel[], const szWeaponModel[], iAnim, const szAnimExt[], skiplocal = 0); + +/* +* Reloads a weapon or a player's active weapon using the CBasePlayerWeapon::DefaultReload function. +* +* @param entity Weapon to reload (> MaxClients) OR player index to reload his current active weapon (>= 1 & <= MaxClients). +* @param iClipSize Weapon max clip to check. 0 = weapon max clip stored in ItemInfo +* @param iAnim Weapon view model animation to play (often "reload", use HLMV to see anim index) +* @param fDelay Player reload duration before clip refill. +* +* @return 1 on successful weapon reload, 0 otherwise. +*/ +native rg_weapon_reload(const entity, iClipSize, iAnim, Float:fDelay); + +/* +* Forces shotgun reload thinking on a weapon or a player's active weapon using the CBasePlayerWeapon::DefaultShotgunReload function. +* +* @param entity Weapon to reload (> MaxClients) OR player index to reload his current active weapon (>= 1 & <= MaxClients). +* @param iAnim Weapon view model "insert" animation to play (use HLMV to see anim index) +* @param iStartAnim Weapon view model "start reload" animation to play (use HLMV to see anim index) +* @param fDelay Delay between each buckshot inserted +* @param fStartDelay Delay before buckshots insertion starts +* @param pszReloadSound1 Sound to play on every insertion +* @param pszReloadSound2 Another sound to play on every insertion +* +* @note This is used inside weapon's Reload function and is often called every frame player is pressing IN_RELOAD button. +* @return 1 while weapon not in delay and with ammo remaining to load, 0 otherwise. +*/ +native rg_weapon_shotgun_reload(const entity, iAnim, iStartAnim, Float:fDelay, Float:fStartDelay, const pszReloadSound1[] = "", const pszReloadSound2[] = ""); + +/* +* Sends a weapon animation using the CBasePlayerWeapon::SendWeaponAnim function. +* +* @param entity Weapon to send animation on owner (> MaxClients) OR player index to send animation (>= 1 & <= MaxClients). +* @param iAnim Weapon view model animation to play (use HLMV to see anim index) +* @param skiplocal If 0, weapon animation will be forced to play on client ignoring active client prediction. +* +* @noreturn +*/ +native rg_weapon_send_animation(const entity, iAnim, skiplocal = 0); + +/* +* Emits a "recoil" effect on weapon's player using the CBasePlayerWeapon::KickBack function. +* +* @param entity Weapon to reload (> MaxClients) OR player index to reload his current active weapon (>= 1 & <= MaxClients). +* @param up_base Minimum vertical punchangle +* @param lateral_base Minimum horizontal punchangle +* @param up_modifier Vertical punchangle units to multiply to m_iShotsFired member +* @param lateral_modifier Horizontal punchangle units to multiply to m_iShotsFired member +* @param up_max Maximum vertical punchangle +* @param lateral_max Maximum horizontal punchangle +* @param direction_change Probability to change punchangle orientation (positive or negative). 0 = 100% (1/1), 1 = 50% (1/2), 2 = 33.3% (1/3), ... +* +* @noreturn +*/ +native rg_weapon_kickback(const entity, Float:up_base, Float:lateral_base, Float:up_modifier, Float:lateral_modifier, Float:up_max, Float:lateral_max, direction_change); + +/* +* Switches player current weapon into the best one on its inventory using the CHalfLifeMultiplay::GetNextBestWeapon function. +* +* @param player Player index. +* @param currentWeapon Current player active weapon. 0 = retrieve from m_pActiveItem member +* +* @note Weapon selection is based on weapon's Weight attribute from ItemInfo structure. +* @return 1 if weapon was found and switched to, 0 otherwise +*/ +native rg_switch_best_weapon(const player, const currentWeapon = 0); + +/* +* Disappear a player from the world. Used when VIP reaches escape zone. Basically a silent kill. +* +* @param player Player index. +* +* @noreturn +*/ +native rg_disappear(const player); + +/* +* Sets player current Observer mode. +* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER). +* +* @param player Player index. +* @param mode Observer mode, see OBS_* constants in cssdk_const.inc +* +* @noreturn +*/ +native rg_set_observer_mode(const player, const mode); + +/* +* Emits a death notice (logs, DeathMsg event, win conditions check) +* +* @param pVictim Player index. +* @param pKiller Killer entity. +* @param pevInflictor Inflictor entity. 0 = world +* +* @noreturn +*/ +native rg_death_notice(const pVictim, const pKiller, const pevInflictor); diff --git a/reapi/src/natives/natives_helper.h b/reapi/src/natives/natives_helper.h index f1cb1621..6ec6b5ea 100644 --- a/reapi/src/natives/natives_helper.h +++ b/reapi/src/natives/natives_helper.h @@ -40,6 +40,10 @@ class CAmxArg { return m_value != 0; } + operator unsigned short() const + { + return (unsigned short)m_value; + } operator CBaseEntity*() const { if (m_value < 0) @@ -78,6 +82,14 @@ class CAmxArg { return static_cast(m_value); } + operator WeaponIdType() const + { + return static_cast(m_value); + } + operator TraceResult *() const + { + return reinterpret_cast(m_value); + } Vector& vector() const { return operator Vector&(); diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index cf803a77..4aa53b4d 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -2612,6 +2612,617 @@ cell AMX_NATIVE_CALL rg_spawn_random_gibs(AMX* amx, cell* params) return TRUE; } +/* +* Spawn a grenade (HEGrenade, Flashbang, SmokeGrenade, or C4) +* +* @param weaponId WEAPON_HEGRENADE, WEAPON_SMOKEGRENADE, WEAPON_FLASHBANG or WEAPON_C4 +* @param pevOwner Grenade owner +* @param vecSrc Grenade spawn position +* @param vecThrow Grenade velocity vector +* @param time Grenade explosion time +* @param iTeam Grenade team, see TEAM_* constants +* @param usEvent Event index related to grenade (returned value of precache_event) +* +* @return Entity index on success, AMX_NULLENT (-1) otherwise +*/ +cell AMX_NATIVE_CALL rg_spawn_grenade(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon_id, arg_index, arg_origin, arg_velocity, arg_time, arg_team, arg_event }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + CAmxArgs args(amx, params); + + CGrenade *pBomb = g_ReGameFuncs->SpawnGrenade(args[arg_weapon_id], + pPlayer->pev, + args[arg_origin], + args[arg_velocity], + args[arg_time], + args[arg_team], + args[arg_event]); + + // Sanity check anyway + if (pBomb) + return indexOfPDataAmx(pBomb); + + return AMX_NULLENT; +} + +/* +* Spawn a weaponbox entity with its properties +* +* @param pItem Weapon entity index to attach +* @param pPlayerOwner Player index to remove pItem entity (0 = no weapon owner) +* @param modelName Model name ("models/w_*.mdl") +* @param origin Weaponbox origin position +* @param angles Weaponbox angles +* @param velocity Weaponbox initial velocity vector +* @param lifeTime Time to stay in world (< 0.0 = use mp_item_staytime cvar value) +* @param packAmmo Set if ammo should be removed from weapon owner +* +* @return Weaponbox ent index on success, AMX_NULLENT (-1) otherwise +*/ +cell AMX_NATIVE_CALL rg_create_weaponbox(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_item, arg_player, arg_modelname, arg_origin, arg_angles, arg_velocity, arg_lifetime, arg_packammo }; + + CHECK_ISENTITY(arg_item); + + CBasePlayerItem *pItem = getPrivate(params[arg_item]); + if (unlikely(pItem == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + CBasePlayer *pPlayer = nullptr; + + if (params[arg_player] != 0) + { + CHECK_ISPLAYER(arg_player); + + pPlayer = getPrivate(params[arg_player]); + CHECK_CONNECTED(pPlayer, arg_player); + } + + CAmxArgs args(amx, params); + + char modelStr[MAX_PATH]; + const char *modelName = getAmxString(amx, params[arg_modelname], modelStr); + CWeaponBox *pBox = g_ReGameFuncs->CreateWeaponBox(pItem, pPlayer, modelName, args[arg_origin], args[arg_angles], args[arg_velocity], args[arg_lifetime], args[arg_packammo]); + + if (pBox) + return indexOfPDataAmx(pBox); + + return AMX_NULLENT; +} + +/* +* Removes an entity using gamedll's UTIL_Remove function, which sets a frame delay to ensure its removal. +* +* @param pEntity Entity index to remove +* +* @return 1 on success, 0 otherwise +*/ +cell AMX_NATIVE_CALL rg_remove_entity(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_entity }; + + CHECK_ISENTITY(arg_entity); + + auto pEntity = getPrivate(params[arg_entity]); + if (!pEntity || (pEntity->pev->flags & FL_KILLME) != 0) + { + return FALSE; + } + + g_ReGameFuncs->UTIL_Remove(pEntity); + + if ((pEntity->pev->flags & FL_KILLME) != 0) + { + return TRUE; + } + + return FALSE; +} + +/* +* Creates a Decal in world based on a traceresult. +* +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param decalNumber Number of decal to spray, see DECAL_ constants on cssdk_const.inc +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_decal_trace(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_trace, arg_decal }; + + CAmxArgs args(amx, params); + g_ReGameFuncs->UTIL_DecalTrace(args[arg_trace], args[arg_decal]); + return TRUE; +} + +/* +* Emits a sound based on a traceresult simulating a bullet hit (metal, wood, concrete, etc.). +* @note Used mostly on trace attacks (bullets, knife). +* +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param vecSrc Start position +* @param vecEnd End position, must match ptr's vecEndPos member +* @param iBulletType Bullet type, see BULLET_* constants in cssdk_const.inc +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_emit_texture_sound(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_trace, arg_start, arg_end, arg_bullet_type }; + + CAmxArgs args(amx, params); + g_ReGameFuncs->TextureTypePlaySound(args[arg_trace], args[arg_start], args[arg_end], args[arg_bullet_type]); + return TRUE; +} + +/* +* Generates an ammo slot in game's logic +* @note To see a visual effect, WeaponList message should be sent using the custom ammo name, +* where ammo icon HUD will be the one listed in "sprites/weapon_.txt" file. +* +* @param szAmmoname Ammo name to create. +* +* @note Maximum ammo index is 31, after that every ammo instantiation will start from 1 overriding existing ones. +* @return New ammo index. If name already exists, will return the matched index from memory. +*/ +cell AMX_NATIVE_CALL rg_add_ammo_registry(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_ammoname }; + + char ammonamebuf[190]; + string_t ammoname = getAmxStringAlloc(amx, params[arg_ammoname], ammonamebuf); + + if (!ammonamebuf || ammonamebuf[0] == '\0') + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: empty ammo name", __FUNCTION__); + return FALSE; + } + + return (cell)g_ReGameFuncs->AddAmmoNameToAmmoRegistry(STRING(ammoname)); +} + +/* +* Deploys a weapon attached to a player using the CBasePlayerWeapon::DefaultDeploy function. +* +* @param entity Weapon to deploy. Must be attached to a player. +* @param szViewModel Weapon view model name ("models/v_*.mdl") +* @param szWeaponModel Weapon world model bame ("models/p_*.mdl") +* @param iAnim Weapon view model animation to play (often "deploy", use HLMV to see anim index) +* @param szAnimExt Player anim extension name to assign. Examples: "carbine", "shotgun", "knife", etc. +* Use HLMV on a player model to see animext names. +* @param skiplocal If 0, weapon animation will be forced to play on client ignoring active client prediction. +* +* @return 1 on successful weapon deploy, 0 otherwise. +*/ +cell AMX_NATIVE_CALL rg_weapon_deploy(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon, arg_viewmodel, arg_weaponmodel, arg_anim, arg_animextension, arg_skiplocal }; + + CHECK_ISENTITY(arg_weapon); + CBasePlayerWeapon *pWeapon = getPrivate(params[arg_weapon]); + + if (unlikely(pWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + + CCSPlayerWeapon *pCSWeapon = pWeapon->CSPlayerWeapon(); + if (unlikely(pCSWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized m_pEntity.", __FUNCTION__); + return FALSE; + } + + char viewmodelbuffer[MAX_PATH], weaponmodelbuffer[MAX_PATH], animextbuffer[32]; + getAmxString(amx, params[arg_viewmodel], viewmodelbuffer); + getAmxString(amx, params[arg_weaponmodel], weaponmodelbuffer); + getAmxString(amx, params[arg_animextension], animextbuffer); + + return pCSWeapon->DefaultDeploy(viewmodelbuffer, weaponmodelbuffer, (int)params[arg_anim], animextbuffer, (int)params[arg_skiplocal]) ? TRUE : FALSE; +} + +/* +* Reloads a weapon or a player's active weapon using the CBasePlayerWeapon::DefaultReload function. +* +* @param entity Weapon to reload (> MaxPlayers) OR player index to reload his current active weapon (>= 1 & <= MaxPlayers). +* @param iClipSize Weapon max clip to check. 0 = weapon max clip stored in ItemInfo +* @param iAnim Weapon view model animation to play (often "reload", use HLMV to see anim index) +* @param fDelay Player reload duration before clip refill. +* +* @return 1 on successful weapon reload, 0 otherwise. +*/ +cell AMX_NATIVE_CALL rg_weapon_reload(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon, arg_clipsize, arg_anim, arg_delay }; + + CBasePlayerWeapon *pWeapon; + + if (params[arg_weapon] > 0 && params[arg_weapon] <= gpGlobals->maxClients) + { + CHECK_ISPLAYER(arg_weapon); + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_weapon]); + CHECK_CONNECTED(pPlayer, arg_weapon); + + if (!pPlayer->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d not alive", __FUNCTION__, params[arg_weapon]); + return FALSE; + } + + pWeapon = static_cast(pPlayer->m_pActiveItem); + } + else + { + CHECK_ISENTITY(arg_weapon); + + pWeapon = getPrivate(params[arg_weapon]); + } + + if (unlikely(pWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + + CCSPlayerWeapon *pCSWeapon = pWeapon->CSPlayerWeapon(); + if (unlikely(pCSWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized m_pEntity.", __FUNCTION__); + return FALSE; + } + + CAmxArgs args(amx, params); + + int clipsize = args[arg_clipsize]; + + if (clipsize <= 0) + clipsize = pWeapon->CSPlayerItem()->m_ItemInfo.iMaxClip; + + return pCSWeapon->DefaultReload(clipsize, args[arg_anim], args[arg_delay]) ? TRUE : FALSE; +} + +/* +* Forces shotgun reload thinking on a weapon or a player's active weapon using the CBasePlayerWeapon::DefaultShotgunReload function. +* +* @param entity Weapon to reload (> MaxClients) OR player index to reload his current active weapon (>= 1 & <= MaxClients). +* @param iAnim Weapon view model "insert" animation to play (use HLMV to see anim index) +* @param iStartAnim Weapon view model "start reload" animation to play (use HLMV to see anim index) +* @param fDelay Delay between each buckshot inserted +* @param fStartDelay Delay before buckshots insertion starts +* @param pszReloadSound1 Sound to play on every insertion +* @param pszReloadSound2 Another sound to play on every insertion +* +* @note This is used inside weapon's Reload function and is often called every frame player is pressing IN_RELOAD button. +* @return 1 while weapon not in delay and with ammo remaining to load, 0 otherwise. +*/ +cell AMX_NATIVE_CALL rg_weapon_shotgun_reload(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon, arg_anim, arg_startanim, arg_delay, arg_startdelay, arg_reloadsound1, arg_reloadsound2 }; + + CBasePlayerWeapon *pWeapon; + + if (params[arg_weapon] > 0 && params[arg_weapon] <= gpGlobals->maxClients) + { + CHECK_ISPLAYER(arg_weapon); + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_weapon]); + CHECK_CONNECTED(pPlayer, arg_weapon); + + if (!pPlayer->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d not alive", __FUNCTION__, params[arg_weapon]); + return FALSE; + } + + pWeapon = static_cast(pPlayer->m_pActiveItem); + } + else + { + CHECK_ISENTITY(arg_weapon); + + pWeapon = getPrivate(params[arg_weapon]); + } + + if (unlikely(pWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + + CCSPlayerWeapon *pCSWeapon = pWeapon->CSPlayerWeapon(); + if (unlikely(pCSWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized m_pEntity.", __FUNCTION__); + return FALSE; + } + + CAmxArgs args(amx, params); + + char sound1buffer[MAX_PATH], sound2buffer[MAX_PATH]; + const char *reloadsound1 = getAmxString(amx, params[arg_reloadsound1], sound1buffer); + const char *reloadsound2 = getAmxString(amx, params[arg_reloadsound2], sound2buffer); + + return pCSWeapon->DefaultShotgunReload(args[arg_anim], args[arg_startanim], args[arg_delay], args[arg_startdelay], reloadsound1, reloadsound2) ? TRUE : FALSE; +} + +/* +* Sends a weapon animation using the CBasePlayerWeapon::SendWeaponAnim function. +* +* @param entity Weapon to send animation on owner (> MaxClients) OR player index to send animation (>= 1 & <= MaxClients). +* @param iAnim Weapon view model animation to play (use HLMV to see anim index) +* @param skiplocal If 0, weapon animation will be forced to play on client ignoring active client prediction. +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_weapon_send_animation(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon, arg_anim, arg_skiplocal }; + + CBasePlayerWeapon *pWeapon; + + if (params[arg_weapon] > 0 && params[arg_weapon] <= gpGlobals->maxClients) + { + CHECK_ISPLAYER(arg_weapon); + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_weapon]); + CHECK_CONNECTED(pPlayer, arg_weapon); + + if (!pPlayer->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d not alive", __FUNCTION__, params[arg_weapon]); + return FALSE; + } + + pWeapon = static_cast(pPlayer->m_pActiveItem); + } + else + { + CHECK_ISENTITY(arg_weapon); + + pWeapon = getPrivate(params[arg_weapon]); + } + + if (unlikely(pWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + + CCSPlayerWeapon *pCSWeapon = pWeapon->CSPlayerWeapon(); + if (unlikely(pCSWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized m_pEntity.", __FUNCTION__); + return FALSE; + } + + CAmxArgs args(amx, params); + + pCSWeapon->SendWeaponAnim(args[arg_anim], args[arg_skiplocal]); + return TRUE; +} + +/* +* Emits a "recoil" effect on weapon's player using the CBasePlayerWeapon::KickBack function. +* +* @param entity Weapon to reload (> MaxClients) OR player index to reload his current active weapon (>= 1 & <= MaxClients). +* @param up_base Minimum vertical punchangle +* @param lateral_base Minimum horizontal punchangle +* @param up_modifier Vertical punchangle units to multiply to m_iShotsFired member +* @param lateral_modifier Horizontal punchangle units to multiply to m_iShotsFired member +* @param up_max Maximum vertical punchangle +* @param lateral_max Maximum horizontal punchangle +* @param direction_change Probability to change punchangle orientation (positive or negative). 0 = 100% (1/1), 1 = 50% (1/2), 2 = 33.3% (1/3), ... +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_weapon_kickback(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_weapon, arg_up_base, arg_lateral_base, arg_up_modifier, arg_lateral_modifier, arg_up_max, arg_lateral_max, arg_direction_change }; + + CBasePlayerWeapon *pWeapon; + + if (params[arg_weapon] > 0 && params[arg_weapon] <= gpGlobals->maxClients) + { + CHECK_ISPLAYER(arg_weapon); + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_weapon]); + CHECK_CONNECTED(pPlayer, arg_weapon); + + if (!pPlayer->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d not alive", __FUNCTION__, params[arg_weapon]); + return FALSE; + } + + pWeapon = static_cast(pPlayer->m_pActiveItem); + } + else + { + CHECK_ISENTITY(arg_weapon); + + pWeapon = getPrivate(params[arg_weapon]); + } + + if (unlikely(pWeapon == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + + CCSPlayerWeapon *pCSWeapon = pWeapon->CSPlayerWeapon(); + if (unlikely(pCSWeapon == nullptr)) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized m_pEntity.", __FUNCTION__); + return FALSE; + } + + CAmxArgs args(amx, params); + + pCSWeapon->KickBack(args[arg_up_base], args[arg_lateral_base], args[arg_up_modifier], args[arg_lateral_modifier], args[arg_up_max], args[arg_lateral_max], args[arg_direction_change]); + return TRUE; +} + +/* +* Switches player current weapon into the best one on its inventory using the CHalfLifeMultiplay::GetNextBestWeapon function. +* +* @param player Player index. +* @param currentWeapon Current player active weapon. 0 = retrieve from m_pActiveItem member +* +* @note Weapon selection is based on weapon's Weight attribute from ItemInfo structure. +* @return 1 if weapon was found and switched to, 0 otherwise +*/ +cell AMX_NATIVE_CALL rg_switch_best_weapon(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_index, arg_weapon }; + + CHECK_GAMERULES(); + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + if (!pPlayer->IsAlive()) + return FALSE; + + CBasePlayerWeapon *pWeapon; + + if (params[arg_weapon] != 0) + { + CHECK_ISENTITY(arg_weapon); + + pWeapon = getPrivate(params[arg_weapon]); + + if (unlikely(pWeapon == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (!pWeapon->IsWeapon()) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: #%d entity is not a weapon.", __FUNCTION__, indexOfEdict(pWeapon->pev)); + return FALSE; + } + } + else + { + pWeapon = static_cast(pPlayer->m_pActiveItem); + + if (unlikely(pWeapon == nullptr)) { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d has invalid m_pActiveItem", __FUNCTION__, params[arg_index]); + return FALSE; + } + } + + return CSGameRules()->GetNextBestWeapon(pPlayer, pWeapon); +} + +/* +* Disappear a player from the world. Used when VIP reaches escape zone. Basically a silent kill. +* +* @param player Player index. +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_disappear(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index) + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + pPlayer->CSPlayer()->Disappear(); + return TRUE; +} + +/* +* Sets player current Observer mode. +* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER). +* +* @param player Player index. +* @param mode Observer mode, see OBS_* constants in cssdk_const.inc +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_set_observer_mode(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_index, arg_mode }; + + CHECK_ISPLAYER(arg_index) + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + pPlayer->CSPlayer()->Observer_SetMode((int)params[arg_mode]); + return TRUE; +} + +/* +* Emits a death notice (logs, DeathMsg event, win conditions check) +* +* @param pVictim Player index. +* @param pKiller Killer entity. +* @param pevInflictor Inflictor entity. 0 = world +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_death_notice(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_victim, arg_killer, arg_inflictor }; + + CHECK_GAMERULES(); + + CHECK_ISPLAYER(arg_victim) + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_victim]); + CHECK_CONNECTED(pPlayer, arg_victim); + + CHECK_ISENTITY(arg_killer) + + CAmxArgs args(amx, params); + CSGameRules()->DeathNotice(pPlayer, args[arg_killer], args[arg_inflictor]); + return TRUE; +} + AMX_NATIVE_INFO Misc_Natives_RG[] = { { "rg_set_animation", rg_set_animation }, @@ -2708,6 +3319,22 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_spawn_head_gib", rg_spawn_head_gib }, { "rg_spawn_random_gibs", rg_spawn_random_gibs }, + { "rg_spawn_grenade", rg_spawn_grenade }, + { "rg_create_weaponbox", rg_create_weaponbox }, + { "rg_remove_entity", rg_remove_entity }, + { "rg_decal_trace", rg_decal_trace }, + { "rg_emit_texture_sound", rg_emit_texture_sound }, + { "rg_add_ammo_registry", rg_add_ammo_registry }, + { "rg_weapon_deploy", rg_weapon_deploy }, + { "rg_weapon_reload", rg_weapon_reload }, + { "rg_weapon_shotgun_reload", rg_weapon_shotgun_reload }, + { "rg_weapon_send_animation", rg_weapon_send_animation }, + { "rg_weapon_kickback", rg_weapon_kickback }, + { "rg_switch_best_weapon", rg_switch_best_weapon }, + { "rg_disappear", rg_disappear }, + { "rg_set_observer_mode", rg_set_observer_mode }, + { "rg_death_notice", rg_death_notice }, + { nullptr, nullptr } }; From 1e9f3f1a3ade88b3f9c03d04d37cd8bf47644bec Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Dec 2023 16:24:49 +0700 Subject: [PATCH 47/50] s/get_member: Added a throw error for clarity if the member type is not supported --- reapi/src/member_list.h | 35 +++++++++++++++++++++++ reapi/src/natives/natives_members.cpp | 41 +++++++++++++++------------ reapi/src/natives/natives_members.h | 4 +-- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index 58969330..4dc774e5 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -98,6 +98,41 @@ struct member_t const char *name; MType type; bool (*pfnIsRefsToClass)(void *pEntity); + + inline static const char *getTypeString(MType memberType) + { + switch (memberType) + { + case MEMBER_FLOAT: return "Float"; + case MEMBER_DOUBLE: return "Double"; + case MEMBER_ENTITY: return "Entity"; + case MEMBER_CLASSPTR: return "ClassPtr"; + case MEMBER_EHANDLE: return "EHANDLE"; + case MEMBER_EVARS: return "entvars"; + case MEMBER_EDICT: return "edict"; + case MEMBER_VECTOR: return "Vector"; + case MEMBER_STRING: return "String"; + case MEMBER_QSTRING: return "QStirng"; + case MEMBER_INTEGER: return "Integer"; + case MEMBER_SHORT: return "Short"; + case MEMBER_BYTE: return "Byte"; + case MEMBER_BOOL: return "Bool"; + case MEMBER_SIGNALS: return "Signals"; + case MEBMER_REBUYSTRUCT: return "RebuyStruct"; + case MEMBER_PMTRACE: return "pmtrace"; + case MEBMER_USERCMD: return "usercmd"; + case MEMBER_TRACERESULT: return "TraceResult"; + default: + { + static char string[16]; + Q_snprintf(string, sizeof(string), "%d", memberType); + return string; + } + } + + return ""; // shut up compiler + } + }; inline bool member_t::isTypeReturnable() const diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index 54ba699c..699c2a02 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -29,6 +29,7 @@ cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) size_t element = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; return set_member( + amx, get_pdata_custom(getPrivate(pEdict), params[arg_member]), member, value, @@ -99,7 +100,7 @@ cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) break; } - return get_member( + return get_member(amx, get_pdata_custom(getPrivate(pEdict), params[arg_member]), member, dest, @@ -145,6 +146,7 @@ cell AMX_NATIVE_CALL set_member_s(AMX *amx, cell *params) } return set_member( + amx, pEntity, member, value, @@ -225,6 +227,7 @@ cell AMX_NATIVE_CALL get_member_s(AMX *amx, cell *params) } return get_member( + amx, pEntity, member, dest, @@ -257,7 +260,7 @@ cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) cell* value = getAmxAddr(amx, params[arg_value]); size_t element = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; - return set_member(g_pGameRules, member, value, element); + return set_member(amx, g_pGameRules, member, value, element); } /* @@ -308,7 +311,7 @@ cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) length = 0; } - return get_member(g_pGameRules, member, dest, element, length); + return get_member(amx, g_pGameRules, member, dest, element, length); } /* @@ -337,7 +340,7 @@ cell AMX_NATIVE_CALL set_entvar(AMX *amx, cell *params) cell* value = getAmxAddr(amx, params[arg_value]); size_t element = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; - return set_member(&pEdict->v, member, value, element); + return set_member(amx, &pEdict->v, member, value, element); } /* @@ -399,7 +402,7 @@ cell AMX_NATIVE_CALL get_entvar(AMX *amx, cell *params) length = 0; } - return get_member(&pEdict->v, member, dest, element, length); + return get_member(amx, &pEdict->v, member, dest, element, length); } /* @@ -424,7 +427,7 @@ cell AMX_NATIVE_CALL set_pmove(AMX *amx, cell *params) cell* value = getAmxAddr(amx, params[arg_value]); size_t element = (PARAMS_COUNT == 3) ? *getAmxAddr(amx, params[arg_elem]) : 0; - return set_member(g_pMove, member, value, element); + return set_member(amx, g_pMove, member, value, element); } /* @@ -492,7 +495,7 @@ cell AMX_NATIVE_CALL get_pmove(AMX *amx, cell *params) length = 0; } - return get_member(g_pMove, member, dest, element, length); + return get_member(amx, g_pMove, member, dest, element, length); } /* @@ -515,7 +518,7 @@ cell AMX_NATIVE_CALL set_movevar(AMX *amx, cell *params) } cell* value = getAmxAddr(amx, params[arg_value]); - return set_member(g_pMove->movevars, member, value, 0); + return set_member(amx, g_pMove->movevars, member, value, 0); } /* @@ -552,7 +555,7 @@ cell AMX_NATIVE_CALL get_movevar(AMX *amx, cell *params) length = 0; } - return get_member(g_pMove->movevars, member, dest, element, length); + return get_member(amx, g_pMove->movevars, member, dest, element, length); } /* @@ -573,7 +576,7 @@ cell AMX_NATIVE_CALL set_ucmd(AMX *amx, cell *params) cell* cmd = (cell *)params[arg_cmd]; cell* value = getAmxAddr(amx, params[arg_value]); - return set_member(cmd, member, value, 0); + return set_member(amx, cmd, member, value, 0); } /* @@ -605,7 +608,7 @@ cell AMX_NATIVE_CALL get_ucmd(AMX *amx, cell *params) } cell* cmd = (cell *)params[arg_cmd]; - return get_member(cmd, member, dest, element); + return get_member(amx, cmd, member, dest, element); } /* @@ -629,7 +632,7 @@ cell AMX_NATIVE_CALL set_pmtrace(AMX *amx, cell *params) cell* tr = (cell *)params[arg_tr]; cell* value = getAmxAddr(amx, params[arg_value]); - return set_member(tr, member, value, 0); + return set_member(amx, tr, member, value, 0); } /* @@ -664,7 +667,7 @@ cell AMX_NATIVE_CALL get_pmtrace(AMX *amx, cell *params) } cell* tr = (cell *)params[arg_tr]; - return get_member(tr, member, dest, element); + return get_member(amx, tr, member, dest, element); } /* @@ -782,7 +785,7 @@ cell AMX_NATIVE_CALL set_rebuy(AMX *amx, cell *params) return FALSE; } - return set_member(handle, member, ¶ms[arg_value], 0); + return set_member(amx, handle, member, ¶ms[arg_value], 0); } /* @@ -810,7 +813,7 @@ cell AMX_NATIVE_CALL get_rebuy(AMX *amx, cell *params) return FALSE; } - return get_member(handle, member, nullptr, 0); + return get_member(amx, handle, member, nullptr, 0); } AMX_NATIVE_INFO EngineVars_Natives[] = @@ -862,7 +865,7 @@ void RegisterNatives_Members() g_amxxapi.AddNatives(EngineVars_Natives); } -cell set_member(void* pdata, const member_t *member, cell* value, size_t element) +cell set_member(AMX *amx, void* pdata, const member_t *member, cell* value, size_t element) { if (!pdata) { return FALSE; @@ -981,6 +984,7 @@ cell set_member(void* pdata, const member_t *member, cell* value, size_t element case MEBMER_REBUYSTRUCT: case MEMBER_PMTRACE: case MEBMER_USERCMD: + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: member type %s (%s) is not supported", __FUNCTION__, member_t::getTypeString(member->type), member->name); return FALSE; default: break; @@ -989,7 +993,7 @@ cell set_member(void* pdata, const member_t *member, cell* value, size_t element return FALSE; } -cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, size_t length) +cell get_member(AMX *amx, void* pdata, const member_t *member, cell* dest, size_t element, size_t length) { if (!pdata) { return 0; @@ -1103,7 +1107,8 @@ cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, case MEMBER_ENTITY: case MEMBER_EVARS: - return 0; + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: member type %s (%s) is not supported", __FUNCTION__, member_t::getTypeString(member->type), member->name); + return FALSE; case MEMBER_TRACERESULT: return (cell)get_member_direct(pdata, member->offset, element); case MEBMER_REBUYSTRUCT: diff --git a/reapi/src/natives/natives_members.h b/reapi/src/natives/natives_members.h index 3af37b69..79c3b367 100644 --- a/reapi/src/natives/natives_members.h +++ b/reapi/src/natives/natives_members.h @@ -3,7 +3,7 @@ void RegisterNatives_Members(); void *get_pdata_custom(CBaseEntity *pEntity, cell member); -cell set_member(void* pdata, const member_t *member, cell* value, size_t element); -cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, size_t length = 0); +cell set_member(AMX *amx, void* pdata, const member_t *member, cell* value, size_t element); +cell get_member(AMX *amx, void* pdata, const member_t *member, cell* dest, size_t element, size_t length = 0); bool isTypeReturnable(MType type); From 39e4ba8a819ea3926b39eee529bc587aaef0fdbd Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Dec 2023 16:25:57 +0700 Subject: [PATCH 48/50] Fix wrong member region for CCSEntity --- reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index f1d1fbac..5f2d6ae2 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -6355,7 +6355,7 @@ enum CCSEntity_Members * Get params: get_member(index, member); * Set params: set_member(index, member, value); */ - m_ucDmgPenetrationLevel = BEGIN_MEMBER_REGION(csplayerweapon), + m_ucDmgPenetrationLevel = BEGIN_MEMBER_REGION(csentity), /* * Description: Cached inflictor passed inside TakeDamage to retrieve in Killed From 1d17078fd6b20531f6b965834487eb58d85eec6a Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sun, 3 Dec 2023 16:31:44 +0700 Subject: [PATCH 49/50] s/get_member: Added support for members with entvars type --- reapi/src/natives/natives_members.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index 699c2a02..b80dbf42 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -895,6 +895,13 @@ cell set_member(AMX *amx, void* pdata, const member_t *member, cell* value, size set_member(pdata, member->offset, pEdictValue, element); return TRUE; } + case MEMBER_EVARS: + { + // native set_member(_index, any:_member, _value, _elem); + entvars_t *pev = PEV(*value); + set_member(pdata, member->offset, pev, element); + return TRUE; + } case MEMBER_VECTOR: { // native set_member(_index, any:_member, Float:_value[3], _elem); @@ -978,15 +985,12 @@ cell set_member(AMX *amx, void* pdata, const member_t *member, cell* value, size set_member(pdata, member->offset, *(TraceResult *)value, element); return TRUE; } - case MEMBER_ENTITY: - case MEMBER_EVARS: case MEBMER_REBUYSTRUCT: case MEMBER_PMTRACE: case MEBMER_USERCMD: AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: member type %s (%s) is not supported", __FUNCTION__, member_t::getTypeString(member->type), member->name); return FALSE; - default: break; } @@ -1020,6 +1024,12 @@ cell get_member(AMX *amx, void* pdata, const member_t *member, cell* dest, size_ edict_t *pEntity = get_member(pdata, member->offset, element); return pEntity ? indexOfEdict(pEntity) : AMX_NULLENT; } + case MEMBER_EVARS: + { + // native any:get_member(_index, any:_member, element); + entvars_t *pev = get_member(pdata, member->offset, element); + return pev ? indexOfEdict(pev) : AMX_NULLENT; + } case MEMBER_VECTOR: { // native any:get_member(_index, any:_member, any:output[], element); @@ -1104,9 +1114,7 @@ cell get_member(AMX *amx, void* pdata, const member_t *member, cell* dest, size_ pSignals[_State] = signal.GetState(); return 1; } - case MEMBER_ENTITY: - case MEMBER_EVARS: AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: member type %s (%s) is not supported", __FUNCTION__, member_t::getTypeString(member->type), member->name); return FALSE; case MEMBER_TRACERESULT: From f1555887f50aaf08ad787a7d36e0555b6531dc2d Mon Sep 17 00:00:00 2001 From: s1lentq Date: Tue, 12 Dec 2023 19:31:12 +0700 Subject: [PATCH 50/50] Fixed incorrect conversion IGameClient pointer --- reapi/src/hook_callback.cpp | 18 +++++++++--------- reapi/src/type_conversion.h | 12 ++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 5962a26b..518a74e0 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -20,7 +20,7 @@ void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash { auto original = [chain](int _cl, bool _crash, const char *_fmt) { - chain->callNext(g_RehldsSvs->GetClient(_cl - 1), _crash, _fmt); + chain->callNext(clientByIndex(_cl), _crash, _fmt); }; callVoidForward(RH_SV_DropClient, original, cl->GetId() + 1, crash, fmt); @@ -50,7 +50,7 @@ void SV_WriteFullClientUpdate_AMXX(SV_WriteFullClientUpdate_t *data, IGameClient { auto original = [data](int _client, size_t _buffer, int _receiver) { - data->m_chain->callNext(g_RehldsSvs->GetClient(_client - 1), (char *)_buffer, data->m_args.maxlen, data->m_args.message, g_RehldsSvs->GetClient(_receiver - 1)); + data->m_chain->callNext(clientByIndex(_client), (char *)_buffer, data->m_args.maxlen, data->m_args.message, clientByIndex(_receiver)); }; callVoidForward(RH_SV_WriteFullClientUpdate, original, client->GetId() + 1, buffer, receiver ? receiver->GetId() + 1 : AMX_NULLENT); @@ -87,7 +87,7 @@ void ClientConnected(IRehldsHook_ClientConnected* chain, IGameClient* cl) { auto original = [chain](int client) { - chain->callNext(g_RehldsSvs->GetClient(client - 1)); + chain->callNext(clientByIndex(client)); }; callVoidForward(RH_ClientConnected, original, cl->GetId() + 1); @@ -107,7 +107,7 @@ void SV_EmitPings_AMXX(SV_EmitPings_t* data, IGameClient* cl) { auto original = [data](int _cl) { - data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_args.message); + data->m_chain->callNext(clientByIndex(_cl), data->m_args.message); }; callVoidForward(RH_SV_EmitPings, original, cl->GetId() + 1); @@ -236,10 +236,10 @@ void ExecuteServerStringCmd(IRehldsHook_ExecuteServerStringCmd* chain, const cha { auto original = [chain](const char* _cmdName, cmd_source_t _cmdSrc, int client) { - chain->callNext(_cmdName, _cmdSrc, _cmdSrc == src_client ? g_RehldsSvs->GetClient(client) - 1 : 0); + chain->callNext(_cmdName, _cmdSrc, _cmdSrc == src_client ? clientByIndex(client) : nullptr); }; - callVoidForward(RH_ExecuteServerStringCmd, original, cmdName, cmdSrc, cmdSrc == src_client ? cl->GetId() + 1 : 0); + callVoidForward(RH_ExecuteServerStringCmd, original, cmdName, cmdSrc, cmdSrc == src_client ? cl->GetId() + 1 : AMX_NULLENT); } /* @@ -1734,7 +1734,7 @@ void FileConsistencyProcess_AMXX(FileConsistencyProcess_t *data, IGameClient *cl int hashCopy = responseHash; auto original = [data, hashCopy](int _cl, const char *_filename, const char *_cmd, ResourceType_e _type, uint32 _hash, bool _isBreak) { - data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_args, _type, hashCopy); + data->m_chain->callNext(clientByIndex(_cl), data->m_args, _type, hashCopy); }; if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { @@ -1754,7 +1754,7 @@ void FileConsistencyFinal(IRecheckerHook_FileConsistencyFinal *chain, IGameClien { auto original = [chain](int _cl) { - chain->callNext(g_RehldsSvs->GetClient(_cl - 1)); + chain->callNext(clientByIndex(_cl)); }; callVoidForward(RC_FileConsistencyFinal, original, cl->GetId() + 1); @@ -1765,7 +1765,7 @@ void CmdExec_AMXX(CmdExec_t *data, IGameClient *cl, const char *filename, char * int hashCopy = responseHash; auto original = [data, hashCopy](int _cl, const char *_filename, char *_cmd, uint32 _responseHash) { - data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_args, _cmd, hashCopy); + data->m_chain->callNext(clientByIndex(_cl), data->m_args, _cmd, hashCopy); }; if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { diff --git a/reapi/src/type_conversion.h b/reapi/src/type_conversion.h index 29a9c22d..41b9e0c8 100644 --- a/reapi/src/type_conversion.h +++ b/reapi/src/type_conversion.h @@ -1,12 +1,16 @@ #pragma once #include +#include #define INDEXENT edictByIndex #define ENTINDEX indexOfEdict #define AMX_NULLENT -1 +class IGameClient; + extern edict_t* g_pEdicts; +extern IRehldsServerStatic* g_RehldsSvs; inline size_t indexOfEdict(const edict_t* ed) { @@ -41,6 +45,14 @@ inline edict_t* edictByIndex(const int index) return g_pEdicts + index; } +inline IGameClient* clientByIndex(const int index) +{ + IGameClient* cl = nullptr; + if (likely(index > 0)) + cl = g_RehldsSvs->GetClient(index - 1); + return cl; +} + // safe to index -1 inline edict_t* edictByIndexAmx(const int index) {