root | Дата: Воскресенье, 03.02.2013, 10:26 | Сообщение # 1 |
Генералиссимус
Группа: Администраторы
Сообщений: 561
Статус: Offline
| Создание меню в SourcePawn
SourceMod имеет обширный API для создания и отображения меню клиентам.
Стили Объект верхнего уровня MenuStyle (IMenuStyle в C++). Есть два стиля отображения меню
- Стиль Valve - так называемое "ESC" меню; 8 элементов на странице
- Стиль Radio - так называемое "AMX" меню; 10 элементов на странице
Каждый MenuStyle имеет свои собственные правила и свойства. Два разных меню могут существовать на экране игрока как Valve меню и Radio меню. В то же время, SourceMod будет в состоянии управлять этими меню. Это связано с тем, что каждый стиль отслеживает свое меню отдельно.
Панели Объект с более низким уровня интерфейсом Panels (IMenuPanel в C++). Панели позволяют сделать отображение, используя лишь только текст т.е. не используя выделительных пунктов (Select). Панели отображаются временно. Хотя они могут быть сохранены на неопределенный срок, не рекомендуется это делать. Стиль Valve
- Максимальное количество элементов на странице 8
- Заблокированные элементы не могут быть осуществлены
- Raw текст не может быть осуществлен
- Осуществление между текстом пространства не добавят возможности добавить в панель больше символов
- Клиент должен будет нажать кнопку "ESC" или, по крайней открыть консоль для просмотра меню
Стиль Radio
- Максимальное количество элементов на странице 10
- Оглавление белое, элементы желтые, но если их отключить, то они будут белыми
- Элемент '0' всегда белый. Это означает, что навигационные кнопки управления всегда белого цвета
Меню Есть простые Menu (IBaseMenu в C++). Эти вспомогательные объекты, предназначенные для хранения меню на основе выбора элементов. В отличие от низкого уровня панелей, меню могут содержать множество элементов, а также могут содержать только те пункты, которые выбираются (т. е. не содержат "белого" текста). Они делятся на две категории: Не пронумерованные - меню содержит в себе только лишь определенное количество элементов. Нет пунктов навигации (Вперед; Назад). Исключение: Выход.
- Назад (Previous) - Используется для возвращения просмотренных элементов; Перелистываемые страницы назад
- Стиль Valve: Позиция в меню: 6
- Стиль Radio: Позиция в меню: 8
- Далее (Next) - Используется для просматривания следующих страниц; Перелистывание страницы вперед
- Стиль Valve: Позиция в меню: 7
- Стиль Radio: Позиция в меню: 9
- Выход (Exit) - Используется для выхода из меню
- Стиль Valve: Позиция в меню: 8
- Стиль Radio: Позиция в меню: 10
Цель меню - Упростить процедуру хранения и отображения информации. Таким образом, меню не позволяют добавить raw текст, так как это значительно усложняет отображение алгоритма. Примечание. C++ API поддерживает подключение IBaseMenu процедуры отображения и добавления raw текста, это будет добавлено в сценарии API в ближайшее время. Внутри меню отображение используется с помощью RenderMenu алгоритма. Этот алгоритм создает временную панель и наполняет ее элементы из меню. Эта панель будет отображаться на клиенте. Алгоритм пытается создать свободное перемещение между всеми меню, и во всех стилях. Таким образом, любое меню отображается с помощью IBaseMenu класса, или меню Handle будет отображаться и использоваться так же как и меню Panel API.
Обзор Меню являются системой обратного вызова. Каждый обратный вызов представляет собой действие, которое происходит во время всего цикла действия меню. Цикл состоит из некоторых уведомлений:
- Начало действия уведомлений
- Отображение уведомления клиенту
- Выбор пункта в меню
- Конец действия уведомлений
Спецификация Для C++, IBaseMenu всегда доступен. Для SourcePawn, Menu Handle и MenuAction всегда устанавливаются в MenuHandler обратного вызова. В отличие от C++, API позволяет SourcePawn выполнять определенные действия, если только меню было запрошено во время создания. Это оптимизация. Тем не менее, некоторые действия не могут быть предотвращены создания.
Start. Создание меню, причем OnMenuEnd гарантированно будет вызываться.
- MenuAction_Start() в SourcePawn. Это действие не срабатывает при вызове.
- param1: Игнорирование. Всегда 0
- param2: Игнорирование. Всегда 0
Display. Отображение меню клиенту.
- MenuAction_Display в SourcePawn. Это действие не срабатывает при вызове.
- param1: Индекс клиента, которому показано меню
- param2: Handle в меню
Select. Выбор пункта меню.
- MenuAction_Select в SourcePawn. Это действие срабатывает, не смотря на вызов.
- param1: Индекс клиента, который выбрал пункт
- param2: Индекс пункта, который выбрал клиент
Cancel. Отмена показа меню
- MenuAction_Cancel в SourcePawn. Это действие срабатывает, не смотря на вызов.
- param1: Индекс клиента, который отменил показ меню
- param2: Код причины отмены показа меню
End. Окончание показа меню
- MenuAction_End в SourcePawn. Это действие всегда срабатывает, то ли просьба или нет.
- param1: Причина окончания показа меню
- param2: Если param1 был MenuEnd_Cancelled, это содержит причину отмены показа меню
Панели Для панелей, функции обратного вызова всегда меняются. Для SourcePawn, Menu Handle всегда будет INVALID_HANDLE. Select. Выбор пункта в панели
- MenuAction_Select в SourcePawn.
- param1: Индекс клиента, который выбрал пункт
- param2: Индекс пункта, который выбрал клиент
Cancel. Отмена показа панели
- MenuAction_Cancel в SourcePawn.
- param1: Индекс клиента, который отменил показ панели
- param2: Код причины отмены показа панели
Пример Разберем создание панели и меню с вопросамиКод: ваш вопрос 1. ответ 1 2. ответ 2 МенюPHP код: // Подключаем библиотеки #include <sourcemod>
// Старт плагина public OnPluginStart() { // Регистрируем команду, введя которую нам отобразится меню RegConsoleCmd("menu", Menu) }
// Обрабатываем команду public Action:Menu(client, args) { // Создаем Handle меню // MenuHandler - Значит что, нажав на один из пунктов, произойдет дальнейшее действие // То есть, нажав к примеру на "Да", нам выведется в консоль о том, что вы выбрали именно этот пункт new Handle:menu = CreateMenu(MenuHandler) SetMenuTitle(menu, "Вы любите Counter-Strike:Source?") AddMenuItem(menu, "yes", "Да") AddMenuItem(menu, "no", "Нет") SetMenuExitButton(menu, false) DisplayMenu(menu, client, 20) return Plugin_Handled }
public MenuHandler(Handle:menu, MenuAction:action, param1, param2) { /* Если пункт меню был выбран, выводим в его консоль об этом */ if (action == MenuAction_Select) { decl String:info[32] new bool:found = GetMenuItem(menu, param2, info, sizeof(info)) PrintToConsole(param1, "Вы выбрали пункт: %d (Найдено: %d Информация: %s)", param2, found, info) } /* Если клиент отменил показ меню, выводим в консоль сервера */ else if (action == MenuAction_Cancel) { PrintToServer("Клиент %d Отменил показ меню. Причина: %d", param1, param2) } /* Если показ меню закончился, закрываем Handle */ else if (action == MenuAction_End) { CloseHandle(menu) } }
Обратите внимание на несколько очень важных примечаний - Один из пунктов Select или Cancel будет направлен в действие обрабатывания меню
- Пункт End всегда будет направлен в действие обрабатывания меню
- Уничтожение меню следует производить только, если клиент отменил меню, или оно закончилось
- В меню, по умолчанию, есть пункт выхода
- Продолжительно показа меню зависит от DisplayMenu
|
|
| |
root | Дата: Вторник, 26.03.2013, 15:30 | Сообщение # 2 |
Генералиссимус
Группа: Администраторы
Сообщений: 561
Статус: Offline
| Панель
PHP код: // Подключаем библиотеки #include <sourcemod>
// Старт плагина public OnPluginStart() { // Регистрируем команду, введя которую нам отобразится меню RegConsoleCmd("panel", Panel) }
// Обрабатываем команду public Action:Panel(client, args) { // Создаем Handle панели new Handle:panel = CreatePanel(); SetPanelTitle(panel, "Вы любите спать?") DrawPanelItem(panel, "Да") DrawPanelItem(panel, "Нет") SendPanelToClient(panel, client, PanelHandler, 20) CloseHandle(panel) return Plugin_Handled }
public PanelHandler(Handle:menu, MenuAction:action, param1, param2) { if (action == MenuAction_Select) { PrintToConsole(param1, "Вы выбрали пункт: %d", param2) } else if (action == MenuAction_Cancel) { PrintToServer("Клиент %d отменил показ панели. Причина: %d", param1, param2) } }
Некоторые примечания
- Есть лимит добавления элементов в панель
- Возможность уничтожения панели после окончания отображения
- У обработчика всегда есть информация (Отменили показ панели;Выбрали пункт)
Расширенное меню Теперь рассмотрим более сложный пример. Меню, в котором элементы расположены на нескольких страницах. Суть плагина: Отображение карт, с последующей сменой при выборе
PHP код: new Handle:g_MapMenu = INVALID_HANDLE public OnPluginStart() { RegConsoleCmd("menu_changemap", Command_ChangeMap); } public OnMapStart() { g_MapMenu = BuildMapMenu(); } public OnMapEnd() { if (g_MapMenu != INVALID_HANDLE) { CloseHandle(g_MapMenu); g_MapMenu = INVALID_HANDLE; } } Handle:BuildMapMenu() { /* Открытие файла */ new Handle:file = OpenFile("maplist.txt", "rt"); if (file == INVALID_HANDLE) { return INVALID_HANDLE; } /* Создание Handle меню */ new Handle:menu = CreateMenu(Menu_ChangeMap); new String:mapname[255]; while (!IsEndOfFile(file) && ReadFileLine(file, mapname, sizeof(mapname))) { if (mapname[0] == ';' || !IsCharAlpha(mapname[0])) { continue; } new len = strlen(mapname); for (new i=0; i<len; i++) { if (IsCharSpace(mapname[i])) { mapname[i] = '\0'; break; } } /* Проверка на то, что карта действительна */ if (!IsMapValid(mapname)) { continue; } /* Добавление в меню */ AddMenuItem(menu, mapname, mapname); } /* Закрытие Handle */ CloseHandle(file); /* Заголовок */ SetMenuTitle(menu, "Please select a map:"); return menu; } public Menu_ChangeMap(Handle:menu, MenuAction:action, param1, param2) { if (action == MenuAction_Select) { new String:info[32]; /* Получение информации пункта */ new bool:found = GetMenuItem(menu, param2, info, sizeof(info)); /* Информация о выборе клиента */ PrintToConsole(param1, "You selected item: %d (found? %d info: %s)", param2, found, info); /* Смена карты */ ServerCommand("changelevel %s", info); } } public Action:Command_ChangeMap(client, args) { if (g_MapMenu == INVALID_HANDLE) { PrintToConsole(client, "The maplist.txt file was not found!"); return Plugin_Handled; } DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER); return Plugin_Handled; }
|
|
| |
root | Дата: Вторник, 26.03.2013, 15:31 | Сообщение # 3 |
Генералиссимус
Группа: Администраторы
Сообщений: 561
Статус: Offline
| Меню будет выглядеть так Примечания
- Автоматическое отображение или скрытие элементов управления
- Время, указанное для отображения клиенту меню, не меняется при использовании меню
- Позиции элементов управления не могут быть изменены
Голосование Голосование в SourceMod имеет сходные черты с меню
- MenuAction_VoteStart. Начало голосования
- MenuAction_VoteEnd. Конец голосования. Клиенты отменили, проголосовали или оставили не выбрали один из элементов
- MenuAction_VoteCancel. Клиент отменил показ голосования. Причина отмены будет содержаться в параметре param1
Стоить отметить некоторые примечания
- Выбор отключившегося клиента недействителен
- Результаты голосования вы должны самостоятельно получать
Простое голосование
PHP код: public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2) { if (action == MenuAction_End) { /* Закрытие Handle, если меню стало неактивным */ CloseHandle(menu); } else if (action == MenuAction_VoteEnd) { /* 0 = Да, 1 = Нет */ if (param1 == 0) { new String:map[64] GetMenuItem(menu, param1, map, sizeof(map)) ServerCommand("changelevel %s", map); } } } DoVoteMenu(const String:map[]) { if (IsVoteInProgress()) { return; } new Handle:menu = CreateMenu(Handle_VoteMenu) SetMenuTitle(menu, "Сменить карту на %s?", map) AddMenuItem(menu, map, "Да") AddMenuItem(menu, "no", "Нет") SetMenuExitButton(menu, false) VoteMenuToAll(menu, 20); }
Расширенное голосование PHP код: public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2) { if (action == MenuAction_End) { /* Закрытие Handle */ CloseHandle(menu); } } public Handle_VoteResults(Handle:menu, num_votes, num_clients, const client_info[][2], num_items, const item_info[][2]) { /* Поиск элемента, набравшего больше всего голосов */ new winner = 0; if (num_items > 1 && (item_info[0][VOTEINFO_ITEM_VOTES] == item_info[1][VOTEINFO_ITEM_VOTES])) { winner = GetRandomInt(0, 1); } new String:map[64] GetMenuItem(menu, item_info[winner][VOTEINFO_ITEM_INDEX], map, sizeof(map)) ServerCommand("changelevel %s", map) } DoVoteMenu(const String:map[]) { if (IsVoteInProgress()) { return; } new Handle:menu = CreateMenu(Handle_VoteMenu) SetVoteResultCallback(menu, Handle_VoteResults) SetMenuTitle(menu, "Сменить карту на %s?", map) AddMenuItem(menu, map, "Да") AddMenuItem(menu, "no", "Нет") SetMenuExitButton(menu, false) VoteMenuToAll(menu, 20); }
Перевод фраз в голосовании
PHP код: public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2) { if (action == MenuAction_End) { /* Закрытие Handle */ CloseHandle(menu); } else if (action == MenuAction_VoteEnd) { /* 0=yes, 1=no */ if (param1 == 0) { new String:map[64] GetMenuItem(menu, param1, map, sizeof(map)) ServerCommand("changelevel %s", map); } } else if (action == MenuAction_DisplayItem) { /* Получение строки в меню, после получения будем его использовать как фразу для перевода */ decl String:display[64]; GetMenuItem(menu, param2, "", 0, _, display, sizeof(display)); /* Перевод текста, отображенный клиенту */ decl String:buffer[255]; Format(buffer, sizeof(buffer), "%T", display, param1); return RedrawMenuItem(buffer); } else if (action == MenuAction_Display) { /* Handle панели является вторым параметром */ new Handle:panel = Handle:param2; /* Получение имени карты */ decl String:map[64]; GetMenuItem(menu, 0, map, sizeof(map)); /* Фраза для перевода */ decl String:buffer[255]; Format(buffer, sizeof(buffer), "%T", "Change map to?", client, map); SetPanelTitle(panel, buffer); } } DoVoteMenu(const String:map[]) { if (IsVoteInProgress()) { return; } new Handle:menu = CreateMenu(Handle_VoteMenu, MenuAction_DisplayItem|MenuAction_Display) SetMenuTitle(menu, "Сменить карту на %s?", map) AddMenuItem(menu, map, "Да") AddMenuItem(menu, "no", "Нет") SetMenuExitButton(menu, false) VoteMenuToAll(menu, 20); }
Оригинал
|
|
| |