Иконка ресурса

Menu modular 1.0.2

Нет прав для скачивания
Установка
Раскидать файлы по папкам, скомпилировать, прописать в plugins.ini

В архиве лежит плагин-пример как правильно сделать простое меню.
Небольшой пример для избранных (как сделать более сложное меню с неопределенным количеством пунктов)

* Итемы для меню можно создавать в хуке mm_preopen_menu (пробежаться по текущим игрокам например)
Исходный код
Код:
#include <amxmodx>
#include <menu_modular>

public stock const PluginName[] = "Menu modular";
public stock const PluginVersion[] = "1.0.2";
public stock const PluginAuthor[] = "cpctrl";
public stock const PluginURL[] = "https://goldsrc.ru/members/3085/";

const MAX_ITEMS_MENU = 8;
const MAX_ITEMS = 180;

enum fwdStruct  {
    FWD_SELECTED,
    FWD_PREOPEN_MENU,
    FWD_OPENED_MENU
};

enum playerStruct {
    PLAYER_POS,
    PLAYER_MENU
};

enum itemStruct {
    ITEM_NAME[ITEM_MAX_NAME],
    ITEM_INFO[ITEM_INFO_MAX_NAME],
    ITEM_MENU,
    ITEM_ACCESS,
    bool: ITEM_BR,
    bool: ITEM_BLOCKED
};

new g_fwdHandle[fwdStruct];
new g_itemData[itemStruct];

new Array: g_aMenus;
new Array: g_aItems;

new bool: g_bConnected[MAX_PLAYERS + 1];
new g_iPlayerData[MAX_PLAYERS + 1][playerStruct];
new g_iMenuItems[MAX_PLAYERS + 1][MAX_ITEMS];

public plugin_init()    {
    register_menucmd(register_menuid("MENU_MODULAR_MAIN"), 1023, "HandlerMenuModular");

    g_fwdHandle[FWD_SELECTED] = CreateMultiForward("mm_item_selected", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_VAL_BYREF);
    g_fwdHandle[FWD_PREOPEN_MENU] = CreateMultiForward("mm_preopen_menu", ET_IGNORE, FP_CELL, FP_CELL);
    g_fwdHandle[FWD_OPENED_MENU] = CreateMultiForward("mm_opened_menu", ET_IGNORE, FP_CELL, FP_CELL);
}

public plugin_cfg() {
    register_dictionary("menu_modular.txt");
}

public client_putinserver(id)   {
    if (is_user_hltv(id) && is_user_bot(id))    {
        return;
    }

    g_bConnected[id] = true;
}

public client_disconnected(id)  {
    if (g_bConnected[id])   {
        g_bConnected[id] = false;
    }
}

Show_MenuModular(id, menu, pos)    {
    if (pos < 0)    {
        return -1;
    }

    new fwdReturn;
    ExecuteForward(g_fwdHandle[FWD_PREOPEN_MENU], fwdReturn, id, menu);

    if (fwdReturn == PLUGIN_HANDLED)    {
        return -1;
    }

    new items;
    for (new i; i < ArraySize(g_aItems); i++)  {
        ArrayGetArray(g_aItems, i, g_itemData, sizeof g_itemData);

        if (g_itemData[ITEM_MENU] == menu)  {
            if (g_itemData[ITEM_ACCESS] == ADMIN_ALL || g_itemData[ITEM_ACCESS] != ADMIN_ALL && (get_user_flags(id) & g_itemData[ITEM_ACCESS])) {
                g_iMenuItems[id][items++] = i;
            }
        }
    }

    new start = pos * MAX_ITEMS_MENU;

    if (start > items)  {
        start = items;
    }

    start = start - (start % MAX_ITEMS_MENU);

    g_iPlayerData[id][PLAYER_POS] = (start / MAX_ITEMS_MENU);

    new end = start + MAX_ITEMS_MENU;

    if (end > items)    {
        end = items;
    }

    new menuStr[512], len, keys = (1 << 9);

    new menuName[MENU_MAX_NAME];
    ArrayGetString(g_aMenus, menu, menuName, MENU_MAX_NAME - 1);
    len = formatex(menuStr, charsmax(menuStr), "%L \d[%d|%d]^n^n", id, menuName, pos + 1, items / MAX_ITEMS_MENU + ((items % MAX_ITEMS_MENU) ? 1 : 0));

    new info[ITEM_INFO_MAX_NAME], item;

    for (new b, a = start; a < end; a++)   {
        item = g_iMenuItems[id][a];
        ArrayGetArray(g_aItems, item, g_itemData, sizeof g_itemData);

        if (g_itemData[ITEM_INFO])  {
            formatex(info, ITEM_INFO_MAX_NAME - 1, " \d[\w%s\d]", g_itemData[ITEM_INFO]);
        }

        if (g_itemData[ITEM_BLOCKED])   {
            len += formatex(menuStr[len], charsmax(menuStr) - len, "\d[%d] \r%L%s%s^n", ++b, id, g_itemData[ITEM_NAME], info[0] != EOS ? info : "", (g_itemData[ITEM_BR]) ? "^n" : "");
            continue;
        }

        keys |= (1 << b);

        len += formatex(menuStr[len], charsmax(menuStr) - len, "\d[%d] \y%L%s%s^n",
        ++b, id, g_itemData[ITEM_NAME], info[0] != EOS ? info : "", (g_itemData[ITEM_BR]) ? "^n" : "");
    }

    new tmp[15];
    setc(tmp, MAX_ITEMS_MENU - (end - start) + 1, '^n');
    len += copy(menuStr[len], charsmax(menuStr) - len, tmp);

    if (end < items)    {
        keys |= (1 << 8);
        formatex(menuStr[len], charsmax(menuStr) - len, "\d[9] \y%L^n\d[0] \y%L", id, "MENU_NEXT", id, pos ? "MENU_BACK" : "MENU_EXIT");
    }
    else    {
        formatex(menuStr[len], charsmax(menuStr) - len, "\d[0] \y%L", id, pos ? "MENU_BACK" : "MENU_EXIT");
    }

    ExecuteForward(g_fwdHandle[FWD_OPENED_MENU], _, id, menu);

    return show_menu(id, keys, menuStr, -1, "MENU_MODULAR_MAIN");
}

