From 166b5ca650644a7fddfb785e1417fc9f0b11c159 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 29 Jul 2005 06:33:57 +0000 Subject: [PATCH] omg new menu system --- amxmodx/CMenu.h | 6 +- amxmodx/meta_api.cpp | 3 + amxmodx/modules.cpp | 2 + amxmodx/msvc/amxmodx_mm.vcproj | 6 + amxmodx/newmenus.cpp | 375 +++++++++++++++++++++++++++++++++ amxmodx/newmenus.h | 67 ++++++ 6 files changed, 454 insertions(+), 5 deletions(-) create mode 100755 amxmodx/newmenus.cpp create mode 100755 amxmodx/newmenus.h diff --git a/amxmodx/CMenu.h b/amxmodx/CMenu.h index 66e89b2c..9360f2ba 100755 --- a/amxmodx/CMenu.h +++ b/amxmodx/CMenu.h @@ -83,7 +83,7 @@ public: int findMenuId(const char* name, AMX* a = 0); int registerMenuId(const char* n, AMX* a ); - void registerMenuCmd( CPluginMngr::CPlugin *a,int mi, int k , int f ); + void registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f); void clear(); class iterator { @@ -98,10 +98,6 @@ public: }; inline iterator begin() const { return iterator(headcmd); } inline iterator end() const { return iterator(0); } - - }; #endif - - diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 8e6a357c..0331e590 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -32,6 +32,7 @@ #include #include "amxmodx.h" #include "fakemeta.h" +#include "newmenus.h" plugin_info_t Plugin_info = { META_INTERFACE_VERSION, // ifvers @@ -460,6 +461,7 @@ void C_ServerDeactivate_Post() { g_logevents.clearLogEvents(); g_events.clearEvents(); g_menucmds.clear(); + ClearMenus(); g_vault.clear(); g_xvars.clear(); g_plugins.clear(); @@ -1140,6 +1142,7 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { g_logevents.clearLogEvents(); g_events.clearEvents(); g_menucmds.clear(); + ClearMenus(); g_vault.clear(); g_xvars.clear(); g_plugins.clear(); diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index ac8107e9..8000fece 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -40,6 +40,7 @@ #include "CFile.h" #include "amxxfile.h" #include "amxdbg.h" +#include "newmenus.h" CList g_modules; CList g_loadedscripts; @@ -544,6 +545,7 @@ int set_amxnatives(AMX* amx,char error[128]) amx_Register(amx, power_Natives, -1); amx_Register(amx, time_Natives, -1); amx_Register(amx, vault_Natives, -1); + amx_Register(amx, g_NewMenuNatives, -1); if (CheckModules(amx, error)) { diff --git a/amxmodx/msvc/amxmodx_mm.vcproj b/amxmodx/msvc/amxmodx_mm.vcproj index 9a7da04b..0ac5f288 100755 --- a/amxmodx/msvc/amxmodx_mm.vcproj +++ b/amxmodx/msvc/amxmodx_mm.vcproj @@ -659,6 +659,9 @@ + + @@ -793,6 +796,9 @@ + + diff --git a/amxmodx/newmenus.cpp b/amxmodx/newmenus.cpp new file mode 100755 index 00000000..1f167a70 --- /dev/null +++ b/amxmodx/newmenus.cpp @@ -0,0 +1,375 @@ +#include "amxmodx.h" +#include "newmenus.h" + +CVector g_NewMenus; + +void ClearMenus() +{ + for (size_t i=0; iname.assign(name); + pItem->cmd.assign(cmd); + pItem->access = access; + pItem->id = m_Items.size(); + pItem->handler = -1; + pItem->pfn = NULL; + + m_Items.push_back(pItem); + + return pItem; +} + +menuitem *Menu::GetMenuItem(item_t item) +{ + if (item >= m_Items.size()) + return NULL; + + return m_Items[item]; +} + +size_t Menu::GetItemCount() +{ + return m_Items.size(); +} + +size_t Menu::GetPageCount() +{ + size_t items = GetItemCount(); + page_t numPages = (items / MENUITEMS) + 1; + + if (!items) + return 0; + + if (numPages % MENUITEMS == 0) + numPages--; + + return numPages; +} + +int Menu::PagekeyToItem(page_t page, item_t key) +{ + page_t pages = GetPageCount(); + item_t numItems = GetItemCount(); + + if (page >= pages) + return MENU_EXIT; + + item_t start = page * 7; + + if (page == 0) + { + item_t rem = numItems >= 7 ? 7 : numItems; + if (key == rem) + { + if (pages > 1) + return MENU_MORE; + else + return MENU_EXIT; + } else if (key == rem+1) { + return MENU_EXIT; + } + } else if (page == pages - 1) { + //find number of remaining items + //for example, 11 items on page 1... means start=7, 11-7=4 + item_t rem = numItems - start; + //however, the last item is actually this -1, so... + if (key == rem) + { + return MENU_EXIT; + } else if (key == rem+1) { + return MENU_BACK; + } + } else { + if (key == 7) + { + return MENU_MORE; + } else if (key == 8) { + return MENU_BACK; + } + } + + return (start + key); +} + +bool Menu::Display(int player, page_t page) +{ + int keys = 0; + const char *str = GetTextString(player, page, keys); + + if (!str) + return false; + + static char buffer[2048]; + int len = _snprintf(buffer, sizeof(buffer)-1, "%s", str); + + CPlayer *pPlayer = GET_PLAYER_POINTER_I(player); + + pPlayer->keys = keys; + pPlayer->menu = menuId; + + UTIL_ShowMenu(pPlayer->pEdict, keys, -1, buffer, len); + + return true; +} + +const char *Menu::GetTextString(int player, page_t page, int &keys) +{ + page_t pages = GetPageCount(); + item_t numItems = GetItemCount(); + + if (page >= pages) + return NULL; + + m_Text.clear(); + + char buffer[255]; + if (g_coloredmenus) + _snprintf(buffer, sizeof(buffer)-1, "\\y%s %d/%d\n\\w\n", m_Title.c_str(), page+1, pages); + else + _snprintf(buffer, sizeof(buffer)-1, "%s %d/%d\n\n", m_Title.c_str(), page+1, pages); + m_Text.append(buffer); + + item_t start = page * 7; + item_t end = 0; + if (start + 7 <= numItems) + { + end = start + 7; + } else { + end = numItems; + } + + menuitem *pItem = NULL; + int option = 0; + keys = 0; + bool enabled = true; + int ret = 0; + for (item_t i=start; iaccess && !(pItem->access & g_players[player].flags[0])) + enabled = false; + if (pItem->handler != -1) + { + ret = executeForwards(pItem->handler, player, thisId, i); + if (ret == ITEM_ENABLED) + enabled = true; + else if (ret == ITEM_DISABLED) + enabled = false; + } + if (pItem->pfn) + { + ret = (pItem->pfn)(player, thisId, i); + if (ret == ITEM_ENABLED) + enabled = true; + else if (ret == ITEM_DISABLED) + enabled = false; + } + if (enabled) + { + keys |= (1<name.c_str()); + } else { + if (g_coloredmenus) + { + _snprintf(buffer, sizeof(buffer)-1, "\\d%d. %s\n\\w", ++option, pItem->name.c_str()); + } else { + _snprintf(buffer, sizeof(buffer)-1, "#. %s\n", pItem->name.c_str()); + option++; + } + } + m_Text.append(buffer); + } + //now for a weird part >:o + //this will either be MORE or BACK.. + keys |= (1< 1)) + { + _snprintf(buffer, sizeof(buffer)-1, "%d. %s\n", option, "More"); + } else { + _snprintf(buffer, sizeof(buffer)-1, "%d. %s\n", option, "Exit"); + } + m_Text.append(buffer); + if (pages > 1) + { + keys |= (1<= (int)g_NewMenus.size() || p < 0) { \ + LogError(amx, AMX_ERR_NATIVE, "Invalid menu id %d", p); \ + return 0; } \ + Menu *pMenu = g_NewMenus[p]; + +//Makes a new menu handle (-1 for failure) +//native csdm_makemenu(title[]); +static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params) +{ + int len; + char *title = get_amxstring(amx, params[1], 0, len); + char *handler = get_amxstring(amx, params[2], 1, len); + + int func = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_DONE); + if (func == -1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Invalid function \"%s\"", handler); + return 0; + } + + int id = g_menucmds.registerMenuId(title, amx); + g_menucmds.registerMenuCmd( g_plugins.findPluginFast(amx), id, 1023, func ); + + Menu *pMenu = new Menu(title, id, (int)g_NewMenus.size()); + g_NewMenus.push_back(pMenu); + + return (int)g_NewMenus.size() - 1; +} + +//Adds an item to the menu (returns current item count - 1) +//native menu_additem(menu, const name[], const command[]="", access=0); +static cell AMX_NATIVE_CALL menu_additem(AMX *amx, cell *params) +{ + int len; + char *name, *cmd; + int access; + + GETMENU(params[1]); + + name = get_amxstring(amx, params[2], 0, len); + cmd = get_amxstring(amx, params[3], 1, len); + access = params[4]; + + menuitem *pItem = pMenu->AddItem(name, cmd, access); + + pItem->handler = params[5]; + + return 1; +} + +//Returns the number of pages in a menu +//native csdm_menu_pages(menu); +static cell AMX_NATIVE_CALL menu_pages(AMX *amx, cell *params) +{ + GETMENU(params[1]); + return pMenu->GetPageCount(); +} + +//Returns the number of items in a menu +//native csdm_menu_items(menu); +static cell AMX_NATIVE_CALL menu_items(AMX *amx, cell *params) +{ + GETMENU(params[1]); + + return pMenu->GetItemCount(); +} + +//Builds the menu string for a specific page (set title to 0 to not include title) +//page indices start at 0! +static cell AMX_NATIVE_CALL menu_display(AMX *amx, cell *params) +{ + GETMENU(params[2]); + + int player = params[1]; + int page = params[3]; + + return pMenu->Display(player, page); +} + +//Finds the id of a menu item for a specific page and key value. +//Note that key should be from 0-6, as it only displays 7 per page. +//page indices start at 0 +//native menu_keyid(menu, page, key); +static cell AMX_NATIVE_CALL menu_find_id(AMX *amx, cell *params) +{ + GETMENU(params[1]); + + page_t page = static_cast(params[2]); + item_t key = static_cast(params[3]); + + return pMenu->PagekeyToItem(page, key); +} + +//Gets info about a menu option +//native menu_item_getinfo(menu, item, &access, command[], cmdlen, name[]="", namelen=0, &callback); +static cell AMX_NATIVE_CALL menu_item_getinfo(AMX *amx, cell *params) +{ + GETMENU(params[1]); + + menuitem *pItem = pMenu->GetMenuItem(static_cast(params[2])); + + if (!pItem) + return 0; + + cell *addr = get_amxaddr(amx, params[3]); + addr[0] = pItem->access; + + set_amxstring(amx, params[4], pItem->cmd.c_str(), params[5]); + set_amxstring(amx, params[6], pItem->name.c_str(), params[7]); + + if (params[8]) + { + addr = get_amxaddr(amx, params[8]); + if (addr) + addr[0] = pItem->handler; + } + + return 1; +} + +static cell AMX_NATIVE_CALL menu_makecallback(AMX *amx, cell *params) +{ + int len; + char *name = get_amxstring(amx, params[1], 0, len); + + int id = registerSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + + if (id == -1) + { + LogError(amx, AMX_ERR_NOTFOUND, "Invalid function %s", name); + return -1; + } + + return id; +} + +AMX_NATIVE_INFO g_NewMenuNatives[] = +{ + {"menu_create", menu_create}, + {"menu_additem", menu_additem}, + {"menu_pages", menu_pages}, + {"menu_items", menu_items}, + {"menu_display", menu_display}, + {"menu_find_id", menu_find_id}, + {"menu_item_getinfo", menu_item_getinfo}, + {"menu_makecallback", menu_makecallback}, + {NULL, NULL}, +}; \ No newline at end of file diff --git a/amxmodx/newmenus.h b/amxmodx/newmenus.h new file mode 100755 index 00000000..5c29bb95 --- /dev/null +++ b/amxmodx/newmenus.h @@ -0,0 +1,67 @@ +#ifndef _INCLUDE_NEWMENUS_H +#define _INCLUDE_NEWMENUS_H + +#define MENU_EXIT -3 +#define MENU_BACK -2 +#define MENU_MORE -1 +#define ITEM_IGNORE 0 +#define ITEM_ENABLED 1 +#define ITEM_DISABLED 2 + +#define MENUITEMS 7 + +typedef int (*MENUITEM_CALLBACK)(int, int, int); + +struct menuitem +{ + String name; + String cmd; + int access; + int handler; + MENUITEM_CALLBACK pfn; + size_t id; +}; + +typedef unsigned int menu_t; +typedef unsigned int item_t; +typedef unsigned int page_t; + +class Menu +{ +public: + Menu(const char *title, int menuId, int thisId); + ~Menu(); + menuitem *GetMenuItem(item_t item); + size_t GetPageCount(); + size_t GetItemCount(); + menuitem *AddItem(const char *name, const char *cmd, int access); + const char *GetTextString(int player, page_t page, int &keys); + bool Display(int player, page_t page); + int PagekeyToItem(page_t page, item_t key); + int GetMenuMenuid(); +private: + CVector m_Items; + String m_Title; + String m_Text; + int menuId; + int thisId; +}; + +/*Menu *CreateMenu(const char *title); +Menu *GetMenuById(menu_t menu); +menuitem *GetMenuItem(menu_t menu, item_t item); +size_t GetMenuPages(menu_t menu); +size_t GetMenuItems(menu_t menu); +menuitem *AddMenuItem(menu_t menu, const char *name, const char *cmd, int access); +bool DisplayMenu(menu_t menu, int player, page_t page); +int MenuPagekeyToItem(menu_t menu, page_t page, int key); +int FindByMenuid(int menuid); +int GetMenuMenuid(menu_t menu); +const char *GetItemName(menu_t menu, item_t item); +const char *GetItemCmd(menu_t menu, item_t item);*/ + +void ClearMenus(); + +extern AMX_NATIVE_INFO g_NewMenuNatives[]; + +#endif //_INCLUDE_NEWMENUS_H