| 
 
 
	
		
		
			| Создание Меню |  |  |  | 
| _wS_ | Дата: Суббота, 14.01.2012, 05:57:27 | Сообщение # 1 |  |   | Ниже будут приведены примеры кода для создания разных типов меню.Лучше не копируйте код, а скачайте архив в прикреплениях, чтобы вручную отступы не поправлять.
 
 Panel (панель)
 
 
 Код public OnPluginStart() {RegConsoleCmd("test", test);
 }
 
 public Action:test(client, args) {
 if (client > 0 && args < 1) {
 ShowMyPanel(client);
 }
 return Plugin_Handled;
 }
 
 ShowMyPanel(client)
 {
 new Handle:panel = CreatePanel();
 SetPanelTitle(panel, "Животные:\n ");
 DrawPanelItem(panel, "Кот");
 DrawPanelText(panel, "Носорог");
 DrawPanelItem(panel, "Собак");
 DrawPanelItem(panel, "Хамелеон");
 DrawPanelItem(panel, "Тигр \n ");
 DrawPanelItem(panel, "Выход");
 SendPanelToClient(panel, client, Select_Panel, 0);
 CloseHandle(panel);
 ClientCommand(client, "playgamesound items/nvg_off.wav");
 }
 
 public Select_Panel(Handle:panel, MenuAction:action, client, option) {
 if (action == MenuAction_Select) {
 PrintToChat(client, "Номер выбранной опции: %d", option);
 if (option < 5) {
 ShowMyPanel(client);
 }
 }
 }
Запустите этот плагин, войдите в игру и введите в консоль test. Откроется такое меню:
 
 
  
 Выбрав опцию, вы увидите её номер в чате, и если она меньше 5 (5 это выход), то меню снова откроется.
 Опцию 'Носорог' нельзя выбрать и она без номера, это просто текст.
 Максимум опций (которые можно выбрать): 10
 
 Если в меню хранятся постоянные одинаковые данные, то нет смысла его постоянно пересоздавать, просто создайте глобальную переменную и сохраните в ней Handle вашего меню. И после отправки менюшки игроку, если оно вам еще надо, не делайте CloseHandle(), ибо это убивает меню.
 
 Handle:CreatePanel(Handle:hStyle=INVALID_HANDLE); - создаёт панель и возвращает её Handle.
 Если вернёт INVALID_HANDLE, значит произошла ошибка.
 
 
 Код hStyle (стиль меню):
 MenuStyle_Default = 0 // The "default" menu style for the mod
 MenuStyle_Valve = 1 // The Valve provided menu style (Used on HL2DM)
 MenuStyle_Radio = 2 // The simpler menu style commonly used on CS:S
Handle:SetPanelTitle(Handle:panel, const String:text[], bool:onlyIfEmpty=false);
 Устанавливает название меню. Если onlyIfEmpty true, то название установится, только если оно ещё не установлено.
 
 DrawPanelItem(Handle:panel, const String:text[], style=ITEMDRAW_DEFAULT); - добавляет опцию в меню
 
 
 Код Тип опции (style):ITEMDRAW_DEFAULT - используется по умолчанию
 ITEMDRAW_DISABLED - опцию нельзя выбрать + текст становится белым)
 ITEMDRAW_RAWLINE - Item should be a raw line, without a slot
 ITEMDRAW_NOTEXT - No text should be drawn
 ITEMDRAW_SPACER - Item should be drawn as a spacer, if possible
 ITEMDRAW_IGNORE - Item should be completely ignored (rawline + notext)
 ITEMDRAW_CONTROL - Item is control text (back/next/exit)
bool:DrawPanelText(Handle:panel, const String:text[]);
 Это не считается опцией, которую можно выбрать, это добавляет обычный текст
 
 bool:SendPanelToClient(Handle:panel, client, <функция>, time);
 Отправляет (показывает) игроку меню на time секунд (0 = всегда). Функция выглядит так:
 
 
 Код public xzFuncName(Handle:panel, MenuAction:action, param1, param2){
 // если надо ловить момент выбора опций:
 if (action == MenuAction_Select)
 {
 // ваш код
 }
 }
