#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; pPlayer->newmenu = thisId; pPlayer->page = (int)page; 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_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}, };