2
0
mirror of https://github.com/rehlds/reapi.git synced 2025-02-06 18:42:19 +03:00

Enhanced natives SetThink, SetTouch, SetUse, SetBlocked, SetMoveDone

This commit is contained in:
s1lent 2017-10-03 18:37:11 +07:00
parent e636819f02
commit 9cedc733b7
No known key found for this signature in database
GPG Key ID: 0FE401DC73916B5C
7 changed files with 165 additions and 76 deletions

View File

@ -1195,3 +1195,11 @@ enum InfoMapBuyParam
BUYING_ONLY_TERRORISTS, BUYING_ONLY_TERRORISTS,
BUYING_NO_ONE, BUYING_NO_ONE,
}; };
enum USE_TYPE
{
USE_OFF,
USE_ON,
USE_SET,
USE_TOGGLE
};

View File

@ -7,60 +7,70 @@
#include <reapi_gamedll_const> #include <reapi_gamedll_const>
/* /*
* Sets callback for entity * Sets Think callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Think_Callback(const ent)"
* *
* @noreturn * @noreturn
*/ */
native SetThink(const ent, const callback[]); native SetThink(const ent, const callback[], const params[] = "", const len = 0);
/* /*
* Sets callback for entity * Sets Touch callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)"
* *
* @noreturn * @noreturn
*/ */
native SetTouch(const ent, const callback[]); native SetTouch(const ent, const callback[], const params[] = "", const len = 0);
/* /*
* Sets callback for entity * Sets Use callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)"
* *
* @noreturn * @noreturn
*/ */
native SetUse(const ent, const callback[]); native SetUse(const ent, const callback[], const params[] = "", const len = 0);
/* /*
* Sets callback for entity * Sets Blocked callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)"
* *
* @noreturn * @noreturn
*/ */
native SetBlocked(const ent, const callback[]); native SetBlocked(const ent, const callback[], const params[] = "", const len = 0);
/* /*
* Sets callback for entity * Sets MoveDone callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Entity should be inherited from CBaseToggle, otherwise server can crash * @note Entity should be inherited from CBaseToggle, otherwise server can crash
* * @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)"
* @param entity Entity index
* @param callback The forward to call
* @note Use "" to reset callback
* *
* @noreturn * @noreturn
*/ */
native SetMoveDone(const ent, const callback[]); native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0);
/* /*
* Sets a value to CSGameRules_Members members. * Sets a value to CSGameRules_Members members.

View File

@ -8,7 +8,7 @@ enum fwdstate
FSTATE_STOPPED FSTATE_STOPPED
}; };
template <typename T = int> template <typename T = void>
class CAmxxHook class CAmxxHook
{ {
public: public:
@ -18,9 +18,11 @@ public:
g_amxxapi.UnregisterSPForward(m_index); g_amxxapi.UnregisterSPForward(m_index);
m_index = -1; m_index = -1;
} }
delete m_uniqueData;
} }
CAmxxHook(AMX *amx, const char *funcname, int index, T data = (T)0) : CAmxxHook(AMX *amx, const char *funcname, int index, T *data = nullptr) :
m_index(index), m_index(index),
m_state(FSTATE_ENABLED), m_state(FSTATE_ENABLED),
m_amx(amx), m_amx(amx),
@ -29,7 +31,7 @@ public:
Q_strlcpy(m_CallbackName, funcname); Q_strlcpy(m_CallbackName, funcname);
}; };
T GetUnique() const; T *GetUnique() const;
int GetIndex() const; int GetIndex() const;
fwdstate GetState() const; fwdstate GetState() const;
AMX *GetAmx() const; AMX *GetAmx() const;
@ -38,7 +40,7 @@ public:
void SetState(fwdstate st); void SetState(fwdstate st);
private: private:
T m_uniqueData; T *m_uniqueData;
int m_index; int m_index;
char m_CallbackName[64]; char m_CallbackName[64];
fwdstate m_state; fwdstate m_state;
@ -47,7 +49,7 @@ private:
// Inlines // Inlines
template <typename T> template <typename T>
inline T CAmxxHook<T>::GetUnique() const inline T *CAmxxHook<T>::GetUnique() const
{ {
return m_uniqueData; return m_uniqueData;
} }

View File

@ -7,10 +7,10 @@ void CEntityCallback::PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type)
auto it = m_callbacks.begin(); auto it = m_callbacks.begin();
while (it != m_callbacks.end()) while (it != m_callbacks.end())
{ {
EntityCallback_t data = (*it)->GetUnique(); eCallback_t *pUnique = (*it)->GetUnique();
// this callback was already sets, need to unregister the current forward // this callback was already sets, need to unregister the current forward
if (data.m_callbackType == type && data.m_entity == pEntity) { if (pUnique->m_callbackType == type && pUnique->m_entity == pEntity) {
delete (*it); delete (*it);
it = m_callbacks.erase(it); it = m_callbacks.erase(it);
} else { } else {
@ -26,8 +26,8 @@ void CEntityCallback::Clear(CBaseEntity *pEntity)
auto it = m_callbacks.begin(); auto it = m_callbacks.begin();
while (it != m_callbacks.end()) while (it != m_callbacks.end())
{ {
EntityCallback_t data = (*it)->GetUnique(); eCallback_t *pUnique = (*it)->GetUnique();
if (data.m_entity == pEntity) { if (pUnique->m_entity == pEntity) {
delete (*it); delete (*it);
it = m_callbacks.erase(it); it = m_callbacks.erase(it);
} else { } else {
@ -45,82 +45,107 @@ void CEntityCallback::Clear(CBaseEntity *pEntity)
} }
} }
bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{ {
PurgeCallbacks(pEntity, CType_Think); PurgeCallbacks(pEntity, CType_Think);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); 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) { if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false; return false;
} }
EntityCallback_t entry(pEntity, CType_Think); m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Think)));
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
pEntity->SetThink(&CBaseEntity::SUB_Think); pEntity->SetThink(&CBaseEntity::SUB_Think);
return true; return true;
} }
bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{ {
PurgeCallbacks(pEntity, CType_Touch); PurgeCallbacks(pEntity, CType_Touch);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); 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) { if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false; return false;
} }
EntityCallback_t entry(pEntity, CType_Touch); m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Touch)));
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
pEntity->SetTouch(&CBaseEntity::SUB_Touch); pEntity->SetTouch(&CBaseEntity::SUB_Touch);
return true; return true;
} }
bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{ {
PurgeCallbacks(pEntity, CType_Use); PurgeCallbacks(pEntity, CType_Use);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE); 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) { if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false; return false;
} }
EntityCallback_t entry(pEntity, CType_Use); m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Use)));
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
pEntity->SetUse(&CBaseEntity::SUB_Use); pEntity->SetUse(&CBaseEntity::SUB_Use);
return true; return true;
} }
bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{ {
PurgeCallbacks(pEntity, CType_Blocked); PurgeCallbacks(pEntity, CType_Blocked);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); 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) { if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false; return false;
} }
EntityCallback_t entry(pEntity, CType_Blocked); m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Blocked)));
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
pEntity->SetTouch(&CBaseEntity::SUB_Blocked); pEntity->SetTouch(&CBaseEntity::SUB_Blocked);
return true; return true;
} }
bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{ {
PurgeCallbacks(pEntity, CType_MoveDone); PurgeCallbacks(pEntity, CType_MoveDone);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); 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) { if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false; return false;
} }
EntityCallback_t entry(pEntity, CType_MoveDone); m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_MoveDone)));
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
// TODO: Make sure that the entity actually inherited from CBaseToggle // TODO: Make sure that the entity actually inherited from CBaseToggle
((CBaseToggle *)pEntity)->SetMoveDone(&CBaseToggle::SUB_MoveDone); ((CBaseToggle *)pEntity)->SetMoveDone(&CBaseToggle::SUB_MoveDone);

View File

@ -7,11 +7,11 @@ class CEntityCallback
public: public:
void Clear(CBaseEntity *pEntity = nullptr); void Clear(CBaseEntity *pEntity = nullptr);
bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback); bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
enum CallbackType_e enum CallbackType_e
{ {
@ -26,24 +26,53 @@ public:
void FireCallbacks(CBaseEntity *pEntity, CallbackType_e type, volatile f_args... args) void FireCallbacks(CBaseEntity *pEntity, CallbackType_e type, volatile f_args... args)
{ {
for (auto fwd : m_callbacks) { for (auto fwd : m_callbacks) {
if (fwd->GetUnique().m_entity == pEntity && fwd->GetUnique().m_callbackType == type) { auto data = fwd->GetUnique();
g_amxxapi.ExecuteForward(fwd->GetIndex(), args...); if (data->m_entity == pEntity && data->m_callbackType == type)
{
if (data->m_iParamLen > 0) {
g_amxxapi.ExecuteForward(fwd->GetIndex(), args..., g_amxxapi.PrepareCellArrayA(data->m_pParams, data->m_iParamLen, true));
} else {
g_amxxapi.ExecuteForward(fwd->GetIndex(), args...);
}
} }
} }
} }
private: private:
void PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type); void PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type);
struct EntityCallback_t struct eCallback_t
{ {
EntityCallback_t(CBaseEntity *pEntity, CallbackType_e type) : eCallback_t(CBaseEntity *pEntity, const cell *pParams, size_t iParamsLen, CallbackType_e type) :
m_entity(pEntity), m_callbackType(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; CBaseEntity *m_entity;
CallbackType_e m_callbackType; CallbackType_e m_callbackType;
cell *m_pParams;
size_t m_iParamLen;
}; };
std::vector<CAmxxHook<EntityCallback_t> *> m_callbacks; std::vector<CAmxxHook<eCallback_t> *> m_callbacks;
}; };
extern CEntityCallback g_entCallback; extern CEntityCallback g_entCallback;

View File

@ -33,7 +33,7 @@ META_FUNCTIONS gMetaFunctionTable =
NULL, // pfnGetEntityAPI_Post META; called after game DLL NULL, // pfnGetEntityAPI_Post META; called after game DLL
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL GetNewDLLFunctions, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
NULL, // pfnGetEngineFunctions META; called before HL engine NULL, // pfnGetEngineFunctions META; called before HL engine
NULL, // pfnGetEngineFunctions_Post META; called after HL engine NULL, // pfnGetEngineFunctions_Post META; called after HL engine

View File

@ -256,19 +256,21 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params)
} }
/* /*
* Sets callback for entity * Sets Think callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Think_Callback(const ent)"
* *
* @noreturn * @noreturn
* *
* native SetThink(const ent, const callback[]); * native SetThink(const ent, const callback[], const params[] = "", const len = 0);
*/ */
cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params) cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params)
{ {
enum args_e { arg_count, arg_index, arg_handler }; enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index); CHECK_ISENTITY(arg_index);
@ -290,23 +292,26 @@ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params)
return FALSE; return FALSE;
} }
return (cell)g_entCallback.SetThink(amx, pEntity, funcname); cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetThink(amx, pEntity, funcname, pParams, params[arg_len]);
} }
/* /*
* Sets callback for entity * Sets Touch callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)"
* *
* @noreturn * @noreturn
* *
* native SetTouch(const ent, const callback[]); * native SetTouch(const ent, const callback[], const params[] = "", const len = 0);
*/ */
cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params) cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params)
{ {
enum args_e { arg_count, arg_index, arg_handler }; enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index); CHECK_ISENTITY(arg_index);
@ -328,23 +333,26 @@ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params)
return FALSE; return FALSE;
} }
return (cell)g_entCallback.SetTouch(amx, pEntity, funcname); cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetTouch(amx, pEntity, funcname, pParams, params[arg_len]);
} }
/* /*
* Sets callback for entity * Sets Use callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)"
* *
* @noreturn * @noreturn
* *
* native SetUse(const ent, const callback[]); * native SetUse(const ent, const callback[], const params[] = "", const len = 0);
*/ */
cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params) cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params)
{ {
enum args_e { arg_count, arg_index, arg_handler }; enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index); CHECK_ISENTITY(arg_index);
@ -366,23 +374,26 @@ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params)
return FALSE; return FALSE;
} }
return (cell)g_entCallback.SetUse(amx, pEntity, funcname); cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetUse(amx, pEntity, funcname, pParams, params[arg_len]);
} }
/* /*
* Sets callback for entity * Sets Blocked callback for entity
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)"
* *
* @noreturn * @noreturn
* *
* native SetBlocked(const ent, const callback[]); * native SetBlocked(const ent, const callback[], const params[] = "", const len = 0);
*/ */
cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params) cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params)
{ {
enum args_e { arg_count, arg_index, arg_handler }; enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index); CHECK_ISENTITY(arg_index);
@ -404,24 +415,27 @@ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params)
return FALSE; return FALSE;
} }
return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname); cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname, pParams, params[arg_len]);
} }
/* /*
* Sets callback for entity * Sets MoveDone callback for entity
* @note Entity should be inherited from CBaseToggle, otherwise server can crash
* *
* @param entity Entity index * @param entity Entity index
* @param callback The forward to call * @param callback The forward to call
*
* @note Use "" to reset callback * @note Use "" to reset callback
* @note Entity should be inherited from CBaseToggle, otherwise server can crash
* @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)"
* *
* @noreturn * @noreturn
* *
* native SetMoveDone(const ent, const callback[]); * native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0);
*/ */
cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params)
{ {
enum args_e { arg_count, arg_index, arg_handler }; enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index); CHECK_ISENTITY(arg_index);
@ -443,7 +457,8 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params)
return FALSE; return FALSE;
} }
return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname); cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname, pParams, params[arg_len]);
} }
AMX_NATIVE_INFO Natives_Common[] = AMX_NATIVE_INFO Natives_Common[] =