public HandlerMenuModular(id, key)  {
    if (!g_bConnected[id])  {
        return PLUGIN_HANDLED;
    }

    switch (key)    {
        case 8: return Show_MenuModular(id, g_iPlayerData[id][PLAYER_MENU], ++g_iPlayerData[id][PLAYER_POS]);
        case 9: return Show_MenuModular(id, g_iPlayerData[id][PLAYER_MENU], --g_iPlayerData[id][PLAYER_POS]);
        default:    {
            new item = g_iMenuItems[id][(g_iPlayerData[id][PLAYER_POS] * MAX_ITEMS_MENU + key)];

            new again;
            ExecuteForward(g_fwdHandle[FWD_SELECTED], _, id, g_iPlayerData[id][PLAYER_MENU], item, again);
            again && Show_MenuModular(id, g_iPlayerData[id][PLAYER_MENU], g_iPlayerData[id][PLAYER_POS]);
        }
    }

    return PLUGIN_HANDLED;
}

public plugin_natives() {
    register_library("menu_modular");

    register_native("mm_add_menu", "add_menu");
    register_native("mm_add_item", "add_item");

    register_native("mm_item_setinfo", "item_setinfo");

    register_native("mm_show_menu", "_show_menu");
}

public add_menu(plugin, argc)   {
    enum    {
        arg_name = 1
    };

    if (!g_aMenus)  {
        g_aMenus = ArrayCreate(MENU_MAX_NAME);
    }

    new menuName[MENU_MAX_NAME];
    get_string(arg_name, menuName, MENU_MAX_NAME - 1);

    if (ArrayFindString(g_aMenus, menuName) != -1)  {
        return -1;
    }

    return ArrayPushString(g_aMenus, menuName);
}

public add_item(plugin, argc)   {
    enum    {
        arg_menu = 1,
        arg_name,
        arg_info,
        arg_access,
        arg_br,
        arg_blocked
    };

    if (!g_aItems)  {
        g_aItems = ArrayCreate(itemStruct);
    }

    get_string(arg_name, g_itemData[ITEM_NAME], ITEM_MAX_NAME - 1);

    new info[ITEM_INFO_MAX_NAME];
    get_string(arg_info, info, ITEM_INFO_MAX_NAME - 1);

    if (info[0] != EOS) {
        copy(g_itemData[ITEM_INFO], ITEM_INFO_MAX_NAME - 1, info);
    }
    else    {
        g_itemData[ITEM_INFO][0] = EOS;
    }

    g_itemData[ITEM_MENU] = get_param(arg_menu);
    g_itemData[ITEM_ACCESS] = get_param(arg_access);
    g_itemData[ITEM_BR] = bool: get_param(arg_br);
    g_itemData[ITEM_BLOCKED] = bool: get_param(arg_blocked);

    return ArrayPushArray(g_aItems, g_itemData);
}

