1. vesuvius Пользователь

    Регистрация:
    14.07.15
    Сообщения:
    101
    Симпатии:
    8
    Пол:
    Мужской
    Skype:
    victor100993
    В большинстве случаев первым что хочется сделать новичку сриптеру это игровое меню, так как это очень наглядно. С помощью новой системы меню можно создавать очень гибкую систему различных менюшек, главное разобраться с небольшим количеством функций и обладать логическим мышлением, что бы придумывать собственные алгоритмы работы плагинов использую данный набор функций.
    Парочка советов:
    • Если ваше меню не динамическое (пункты меню не меняются при каждом открытии) то его лучше создавать глобальным (не пересоздавать каждый раз при открытии, это сэкономит ресурсы сервера)
    • Если в создаваемом меню нет пунктов - оно не будет показано
    • Что бы закрыть меню( убрать его с экрана игрока ) воспользуйтесь следующей функцией:
      Код:
      show_menu(id, 0, "^n", 1)
      ( показ пустого меню старой системой )
    • Если необходимо выровнять текст в меню по правому краю, то используйте \R.
    Функции новой системы меню:
    Давайте начнем с изучения функции которая создает меню - menu_create
    Инфо из newmenu.inc:
    Код:
    /**
    * @brief Creates a new menu object.
    *
    * The handler function should be prototyped as:
    *
    * public <function>(menu, id, item)
    *  menu   - Menu resource identifier.
    *  id     - Client the menu is being acted upon.
    *  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.
    *
    * The handler function should always return PLUGIN_HANDLED to block
    * any old menu handlers from potentially feeding on the menu, unless
    * that is the desired functionality.
    *
    * @param title         Title the menu should use.
    * @param handler        Name of the handler function.  The function will be invoked
    *                once and only once to every menu_display() call.
    * @param ml        Unused (should be 0).
    * @return        Menu resource identifier which must be destroyed via
    *                menu_destroy().  All menus are destroyed when the plugin
    *                unloads.
    * @error            Function name not found.
    */
    native menu_create(const title[], const handler[], ml=0);
    Синтаксис:
    Код:
    menu_create ( title[], handler[], ml=0 )

    • [*]title[]
      - Заголовок меню
    • handler[] - Функция обработчик ( какая функция будет вызвана при выборе какого то пункта меню.)
    • ml=0 - Должно быть ноль. (скудная информация с офф сайта)
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_create"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    new mTEST // Menu
    
    public plugin_init() {
        mTEST = menu_create("TEST", "mh_TEST")
        register_plugin(PLUGIN, VERSION, AUTHOR)
    }
    Описание:
    Обратите внимание, что данная функция создает меню, а не показывает его игроку.
    То есть меню надо сначала создать, внести туда все необходимые данные и только потом его показывать игроку.
    Если меню не будет изменяться динамически, лучше его создавать в plugin_init, что немного оптимизирует плагин.
    Если же у вас будет меню со списком игроков ( что в течении карты многократно изменяется) то создавать меню придется каждый раз при вызове функции и заново добавлять в него пункты ( список игроков) меню.

    Так же функция возвращает идентификатор меню, по которому в дальнейшем это меню можно уничтожить.
    Если вам необходимо проверять и делать активным/неактивным какой то из пунктов меню, именно не активным, а не просто не показывать, то без функции
    menu_makecallback вам просто не обойтись. Функция обработчик вызывается чуть ранее чем добавляется пункт в систему меню, тем самым дает время на проверку и запрет/разрешение использование какого то пункта меню. Обратит внимание что эта функция только создает обработчик и задает идентификатор, и ни чего сама не вызывает.

    Инфо из newmenu.inc:
    Код:
    /**
    * Creates a menu item callback handler.
    *
    * The handler function should be prototyped as:
    *
    * public <function>(id, menu, item)
    *  id      - Client index being displayed to.
    *  menu    - Menu resource identifier.
    *  item    - Item being drawn.
    * <return> - ITEM_IGNORE to use the default functionality.  ITEM_ENABLED to
    *            explicitly enable or ITEM_DISABLED to explicitly disable.
    *
    * @param function        Function name.
    * @return                Menu callback ID.
    */
    native menu_makecallback(const function[]);
    Синтаксис:
    Код:
    menu_makecallback ( function[] )
    • function[] - Исполняемая функция
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_additem"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
    
        register_plugin(PLUGIN, VERSION, AUTHOR)
    
        mTEST = menu_create("TEST", "mh_TEST")
    
        mcbTEST = menu_makecallback("mcb_TEST")
    Описание:
    Обратите внимание, что переменные для хранения идентификаторов глобальные, так как создание меню и обработчики находятся в разных форвардах (функциях)
    Я понимаю, еще пока что все запутано, но необходимо все изучить по отдельности, прежде чем в омут функций меню окунуться с головой.
    Потерпите еще немного, скоро уже будет рабочее меню.

    Немного поразмыслив, решил сюда дописать готовый рабочий пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] Callback"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
      
        register_plugin(PLUGIN, VERSION, AUTHOR)
      
        register_clcmd("say /menu","func_menu")
      
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
      
        new szItem[64]
        for (new i=1; i < 25; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_VOTE, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
      
    }
    public func_menu(id){
      
        menu_display(id, mTEST, 0)
    }
    public mh_TEST(id, menu, item) {
      
        new s_Data[30], s_Name[64], i_Access, i_Callback
        menu_item_getinfo(menu, item, i_Access, s_Data, charsmax(s_Data), s_Name, charsmax(s_Name), i_Callback)
      
        console_print(id,"item[%d]",item)
        console_print(id,"Access[%d]",i_Access)
        console_print(id,"Data[%s]",s_Data)
        console_print(id,"Name[%s]",s_Name)
        console_print(id,"Callback[%d]",i_Callback)
      
    }
    public mcb_TEST(id, menu, item){
      
        if(item == 0 || item == 2){
          
            return ITEM_DISABLED
        }
        return ITEM_ENABLED
    }[CODE][/spoiler][spoiler=[b]menu_additem[/b] - добавляет пункт в меню]
    После того как объект меню создан, необходимо добавить в это меню пункты для выбора игроком или админом.
    На мой взгляд эта функция уже имеет огромное преимущество перед старой системой меню.
    например своей возможностью использовать предварительный вызов и обработку пунктов меню (callback)
    То есть можно выполнить проверку пункта и сделать его не активным. Но ботом в другой раз.
    
    Инфо из [b]newmenu.inc:[/b]
    [CODE]/**
    * Adds an menu to a menu.
    *
    * @param menu            Menu resource identifier.
    * @param name            Item text to display.
    * @param info            Item info string 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.
    * @noreturn
    * @error                Invalid menu resource.
    */
    native menu_additem(menu, const name[], const info[]="", paccess=0, callback=-1);
    Синтаксис:
    Код:
    menu_additem ( menu, const name[], const info[]="", paccess=0, callback=-1 )
    • menu - Идентификатор меню ( в какое меню добавляем пункт)
    • const name[] - Имя пункта меню ( что будет видеть игрок)
    • const info[]="" - Передача информации от пункта меню к функции обработчику
    • paccess=0 - Флаг доступа к данному пункту меню
    • callback=-1 - Если используется callback, то указывается его глобальный идентификатор или -1 если нет.
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_additem"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
    
        register_plugin(PLUGIN, VERSION, AUTHOR)
    
        mTEST = menu_create("TEST", "mh_TEST")
    
        mcbTEST = menu_makecallback("mcb_TEST")
    
        menu_additem(mTEST, "123 test", "ma_TEST", ADMIN_ALL, mcbTEST)
    Описание:
    Обратите внимание, что идентификаторы меню и callback функции глобальны.
    И в функции добавления пункта меню, указаны эти идентификаторы.
    Большинство меню всегда открываются на первой странице или на той же что и были ( при навигации или со вложенными меню) по этому я не встречал что бы кто то использовал функцию menu_pages, которая получает количество страниц в созданном меню.

    Инфо из newmenus.inc:
    Код:
    /**
    * Returns the number of pages in a menu.
    *
    * @param menu            Menu resource identifier.
    * @return                Number of pages in the menu.
    * @error                Invalid menu resource.
    */
    native menu_pages(menu);
    Синтаксис:
    Код:
    menu_pages(menu)
    • menu - Идентификатор меню
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_pages"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
      
        register_plugin(PLUGIN, VERSION, AUTHOR)
      
        register_clcmd("say /menu","func_menu")
      
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
      
        new szItem[64]
        for (new i=1; i < 10; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_ALL, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
      
        new iPages
        iPages = menu_pages(mTEST)
        server_print("[NewMenus] Number pages:%d",iPages)
    }
    public func_menu(id)
        menu_display(id, mTEST, 0)
      
    public mh_TEST(id, menu, item) {
        item++
        client_print(id,print_chat,"You select %d",item)
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    Количество страниц в статичном меню всегда одинаково, ведь оно статично, по этому мы можем не заходя на сервер,а прямо в консоли вывести информацию о количестве страниц в нашем меню. Что в данном примере и сделано:
    Код:
    new iPages
        iPages = menu_pages(mTEST)
        server_print("[NewMenus] Number pages:%d",iPages)
    Получили в новую переменную количество страниц и вывели в консоль сервера.
    Функция получает количество элементов в созданном меню.

    Инфо из newmenus.inc:
    Код:
    /**
    * Returns the number of items in a menu.
    *
    * @param menu            Menu resource identifier.
    * @return                Number of items in the menu.
    * @error                Invalid menu resource.
    */
    native menu_items(menu);
    Синтаксис:
    Код:
    menu_items ( menu )
    • menu - Идентификатор меню
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_items"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
      
        register_plugin(PLUGIN, VERSION, AUTHOR)
      
        register_clcmd("say /menu","func_menu")
      
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
      
        new szItem[64]
        for (new i=1; i < 10; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_ALL, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
      
        new iItems
        iItems = menu_items(mTEST)
        server_print("[NewMenus] Number items:%d",iItems)
    }
    public func_menu(id)
        menu_display(id, mTEST, 0)
      
    public mh_TEST(id, menu, item) {
        item++
        client_print(id,print_chat,"You select %d",item)
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    Работа функции аналогична функции menu_pages и так же редко используется в плагинах.
    Выделю пример ее работы и закончу на этом:
    Код:
    new iItems
        iItems = menu_items(mTEST)
        server_print("[NewMenus] Number items:%d",iItems)
    И так в прошлых функциях мы составляли заголовок меню, пункты,обработчики и callback функции.
    Настало время показать наше меню игроку. Делается это с помощью функции menu_display.
    Для тех кто не читал предыдущие материалы, напоминаю:прежде чем показать игроку меню, его нужно сначала создать, добавить в него пункты меню и не забыть про функцию обработчик.

    Инфо из newmenu.inc:
    Код:
    /**
    * Displays a menu to one client.  This should never be called from a handler
    * when the item is less than 0 (i.e. calling this from a cancelled menu will
    * result in an error).
    *
    * @param id            Client index.
    * @param menu            Menu resource identifier.
    * @param page            Page to start from (starting from 0).
    * @noreturn
    * @error                Invalid menu resource or client index.
    */
    native menu_display(id, menu, page=0);
    
    Синтаксис:
    Код:
    menu_display ( id, menu, page )
    • id - Индекс игрока
    • menu - Идентификатор меню ( какое меню открыть, мало ли у вас их 10 штук в одном плагине)
    • page - Номер страницы меню, с какой необходимо открыть меню ( ну например не с первой, а сразу с пятой страницы или когда идет переход на следующую страницу меню)
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_display"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
      
        register_plugin(PLUGIN, VERSION, AUTHOR)
      
        register_clcmd("say /menu","func_menu")
    
        /* Menu TEST */
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        menu_additem(mTEST, "Menu test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "Menu test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
        /* Menu End */
    
    
    }
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
        menu_display(id, mTEST, 0)
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
        // Функция вызывается при выборе одного из пунктов меню
    }
    public mcb_TEST(id, menu, item) {
        // Тут код для активации/де активации пунктов меню
    }
    Описание:
    И так для наглядности Все что связано с нашим меню имеет в своих названиях слово TEST.
    Грубо говоря, везде где есть это слово были произведены необходимые изменения в функциях, такие как объявление переменных или указание идентификатора.

    Сама по себе работа функции показа меню очень проста:
    Код:
    menu_display(id, mTEST, 0)
    Показываем игроку с айди таким то, меню такое то, со страницы 0 ( то есть с первой)
    Если было бы в меню 30 пунктов, то можно было указать скажем с третьей страницы.И у игрока меню открылось бы сразу примерно с 23 пункта.

    Функции идущие после строки
    Код:
    /* Menu TEST */
    Это функции обработчики, одна обрабатывает пункты меню до того как они появятся у пользователя, другая после того как пользователь выберет один из пунктов.

    На этом основная часть меню можно сказать сделана, остальные функции расширяют возможности нового меню.
    Но о них позже.
    Откровенно говоря, я сам не смог найти пример использования этой функции, найти пример мне помог DJ_WEST, так как я сам искал ка кэту функцию применять немного не в том месте, но теперь я понял, что эта функция получает id пункта из меню, где надо указать страницу где этот пункт меню и его номер. Использование данной функции скорее пригодится опытным скриптерам, чем новичкам.

    Инфо из newmenu.inc:
    Код:
    /**
    * Given a page on a menu and a keypress on that page, returns the item id selected.
    * If the item is less than 0, a special option was chosen (such as MENU_EXIT).
    *
    * @param menu            Menu resource identifier.
    * @param page            Page on the menu.
    * @param key            Key pressed (from 1 to 10).
    * @return                Item identifier, or <0 for a special selection code.
    * @error                Invalid menu resource.
    */
    native menu_find_id(menu, page, key);
    Синтаксис:
    Код:
    menu_find_id(menu, page, key)
    • menu - id меню
    • page - Страница на которой находится нужный итем
    • key - Номер нужного итема
    Функция вернет id интересующего имтема

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_items"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
      
        register_plugin(PLUGIN, VERSION, AUTHOR)
      
        register_clcmd("say /menu","func_menu")
      
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
      
        new szItem[64]
        for (new i=1; i < 25; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_ALL, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
      
        new iItems
        iItems = menu_items(mTEST)
        server_print("[NewMenus] Number items:%d",iItems)
    }
    public func_menu(id){
    
      
        new menu_item_id = menu_find_id(mTEST,1,2)
    
        menu_item_setname(mTEST,menu_item_id,"New Menu Item Name")
      
        menu_display(id, mTEST, 0)
    }
    public mh_TEST(id, menu, item) {
        item++
        client_print(id,print_chat,"You select %d",item)
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    Для наглядности работы функции, мы получим айди итема и изменим его название.

    Использовать ее можно где угодно и когда угодно, тут же она используется перед открытием меню, для наглядности.
    Вы допустим можете после первого открытия меню, изменить пункт меню на другой.
    Например если у вас есть АВП, то пункт меню изменится на АК и на оброт. Тут уже все зависит от вашей задачи.

    Вернемся к нашим баранам...
    А так у нас есть меню состоящее из более чем двадцати пунктов, а нам допустим необходимо изменить пункт 2 на второй же странице.
    Для этого получаем его айди:
    Код:
    new menu_item_id = menu_find_id(mTEST,1,2)
    Обратите внимание, нумерация страниц начинается с нуля, асамих итемов с 1.

    Дальше дело техники и функции menu_item_setname для изменения названия на первую же пришедшую в голову белиберду.
    --- добавлено 26.03.16 ---

    Источник - amxxmodx.ru

    Конечно я не автор данной статьи ... так как полный 0 в скриптах...
    Пытаюсь создать собственное меню и случайно наткнулся в гугле на эту статью.
    Надеюсь она и вам принесет хоть какую-то ясность что и для чего нужно!
     
    Последнее редактирование: 26.03.16
    SpeedFighter, BaJIepbI4 и Саньок нравится это.
  2. Mistrick Разработчик

    Регистрация:
    13.07.15
    Сообщения:
    161
    Симпатии:
    87
    Пол:
    Мужской
    vesuvius, описание handler'a для menu_create неверное. Расположение параметров другое.
     
    Саньок нравится это.
  3. vesuvius Пользователь

    Регистрация:
    14.07.15
    Сообщения:
    101
    Симпатии:
    8
    Пол:
    Мужской
    Skype:
    victor100993
    После того как мы создали меню, добавили в него нужные пункты, создали функции обратного вызова (callback) и красиво его оформили, необходимо обработать выбор пользователя и получить необходимую информацию, а сделать это можно при помощи функции menu_item_getinfo

    Инфо из newmenus.inc:
    Код:
    /**
    * Retrieves info about a menu item.
    *
    * @param menu            Menu resource identifier.
    * @param item            Item identifier.
    * @param access        Variable to store access value.
    * @param info            Buffer to store item info.
    * @param infolen        Item info buffer length.
    * @param name            Buffer to store item display text.
    * @param namelen        Item name buffer length.
    * @param callback        Callback ID.
    * @return                1 on success, 0 on failure.
    * @error                Invalid menu resource.
    */
    native menu_item_getinfo(menu, item, &access, info[], infolen, name[]="", namelen=0, &callback);
    Синтаксис:
    Код:
    menu_item_getinfo(menu, item, &access, info[], infolen, name[]="", namelen=0, &callback)
    • menu - Указывается айди меню
    • item - Какой пункт выбран
    • &access, - Права доступа к пункту
    • info[] - Инфо константа из функции menu_additem
    • infolen - Длина info
    • name[]="" - Имя пункта меню
    • namelen=0 - Его длина
    • &callback - Айди функции callback
    Функция вернет 1 если все прошло успешно и 0 если нет.

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_item_getinfo"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
        
        register_plugin(PLUGIN, VERSION, AUTHOR)
        
        register_clcmd("say /menu","func_menu")
        
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        
        new szItem[64]
        for (new i=1; i < 25; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_VOTE, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
        
        new iItems
        iItems = menu_items(mTEST)
        server_print("[NewMenus] Number items:%d",iItems)
    }
    public func_menu(id){
    
        menu_display(id, mTEST, 0)
    }
    public mh_TEST(id, menu, item) {
        
        new s_Data[30], s_Name[64], i_Access, i_Callback
        menu_item_getinfo(menu, item, i_Access, s_Data, charsmax(s_Data), s_Name, charsmax(s_Name), i_Callback)
        
        console_print(id,"item[%d]",item)
        console_print(id,"Access[%d]",i_Access)
        console_print(id,"Data[%s]",s_Data)
        console_print(id,"Name[%s]",s_Name)
        console_print(id,"Callback[%d]",i_Callback)
        
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    В привычный пример меню, добавляем последний штрих в виде заключительной функции menu_item_getinfo, с помощью которой получим передаваемую информацию из пункта меню в функцию обработчик.

    И так, по умолчанию в функцию приходят следующие данные:
    (id, menu, item)
    Это Айди игрока, айди меню и выбранный пункт меню.
    Имея эти данные, точнее айд меню и итема, мы можем их передать в функцию menu_item_getinfo, которая в замен нам отдаст информацию о Названии пункта меню и информации из функции menu_additem(mTEST,szItem, "ma_TEST", ADMIN_VOTE, mcbTEST) , а именно "ma_TEST". Эту константу игрок не видит, мы же допустим можем туда писать номер пункта меню, так как нумерация итемов начинается с нуля и можно запутаться.

    Если я не ошибаюсь, то это последняя из функций в newmenus.inc, теперь вы можете создать любое меню.
    Главное что бы была фантазия, а не копировать чужие идеи. Удачи в творчестве.

    Ах да, вот результат из моей консоли, я выбрал 2 пункт меню:
    Код:
    item[1]
    Access[512]
    Data[ma_TEST]
    Name[Item 2]
    Callback[373]
    Обратили внимание что итем 1 ,а я выбрал 2 пункт, зато имя пункта меню верное.
    Функция будет полезна тем, кто задумывается об оптимизации плагина.
    Представьте себе следующие: Вы создаете меню во время инициализации плагина, то есть это происходит 1 раз и изменить меню по идее уже ни как, по этому что бы его менять, его создание будет вынесено в отдельную функцию и оно будет создаваться при каждом вызове, что не является оптимальным.
    Функция menu_item_setname может изменить пункт в меню, которое уже было создано.
    Обращаю внимание, что данная функция меняет только отображаемое название, остальные свойства меняют другие функции, но оних отдельно поговорим.

    Инфо из newmenu.inc:
    Код:
    /**
    * Sets an item's display text.
    *
    * @param menu            Menu resource identifier.
    * @param item            Item identifier.
    * @param name            New item display text.
    * @return                1 on success, 0 on failure.
    * @error                Invalid menu resource.
    */
    native menu_item_setname(menu, item, const name[]);
    Синтаксис:
    Код:
    menu_item_setname ( menu, item, name[] )
    • menu - Идентификатор меню
    • item - Пункт меню
    • name[] - Новый текст для пункта меню
    Функция возвращает 1, если пункт меню был изменен, 0 если нет.

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_item_setname"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
        
        register_plugin(PLUGIN, VERSION, AUTHOR)
        
        register_clcmd("say /menu","func_menu")
        register_clcmd("say /SetOptions","f_SetOptions")
        
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        
        new szItem[64]
        for (new i=1; i < 10; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_ALL, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
    }
    public func_menu(id)
        menu_display(id, mTEST, 0)
    
    public f_SetOptions()
        menu_item_setname(mTEST,0,"New name to item")
        
    public mh_TEST(id, menu, item) {
        item++
        client_print(id,print_chat,"You select %d",item)
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    В данном примере я немного причесал код, так смотрится красивее, да и правильнее.
    Для того что бы оценить работу примера, зайдите на сервер и попробуйте открыть меню say /menu,
    вы увидите ровный столбик имен пунктов меню. Закройте меню и выполните команду say /SetOptions, которая вызовет функцию:
    Код:
    public f_SetOptions()
        menu_item_setname(mTEST,0,"New name to item")
    Внутри которой происходит изменение названия пункта меню.
    Это изменение можно производить сколько угодно раз и в любое время.
    Напоминаю. что функция изменяет только название пункта меню, остальные свойства изменяют функции menu_item_set***.
    Функция актуально в основном только в тех случаях, когда меню создается статично.
    Она позволяет изменить исполняемую callback функцию для конкретного меню.

    Инфо из newmenus.inc:
    Код:
    /**
    * Sets an item's callback.
    *
    * @param menu            Menu resource identifier.
    * @param item            Item identifier.
    * @param callback        New callback from menu_makecallback(), or -1 to clear.
    * @return                1 on success, 0 on failure.
    * @error                Invalid menu resource.
    */
    native menu_item_setcall(menu, item, callback=-1);
    Синтаксис:
    Код:
    menu_item_setcall ( menu, item, callback=-1 )
    • menu - Идентификатор меню
    • item - Пункт в меню
    • callback=-1 - Функция callback

    Тип функции:
    Native

    Пример:
    Код:
    //None
    Описание:
    Работа функции аналогична функции menu_item_setname, по этому не буду повторяться и писать одинаковые коды.
    Смотрите пример там.
    Меню можно создавать двумя разными способами:
    • Статичное меню - создается один раз.
    • Динамичное меню - создается многократно, обычно при каждом вызове.
    У каждого из них свои плюсы и минусы, но у второго есть еще необходимость, после того как оно отработало его удалить, иначе у вас будет происходить утечка памяти и сервер в итоге просто зависнет от нехватки оперативной памяти.
    Если же удалить статичное меню, то при попытки открыть его - сервер выдаст ошибку, о неправильном id меню.

    Инфо из newmenus.inc:
    Код:
    /**
    * Destroys a menu.  Player menus will be cancelled (although may still linger
    * on the HUD), and future attempts to access the menu resource will result in
    * an error.
    *
    * This must be called if you create menus dynamically, otherwise you will
    * leak memory.  For normal dynamic menus, you will destroy the menu in the
    * handler function (remembering to handle the case of a menu being cancelled,
    * it must still be destroyed).
    *
    * @param menu            Menu resource identifier.
    * @noreturn
    * @error                Invalid menu resource.
    */
    native menu_destroy(menu);
    Синтаксис:
    Код:
    menu_destroy ( menu )
    • menu - Идентификатор уничтожаемого меню.

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_destroy"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
        
        register_plugin(PLUGIN, VERSION, AUTHOR)
        
        register_clcmd("say /menu","func_menu")
        register_clcmd("say /del_menu","f_menu_destroy")
        
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        
        new szItem[64]
        for (new i=1; i < 10; i++){
            format(szItem,63,"Item %i",i)
            menu_additem(mTEST,szItem, "ma_TEST", ADMIN_ALL, mcbTEST)
        }
        menu_setprop(mTEST,MPROP_EXIT, 1)
    }
    public func_menu(id)
        menu_display(id, mTEST, 0)
    
    public f_menu_destroy(id)
        menu_destroy(mTEST)
        
    public mh_TEST(id, menu, item) {
        item++
        client_print(id,print_chat,"You select %d",item)
    }
    public mcb_TEST(id, menu, item){
        //callback
    }
    Описание:
    При загрузке плагина, будет создано меню и его можно будет взывать сколько угодно раз.
    Но попробуй потом ввести команду say /del_menu.
    Она вызовет функцию которая уничтожит созданное в самом начале меню и сервер в консоль выдаст ошибку:
    Код:
    L 12/18/2011 - 22:51:21: Invalid menu id 0(1)
    L 12/18/2011 - 22:51:21: [AMXX] Displaying debug trace (plugin "AMXXMODX-for-site.amxx")
    L 12/18/2011 - 22:51:21: [AMXX] Run time error 10: native error (native "menu_display")
    L 12/18/2011 - 22:51:21: [AMXX]    [0] AMXXMODX-for-site.sma::func_menu (line 31)
    Так как это меню создавалось один раз при старте плагина. То есть оно статично.

    Если же вы создаете меню динамично, то есть функция menu_create вызывается многократно, то после каждого создания - необходимо его уничтожение. Иначе будет утечка памяти. что очень плохо для сервера.
     
    Саньок нравится это.
  4. vesuvius Пользователь

    Регистрация:
    14.07.15
    Сообщения:
    101
    Симпатии:
    8
    Пол:
    Мужской
    Skype:
    victor100993
    Если вам необходимо проверить видит игрок меню или нет, то эта функция для вас.
    Она работает как со старой системой меню так и новой. Думаю что полезна данная функция будет в меню с банами и подобными вещами для избыточной проверки процесса и исключения случайных банов. А может кто то придумает более интересное применение функции player_menu_info

    Инфо из newmenus.inc:
    Код:
    /**
     * Returns information about a menu (if any) the client is currently viewing.
     *
     * If newmenu is valid, then the menu will refer to the menuid associated with 
     * the title.  If newmenu is not valid, and the menu is valid, then the player 
     * is viewing a menu displayed with show_menu().
     *
     * Both may be invalid if the player is not viewing a menu.
     *
     * @param id            Client index.
     * @param menu            Variable to store old menu id.  If none, then <1 will be 
     *                        stored.
     * @param newmenu        Variable to store new menu id.  If none, then -1 will be 
     *                        stored.
     * @param menupage        Variable to store current page of the new menu, if any.
     * @return                1 if the player is viewing a menu, 0 otherwise.
     * @error                Invalid client.
     */
    native player_menu_info(id, &menu, &newmenu, &menupage=0);
    Синтаксис:
    Код:
    player_menu_info(id, &menu, &newmenu, &menupage=0)
    • id - Идентификатор игрока, для кого выполняется функция
    • &menu - Переменная для сохранения идентификатора меню(старого типа) ( что бы в дальнейшем работало)
    • &newmenu - Переменная для сохранения идентификатора меню(нового типа) ( что бы в дальнейшем работало)
    • &menupage=0 - Если указать, то будет проверяться какая именно страница или любая.
    Тип функции:
    Native

    Пример:
    [/CODE]/* Plugin generated by AMXX-Studio */

    #include <amxmodx>
    #include <amxmisc>

    #define PLUGIN "[newmenu.inc] player_menu_info"
    #define VERSION "1.0"
    #define AUTHOR "Admin"

    new mTEST // Menu
    new mcbTEST // Menu Callback

    public plugin_init() {

    register_plugin(PLUGIN, VERSION, AUTHOR)

    register_clcmd("say /menu","func_menu")
    register_clcmd("say /tmenu","f_player_see_menu")

    /* Menu TEST */
    mTEST = menu_create("TEST", "mh_TEST")
    mcbTEST = menu_makecallback("mcb_TEST")
    menu_additem(mTEST, "M test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 3", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 4", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 5", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 6", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 7", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 8", "ma_TEST", ADMIN_ALL, mcbTEST)
    menu_additem(mTEST, "M test 9", "ma_TEST", ADMIN_ALL, mcbTEST)

    menu_setprop(mTEST,MPROP_EXIT, 1)

    /* Menu End */

    }
    public f_player_see_menu(id){
    new menu,newmenu
    new inmenu = player_menu_info(id,menu, newmenu)
    client_print(id,print_chat,"You see menu ? - %s",inmenu ? "Yes" : "No")

    }
    public func_menu(id){
    //Функция показывает меню,
    //которое было сформировано еще в plugin_init
    menu_display(id, mTEST, 0)
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
    // Функция вызывается при выборе одного из пунктов меню
    item++
    client_print(id,print_chat,"You select %d",item)

    }
    public mcb_TEST(id, menu, item) {
    // Тут код для активации/де активации пунктов меню
    }
    [/CODE]
    Описание:
    Выполните команду
    say /tmenu и вы получите вопрос с ответом - видите вы меню или нет.
    Затем откройте меню
    say /menu и повторите предыдущую команду и вы увидите отличие в ответе.

    Пример использования функции вы можете посмотреть в плагине restmenu.
    Учитывая что функция не пользуется популярностью, не вижу смысла на долго на ней останавливаться.
    Если будут какие то вопросы, обсудим.А пока что на этом все.
    Продолжаем знакомиться с новой системой меню. Иногда необходимо сделать пропуск в меню, может для выделения одно из пунктов, а может для удобства конкретного меню. Ведь не все меню делаются для выбора вип возможностей, бывают и более сложны и нужные меню.
    Для того что бы сделать отступ в меню есть функция menu_addblank, которая может делать два типа отступа.

    Инфо из newmenu.inc:
    Код:
    /**
     * Adds a blank line to a menu.
     *
     * @param menu            Menu resource identifier.
     * @param slot            1 (default) if the line should shift the numbering down.
     *                         0 if the line should be a visual shift only.
     * @noreturn
     * @error                Invalid menu resource.
     */
    native menu_addblank(menu, slot=1);
    Синтаксис:
    Код:
    menu_addblank ( menu, slot=1 )
    • menu - Идентификатор меню
    • slot=1 - Если 1 то пустая строка занимает порядковый номер и следующий пункт меню будет больше на количество пропусков.
      Если 0, то пропуск не будет занимать порядковые номера.
      На рисунке пример, как первый пропуск сбивает нумерацию на 1, а второй нет, но нумерация уже была сбита ранее.
    [attachment=39106:1323772904_menu.jpg]
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    #include <amxmodx>
    #include <amxmisc>
    #define PLUGIN "[newmenu.inc] menu_addblank"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    new mTEST // Menu
    new mcbTEST // Menu Callback
    public plugin_init() {
         
        register_plugin(PLUGIN, VERSION, AUTHOR)
         
        register_clcmd("say /menu","func_menu")
        /* Menu TEST */
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        menu_additem(mTEST, "M test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_addblank(mTEST, 1)
        menu_additem(mTEST, "M test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_addblank(mTEST, 0)
        menu_additem(mTEST, "M test 3", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 4", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 5", "ma_TEST", ADMIN_ALL, mcbTEST)
        /* Menu End */
    }
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
        menu_display(id, mTEST, 0)
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
        // Функция вызывается при выборе одного из пунктов меню
    }
    public mcb_TEST(id, menu, item) {
        // Тут код для активации/де активации пунктов меню
    }
    Описание:
    В описании синтаксиса уже показан пример и объяснено что и как делает данная функция, хочу только обратить ваше внимание на следующие:
    пустые строки могут быть добавлены Только после элементов меню, то есть нельзя сделать отступ перед первым элементом в меню.
    Иногда есть необходимость сделать небольшое объяснение к пункту меню, что бы это пояснение выглядело красиво используйте функцию menu_addtext, которая добавляет текст между пунктами меню.

    Инфо из newmenu.inc:
    Код:
    /**
     * Adds a text line to a menu.  Only available in amxmodx 1.8.1 and above.
     *
     * @param menu            Menu resource identifier.
     * @param text            Text to add.
     * @param slot            1 (default) if the line should shift the numbering down.
     *                         0 if the line should be a visual shift only.
     * @noreturn
     * @error                Invalid menu resource.
     */
    native menu_addtext(menu, const text[], slot=1);
    
    Синтаксис:
    Код:
    menu_addtext(menu, const text[], slot=1);
    • menu - Идентификатор меню
    • const text[] - Массив с добавляемым текстом или текст заключенный в двойные кавычки
    • slot=1 - Занимает ли текст слот меню или нет.

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    #include <amxmodx>
    #include <amxmisc>
    #define PLUGIN "[newmenu.inc] menu_addtext"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    new mTEST // Menu
    new mcbTEST // Menu Callback
    public plugin_init() {
         
        register_plugin(PLUGIN, VERSION, AUTHOR)
         
        register_clcmd("say /menu","func_menu")
        /* Menu TEST */
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        menu_additem(mTEST, "M test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_addblank(mTEST, 0)
        menu_additem(mTEST, "M test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_addtext(mTEST,"\rMy \wMega \dSuperPuper \yText ",0)
        menu_additem(mTEST, "M test 3", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 4", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 5", "ma_TEST", ADMIN_ALL, mcbTEST)
        /* Menu End */
    }
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
        menu_display(id, mTEST, 0)
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
        // Функция вызывается при выборе одного из пунктов меню
    }
    public mcb_TEST(id, menu, item) {
        // Тут код для активации/де активации пунктов меню
    }
    Описание:
    Как видно на картинке, результатом работы данного примера является меню и между пунктами 2 и 3 добавлена строка с текстом.А между первыми вторым просто пустое место.
    [attachment=39107:13237751...enu_text.jpg]
    Некоторые скриптеры, не зная всех функций пишут "костыли" - просто перенос строки пункта меню,но я считаю, что использование специальных функций это правильный метод и более красивый код.
    У меню есть несколько важных свойств, например как название пунктов для навигации по страницам или пункта выхода выхода, количество пунктов на странице и тому подобное, все они задаются в одной функции menu_setprop

    Инфо из newmenus.inc:
    Код:
    /**
     * Sets a menu property.
     *
     * @param menu            Menu resource identifier.
     * @param prop            MPROP_ constant.
     * @param ...            Property parameters.
     * @return                1 on success, 0 on failure.
     * @error                Invalid menu resource or property.
     */
    native menu_setprop(menu, prop, ...);
    Синтаксис:
    Код:
    menu_setprop ( menu, prop, ... )
    • menu - Идентификатор меню
    • prop - Константа свойства
    • Код:
      // Число пунктов на странице. 0 - без нумерации страниц.
      #define MPROP_PERPAGE 1
      // Название кнопки "Назад". Параметр - строка.
      #define MPROP_BACKNAME    2
      // Название кнопки "Дальше". Параметр - строка.
      #define MPROP_NEXTNAME    3    
      // Название кнопки "Выход". Параметр - строка.
      #define MPROP_EXITNAME 4  
      // Текст заголовка меню. Параметр - строка.    
      #define MPROP_TITLE 5          
      // Возможность выхода. Параметр - число, смотрите константы MEXIT.
      #define MPROP_EXIT 6          
      // Цвет чисел. Параметр - строка. (По умолчанию "\r")
      #define MPROP_NUMBER_COLOR 10  
      
    • ... - Значение для свойства:

      [*]Для MPROP_EXIT
      [*]
      Код:
      #define MEXIT_ALL 1           // В меню будет кнопка выхода (по умолчанию)
      #define MEXIT_NEVER -1         // В меню не будет кнопки выхода
      [*]Для остальных см. выше.​
    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_setprop"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
         
        register_plugin(PLUGIN, VERSION, AUTHOR)
         
        register_clcmd("say /menu","func_menu")
         
        /* Menu TEST */
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        menu_additem(mTEST, "M test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 3", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 4", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 5", "ma_TEST", ADMIN_ALL, mcbTEST)
         
        menu_setprop(mTEST,MEXIT_ALL, 0)
         
        /* Menu End */
         
         
         
    }
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
        menu_display(id, mTEST, 0)
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
        // Функция вызывается при выборе одного из пунктов меню
    }
    public mcb_TEST(id, menu, item) {
        // Тут код для активации/де активации пунктов меню
    }
    Описание:
    В данном примере я не буду рассматривать все свойства, они описаны в синтаксисе, я приведу лишь один пример, как убрать пункт "выход" из меню.
    Что бы не пояснять весь код, повторю функцию:
    Код:
    menu_setprop(mTEST,MEXIT_ALL, 0)
    mTEST это идентификатор созданного меню, далее идет свойство описанное в синтаксисе и третий аргумент указывает что это свойство будет выключено.
    На картинке результат работы примера:
    [attachment=39108:13240413..._no_exit.jpg]
    Представьте себе ситуацию, в плагине магазина игрок открыл меню пока живой, а пункт меню выберет после того как умрет - что будет? понятное дело что в хорошем плагине это будет предусмотрено, но все же, есть функция menu_cancel, которая как бы выберет за игрока пункт выход, при этом само меню не будет закрыто у игрока. На само деле результат работы функции можно выполнить и дургими способами, вернее ими все и пользуются, так что, выбор каким методом пользоваться остается за вами.

    Инфо из newmenus.inc:
    Код:
    /**
     * Cancels a player's menu, effectively forcing the player to select MENU_EXIT.
     * The menu will still exist on their screen but any results are invalidated,
     * and the callback is invoked.
     *
     * @param player        Client index.
     * @noreturn
     * @error                Invalid client index.
     */
    native menu_cancel(player);
    Синтаксис:
    Код:
    menu_cancel ( player )
    • player - id игрока кому надо отменить меню.

    Тип функции:
    Native

    Пример:
    Код:
    /* Plugin generated by AMXX-Studio */
    
    #include <amxmodx>
    #include <amxmisc>
    
    #define PLUGIN "[newmenu.inc] menu_cancel"
    #define VERSION "1.0"
    #define AUTHOR "Admin"
    
    new mTEST // Menu
    new mcbTEST // Menu Callback
    
    public plugin_init() {
         
        register_plugin(PLUGIN, VERSION, AUTHOR)
         
        register_clcmd("say /menu","func_menu")
         
        /* Menu TEST */
        mTEST = menu_create("TEST", "mh_TEST")
        mcbTEST = menu_makecallback("mcb_TEST")
        menu_additem(mTEST, "M test 1", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 2", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 3", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 4", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 5", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 6", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 7", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 8", "ma_TEST", ADMIN_ALL, mcbTEST)
        menu_additem(mTEST, "M test 9", "ma_TEST", ADMIN_ALL, mcbTEST)
         
        menu_setprop(mTEST,MPROP_EXIT, 1)
         
        /* Menu End */
         
    }
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
         
        menu_display(id, mTEST, 0)
    
        menu_cancel(id)
         
    }
    /* Menu TEST */
    public mh_TEST(id, menu, item) {
        // Функция вызывается при выборе одного из пунктов меню
        item++
        client_print(id,print_chat,"You select %d",item)
         
    }
    public mcb_TEST(id, menu, item) {
        // Тут код для активации/де активации пунктов меню
    }
    Описание:
    Результат работы примера:
    [attachment=39109:13242167...u_cancel.jpg]
    Обратите внимание, на то, что уже перед тем как в чат вывелась команда, в меню уже отправлена команда на выход You select -2:
    Код:
    public func_menu(id){
        //Функция показывает меню,
        //которое было сформировано еще в plugin_init
         
        menu_display(id, mTEST, 0)
    
        menu_cancel(id)
    }
    Так как функция отмены меню идет сразу же за его показом.
    И если вы выберите любой из пунктов меню, то уже не произойдет ничего, так как меню находится только у вас на экране и ни каких функций оно уже не исполнит.
    Написать функционально меню это только пол дела, его необходимо еще и красиво оформить, при необходимости перевести на другой язык или изменить цвет какому то пункту или части строки. Некрасивое меню может испортить даже очень интересную задумку, но при этом злоупотреблять цветами тоже не стоит, все таки это меню, а не разукрашенный всеми цветами радуги клоун.

    Далее будут описаны все свойства меню, доступные вам для его форматирования. Примеры приводить для каждого не буду, если вы разбирались с функциями новой системы меню Amx, то вопросов у вас не должно возникнуть.
    Свойства меню

    Код:
    #define MEXIT_ALL 1           // В меню будет кнопка выхода (по умолчанию)
    #define MEXIT_NEVER -1         // В меню не будет кнопки выхода
    #define MPROP_PERPAGE 1        // Число пунктов на странице. 0 - без нумерации страниц.
    #define MPROP_BACKNAME    2      // Название кнопки "Назад". Параметр - строка.
    #define MPROP_NEXTNAME    3      // Название кнопки "Дальше". Параметр - строка.
    #define MPROP_EXITNAME 4       // Название кнопки "Выход". Параметр - строка.
    #define MPROP_TITLE 5          // Текст заголовка меню. Параметр - строка.
    #define MPROP_EXIT 6           // Возможность выхода из меню. Параметр - число, смотрите константы MEXIT.
    #define MPROP_NUMBER_COLOR 10  // Цвет чисел. Параметр - строка. (По умолчанию "\r")
    Оформление

    Цвет текста
    • \w - белый цвет
    • \r - красный цвет
    • \y - желтый цвет
    • \d - серый цвет (неактивный)
    Форматирование

    • ^n - новая строка( перенос строки )
    • ^t - отступ ( пробел )
    • \R - выравнивает текст по правому краю. (Proo.Noob)
    Не бойтесь экспериментировать, создайте тестовый плагин, и пробуйте на нем изменять, подставлять, удалять и добавлять функции. Это поможет вам быстрее во всем разобраться.
    Еще одна маленькая подсказка:
    Не забывайте о том, что игроку все равно дважды или трижды было пересоздано меню, он их не отличит.Зато вы этим можете воспользоваться ( например сделать таймер в меню )