diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 6a4e10ad..208ceba4 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -1143,17 +1143,24 @@ void C_ClientCommand(edict_t *pEntity) executeForwards(pMenu->pageCallback, static_cast(pPlayer->index), static_cast(MENU_BACK)); pMenu->Display(pPlayer->index, pPlayer->page - 1); - } else if (item == MENU_MORE) { + } + else if (item == MENU_MORE) + { if (pMenu->pageCallback >= 0) executeForwards(pMenu->pageCallback, static_cast(pPlayer->index), static_cast(MENU_MORE)); pMenu->Display(pPlayer->index, pPlayer->page + 1); - } else { - ret = executeForwards(pMenu->func, static_cast(pPlayer->index), static_cast(menu), static_cast(item)); + } + else + { + auto pItem = pMenu->GetMenuItem(static_cast(item)); + ret = executeForwards(pMenu->func, static_cast(pPlayer->index), static_cast(menu), static_cast(item), pItem ? static_cast(pItem->data) : 0); if (ret & 2) { result = MRES_SUPERCEDE; - } else if (ret & 1) { + } + else if (ret & 1) + { RETURN_META(MRES_SUPERCEDE); } } diff --git a/amxmodx/newmenus.cpp b/amxmodx/newmenus.cpp index 59bdd7e6..3c495318 100755 --- a/amxmodx/newmenus.cpp +++ b/amxmodx/newmenus.cpp @@ -11,6 +11,7 @@ #include "CMenu.h" #include "newmenus.h" #include "format.h" +#include "CDataPack.h" ke::Vector g_NewMenus; CStack g_MenuFreeStack; @@ -120,9 +121,12 @@ isDestroying(false), pageCallback(-1), showPageNumber(true), useMultilingual(use Menu::~Menu() { - for (size_t i = 0; i < m_Items.length(); i++) + for (auto &item : m_Items) { - delete m_Items[i]; + if (item->isDataDataPack && item->data > 0) + DataPackHandles.destroy(item->data); + + delete item; } unregisterSPForward(this->func); @@ -131,7 +135,7 @@ Menu::~Menu() m_Items.clear(); } -menuitem *Menu::AddItem(const char *name, const char *cmd, int access) +menuitem *Menu::AddItem(const char *name, const char *cmd, int access, int handler = -1) { menuitem *pItem = new menuitem; @@ -139,7 +143,7 @@ menuitem *Menu::AddItem(const char *name, const char *cmd, int access) pItem->cmd = cmd; pItem->access = access; pItem->id = m_Items.length(); - pItem->handler = -1; + pItem->handler = handler; pItem->isBlank = false; pItem->pfn = NULL; @@ -441,22 +445,26 @@ const char *Menu::GetTextString(int player, page_t page, int &keys) if (pItem->handler != -1) { - ret = executeForwards(pItem->handler, static_cast(player), static_cast(thisId), static_cast(i)); + ret = executeForwards(pItem->handler, static_cast(player), static_cast(thisId), static_cast(i), static_cast(pItem->data)); if (ret == ITEM_ENABLED) { enabled = true; - } else if (ret == ITEM_DISABLED) { + } + else if (ret == ITEM_DISABLED) + { enabled = false; } } if (pItem->pfn) { - ret = (pItem->pfn)(player, thisId, i); + ret = (pItem->pfn)(player, thisId, i, pItem->data); if (ret == ITEM_ENABLED) { enabled = true; - } else if (ret == ITEM_DISABLED) { + } + else if (ret == ITEM_DISABLED) + { enabled = false; } } @@ -795,8 +803,6 @@ static cell AMX_NATIVE_CALL menu_addtext2(AMX *amx, cell *params) static cell AMX_NATIVE_CALL menu_additem(AMX *amx, cell *params) { int len; - char *name, *cmd; - int access; GETMENU(params[1]); @@ -806,14 +812,36 @@ static cell AMX_NATIVE_CALL menu_additem(AMX *amx, cell *params) return 0; } - name = get_amxstring(amx, params[2], 0, len); + auto name = get_amxstring(amx, params[2], 0, len); validate_menu_text(name); - cmd = get_amxstring(amx, params[3], 1, len); - access = params[4]; + auto cmd = get_amxstring(amx, params[3], 1, len); - menuitem *pItem = pMenu->AddItem(name, cmd, access); + pMenu->AddItem(name, cmd, params[4], params[5]); - pItem->handler = params[5]; + return 1; +} + +//Adds an item to the menu +//native menu_additem2(menu, const name[], any:data = 0, access = 0, callback = -1, bool:dp_data = false); +static cell AMX_NATIVE_CALL menu_additem2(AMX *amx, cell *params) +{ + int len; + + GETMENU(params[1]); + + if (!pMenu->items_per_page && pMenu->GetItemCount() >= 10) + { + LogError(amx, AMX_ERR_NATIVE, "Non-paginated menus are limited to 10 items."); + return 0; + } + + auto name = get_amxstring(amx, params[2], 0, len); + validate_menu_text(name); + + auto pItem = pMenu->AddItem(name, "", params[4], params[5]); + + pItem->data = params[3]; + pItem->isDataDataPack = params[6] != 0; return 1; } @@ -928,9 +956,9 @@ static cell AMX_NATIVE_CALL menu_item_getinfo(AMX *amx, cell *params) static cell AMX_NATIVE_CALL menu_makecallback(AMX *amx, cell *params) { int len; - char *name = get_amxstring(amx, params[1], 0, len); + auto name = get_amxstring(amx, params[1], 0, len); - int id = registerSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + auto id = registerSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); if (id == -1) { @@ -979,6 +1007,24 @@ static cell AMX_NATIVE_CALL menu_item_setcmd(AMX *amx, cell *params) return 1; } +static cell AMX_NATIVE_CALL menu_item_setdata(AMX *amx, cell *params) +{ + GETMENU(params[1]); + + auto pItem = pMenu->GetMenuItem(static_cast(params[2])); + + if (!pItem) + return 0; + + if (pItem->isDataDataPack && pItem->data > 0) + DataPackHandles.destroy(pItem->data); + + pItem->data = params[3]; + pItem->isDataDataPack = params[4] != 0; + + return 1; +} + static cell AMX_NATIVE_CALL menu_item_setcall(AMX *amx, cell *params) { GETMENU(params[1]); @@ -1215,6 +1261,7 @@ AMX_NATIVE_INFO g_NewMenuNatives[] = { {"menu_create", menu_create}, {"menu_additem", menu_additem}, + {"menu_additem2", menu_additem2}, {"menu_addblank", menu_addblank}, {"menu_addtext", menu_addtext}, {"menu_pages", menu_pages}, @@ -1225,6 +1272,7 @@ AMX_NATIVE_INFO g_NewMenuNatives[] = {"menu_makecallback", menu_makecallback}, {"menu_item_setcall", menu_item_setcall}, {"menu_item_setcmd", menu_item_setcmd}, + {"menu_item_setdata", menu_item_setdata}, {"menu_item_setname", menu_item_setname}, {"menu_destroy", menu_destroy}, {"menu_setprop", menu_setprop}, diff --git a/amxmodx/newmenus.h b/amxmodx/newmenus.h index 8b53a52a..d88304c7 100755 --- a/amxmodx/newmenus.h +++ b/amxmodx/newmenus.h @@ -33,7 +33,7 @@ #define MPROP_PAGE_CALLBACK 11 #define MPROP_SHOWPAGE 12 -typedef int (*MENUITEM_CALLBACK)(int, int, int); +typedef int (*MENUITEM_CALLBACK)(int, int, int, int); class BlankItem { @@ -81,6 +81,8 @@ struct menuitem int access; int handler; bool isBlank; + int data; + bool isDataDataPack; MENUITEM_CALLBACK pfn; size_t id; @@ -101,7 +103,7 @@ public: menuitem *GetMenuItem(item_t item); size_t GetPageCount(); size_t GetItemCount(); - menuitem *AddItem(const char *name, const char *cmd, int access); + menuitem *AddItem(const char *name, const char *cmd, int access, int handler); const char *GetTextString(int player, page_t page, int &keys); bool Display(int player, page_t page); diff --git a/plugins/include/newmenus.inc b/plugins/include/newmenus.inc index 79a88f7b..7af47941 100644 --- a/plugins/include/newmenus.inc +++ b/plugins/include/newmenus.inc @@ -102,13 +102,14 @@ * * The handler function should be prototyped as: * - * public (id, menu, item) + * public (id, menu, item, any:data) * id - Client the menu is being acted upon. * menu - Menu resource identifier. * item - Item the client selected. If less than 0, the menu was * cancelled and the item is a status code. menu_display * should never be called immediately if the item is a status * code, for re-entrancy reasons. + * data - Item's data the client selected. * * The handler function should always return PLUGIN_HANDLED to block * any old menu handlers from potentially feeding on the menu, unless @@ -131,10 +132,11 @@ native menu_create(const title[], const handler[], bool:ml = false); * * The handler function should be prototyped as: * - * public (id, menu, item) + * public (id, menu, item, any:data) * id - Client index being displayed to. * menu - Menu resource identifier. * item - Item being drawn. + * data - Item's data. * - ITEM_IGNORE to use the default functionality. ITEM_ENABLED to * explicitly enable or ITEM_DISABLED to explicitly disable. * @@ -157,6 +159,22 @@ native menu_makecallback(const function[]); */ native menu_additem(menu, const name[], const info[]="", paccess=0, callback=-1); +/** + * Adds an item to a menu. + * + * @param menu Menu resource identifier. + * @param name Item text to display. + * @param info Item data for internal information. + * @param paccess Access required by the player viewing the menu. + * @param callback If set to a valid ID from menu_makecallback(), the + * callback will be invoked before drawing the item. + * @param dp_data If true, item's data will be treated as DataPack and be destroyed + * along with the menu. + * @noreturn + * @error Invalid menu resource. + */ +native menu_additem2(menu, const name[], any:data = 0, access = 0, callback = -1, bool:dp_data = false); + /** * Returns the number of pages in a menu. * @@ -246,6 +264,19 @@ native menu_item_setname(menu, item, const name[]); */ native menu_item_setcmd(menu, item, const info[]); +/** + * Sets an item's data. + * + * @param menu Menu resource identifier. + * @param item Item identifier. + * @param data New item data. + * @param dp_data If true, item's data will be treated as DataPack and be destroyed + * along with the menu. + * @return 1 on success, 0 on failure. + * @error Invalid menu resource. + */ +native menu_item_setdata(menu, item, any:data = 0, bool:dp_data = false); + /** * Sets an item's callback. * diff --git a/plugins/pluginmenu.sma b/plugins/pluginmenu.sma index 80f43fc3..dd52eb9a 100644 --- a/plugins/pluginmenu.sma +++ b/plugins/pluginmenu.sma @@ -121,8 +121,8 @@ stock DisplayPluginMenu(id,const MenuText[], const Handler[], const Command[], c new PluginName[64]; new func=get_func_id(Callback); new tally; - new PluginCmd[64]; new MenuText[64]; + new DataPack:itemData; for (new i=0, max=get_pluginsnum(); i