public bool: item_setinfo(plugin, argc)   {
    enum    {
        arg_item = 1,
        arg_name,
        arg_info,
        arg_access,
        arg_br,
        arg_blocked
    };

    new item = get_param(arg_item);

    if (item < 0 || item > ArraySize(g_aItems)) {
        return false;
    }

    ArrayGetArray(g_aItems, item, g_itemData);

    new name[ITEM_MAX_NAME];
    get_string(arg_name, name, ITEM_MAX_NAME - 1);

    if (name[0] != EOS) {
        copy(g_itemData[ITEM_NAME], ITEM_MAX_NAME - 1, name);
    }

    new info[ITEM_INFO_MAX_NAME];
    get_string(arg_info, info, ITEM_INFO_MAX_NAME - 1);

    if (info[0] == 'E' && info[2] == 'S')  {
        g_itemData[ITEM_INFO][0] = EOS;
    }
    else if (info[0] != EOS) {
        copy(g_itemData[ITEM_INFO], ITEM_INFO_MAX_NAME - 1, info);
    }

    new access = get_param(arg_access);
    if (access != g_itemData[ITEM_ACCESS])  {
        g_itemData[ITEM_ACCESS] = access;
    }

    new bool: br = bool: get_param(arg_br);
    if (br != g_itemData[ITEM_BR]) {
        g_itemData[ITEM_BR] = br;
    }

    new bool: blocked = bool: get_param(arg_blocked);
    if (blocked != g_itemData[ITEM_BLOCKED])    {
        g_itemData[ITEM_BLOCKED] = blocked;
    }

    ArraySetArray(g_aItems, item, g_itemData);

    return true;
}

public _show_menu(plugin, argc)  {
    enum    {
        arg_player = 1,
        arg_menu
    };

    new id = get_param(arg_player);

    if (!g_bConnected[id])  {
        return -1;
    }

    new menu = get_param(arg_menu);

    if (0 > menu && menu > ArraySize(g_aMenus))   {
        return -1;
    }

    return Show_MenuModular(id, g_iPlayerData[id][PLAYER_MENU] = menu, g_iPlayerData[id][PLAYER_POS] = 0);
}
Интерфейсы (API)
Код:
#if defined _menu_modular_included
    #endinput
#endif

#define _menu_modular_included

const MENU_MAX_NAME = 32;
const ITEM_MAX_NAME = 32;
const ITEM_INFO_MAX_NAME = 32;

/**
*    Add a new menu
*
*    @param name                Menu title with Lang Key
*
*    @return                    menu index if success, -1 if menu name already added
*/
native mm_add_menu(const name[MENU_MAX_NAME]);

/**
*    Add a new item for menu
*
*    @param menu                Menu index from mm_add_menu
*    @param name                Item title with lang key
*    @param info                Info of this item
*    @param access            Access flags to menu like ADMIN_* from amxconst.inc
*    @param bBreak            Make a break after this item (^n)   
*    @param blocked            Don't show this item       
*
*    @return                    item index
*/
native mm_add_item(const menu, const name[ITEM_MAX_NAME], info[ITEM_INFO_MAX_NAME] = "", access = ADMIN_ALL, bool: bBreak = false, bool: blocked = false);

/**
*    Change data on item
*
*    @param item                item index from mm_add_item
*    @param name                New item title
*    @param info                new item info
*    @param access            new item access
*    @param bBreak            Make a break after this item (^n)
*    @param blocked            Don't show this item
*
*    @return                    true if success, false otherwise
*/
native bool: mm_item_setinfo(const item, name[ITEM_MAX_NAME] = "", info[ITEM_INFO_MAX_NAME] = "", access = ADMIN_ALL, bool: bBreak = false, bool: blocked = false);

/**
*    Show menu to client
*
*    @param id                Client index
*    @param menu                Menu index from mm_add_menu
*
*    @return                    1 if success
*/
native mm_show_menu(const id, const menu);

/**
*    Called when player selected a item
*
*    @param id                Client index
*    @param menu                Choosed menu index
*    @param item                Choosed item index
*    @param again            Show menu again after selected
*/
forward mm_item_selected(const id, const menu, const item, &again);

/**
*    Called when client opened menu (before his show)
*
*    @param id                Client index
*    @param menu                Menu index
*
*    @note                    if you want block showing this menu on this client use return PLUGIN_HANDLED
*/
forward mm_preopen_menu(const id, const menu);

/**
*    Called when client opened menu
*
*    @param id                Client index
*    @param menu                Menu index
*
*/
forward mm_opened_menu(const id, const menu);
Сверху Снизу