diff --git a/amxmodx/CEvent.cpp b/amxmodx/CEvent.cpp index 3257dfd5..41b88aa8 100755 --- a/amxmodx/CEvent.cpp +++ b/amxmodx/CEvent.cpp @@ -14,6 +14,8 @@ // class ClEvent // ***************************************************** +Handle EventHandles; + EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags) { m_Plugin = plugin; @@ -47,6 +49,7 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags) m_Stamp = 0.0f; m_Done = false; + m_State = FSTATE_ACTIVE; m_Conditions = NULL; } @@ -188,20 +191,31 @@ void EventsMngr::ClEvent::registerFilter(char *filter) m_Conditions = tmpCond; } -EventsMngr::ClEvent* EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid) +void EventsMngr::ClEvent::setForwardState(ForwardState state) { - // validate parameter - if (msgid < 0 || msgid >= MAX_AMX_REG_MSG) - return NULL; + m_State = state; +} - ClEvent *event = new ClEvent(plugin, func, flags); + +int EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid) +{ + if (msgid < 0 || msgid >= MAX_AMX_REG_MSG) + { + return 0; + } + + auto event = new ClEvent(plugin, func, flags); + + int handle = EventHandles.create(event); - if (!event) - return NULL; + if (!handle) + { + return 0; + } m_Events[msgid].put(event); - return event; + return handle; } void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index) @@ -454,7 +468,10 @@ void EventsMngr::executeEvents() (*iter).m_Stamp = (float)*m_Timer; - executeForwards((*iter).m_Func, static_cast(m_ReadVault ? m_ReadVault[0].iValue : 0)); + if ((*iter).m_State == FSTATE_ACTIVE) + { + executeForwards((*iter).m_Func, static_cast(m_ReadVault ? m_ReadVault[0].iValue : 0)); + } } // Restore old read data, either resetting to default or to previous event data @@ -530,7 +547,9 @@ void EventsMngr::clearEvents(void) { m_Events[i].clear(); } - + + EventHandles.clear(); + // delete parsevault if (m_ParseVault) { diff --git a/amxmodx/CEvent.h b/amxmodx/CEvent.h index e9729165..c406252f 100755 --- a/amxmodx/CEvent.h +++ b/amxmodx/CEvent.h @@ -10,6 +10,8 @@ #ifndef __CEVENTS_H__ #define __CEVENTS_H__ +#include "natives_handles.h" + #define MAX_AMX_REG_MSG MAX_REG_MSGS + 16 enum @@ -24,6 +26,12 @@ enum // class EventsMngr // ***************************************************** +enum ForwardState +{ + FSTATE_ACTIVE, + FSTATE_STOP +}; + class EventsMngr { enum MsgParamType @@ -63,6 +71,7 @@ public: float m_Stamp; // for 'once' flag bool m_Done; + ForwardState m_State; // conditions struct cond_t @@ -87,6 +96,7 @@ public: inline CPluginMngr::CPlugin* getPlugin(); inline int getFunction(); void registerFilter(char* filter); // add a condition + void setForwardState(ForwardState value); }; private: @@ -125,8 +135,8 @@ public: // Interface - ClEvent* registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid); - + int registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid); + void parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index); void parseValue(int iValue); void parseValue(float fValue); @@ -142,4 +152,12 @@ public: int getCurrentMsgType(); }; +struct EventHook +{ + EventHook(EventsMngr::ClEvent *event) : m_event(event) {} + EventsMngr::ClEvent *m_event; +}; + +extern Handle EventHandles; + #endif //__CEVENTS_H__ diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 4f060816..a51dd331 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -19,6 +19,7 @@ #include "nongpl_matches.h" #include "format.h" #include +#include "CEvent.h" extern CFlagManager FlagMan; ke::Vector DynamicAdmins; @@ -1722,26 +1723,28 @@ static cell AMX_NATIVE_CALL get_concmdsnum(AMX *amx, cell *params) /* 1 param */ return g_commands.getCmdNum(CMD_ConsoleCommand, params[1]); } -static cell AMX_NATIVE_CALL register_event(AMX *amx, cell *params) /* 2 param */ +// native register_event(const event[], const function[], const flags[], const cond[] = "", ...); +static cell AMX_NATIVE_CALL register_event(AMX *amx, cell *params) { CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast(amx); - int len, pos, iFunction; + int len, eventId, forwardId; - char* sTemp = get_amxstring(amx, params[1], 0, len); + const char* eventName = get_amxstring(amx, params[1], 0, len); - if ((pos = g_events.getEventId(sTemp)) == 0) + if ((eventId = g_events.getEventId(eventName)) == 0) { - LogError(amx, AMX_ERR_NATIVE, "Invalid event (name \"%s\") (plugin \"%s\")", sTemp, plugin->getName()); + LogError(amx, AMX_ERR_NATIVE, "Invalid event (name \"%s\") (plugin \"%s\")", eventName, plugin->getName()); return 0; } - sTemp = get_amxstring(amx, params[2], 0, len); - iFunction = registerSPForwardByName(amx, sTemp, FP_CELL, FP_DONE); + const char* callback = get_amxstring(amx, params[2], 0, len); + + forwardId = registerSPForwardByName(amx, callback, FP_CELL, FP_DONE); - if (iFunction == -1) + if (forwardId == -1) { - LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", sTemp); + LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", callback); return 0; } @@ -1749,15 +1752,53 @@ static cell AMX_NATIVE_CALL register_event(AMX *amx, cell *params) /* 2 param */ int flags = 0; if (numparam > 2) + { flags = UTIL_ReadFlags(get_amxstring(amx, params[3], 0, len)); + } - EventsMngr::ClEvent* a = g_events.registerEvent(plugin, iFunction, flags, pos); + int handle = g_events.registerEvent(plugin, forwardId, flags, eventId); - if (a == 0) + if (!handle) + { return 0; + } + + auto event = EventHandles.lookup(handle)->m_event; for (int i = 4; i <= numparam; ++i) - a->registerFilter(get_amxstring(amx, params[i], 0, len)); + { + event->registerFilter(get_amxstring(amx, params[i], 0, len)); + } + + return handle; +} + +static cell AMX_NATIVE_CALL enable_event(AMX *amx, cell *params) +{ + auto handle = EventHandles.lookup(params[1]); + + if (!handle) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid event handle %d", params[1]); + return 0; + } + + handle->m_event->setForwardState(FSTATE_ACTIVE); + + return 1; +} + +static cell AMX_NATIVE_CALL disable_event(AMX *amx, cell *params) +{ + auto handle = EventHandles.lookup(params[1]); + + if (!handle) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid event handle: %d", params[1]); + return 0; + } + + handle->m_event->setForwardState(FSTATE_STOP); return 1; } @@ -4589,6 +4630,8 @@ AMX_NATIVE_INFO amxmodx_Natives[] = {"register_concmd", register_concmd}, {"register_dictionary", register_dictionary}, {"register_event", register_event}, + {"enable_event", enable_event}, + {"disable_event", disable_event}, {"register_logevent", register_logevent}, {"register_menucmd", register_menucmd}, {"register_menuid", register_menuid}, diff --git a/plugins/include/amxmodx.inc b/plugins/include/amxmodx.inc index 5b2d93d6..3d2023bf 100755 --- a/plugins/include/amxmodx.inc +++ b/plugins/include/amxmodx.inc @@ -464,6 +464,8 @@ native console_cmd(id, const cmd[], any:...); * @note Due to a long-standing bug that would break compatibility with older * plugins, the client id should be checked for alive/dead state if using * flags "d" or "e". + * @note If multiple conditions are specified for a single parameter, only one + * of them has to hold true for the event function to be called. * * @param event Name of event that should be hooked * @param function Name of callback function @@ -488,13 +490,32 @@ native console_cmd(id, const cmd[], any:...); * The argument is compared to the specified value accordingly * @param ... Any number of additional conditions * - * @return 1 on successfully registering event - * 0 on failure + * @return Event handle * @error If an invalid event name or callback function is provided, * an error will be thrown. */ native register_event(const event[], const function[], const flags[], const cond[] = "", ...); +/** + * Enables a function hook of a game event which has been previously registered with register_event(). + * + * @param handle Value returned from register_event() + * + * @noreturn + * @error If an invalid handle is provided, an error will be thrown. + */ +native enable_event(handle); + +/** + * Disables a function hook of a game event which has been previously registered with register_event(). + * + * @param handle Value returned from register_event() + * + * @noreturn + * @error If an invalid handle is provided, an error will be thrown. + */ +native disable_event(handle); + /** * Registers a function to be called on a given log event. *