Внутри функции вы можете лишь проверять, какую игрок выбрал опцию (номер), и уже исходя из этого что-то делать.
 
 MenuAction:
 
 
 Код MenuAction_Select - игрок выбрал опцию (param1 = client, param2 = номер опции)MenuAction_Cancel - игрок закрыл меню (param1 = client, param2 = reason)
 MenuAction_End - меню стало неактивным (param1 = reason)
 и др.
MenuAction_Cancel reason (причина закрытия меню)
 
 
 Код MenuCancel_Disconnected - игрок покинул серверMenuCancel_Interrupted - меню закрылось, так как открылось новое
 MenuCancel_Exit - игрок нажал "выход"
 MenuCancel_NoDisplay - меню не может быть отображено клиенту
 MenuCancel_Timeout - время отображения меню истекло
 MenuCancel_ExitBack - клиент выбрал "exit back (выйти обратно)" на одной из страниц
MenuAction_End reason
 
 
 Код MenuEnd_Selected - выбрана опция в менюMenuEnd_VotingDone - голосование было завершено
 MenuEnd_VotingCancelled - голосование отменено
 MenuEnd_Cancelled - меню было отменено (param2 = reason)
 MenuEnd_Exit - игрок нажал "exit (выход)"
 MenuEnd_ExitBack - нажал "back"
Handle:GetPanelStyle(Handle:panel); - возвращает Handle стиля панели
 
 Menu (меню)
 
 Это меню может содержать множество опций, а не 10, как в панели. Если опций больше 7, то меню само будет разбиваться на страницы и вы сможете листать их дополнительными кнопками внизу "вперед" и "назад". И еще удобно то, что можно узнать не только позицию выбранной опции, но и значение переменной, которое в ней хранится.
 
 Протестируйте такой код:
 
 
 Код public OnPluginStart() {RegConsoleCmd("test", test);
 }
 
 public Action:test(client, args) {
 if (client > 0 && args < 1) {
 ShowMyMenu(client);
 }
 return Plugin_Handled;
 }
 
 ShowMyMenu(client)
 {
 new Handle:menu = CreateMenu(Select_Menu);
 SetMenuTitle(menu, "Выберите Игрока:\n ");
 decl String:userid[16], String:name[32];
 for (new i = 1; i <= MaxClients; i++) {
 if (IsClientInGame(i))
 {
 IntToString(GetClientUserId(i), userid, sizeof(userid));
 GetClientName(i, name, sizeof(name));
 AddMenuItem(menu, userid, name);
 }
 }
 DisplayMenu(menu, client, 0);
 }
 
 public Select_Menu(Handle:menu, MenuAction:action, client, option)
 {
 if (action == MenuAction_End)
 {
 // Если меню стало неактивным, обязательно уничтожьте его.
 // Исключение:
 // Меню глобальное и оно еще вам нужно.
 CloseHandle(menu);
 return;
 }
 
 if (action != MenuAction_Select) {
 return;
 }
 
 decl String:userid[16];
 GetMenuItem(menu, option, userid, sizeof(userid));
 
 new target = GetClientOfUserId(StringToInt(userid));
 if (target > 0)
 {
 PrintToChat(client, "Индекс игрока: %d | id: %s", target, userid);
 new cash = GetEntProp(target, Prop_Send, "m_iAccount") + 1;
 if (cash < 16001)
 {
 SetEntProp(target, Prop_Send, "m_iAccount", cash);
 PrintToChatAll("Игроку < %N > добавлен $1", target);
 }
 else {
 PrintToChat(client, "У него $16000");
 }
 }
 else {
 PrintToChat(client, "Игрок не найден (вышел с сервера)");
 }
 ShowMyMenu(client);
 }
  
 Handle:CreateMenu(<функция>, MenuAction:actions=MENU_ACTIONS_DEFAULT);
 Создаёт меню и возвращает его Handle
 
 SetMenuTitle(Handle:menu, const String:fmt[], any:...); - устанавливает название
 AddMenuItem(Handle:menu, const String:info[], const String:display[], style=ITEMDRAW_DEFAULT);
 
 Добавляет опцию в меню:
 info - строка, которую можно будет получить с помощью GetMenuItem
 display - текст, отображающийся в меню
 
 bool:DisplayMenu(Handle:menu, client, time); - отправить меню игроку на time сек (0 = всегда)
 bool:DisplayMenuAtItem(Handle:menu, client, first_item, time);
 То же самое, но меню можно открыть на определенной странице/опции, надо указать позицию first_item
 
 GetMenuSelectionPosition() - возвращает позицию первого элемента на текущей странице (MenuAction_Select).
 Используется для того, чтобы можно было отправить меню в исходном положении.
 Можно использовать так:
 
 
 Код DisplayMenuAtItem(menu, client, GetMenuSelectionPosition(), 0);bool:GetMenuItem(Handle:menu, position, String:infoBuf[], infoBufLen, &style=0, String:dispBuf[]="", dispBufLen=0);
 Это позволять получить значение, которое было записано в info, когда делали AddMenuItem.
 dispBuf - это текст, отображаемый в меню, и dispBufLen его длина.
 
 GetMenuTitle(Handle:menu, String:buffer[], maxlength); - получить название меню (запишется в buffer)
 
 bool:GetMenuExitButton(Handle:menu); - вернёт true, если в меню есть кнопка "выход"
 bool:SetMenuExitButton(Handle:menu, bool:button); - запретить(false)/разрешить(true) кнопку "выход"
 
 bool:GetMenuExitBackButton(Handle:menu); - true, если есть кнопка "назад"
 SetMenuExitBackButton(Handle:menu, bool:button); - запретить(false)/разрешить(true) кнопку "назад"
 Если на 1 страницу добавить эту кнопку, то при её выборе сработает MenuEnd_ExitBack.
 
 GetMenuItemCount(Handle:menu); - возвращает количество пунктов (опций) в меню
 Handle:GetMenuStyle(Handle:menu); - возвращает Handle стиля меню
 
 | Гости не могут скачивать файлы | 
 |  |  |  |  |  | 
