[Решено] Проблема с Menu

Nico Yazawa

Бывший MrChester =(
Сообщения
326
Реакции
303
И снова приветствую всех обитателей hlmod.ru. Сегодня я столкнулся проблемой, когда писал свою админ систему. Моей идеей и уникальностью в этом плагине, заключается система уровней и репутации. Когда я начинаю работать с Menu, то происходят странные вещи: Главное меню спокойно отображается, а вот если выбрать в ней пункт, который вызовет еще одно меню, то оно просто не появится. Прикладываю часть кода, список плагинов и версию SourceMod'а.

PHP:
public Action Settings(int iClient, int args)
{
   if(Admin_Level[iClient] < 1)
   {
       PrintToChat(iClient, "Отказано в доступе!");
       return;
   }   
   
   
   Menu hMenu_Settings = new Menu(MenuHandler_Settings, MenuAction_Cancel|MenuAction_Select|MenuAction_Display|MenuAction_DisplayItem);
   char temp[128];
   hMenu_Settings.SetTitle("Админ панель\nВаш уровень: %i", Admin_Level[iClient]);
   hMenu_Settings.AddItem("Настройка спавна", "Убить игрока", Admin_Level[iClient] > 1 ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
   Format(temp, sizeof(temp), "АвтоРеспавн [%s]", isRespawn ? "Вкл" : "Выкл")
   hMenu_Settings.AddItem("Настройка спавна", temp, Admin_Level[iClient] > 3 ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
   hMenu_Settings.Display(iClient, 0);
}

public int MenuHandler_Settings(Menu hMenu, MenuAction action, int iClient, int iItem)
{
   switch(action)
   {
       case MenuAction_Select:
       {
           if(iItem == 0)
           {
               PrintToChatAll("Тест 1 успешный");
               Menu_AllPlayers_Kill(iClient);
               PrintToChatAll("Тест 3 успешный");
               hMenu.Cancel();
           }
           else if(iItem == 1)
           {
               ChangeSpawn(iClient);
               hMenu.Cancel();
               Settings(iClient, 0);
           }
           
       }
   }
}

public void Menu_AllPlayers_Kill(int iClient)
{
   Menu hMenu = new Menu(MenuHandler_AllPlayers_Kill, MenuAction_Cancel|MenuAction_Select|MenuAction_Display|MenuAction_DisplayItem);
   hMenu.SetTitle("Выберите игрока:");
   for(int i = 1; i <= 64; i++)
   {
       if(IsPlayerAlive(i) && Admin_Level[iClient] > Admin_Level[i])
       {
           char temp[128];
           GetClientName(i, temp, sizeof(temp));
           hMenu.AddItem("Клиент", temp);
       }
   }
   hMenu.Display(iClient, 0);
   PrintToChatAll("Тест 2 успешный");
}

public int MenuHandler_AllPlayers_Kill(Menu hMenu, MenuAction action, int iClient, int iItem)
{
   if(action == MenuAction_Select)
   {
       ForcePlayerSuicide(iItem - 1);
       PrintToChatAll("Администратор: %N убил игрока: %N", iClient, iItem - 1);
       hMenu.Cancel();
   }
   
}

01 "Admin File Reader" (1.9.0.6273) by AlliedModders LLC
02 "Admin Help" (1.9.0.6273) by AlliedModders LLC
03 "Admin Menu" (1.9.0.6273) by AlliedModders LLC
04 "[InkCore] AimMod" by inklesspen
05 "Anti-Flood" (1.9.0.6273) by AlliedModders LLC
06 "Basic Ban Commands" (1.9.0.6273) by AlliedModders LLC
07 "Basic Chat" (1.9.0.6273) by AlliedModders LLC
08 "Basic Comm Control" (1.9.0.6273) by AlliedModders LLC
09 "Basic Commands" (1.9.0.6273) by AlliedModders LLC
10 "Basic Info Triggers" (1.9.0.6273) by AlliedModders LLC
11 "Basic Votes" (1.9.0.6273) by AlliedModders LLC
12 "Client Preferences" (1.9.0.6273) by AlliedModders LLC
13 "Fun Commands" (1.9.0.6273) by AlliedModders LLC
14 "Fun Votes" (1.9.0.6273) by AlliedModders LLC
15 "Nextmap" (1.9.0.6273) by AlliedModders LLC
16 "Player Commands" (1.9.0.6273) by AlliedModders LLC
17 "Reserved Slots" (1.9.0.6273) by AlliedModders LLC
18 "respawn_players.smx"
19 "Sound Commands" (1.9.0.6273) by AlliedModders LLC

SourceMod Version: 1.9.0.6273
SourcePawn Engine: 1.9.0.6273, jit-x86 (build 1.9.0.6273)
SourcePawn API: v1 = 4, v2 = 12
Compiled on: Jan 1 2019 12:57:25
Built from: Fix BfRead.BytesLeft not being able to be optional. (fixes #945). · alliedmodders/sourcemod@95027e0
Build ID: 6273:95027e0a
SourceMod: Half-Life 2 Scripting
 

Someone

Участник
Сообщения
1,933
Реакции
1,653
уникальностью в этом плагине, заключается система уровней и репутации.
Не уникально еще со времен CSS.

Резоннее вместо этого добавлять в switch еще одно действие - MenuAction_End. Если конечно планируешь еще и другие действия добавлять, а иначе после всех проверок можно добавить, например после switch. У тебя там при инициализации меню добавляется не только MenuAction_Select, если что.

Admin_Level[iClient] > Admin_Level[i]
И чем это интересно наличие настройки имунитета не угодило ?
Уже не помню точно, но вроде бы, если меню пустое (юез пунктов), то оно не отобразится. Возможно эта проверка не проходит и не дает создаваться пунктам.
Логичнее создать отдельную переменную, которая будет считать кол-во добавленых в меню игроков и в случае, если ни один игрок не будет добавлен - добавлять некликабельный пункт, который будет уведомлять клиента о том, что нет доступных для выбора игроков.

for(int i = 1; i <= 64; i++)
Вместо 64 поставь MaxClients. (MaxClients == кол-во слотов (в CS:GO точно)).

Не надо ничего объявлять внутри цикла. Лучше снаружи. В противном случае, у тебя будет строка по несколько раз инициализироваться, когда может 1 раз, а это снижает производительность.
Да и на длину имени есть уже число - [MAX_NAME_LENGHT] (32).

А вместо 0 можно ставить MENU_TIME_FOREVER. По мне так с ним читабельнне смотрится.

Оффтоп
 
Последнее редактирование:

mika

Участник
Сообщения
1,069
Реакции
641
Оффтоп
 

rejchev

менеджер клоунов
Сообщения
1,669
Реакции
1,291
PHP:
public Action Settings(int iClient, int args)
{
   if(Admin_Level[iClient] < 1)
   {
       PrintToChat(iClient, "Отказано в доступе!");
       return;
   }
 
 
   Menu hMenu_Settings = new Menu(MenuHandler_Settings, MenuAction_Cancel|MenuAction_Select|MenuAction_Display|MenuAction_DisplayItem);
   char temp[128];
   hMenu_Settings.SetTitle("Админ панель\nВаш уровень: %i", Admin_Level[iClient]);
   hMenu_Settings.AddItem("Настройка спавна", "Убить игрока", Admin_Level[iClient] > 1 ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
   Format(temp, sizeof(temp), "АвтоРеспавн [%s]", isRespawn ? "Вкл" : "Выкл")
   hMenu_Settings.AddItem("Настройка спавна", temp, Admin_Level[iClient] > 3 ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
   hMenu_Settings.Display(iClient, 0);
}

Нужно возвращать
C-подобный:
return Plugin_Handled;

Ну а для любителей "поклепать" функции с вызовами Menu, можно использовать следующее:
Это набросок.
PHP:
enum MENU_LIST
{
    MAIN_MENU = 0,
    NEXT_MENU,
    ...
}

public Action CMD_Test(int iClient, int iArgs)
{
    SendMenu(iClient, MAIN_MENU).Display(iClient, MENU_TIME_FOREVER);
    return Plugin_Handled;
}

Menu SendMenu(int iClient, MENU_LIST mList)
{
    Menu hMenu;

    switch(MENU_LIST)
    {
        case MAIN_MENU:
        {
            hMenu = new Menu(MenuMainCB);
            // any settings
        }

        case NEXT_MENU:
        {
            //...
        }

        case ...:
        {
            //...
        }
    }

    return hMenu;
}

public int MenuMainCB(Menu hMenu, MenuAction action, int param1, int param2){
    // CB
}
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,980
Если в меню только 2 пункта, то проще вместо
PHP:
       case MenuAction_Select:
       {
           if(iItem == 0)
           ...
           else if(iItem == 1)
сделать всего 1 проверку
PHP:
       case MenuAction_Select:
       {
           if(!iItem)
           ...
           else
Если пунктов больше 2, то целесообразней использовать switch() вместо if() ... else
PHP:
hMenu.Cancel();
не понял какой в этом смысл, как я понимаю, если убрать эту строку, то у тебя всё равно ничего не изменится
если выбрать в ней пункт, который вызовет еще одно меню, то оно просто не появится.
если в меню нет ни одного пункта, то оно и не появляется, как тебе уже выше написали
В остальном поддерживаю Someone
 
Сверху Снизу