| ЙОДА | Дата: Понедельник, 28.05.2012, 03:22:39 | Сообщение # 2 |  |   
|  |  | Сообщений: 41 Репутация: 0 [ +/- ]
 |  | Хотелось бы узнать, как добавлять текстовую анселектовую строку в меню типа CreateMenu() , также как DrawPanelText() в CreatePanel() Добавлено (28.05.2012, 03:22:39)---------------------------------------------
 Перерыл весь инклуд menus.inc, но так и не смог найти ответ.
 |  |  |  |  |  | 
| _wS_ | Дата: Понедельник, 28.05.2012, 09:28:10 | Сообщение # 3 |  |   | AddMenuItem(menu, "", "Текст\nБелый текст"); |  |  |  |  |  | 
| ЙОДА | Дата: Среда, 20.06.2012, 23:16:47 | Сообщение # 4 |  |   
|  |  | Сообщений: 41 Репутация: 0 [ +/- ]
 |  | Спасибо :) 
 Добавлено (30.05.2012, 02:10:13)
 ---------------------------------------------
 
 Code . . . new Handle:panel = CreatePanel();
 SetPanelTitle(panel, "Животные:\n \n");
 DrawPanelItem(panel, "Кот");
 DrawPanelText(panel, "Носорог");
 DrawPanelItem(panel, "Собак");
 DrawPanelItem(panel, "Хамелеон");
 DrawPanelItem(panel, "Тигр \n \n");
 DrawPanelItem(panel, "Выход");
 SendPanelToClient(panel, client, Select_Panel, 0);
 CloseHandle(panel);
 ClientCommand(client, "playgamesound items/nvg_off.wav");
 . . .
 Собак xD Просто убило ^__^
 Добавлено (20.06.2012, 20:25:53)---------------------------------------------
 2 вопроса:
 
 1 - Можно ли создать пустое меню, где бует только текст с тайтла через /n /n /n и кнопка выхода?
 2 - Можно ли в панели заставить нумерацию кнопок идти не с 1, например ставлю 2 кнопки:назад, выход - как сделать их на 8 и 0?
 Добавлено (20.06.2012, 23:16:47)---------------------------------------------
 Вытащил из исходников сурсмода :
 
 SetPanelCurrentKey(panel,n)
 n - сдвиг на позицию
 при n=10, следующий
 DrawPanelItem будет на цифре 0.
 
 
 Сообщение отредактировал ЙОДА - Среда, 30.05.2012, 02:10:46 |  |  |  |  |  | 
| Vitaminoz | Дата: Воскресенье, 24.06.2012, 12:53:37 | Сообщение # 5 |  |   
|  |  | Сообщений: 141 Репутация: 1 [ +/- ]
 |  | А есть вопрос как создать это дело в Top Menu На SourceMod читал что-то про это но не нашел =(
 |  |  |  |  |  | 
| Scarface_slv | Дата: Воскресенье, 24.06.2012, 18:24:04 | Сообщение # 6 |  |   
|  |  | Сообщений: 737 Репутация: 61 [ +/- ]
 |  | вот тут это обсуждалось http://world-source.ru/forum/102-2549-1 |  |  |  |  |  | 
| sssw | Дата: Воскресенье, 29.07.2012, 07:47:20 | Сообщение # 7 |  |   
|  |  | Сообщений: 123 Репутация: 14 [ +/- ]
 |  | Мне придёться пересдавать меню, если мне нужно изменить одно название пункта из него? К примеру "aktel[MUTED]" поменять на "aktel[UNMUTED]" возможно?
 |  |  |  |  |  | 
| Naykon | Дата: Четверг, 13.09.2012, 01:44:50 | Сообщение # 8 |  |   
|  |  | Сообщений: 439 Репутация: -4 [ +/- ]
 |  | Представим в меню 15 пунктов на 1 страницу к примеру влезло 8 а на вторую 7, когда я выбираю пункт со 2 страницы нужно чтоб меню не исчезало а оставалось на той-же 2 странице. как это можно воплотить? |  |  |  |  |  | 
| _wS_ | Дата: Четверг, 13.09.2012, 12:14:54 | Сообщение # 9 |  |   | Quote (sssw) Мне придёться пересдавать меню, если мне нужно изменить одно название пункта из него?Попробуй RemoveMenuItem, а затем InsertMenuItem (можно и наоборот).
 
 Naykon:
 
 
 Code DisplayMenuAtItem(menu, client, GetMenuSelectionPosition(), 0); |  |  |  |  |  | 
| Naykon | Дата: Четверг, 27.09.2012, 17:32:19 | Сообщение # 10 |  |   
|  |  | Сообщений: 439 Репутация: -4 [ +/- ]
 |  | Как закрыть меню только у 1 игрока ( с индекстом client) |  |  |  |  |  | 
| _wS_ | Дата: Четверг, 27.09.2012, 17:39:22 | Сообщение # 11 |  |   | Можно попробовать заставить выбрать опцию (вряд ли получится): ClientCommand(client, "menuselect 10 или 0");
 
 Ну а точно работающий вариант, это создать пустую панель (CreatePanel()) и отправить игроку.
 Новое меню перебьет старое.
 |  |  |  |  |  | 
| Skybi | Дата: Четверг, 27.09.2012, 19:16:04 | Сообщение # 12 |  |   
|  |  | Сообщений: 4 Репутация: 1 [ +/- ]
 |  | Как можно перевести пункты и название меню через translations phrases(файл перевода)? |  |  |  |  |  | 
| _wS_ | Дата: Четверг, 27.09.2012, 19:41:05 | Сообщение # 13 |  |   |  |  |  |  |  |  | 
| Naykon | Дата: Четверг, 04.10.2012, 17:36:35 | Сообщение # 14 |  |   
|  |  | Сообщений: 439 Репутация: -4 [ +/- ]
 |  | Можно ли сделать так если 1 меню открыто то его не может свернуть другое меню..?? |  |  |  |  |  | 
| _wS_ | Дата: Четверг, 04.10.2012, 17:56:11 | Сообщение # 15 |  |   | Думаю нет. Можно только узнать, когда менюшка была перебита, и отправить ее снова. 
 
 Code public xz(Handle:menu, MenuAction:action, param1, param2) {
 if (action == MenuAction_Cancel && param2 == MenuCancel_Interrupted)
 {
 // menu было перебито дргим меню
 }
 }
Только плохо наверно будет, если то другое меню делает то же самое.
 |  |  |  |  |  
 |