<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=HolyHender</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=HolyHender"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/HolyHender"/>
	<updated>2026-04-18T06:48:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11165</id>
		<title>Category:Ru:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11165"/>
		<updated>2021-02-11T09:39:00Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Эта категория содержит статьи о написании скриптов под SourceMod с использованием SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Введение===&lt;br /&gt;
*[[Ru:Introduction to SourcePawn|Ru:Introduction to SourcePawn]] - Введение в SourcePawn. Обучение синтаксису языка.&lt;br /&gt;
*[[Ru:Introduction to SourceMod Plugins|Ru:Introduction to SourceMod Plugins]] - Введение в SourceMod плагины. Создаем Ваш &amp;quot;первый плагин&amp;quot;.&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - Поиск сценариев в справочнике API.&lt;br /&gt;
&lt;br /&gt;
===Основной API===&lt;br /&gt;
*[[Ru:AutoConfigs (SourceMod Scripting)|Автоконфиги]] - Автоматическое создание .cfg файлов.&lt;br /&gt;
*[[Ru:Commands (SourceMod Scripting)|Команды]] - Консольные команды/ввод.&lt;br /&gt;
*[[Ru:ConVars (SourceMod Scripting)|Консольные переменные (ConVar)]] - Консольные переменные (cvars).&lt;br /&gt;
*[[Ru:Events (SourceMod Scripting)|События (Events)]] - Игровые события Half-Life.&lt;br /&gt;
*[[Ru:KeyValues (SourceMod Scripting)|Структура Ключ-Значение (KeyValues)]] - KeyValues анализ/запись файла.&lt;br /&gt;
*[[Ru:Menu API (SourceMod)|Меню]] - Создание и отображение меню.&lt;br /&gt;
*[[Ru:SQL (SourceMod Scripting)|SQL]] - Использование баз данных (MySQL, SQLite).&lt;br /&gt;
*[[Ru:Timers (SourceMod Scripting)|Таймеры (Timers)]] - Вызов таймеров.&lt;br /&gt;
*[[Ru:DataPacks|Пакеты данных (DataPack)]] - Создание и управление DataPack.&lt;br /&gt;
*[[Ru:Translations (SourceMod Scripting)|Переводы]] - Создание локализаций.&lt;br /&gt;
&lt;br /&gt;
===Продвинутый API===&lt;br /&gt;
*[[Admin API (SourceMod)|API администрирования]] - Использование кэша администратора.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|API админского меню]] - Закрепление в меню администратора.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Создание нативных функция]] - Разоблачение API других плагинов.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|API вызова функция]] - Вызовы внешних функций.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Необязательные требования]] - Управление зависимостями.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Использование мощного SDK уровней абстракции.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Временные объекты]] - Использование временных объектов.&lt;br /&gt;
&lt;br /&gt;
===Информация===&lt;br /&gt;
*[[Ru:Format Class Functions (SourceMod Scripting)|Форматирование текста]] - Всё про форматирование текста.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Обзор Handle и несколько распространённых типов.&lt;br /&gt;
*[[Optimizing Plugins (SourceMod Scripting)|Optimizing Plugins]] - Советы по оптимизации.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - Всё о тэгах.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Объяснение типов Вектора.&lt;br /&gt;
&lt;br /&gt;
===Дополнительные средства===&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - API по кодированию на SourcePawn.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Список игровых событий для популярных модификаций.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Список временных объектов для популярных модификаций.&lt;br /&gt;
*[[SourceMod Profiler]] - Отслеживание производительности и оптимизации.&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11164</id>
		<title>Category:Ru:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11164"/>
		<updated>2021-02-11T09:38:32Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Эта категория содержит статьи о написании скриптов под SourceMod с использованием SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Введение===&lt;br /&gt;
*[[Ru:Introduction to SourcePawn|Ru:Introduction to SourcePawn]] - Введение в SourcePawn. Обучение синтаксису языка.&lt;br /&gt;
*[[Ru:Introduction to SourceMod Plugins|Ru:Introduction to SourceMod Plugins]] - Введение в SourceMod плагины. Создаем Ваш &amp;quot;первый плагин&amp;quot;.&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - Поиск сценариев в справочнике API.&lt;br /&gt;
&lt;br /&gt;
===Основной API===&lt;br /&gt;
*[[Ru:AutoConfigs (SourceMod Scripting)|Автоконфиги]] - Автоматическое создание .cfg файлов.&lt;br /&gt;
*[[Ru:Commands (SourceMod Scripting)|Команды]] - Консольные команды/ввод.&lt;br /&gt;
*[[Ru:ConVars (SourceMod Scripting)|Консольные переменные (ConVar)]] - Консольные переменные (cvars).&lt;br /&gt;
*[[Ru:Events (SourceMod Scripting)|События (Events)]] - Игровые события Half-Life.&lt;br /&gt;
*[[Ru:KeyValues (SourceMod Scripting)|Структура Ключ-Значение (KeyValues)]] - KeyValues анализ/запись файла.&lt;br /&gt;
*[[Ru:Menu API (SourceMod)|Меню]] - Создание и отображение меню.&lt;br /&gt;
*[[Ru:SQL (SourceMod Scripting)|SQL]] - Использование баз данных (MySQL, SQLite).&lt;br /&gt;
*[[Ru:Timers (SourceMod Scripting)|Таймеры (Timers)]] - Вызов таймеров.&lt;br /&gt;
*[[Ru:DataPacks|Пакеты данных (DataPack)]] - Создание и управление DataPack.&lt;br /&gt;
*[[Ru:Translations (SourceMod Scripting)|Переводы]] - Создание локализаций.&lt;br /&gt;
&lt;br /&gt;
===Продвинутый API===&lt;br /&gt;
*[[Admin API (SourceMod)|API администрирования]] - Использование кэша администратора.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|API админского меню]] - Закрепление в меню администратора.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Создание нативных функция]] - Разоблачение API других плагинов.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|API вызова функция]] - Вызовы внешних функций.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Необязательные требования]] - Управление зависимостями.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Использование мощного SDK уровней абстракции.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Временные объекты]] - Использование временных объектов.&lt;br /&gt;
&lt;br /&gt;
===Информация===&lt;br /&gt;
*[[Deprecation Schedule (SourceMod Scripting)|Deprecation Schedule]] - Which functions are getting removed.&lt;br /&gt;
*[[Ru:Format Class Functions (SourceMod Scripting)|Форматирование текста]] - Всё про форматирование текста.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Обзор Handle и несколько распространённых типов.&lt;br /&gt;
*[[Optimizing Plugins (SourceMod Scripting)|Optimizing Plugins]] - Советы по оптимизации.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - Всё о тэгах.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Объяснение типов Вектора.&lt;br /&gt;
&lt;br /&gt;
===Дополнительные средства===&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - API по кодированию на SourcePawn.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Список игровых событий для популярных модификаций.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Список временных объектов для популярных модификаций.&lt;br /&gt;
*[[SourceMod Profiler]] - Отслеживание производительности и оптимизации.&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11163</id>
		<title>Category:Ru:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11163"/>
		<updated>2021-02-11T09:37:43Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Эта категория содержит статьи о написании скриптов под SourceMod с использованием SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Введение===&lt;br /&gt;
*[[Ru:Introduction to SourcePawn|Ru:Introduction to SourcePawn]] - Введение в SourcePawn. Обучение синтаксису языка.&lt;br /&gt;
*[[Ru:Introduction to SourceMod Plugins|Ru:Introduction to SourceMod Plugins]] - Введение в SourceMod плагины. Создаем Ваш &amp;quot;первый плагин&amp;quot;.&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - Поиск сценариев в справочнике API.&lt;br /&gt;
&lt;br /&gt;
===Основной API===&lt;br /&gt;
*[[Ru:AutoConfigs (SourceMod Scripting)|Автоконфиги]] - Автоматическое создание .cfg файлов.&lt;br /&gt;
*[[Ru:Commands (SourceMod Scripting)|Команды]] - Консольные команды/ввод.&lt;br /&gt;
*[[Ru:ConVars (SourceMod Scripting)|Консольные переменные (ConVar)]] - Консольные переменные (cvars).&lt;br /&gt;
*[[Ru:Events (SourceMod Scripting)|События (Events)]] - Игровые события Half-Life.&lt;br /&gt;
*[[Ru:KeyValues (SourceMod Scripting)|Структура Ключ-Значение (KeyValues)]] - KeyValues анализ/запись файла.&lt;br /&gt;
*[[Ru:Menu API (SourceMod)|Меню]] - Создание и отображение меню.&lt;br /&gt;
*[[Ru:SQL (SourceMod Scripting)|SQL]] - Использование баз данных (MySQL, SQLite).&lt;br /&gt;
*[[Ru:Timers (SourceMod Scripting)|Таймеры (Timers)]] - Вызов таймеров.&lt;br /&gt;
*[[Ru:DataPacks|Пакеты данных (DataPack)]] - Создание и управление DataPack.&lt;br /&gt;
*[[Ru:Translations (SourceMod Scripting)|Переводы]] - Создание локализаций.&lt;br /&gt;
&lt;br /&gt;
===Продвинутый API===&lt;br /&gt;
*[[Admin API (SourceMod)|API администрирования]] - Использование кэша администратора.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|API админского меню]] - Закрепление в меню администратора.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Создание нативных функция]] - Разоблачение API других плагинов.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|API вызова функция]] - Вызовы внешних функций.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Необязательные требования]] - Управление зависимостями.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Использование мощного SDK уровней абстракции.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Временные объекты]] - Использование временных объектов.&lt;br /&gt;
&lt;br /&gt;
===Информация===&lt;br /&gt;
*[[Deprecation Schedule (SourceMod Scripting)|Deprecation Schedule]] - Which functions are getting removed.&lt;br /&gt;
*[[Форматирование текста (SourceMod Scripting)|Ru:Format Class Functions]] - Всё про форматирование текста.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Обзор Handle и несколько распространённых типов.&lt;br /&gt;
*[[Optimizing Plugins (SourceMod Scripting)|Optimizing Plugins]] - Советы по оптимизации.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - Всё о тэгах.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Объяснение типов Вектора.&lt;br /&gt;
&lt;br /&gt;
===Дополнительные средства===&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - API по кодированию на SourcePawn.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Список игровых событий для популярных модификаций.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Список временных объектов для популярных модификаций.&lt;br /&gt;
*[[SourceMod Profiler]] - Отслеживание производительности и оптимизации.&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Commands_(SourceMod_Scripting)&amp;diff=11162</id>
		<title>Ru:Commands (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Commands_(SourceMod_Scripting)&amp;diff=11162"/>
		<updated>2021-02-11T09:36:39Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Добавление команд */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SourceMod]] позволяет создать вам консольные команды, похожие на [[AMX Mod X]]. Есть два главных вида консольных команд:&lt;br /&gt;
*'''Серверные команды''' - Срабатывают с одним из следующих способов ввода:&lt;br /&gt;
**С помощью консоли сервера&lt;br /&gt;
**С помощью удаленной консоли (RCON)&lt;br /&gt;
**Функция ServerCommand(), либо из SourceMod либо [[Half-Life 2]] движка&lt;br /&gt;
*'''Консольные команды''' - Срабатывают с одним из следующих способов ввода:&lt;br /&gt;
**С помощью консоли клиента&lt;br /&gt;
**Любой из методов ввода серверных команд&lt;br /&gt;
&lt;br /&gt;
Для серверных команд не существует клиентского индекса.  Для консольных/клиентских команд, существует клиентский индекс, но он может быть 0, чтобы показать, что команда с сервера.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что кнопка-бинд &amp;quot;commands&amp;quot;, такие как +attack и +duck, они не консольные команды.  Эти команды отдельно передаются, посколько они отдельно привязаны.  &lt;br /&gt;
&lt;br /&gt;
=Серверные команды=&lt;br /&gt;
Как отмечалось выше, серверные команды срабатывают через консоль сервера, будь то удалённую, локальную, или через движок Source. Индекс клиента не связан с серверными командами.  &lt;br /&gt;
&lt;br /&gt;
Серверные команды регистрируются через &amp;lt;tt&amp;gt;RegServerCmd()&amp;lt;/tt&amp;gt; функцию, расположенную в &amp;lt;tt&amp;gt;console.inc&amp;lt;/tt&amp;gt;. При регистрации команды, вы можете записать поверх существующей команды, и таким образом, возвращаемое значение становится важным.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will be processed, if there was one. Если серверная команда создана плагином, здесь не будет эффекта.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will not be processed, if there was one. Если серверная команда создана плагином, здесь не будет эффекта.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will not be processed, if there was one.  Additionally, no further hooks will be called for this command until it is fired again.&lt;br /&gt;
&lt;br /&gt;
==Добавление серверных команд==&lt;br /&gt;
Допустим, мы хотим добавить тестовую команду, чтобы показать как Half-Life 2 вычисляет аргументы команды.  Вот возможная реализация:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegServerCmd(&amp;quot;test_command&amp;quot;, Command_Test)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Test(int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg[128]&lt;br /&gt;
	char full[256]&lt;br /&gt;
&lt;br /&gt;
	GetCmdArgString(full, sizeof(full))&lt;br /&gt;
&lt;br /&gt;
	PrintToServer(&amp;quot;Строка аргумента: %s&amp;quot;, full)&lt;br /&gt;
	PrintToServer(&amp;quot;Количество аргументов: %d&amp;quot;, args)&lt;br /&gt;
	for (int i = 1; i &amp;lt;= args; i++)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(i, arg, sizeof(arg))&lt;br /&gt;
		PrintToServer(&amp;quot;Аргумент %d: %s&amp;quot;, i, arg)&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Блокирование серверных команд==&lt;br /&gt;
Допустим мы хотим отключить &amp;quot;kickid&amp;quot; команду на сервере. Нет причин делать это, но для примера сойдет:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegServerCmd(&amp;quot;kickid&amp;quot;, Command_KickId);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Kickid(int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Консольные команды=&lt;br /&gt;
В отличие от серверных команд, консольные могут быть вызваны, как сервером, так и клиентом, так что callback функция получает клиентский индекс, а также количество аргументов.  Если сервер использовал команду, клиентский индекс будет 0.  &lt;br /&gt;
&lt;br /&gt;
When returning the &amp;lt;tt&amp;gt;Action&amp;lt;/tt&amp;gt; from the callback, the following effects will happen:&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt;: The original functionality of the command (if any) will still be processed.  If there was no original functionality, the client will receive &amp;quot;Unknown command&amp;quot; in their console.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;: The original functionality of the command (if any) will be blocked.  If there was no functionality originally, this prevents clients from seeing &amp;quot;Unknown command&amp;quot; in their console.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt;: Same as &amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;, except that this will be the last hook called.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, в отличие от AMX Mod X, SourceMod не сможет зарегистрировать командные фильтры. т.е. нет эквивалента этой команды:&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_clcmd(&amp;quot;say /ff&amp;quot;, &amp;quot;Command_SayFF&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это было удаленно, чтобы сделать наш код проще и быстрее.  Написание такого же функционала легче и показано ниже.&lt;br /&gt;
&lt;br /&gt;
==Добавление команд==&lt;br /&gt;
Создать клиентские команды очень просто.  Давайте переделаем нашу тест команду, чтобы можно было отобразить информацию о клиенте.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;test_command&amp;quot;, Command_Test);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Test(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg[128], full[256];&lt;br /&gt;
&lt;br /&gt;
	GetCmdArgString(full, sizeof(full))&lt;br /&gt;
&lt;br /&gt;
	if (client)&lt;br /&gt;
	{&lt;br /&gt;
		char name[32];&lt;br /&gt;
		GetClientName(client, name, sizeof(name));&lt;br /&gt;
		PrintToServer(&amp;quot;Команда от клиента: %s&amp;quot;, name);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		PrintToServer(&amp;quot;Команда от сервера.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PrintToServer(&amp;quot;Строка аргументов: %s&amp;quot;, full);&lt;br /&gt;
	PrintToServer(&amp;quot;Количество аргументов: %d&amp;quot;, args);&lt;br /&gt;
	&lt;br /&gt;
	for (int i = 1; i &amp;lt;= args; i++)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(i, arg, sizeof(arg));&lt;br /&gt;
		PrintToServer(&amp;quot;Аргумент %d: %s&amp;quot;, i, arg);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Захват команд==&lt;br /&gt;
Пример: захват типичной команды say. Let's say we want to tell players whether FF is enabled when they say '/ff' in game.  &lt;br /&gt;
&lt;br /&gt;
Before we implement this, a common point of confusion with the 'say' command is that Half-Life 2 (and Half-Life 1), by default, send it with the text in one big quoted string.  This means if you say &amp;quot;I like hot dogs,&amp;quot; your command will be broken down as such:&lt;br /&gt;
*Argument string: &amp;quot;I like hot dogs&amp;quot;&lt;br /&gt;
*Argument count: 1&lt;br /&gt;
*Argument #1: I like hot dogs&lt;br /&gt;
&lt;br /&gt;
However, if a player types this in their console: &amp;lt;tt&amp;gt;say I like yams&amp;lt;/tt&amp;gt;, it will be broken up as:&lt;br /&gt;
*Argument string: I like yams&lt;br /&gt;
*Argument count: 3&lt;br /&gt;
*Argument #1: I&lt;br /&gt;
*Argument #2: like&lt;br /&gt;
*Argument #3: yams&lt;br /&gt;
&lt;br /&gt;
Thus, to take into account both of these situations, we are going to use &amp;lt;tt&amp;gt;GetCmdArgString&amp;lt;/tt&amp;gt; and manually parse the input.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;say&amp;quot;, Command_Say)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Say(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char text[192]&lt;br /&gt;
	GetCmdArgString(text, sizeof(text))&lt;br /&gt;
&lt;br /&gt;
	int startidx = 0&lt;br /&gt;
	if (text[0] == '&amp;quot;')&lt;br /&gt;
	{&lt;br /&gt;
		startidx = 1&lt;br /&gt;
		/* Лишаем ковычки от окончания, если есть */&lt;br /&gt;
		int len = strlen(text);&lt;br /&gt;
		if (text[len-1] == '&amp;quot;')&lt;br /&gt;
		{&lt;br /&gt;
			text[len-1] = '\0'&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (StrEqual(text[startidx], &amp;quot;/ff&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		Handle ff = FindConVar(&amp;quot;mp_friendlyfire&amp;quot;)&lt;br /&gt;
		if (GetConVarInt(ff))&lt;br /&gt;
		{&lt;br /&gt;
			PrintToConsole(client, &amp;quot;Огонь по товарищам включен.&amp;quot;)&lt;br /&gt;
		} else {&lt;br /&gt;
			PrintToConsole(client, &amp;quot;Огонь по товарищам выключен.&amp;quot;)&lt;br /&gt;
		}&lt;br /&gt;
		/* Блокирование сообщения клиента от вещания */&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Пусть работает как обычно */&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Создание Админской команды==&lt;br /&gt;
Давайте создадим простую админскую команду, которая позволяет кикнуть игрока, по его полному имени.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;admin_kick&amp;quot;,&lt;br /&gt;
		Command_Kick,&lt;br /&gt;
		ADMFLAG_KICK,&lt;br /&gt;
		&amp;quot;Кикает игрока по нику&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Kick(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	if (args &amp;lt; 1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Использование: admin_kick &amp;lt;ник&amp;gt;&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	char name[32]&lt;br /&gt;
        int maxplayers, target = -1&lt;br /&gt;
	GetCmdArg(1, name, sizeof(name))&lt;br /&gt;
&lt;br /&gt;
	maxplayers = GetMaxClients()&lt;br /&gt;
	for (int i = 1; i &amp;lt;= maxplayers; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (!IsClientConnected(i))&lt;br /&gt;
		{&lt;br /&gt;
			continue&lt;br /&gt;
		}&lt;br /&gt;
		char other[32]&lt;br /&gt;
		GetClientName(i, other, sizeof(other))&lt;br /&gt;
		if (StrEqual(name, other))&lt;br /&gt;
		{&lt;br /&gt;
			target = i&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Не могу найти игрока с ником: \&amp;quot;%s\&amp;quot;&amp;quot;, name)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	ServerCommand(&amp;quot;kickid %d&amp;quot;, GetClientUserId(target));&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Иммунитет==&lt;br /&gt;
В нашем прошлом примере, мы не сделали иммунитет. Иммунитет является гораздно сложной системой в SourceMod, чем это было в AMX Mod X, и не существует просто флага, чтобы обозначить его.  Вместо, этого существует две функции:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CanAdminTarget&amp;lt;/tt&amp;gt;: Проверяет исходные значения AdminId для иммунитета.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CanUserTarget&amp;lt;/tt&amp;gt;: Проверяет внутриигровых клиентов для иммунитета.&lt;br /&gt;
&lt;br /&gt;
While immunity is generally tested ''player versus player'', it is possible you might want to check for immunity and not have a targetting client.  While there is no convenience function for this yet, a good idea might be to check for either ''default'' or ''global'' immunity on the player's groups (these can be user-defined for non-player targeted scenarios).&lt;br /&gt;
&lt;br /&gt;
When checking for immunity, the following heuristics are performed in this exact order:&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;If the targeting AdminId is &amp;lt;tt&amp;gt;INVALID_ADMIN_ID&amp;lt;/tt&amp;gt;, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted AdminId is &amp;lt;tt&amp;gt;INVALID_ADMIN_ID&amp;lt;/tt&amp;gt;, targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targeting admin has &amp;lt;tt&amp;gt;Admin_Root&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ADMFLAG_ROOT&amp;lt;/tt&amp;gt;), targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has global immunity, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has default immunity, and the targeting admin belongs to no groups, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has specific immunity from the targeting admin via group immunities, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If no conclusion is reached via the previous steps, targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, how can we adapt our function about to use immunity?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action Command_Kick(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	if (args &amp;lt; 1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Использование: admin_kick &amp;lt;ник&amp;gt;&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	char name[32]&lt;br /&gt;
        int maxplayers, target = -1&lt;br /&gt;
	GetCmdArg(1, name, sizeof(name))&lt;br /&gt;
&lt;br /&gt;
	maxplayers = GetMaxClients()&lt;br /&gt;
	for (int i = 1; i &amp;lt;= maxplayers; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (!IsClientConnected(i))&lt;br /&gt;
		{&lt;br /&gt;
			continue&lt;br /&gt;
		}&lt;br /&gt;
		char other[32]&lt;br /&gt;
		GetClientName(i, other, sizeof(other))&lt;br /&gt;
		if (StrEqual(name, other))&lt;br /&gt;
		{&lt;br /&gt;
			target = i&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Не могу найти игрока с ником: \&amp;quot;%s\&amp;quot;&amp;quot;, name)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (!CanUserTarget(client, target))&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Вы не можете использовать этого клиента как цель.&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	ServerCommand(&amp;quot;kickid %d&amp;quot;, GetClientUserId(target))&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Только клиентские команды=&lt;br /&gt;
SourceMod exposes a forward that is called whenever a client executes any command string in their console, called &amp;lt;tt&amp;gt;OnClientCommand&amp;lt;/tt&amp;gt;.  An example of this looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action OnClientCommand(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char cmd[16]&lt;br /&gt;
	GetCmdArg(0, cmd, sizeof(cmd));	/* Получаем название команды */&lt;br /&gt;
&lt;br /&gt;
	if (StrEqual(cmd, &amp;quot;test_command&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		/* Получаем клиентскую команду! Блокируем её... */&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is worth noting that not everything a client sends will be available through this command.  Command registered via external sources in C++ may not be available, especially if they are created via &amp;lt;tt&amp;gt;CON_COMMAND&amp;lt;/tt&amp;gt; in the game mod itself.  For example, &amp;quot;say&amp;quot; is usually implemented this way, because it can be used by both clients and the server, and thus it does not channel through this forward.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Чат триггеры=&lt;br /&gt;
SourceMod будет автоматически создавать чат триггеры для каждой команды, которую вы сделали (по ревизии 900).  Для примера, если вы создали консольную команду &amp;quot;sm_megaslap&amp;quot;, администраторы смогут набрать ее и в &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;say_team&amp;lt;/tt&amp;gt; режимах:&lt;br /&gt;
&amp;lt;pre&amp;gt;!sm_megaslap&lt;br /&gt;
!megaslap&lt;br /&gt;
/sm_megaslap&lt;br /&gt;
/megaslap&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceMod будет выполнять эту команду и ее аргументы, как если бы она пришла из консоли клиента.&lt;br /&gt;
*&amp;quot;&amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt;&amp;quot; является ''публичным'' триггером по умолчанию (&amp;lt;tt&amp;gt;PublicChatTrigger&amp;lt;/tt&amp;gt; в &amp;lt;tt&amp;gt;configs/core.cfg&amp;lt;/tt&amp;gt;) и ваша команда будет отображена всем клиентам.&lt;br /&gt;
*&amp;quot;&amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;&amp;quot; является ''скрытым'' триггером по умолчанию (&amp;lt;tt&amp;gt;SilentChatTrigger&amp;lt;/tt&amp;gt; в &amp;lt;tt&amp;gt;configs/core.cfg&amp;lt;/tt&amp;gt;) и ваша команда не будет показана остальным клиентам&lt;br /&gt;
&lt;br /&gt;
SourceMod будет исполнять только те команды, которые зарегистрированы с &amp;lt;tt&amp;gt;RegConsoleCmd&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;RegAdminCmd&amp;lt;/tt&amp;gt;, и только если эти команды уже не используются Half-life 2 движком или другим игровым модом. Если команда идет с префиксом &amp;quot;sm_&amp;quot;, то &amp;quot;sm_&amp;quot; можно исключить, из написания в чате.&lt;br /&gt;
&lt;br /&gt;
Консольные команды, которые хотят поддерживать использование в качестве триггера чата, не должны использовать нативы вроде &amp;lt;tt&amp;gt;PrintTo*&amp;lt;/tt&amp;gt;. Вместо этого, они должны использовать &amp;lt;tt&amp;gt;ReplyToCommand()&amp;lt;/tt&amp;gt;, которая будет автоматически печатать ваше сообщение либо в виде сообщения чата либо в виде консоли клиента, в зависимости от источника команды.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ru:SourceMod Scripting]]&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Commands_(SourceMod_Scripting)&amp;diff=11161</id>
		<title>Ru:Commands (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Commands_(SourceMod_Scripting)&amp;diff=11161"/>
		<updated>2021-02-11T09:35:21Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Блокирование серверных команд */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SourceMod]] позволяет создать вам консольные команды, похожие на [[AMX Mod X]]. Есть два главных вида консольных команд:&lt;br /&gt;
*'''Серверные команды''' - Срабатывают с одним из следующих способов ввода:&lt;br /&gt;
**С помощью консоли сервера&lt;br /&gt;
**С помощью удаленной консоли (RCON)&lt;br /&gt;
**Функция ServerCommand(), либо из SourceMod либо [[Half-Life 2]] движка&lt;br /&gt;
*'''Консольные команды''' - Срабатывают с одним из следующих способов ввода:&lt;br /&gt;
**С помощью консоли клиента&lt;br /&gt;
**Любой из методов ввода серверных команд&lt;br /&gt;
&lt;br /&gt;
Для серверных команд не существует клиентского индекса.  Для консольных/клиентских команд, существует клиентский индекс, но он может быть 0, чтобы показать, что команда с сервера.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что кнопка-бинд &amp;quot;commands&amp;quot;, такие как +attack и +duck, они не консольные команды.  Эти команды отдельно передаются, посколько они отдельно привязаны.  &lt;br /&gt;
&lt;br /&gt;
=Серверные команды=&lt;br /&gt;
Как отмечалось выше, серверные команды срабатывают через консоль сервера, будь то удалённую, локальную, или через движок Source. Индекс клиента не связан с серверными командами.  &lt;br /&gt;
&lt;br /&gt;
Серверные команды регистрируются через &amp;lt;tt&amp;gt;RegServerCmd()&amp;lt;/tt&amp;gt; функцию, расположенную в &amp;lt;tt&amp;gt;console.inc&amp;lt;/tt&amp;gt;. При регистрации команды, вы можете записать поверх существующей команды, и таким образом, возвращаемое значение становится важным.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will be processed, if there was one. Если серверная команда создана плагином, здесь не будет эффекта.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will not be processed, if there was one. Если серверная команда создана плагином, здесь не будет эффекта.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt; - The original server command will not be processed, if there was one.  Additionally, no further hooks will be called for this command until it is fired again.&lt;br /&gt;
&lt;br /&gt;
==Добавление серверных команд==&lt;br /&gt;
Допустим, мы хотим добавить тестовую команду, чтобы показать как Half-Life 2 вычисляет аргументы команды.  Вот возможная реализация:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegServerCmd(&amp;quot;test_command&amp;quot;, Command_Test)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Test(int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg[128]&lt;br /&gt;
	char full[256]&lt;br /&gt;
&lt;br /&gt;
	GetCmdArgString(full, sizeof(full))&lt;br /&gt;
&lt;br /&gt;
	PrintToServer(&amp;quot;Строка аргумента: %s&amp;quot;, full)&lt;br /&gt;
	PrintToServer(&amp;quot;Количество аргументов: %d&amp;quot;, args)&lt;br /&gt;
	for (int i = 1; i &amp;lt;= args; i++)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(i, arg, sizeof(arg))&lt;br /&gt;
		PrintToServer(&amp;quot;Аргумент %d: %s&amp;quot;, i, arg)&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Блокирование серверных команд==&lt;br /&gt;
Допустим мы хотим отключить &amp;quot;kickid&amp;quot; команду на сервере. Нет причин делать это, но для примера сойдет:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegServerCmd(&amp;quot;kickid&amp;quot;, Command_KickId);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Kickid(int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Консольные команды=&lt;br /&gt;
В отличие от серверных команд, консольные могут быть вызваны, как сервером, так и клиентом, так что callback функция получает клиентский индекс, а также количество аргументов.  Если сервер использовал команду, клиентский индекс будет 0.  &lt;br /&gt;
&lt;br /&gt;
When returning the &amp;lt;tt&amp;gt;Action&amp;lt;/tt&amp;gt; from the callback, the following effects will happen:&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt;: The original functionality of the command (if any) will still be processed.  If there was no original functionality, the client will receive &amp;quot;Unknown command&amp;quot; in their console.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;: The original functionality of the command (if any) will be blocked.  If there was no functionality originally, this prevents clients from seeing &amp;quot;Unknown command&amp;quot; in their console.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt;: Same as &amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt;, except that this will be the last hook called.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, в отличие от AMX Mod X, SourceMod не сможет зарегистрировать командные фильтры. т.е. нет эквивалента этой команды:&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_clcmd(&amp;quot;say /ff&amp;quot;, &amp;quot;Command_SayFF&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это было удаленно, чтобы сделать наш код проще и быстрее.  Написание такого же функционала легче и показано ниже.&lt;br /&gt;
&lt;br /&gt;
==Добавление команд==&lt;br /&gt;
Создать клиентские команды очень просто.  Давайте переделаем нашу тест команду, чтобы можно было отобразить информацию о клиенте.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;test_command&amp;quot;, Command_Test)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Test(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg[128]&lt;br /&gt;
	char full[256]&lt;br /&gt;
&lt;br /&gt;
	GetCmdArgString(full, sizeof(full))&lt;br /&gt;
&lt;br /&gt;
	if (client)&lt;br /&gt;
	{&lt;br /&gt;
		char name[32]&lt;br /&gt;
		GetClientName(client, name, sizeof(name))&lt;br /&gt;
		PrintToServer(&amp;quot;Команда от клиента: %s&amp;quot;, name)&lt;br /&gt;
	} else {&lt;br /&gt;
		PrintToServer(&amp;quot;Команда от сервера.&amp;quot;)&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PrintToServer(&amp;quot;Строка аргументов: %s&amp;quot;, full)&lt;br /&gt;
	PrintToServer(&amp;quot;Количество аргументов: %d&amp;quot;, args)&lt;br /&gt;
	for (int i = 1; i &amp;lt;= args; i++)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(i, arg, sizeof(arg))&lt;br /&gt;
		PrintToServer(&amp;quot;Аргумент %d: %s&amp;quot;, i, arg)&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Захват команд==&lt;br /&gt;
Пример: захват типичной команды say. Let's say we want to tell players whether FF is enabled when they say '/ff' in game.  &lt;br /&gt;
&lt;br /&gt;
Before we implement this, a common point of confusion with the 'say' command is that Half-Life 2 (and Half-Life 1), by default, send it with the text in one big quoted string.  This means if you say &amp;quot;I like hot dogs,&amp;quot; your command will be broken down as such:&lt;br /&gt;
*Argument string: &amp;quot;I like hot dogs&amp;quot;&lt;br /&gt;
*Argument count: 1&lt;br /&gt;
*Argument #1: I like hot dogs&lt;br /&gt;
&lt;br /&gt;
However, if a player types this in their console: &amp;lt;tt&amp;gt;say I like yams&amp;lt;/tt&amp;gt;, it will be broken up as:&lt;br /&gt;
*Argument string: I like yams&lt;br /&gt;
*Argument count: 3&lt;br /&gt;
*Argument #1: I&lt;br /&gt;
*Argument #2: like&lt;br /&gt;
*Argument #3: yams&lt;br /&gt;
&lt;br /&gt;
Thus, to take into account both of these situations, we are going to use &amp;lt;tt&amp;gt;GetCmdArgString&amp;lt;/tt&amp;gt; and manually parse the input.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;say&amp;quot;, Command_Say)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Say(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char text[192]&lt;br /&gt;
	GetCmdArgString(text, sizeof(text))&lt;br /&gt;
&lt;br /&gt;
	int startidx = 0&lt;br /&gt;
	if (text[0] == '&amp;quot;')&lt;br /&gt;
	{&lt;br /&gt;
		startidx = 1&lt;br /&gt;
		/* Лишаем ковычки от окончания, если есть */&lt;br /&gt;
		int len = strlen(text);&lt;br /&gt;
		if (text[len-1] == '&amp;quot;')&lt;br /&gt;
		{&lt;br /&gt;
			text[len-1] = '\0'&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (StrEqual(text[startidx], &amp;quot;/ff&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		Handle ff = FindConVar(&amp;quot;mp_friendlyfire&amp;quot;)&lt;br /&gt;
		if (GetConVarInt(ff))&lt;br /&gt;
		{&lt;br /&gt;
			PrintToConsole(client, &amp;quot;Огонь по товарищам включен.&amp;quot;)&lt;br /&gt;
		} else {&lt;br /&gt;
			PrintToConsole(client, &amp;quot;Огонь по товарищам выключен.&amp;quot;)&lt;br /&gt;
		}&lt;br /&gt;
		/* Блокирование сообщения клиента от вещания */&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Пусть работает как обычно */&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Создание Админской команды==&lt;br /&gt;
Давайте создадим простую админскую команду, которая позволяет кикнуть игрока, по его полному имени.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;admin_kick&amp;quot;,&lt;br /&gt;
		Command_Kick,&lt;br /&gt;
		ADMFLAG_KICK,&lt;br /&gt;
		&amp;quot;Кикает игрока по нику&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Kick(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	if (args &amp;lt; 1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Использование: admin_kick &amp;lt;ник&amp;gt;&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	char name[32]&lt;br /&gt;
        int maxplayers, target = -1&lt;br /&gt;
	GetCmdArg(1, name, sizeof(name))&lt;br /&gt;
&lt;br /&gt;
	maxplayers = GetMaxClients()&lt;br /&gt;
	for (int i = 1; i &amp;lt;= maxplayers; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (!IsClientConnected(i))&lt;br /&gt;
		{&lt;br /&gt;
			continue&lt;br /&gt;
		}&lt;br /&gt;
		char other[32]&lt;br /&gt;
		GetClientName(i, other, sizeof(other))&lt;br /&gt;
		if (StrEqual(name, other))&lt;br /&gt;
		{&lt;br /&gt;
			target = i&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Не могу найти игрока с ником: \&amp;quot;%s\&amp;quot;&amp;quot;, name)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	ServerCommand(&amp;quot;kickid %d&amp;quot;, GetClientUserId(target));&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Иммунитет==&lt;br /&gt;
В нашем прошлом примере, мы не сделали иммунитет. Иммунитет является гораздно сложной системой в SourceMod, чем это было в AMX Mod X, и не существует просто флага, чтобы обозначить его.  Вместо, этого существует две функции:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CanAdminTarget&amp;lt;/tt&amp;gt;: Проверяет исходные значения AdminId для иммунитета.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CanUserTarget&amp;lt;/tt&amp;gt;: Проверяет внутриигровых клиентов для иммунитета.&lt;br /&gt;
&lt;br /&gt;
While immunity is generally tested ''player versus player'', it is possible you might want to check for immunity and not have a targetting client.  While there is no convenience function for this yet, a good idea might be to check for either ''default'' or ''global'' immunity on the player's groups (these can be user-defined for non-player targeted scenarios).&lt;br /&gt;
&lt;br /&gt;
When checking for immunity, the following heuristics are performed in this exact order:&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;If the targeting AdminId is &amp;lt;tt&amp;gt;INVALID_ADMIN_ID&amp;lt;/tt&amp;gt;, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted AdminId is &amp;lt;tt&amp;gt;INVALID_ADMIN_ID&amp;lt;/tt&amp;gt;, targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targeting admin has &amp;lt;tt&amp;gt;Admin_Root&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ADMFLAG_ROOT&amp;lt;/tt&amp;gt;), targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has global immunity, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has default immunity, and the targeting admin belongs to no groups, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If the targetted admin has specific immunity from the targeting admin via group immunities, targeting fails.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If no conclusion is reached via the previous steps, targeting succeeds.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, how can we adapt our function about to use immunity?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action Command_Kick(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	if (args &amp;lt; 1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Использование: admin_kick &amp;lt;ник&amp;gt;&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	char name[32]&lt;br /&gt;
        int maxplayers, target = -1&lt;br /&gt;
	GetCmdArg(1, name, sizeof(name))&lt;br /&gt;
&lt;br /&gt;
	maxplayers = GetMaxClients()&lt;br /&gt;
	for (int i = 1; i &amp;lt;= maxplayers; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (!IsClientConnected(i))&lt;br /&gt;
		{&lt;br /&gt;
			continue&lt;br /&gt;
		}&lt;br /&gt;
		char other[32]&lt;br /&gt;
		GetClientName(i, other, sizeof(other))&lt;br /&gt;
		if (StrEqual(name, other))&lt;br /&gt;
		{&lt;br /&gt;
			target = i&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Не могу найти игрока с ником: \&amp;quot;%s\&amp;quot;&amp;quot;, name)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (!CanUserTarget(client, target))&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Вы не можете использовать этого клиента как цель.&amp;quot;)&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	ServerCommand(&amp;quot;kickid %d&amp;quot;, GetClientUserId(target))&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Только клиентские команды=&lt;br /&gt;
SourceMod exposes a forward that is called whenever a client executes any command string in their console, called &amp;lt;tt&amp;gt;OnClientCommand&amp;lt;/tt&amp;gt;.  An example of this looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action OnClientCommand(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char cmd[16]&lt;br /&gt;
	GetCmdArg(0, cmd, sizeof(cmd));	/* Получаем название команды */&lt;br /&gt;
&lt;br /&gt;
	if (StrEqual(cmd, &amp;quot;test_command&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		/* Получаем клиентскую команду! Блокируем её... */&lt;br /&gt;
		return Plugin_Handled&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is worth noting that not everything a client sends will be available through this command.  Command registered via external sources in C++ may not be available, especially if they are created via &amp;lt;tt&amp;gt;CON_COMMAND&amp;lt;/tt&amp;gt; in the game mod itself.  For example, &amp;quot;say&amp;quot; is usually implemented this way, because it can be used by both clients and the server, and thus it does not channel through this forward.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Чат триггеры=&lt;br /&gt;
SourceMod будет автоматически создавать чат триггеры для каждой команды, которую вы сделали (по ревизии 900).  Для примера, если вы создали консольную команду &amp;quot;sm_megaslap&amp;quot;, администраторы смогут набрать ее и в &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;say_team&amp;lt;/tt&amp;gt; режимах:&lt;br /&gt;
&amp;lt;pre&amp;gt;!sm_megaslap&lt;br /&gt;
!megaslap&lt;br /&gt;
/sm_megaslap&lt;br /&gt;
/megaslap&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceMod будет выполнять эту команду и ее аргументы, как если бы она пришла из консоли клиента.&lt;br /&gt;
*&amp;quot;&amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt;&amp;quot; является ''публичным'' триггером по умолчанию (&amp;lt;tt&amp;gt;PublicChatTrigger&amp;lt;/tt&amp;gt; в &amp;lt;tt&amp;gt;configs/core.cfg&amp;lt;/tt&amp;gt;) и ваша команда будет отображена всем клиентам.&lt;br /&gt;
*&amp;quot;&amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;&amp;quot; является ''скрытым'' триггером по умолчанию (&amp;lt;tt&amp;gt;SilentChatTrigger&amp;lt;/tt&amp;gt; в &amp;lt;tt&amp;gt;configs/core.cfg&amp;lt;/tt&amp;gt;) и ваша команда не будет показана остальным клиентам&lt;br /&gt;
&lt;br /&gt;
SourceMod будет исполнять только те команды, которые зарегистрированы с &amp;lt;tt&amp;gt;RegConsoleCmd&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;RegAdminCmd&amp;lt;/tt&amp;gt;, и только если эти команды уже не используются Half-life 2 движком или другим игровым модом. Если команда идет с префиксом &amp;quot;sm_&amp;quot;, то &amp;quot;sm_&amp;quot; можно исключить, из написания в чате.&lt;br /&gt;
&lt;br /&gt;
Консольные команды, которые хотят поддерживать использование в качестве триггера чата, не должны использовать нативы вроде &amp;lt;tt&amp;gt;PrintTo*&amp;lt;/tt&amp;gt;. Вместо этого, они должны использовать &amp;lt;tt&amp;gt;ReplyToCommand()&amp;lt;/tt&amp;gt;, которая будет автоматически печатать ваше сообщение либо в виде сообщения чата либо в виде консоли клиента, в зависимости от источника команды.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ru:SourceMod Scripting]]&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11160</id>
		<title>Category:Ru:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11160"/>
		<updated>2021-02-11T09:34:53Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Информация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Эта категория содержит статьи о написании скриптов под SourceMod с использованием SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Введение===&lt;br /&gt;
*[[Ru:Introduction to SourcePawn|Ru:Introduction to SourcePawn]] - Введение в SourcePawn. Обучение синтаксису языка.&lt;br /&gt;
*[[Ru:Introduction to SourceMod Plugins|Ru:Introduction to SourceMod Plugins]] - Введение в SourceMod плагины. Создаем Ваш &amp;quot;первый плагин&amp;quot;.&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - Поиск сценариев в справочнике API.&lt;br /&gt;
&lt;br /&gt;
===Основной API===&lt;br /&gt;
*[[Ru:AutoConfigs (SourceMod Scripting)|Автоконфиги]] - Автоматическое создание .cfg файлов.&lt;br /&gt;
*[[Ru:Commands (SourceMod Scripting)|Команды]] - Консольные команды/ввод.&lt;br /&gt;
*[[Ru:ConVars (SourceMod Scripting)|Консольные переменные (ConVar)]] - Консольные переменные (cvars).&lt;br /&gt;
*[[Ru:Events (SourceMod Scripting)|События (Events)]] - Игровые события Half-Life.&lt;br /&gt;
*[[Ru:KeyValues (SourceMod Scripting)|Структура Ключ-Значение (KeyValues)]] - KeyValues анализ/запись файла.&lt;br /&gt;
*[[Ru:Menu API (SourceMod)|Меню]] - Создание и отображение меню.&lt;br /&gt;
*[[Ru:SQL (SourceMod Scripting)|SQL]] - Использование баз данных (MySQL, SQLite).&lt;br /&gt;
*[[Ru:Timers (SourceMod Scripting)|Таймеры (Timers)]] - Вызов таймеров.&lt;br /&gt;
*[[Ru:DataPacks|Пакеты данных (DataPack)]] - Создание и управление DataPack.&lt;br /&gt;
*[[Ru:Translations (SourceMod Scripting)|Переводы]] - Создание локализаций.&lt;br /&gt;
&lt;br /&gt;
===Продвинутый API===&lt;br /&gt;
*[[Admin API (SourceMod)|API администрирования]] - Использование кэша администратора.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|API админского меню]] - Закрепление в меню администратора.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Создание нативных функция]] - Разоблачение API других плагинов.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|API вызова функция]] - Вызовы внешних функций.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Необязательные требования]] - Управление зависимостями.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Использование мощного SDK уровней абстракции.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Временные объекты]] - Использование временных объектов.&lt;br /&gt;
&lt;br /&gt;
===Информация===&lt;br /&gt;
*[[Deprecation Schedule (SourceMod Scripting)|Deprecation Schedule]] - Which functions are getting removed.&lt;br /&gt;
*[[Форматирование текста (SourceMod Scripting)|Ru:Format Class Functions]] - Всё про форматирование текста.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Обзор Handle и несколько распространённых типов.&lt;br /&gt;
*[[Оптимизация плагина (SourceMod Scripting)|Optimizing Plugins]] - Советы по оптимизации.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - Всё о тэгах.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Объяснение типов Вектора.&lt;br /&gt;
&lt;br /&gt;
===Дополнительные средства===&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - API по кодированию на SourcePawn.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Список игровых событий для популярных модификаций.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Список временных объектов для популярных модификаций.&lt;br /&gt;
*[[SourceMod Profiler]] - Отслеживание производительности и оптимизации.&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11158</id>
		<title>Category:Ru:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:SourceMod_Scripting&amp;diff=11158"/>
		<updated>2021-02-08T18:01:29Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Основной API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Эта категория содержит статьи о написании скриптов под SourceMod с использованием SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Введение===&lt;br /&gt;
*[[Ru:Introduction to SourcePawn|Ru:Introduction to SourcePawn]] - Введение в SourcePawn. Обучение синтаксису языка.&lt;br /&gt;
*[[Ru:Introduction to SourceMod Plugins|Ru:Introduction to SourceMod Plugins]] - Введение в SourceMod плагины. Создаем Ваш &amp;quot;первый плагин&amp;quot;.&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - Поиск сценариев в справочнике API.&lt;br /&gt;
&lt;br /&gt;
===Основной API===&lt;br /&gt;
*[[Ru:AutoConfigs (SourceMod Scripting)|Автоконфиги]] - Автоматическое создание .cfg файлов.&lt;br /&gt;
*[[Ru:Commands (SourceMod Scripting)|Команды]] - Консольные команды/ввод.&lt;br /&gt;
*[[Ru:ConVars (SourceMod Scripting)|Консольные переменные (ConVar)]] - Консольные переменные (cvars).&lt;br /&gt;
*[[Ru:Events (SourceMod Scripting)|События (Events)]] - Игровые события Half-Life.&lt;br /&gt;
*[[Ru:KeyValues (SourceMod Scripting)|Структура Ключ-Значение (KeyValues)]] - KeyValues анализ/запись файла.&lt;br /&gt;
*[[Ru:Menu API (SourceMod)|Меню]] - Создание и отображение меню.&lt;br /&gt;
*[[Ru:SQL (SourceMod Scripting)|SQL]] - Использование баз данных (MySQL, SQLite).&lt;br /&gt;
*[[Ru:Timers (SourceMod Scripting)|Таймеры (Timers)]] - Вызов таймеров.&lt;br /&gt;
*[[Ru:DataPacks|Пакеты данных (DataPack)]] - Создание и управление DataPack.&lt;br /&gt;
*[[Ru:Translations (SourceMod Scripting)|Переводы]] - Создание локализаций.&lt;br /&gt;
&lt;br /&gt;
===Продвинутый API===&lt;br /&gt;
*[[Admin API (SourceMod)|API администрирования]] - Использование кэша администратора.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|API админского меню]] - Закрепление в меню администратора.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Создание нативных функция]] - Разоблачение API других плагинов.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|API вызова функция]] - Вызовы внешних функций.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Необязательные требования]] - Управление зависимостями.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Использование мощного SDK уровней абстракции.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Временные объекты]] - Использование временных объектов.&lt;br /&gt;
&lt;br /&gt;
===Информация===&lt;br /&gt;
*[[Deprecation Schedule (SourceMod Scripting)|Deprecation Schedule]] - Which functions are getting removed.&lt;br /&gt;
*[[Ru:Format Class Functions (SourceMod Scripting)|Ru:Format Class Functions]] - Всё про форматирование текста.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Обзор Handle и несколько распространённых типов.&lt;br /&gt;
*[[Optimizing Plugins (SourceMod Scripting)|Optimizing Plugins]] - Советы по оптимизации.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - Всё о тэгах.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Объяснение типов Вектора.&lt;br /&gt;
&lt;br /&gt;
===Дополнительные средства===&lt;br /&gt;
*[http://docs.sourcemod.net/api API Reference] - API по кодированию на SourcePawn.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Список игровых событий для популярных модификаций.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Список временных объектов для популярных модификаций.&lt;br /&gt;
*[[SourceMod Profiler]] - Отслеживание производительности и оптимизации.&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Menu_API_(SourceMod)%3Dru&amp;diff=11156</id>
		<title>Menu API (SourceMod)=ru</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Menu_API_(SourceMod)%3Dru&amp;diff=11156"/>
		<updated>2021-02-08T17:39:06Z</updated>

		<summary type="html">&lt;p&gt;HolyHender: /* Простое меню */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceMod обладает большим API для создания и отображений меню для клиентов. В отличии от AMX Mod X, API SourceMod'a обладает широким функционалом. Меню базируются на обратных вызовах (callbacks), которые гарантированно будут вызваны.&lt;br /&gt;
&lt;br /&gt;
Для C++, API меню может быть найдено в &amp;lt;tt&amp;gt;public/IMenuManager.h&amp;lt;/tt&amp;gt;. Для SourcePawn - &amp;lt;tt&amp;gt;scripting/include/menus.inc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Объекты=&lt;br /&gt;
Система меню SourceMod основана на объектно ориентированной иерархии. Понимание этой иерархии, даже для скриптинга, является ключевым моментом для эффективного использования меню.&lt;br /&gt;
&lt;br /&gt;
==Стили==&lt;br /&gt;
Высший уровень объектов называется ''MenuStyle'' (&amp;lt;tt&amp;gt;IMenuStyle&amp;lt;/tt&amp;gt; в C++). Стили описывают уникальную систему меню. Всего есть два стиля, встроенных в SourceMod:&lt;br /&gt;
*Valve Styly, так же называемым &amp;quot;ESC&amp;quot; меню; 8 пунктов на странице, нельзя добавить текст без занятия слота или спрятать (отключить) текст.&lt;br /&gt;
*Radio Style, так же называемый &amp;quot;AMX&amp;quot; меню; 10 пунктов на странице, можно добавить любой текст.&lt;br /&gt;
&lt;br /&gt;
Каждый MenuStyle обладает своими правилами и свойствами. Вы можете считать, что каждый из них существует на раздельных &amp;quot;каналах&amp;quot;. Например, два разных меню могут быть на экране игрока, будучи Valve и Radio меню одновременно, и SourceMod сможет обработать их обоих без всяких проблем. Это всё возможно благодаря тому, что каждый стиль отслеживает свои меню отдельно.&lt;br /&gt;
&lt;br /&gt;
==Панели==&lt;br /&gt;
Меню низшего уровня называется ''Панелью'' (&amp;lt;tt&amp;gt;IMenuPanel&amp;lt;/tt&amp;gt; в C++). Панель - один ''''кусок'''' текста. Пункты и текст могут добавляться к панели столько раз, сколько поддерживает родительский стиль. Например, Valve стиль не поддерживает отображение текста без занятия слота или отключенных пунктов. Однако с Radio стилем панели это становится возможным, и вы можете отобразить большое количество текста так, как вам это захочется. &lt;br /&gt;
&lt;br /&gt;
Панель считается временным объектом. Она создается, рендерится, отображается, и затем удаляется. Хотя она может быть сохранена на неопределенное время, если в этом есть необходимость.&lt;br /&gt;
&lt;br /&gt;
Правила и ограничения Vavle стиля:&lt;br /&gt;
*Максимум пунктов на странице: 8&lt;br /&gt;
*Отключенный текст не отображается.&lt;br /&gt;
*Нельзя написать текст, не заняв слота.&lt;br /&gt;
*Пробелы не добавляются к пробелам\новым линиям, добавляя чувство &amp;quot;ограниченности&amp;quot;. &lt;br /&gt;
*Пользователь должен нажать &amp;quot;ESC&amp;quot; или быть в своей консоли, чтобы увидеть меню.&lt;br /&gt;
&lt;br /&gt;
Правила и ограничения Radio стиля:&lt;br /&gt;
*10 пунктов на странице&lt;br /&gt;
*Заглавия белые; пункты желтые, если не отключены. Если отключены, то белого цвета.&lt;br /&gt;
*Нулевой элемент всегда белый. Для согласованности это значит, что навигационное управление всегда белое и находится в следующей секции, и просто не отрисовывается, если отсутствует.&lt;br /&gt;
&lt;br /&gt;
==Меню==&lt;br /&gt;
Наконец, есть просто ''Меню'' (&amp;lt;tt&amp;gt;IBaseMenu&amp;lt;/tt&amp;gt; in C++). Это вспомогательный объект, созданный для хранения базированных на меню выбираемых пунктов. В отличии от низкоуровневых панелей, меню содержит '''пункты''', и может содержать только те пункты, которые можно выбрать (т.е. занимающие слоты). Они делятся на две категории:&lt;br /&gt;
*Не нумерованные: эти меню могут иметь определенное число пунктов, и не имеют навигационных опций, кроме кнопки &amp;quot;Выход&amp;quot;, которая всегда добавляется на последнюю позицию, поддерживаемую стилем.&lt;br /&gt;
**Valve Стиль: максимум пунктов: 8&lt;br /&gt;
**Radio Стиль: максимум пунктов: 10&lt;br /&gt;
*Нумерованные: такие меню могут содержать сколь угодно пунктов. Во время отображения будет показано только определенное число пунктов. Автоматически будут добавлены навигационные пункты, таким образом, игроки легко могут возвращаться назад и вперед к определенным &amp;quot;страницам&amp;quot; пунктов меню.&lt;br /&gt;
**&amp;quot;Назад&amp;quot; всегда отображается как первый навигационный пункт, третий с конца поддерживаемых позиций. Не будет добавлен, если меню содержит только одну страницу. Если нет никаких предыдущих страниц, текст никогда не будет отображен, ни в каком стиле. Если возможно, то меню будет дополнено необходимыми пробелами.&lt;br /&gt;
***Valve Стиль, позиция: 6&lt;br /&gt;
***Radio Стиль, позиция: 8&lt;br /&gt;
**&amp;quot;Вперед&amp;quot; всегда отображается как второй навигационный пункт, второй с конца из доступных позиций. Не отображается, если меню состоит из одной страницы. Если нет следующих страниц, то текс не будет отображен при любом стиле. Если возможно, то меню будет дополнено необходимыми пробелами.&lt;br /&gt;
***Valve Стиль, позиция: 7&lt;br /&gt;
***Radio Стиль, позиция: 9&lt;br /&gt;
**&amp;quot;Выход&amp;quot; отображается, если у меню включена кнопка &amp;quot;выход&amp;quot;. Всегда занимает последнюю из возможных позиций&lt;br /&gt;
***Valve Стиль, позиция: 8&lt;br /&gt;
***Radio Стиль, позиция: 10&lt;br /&gt;
&lt;br /&gt;
Цель меню - упростить процедуру хранения, отображения, и вычисления выбранного пункта. Таким образом, меню не позволяет добавлять пустой текст, так как это значительно усложняет алгоритм отображения.  &lt;br /&gt;
&lt;br /&gt;
Внутренне, меню отображается через ''RenderMenu'' алогритм. Этот алгоритм создает временную панель и заполняет её пунктами из меню. Эта панель отображается клиенту. Алгоритм пытается создать свободное перемещение по всем меню, и по всем стилям. Таким образом, все меню отображаются через &amp;lt;tt&amp;gt;IBaseMenu&amp;lt;/tt&amp;gt; класс, или &amp;lt;tt&amp;gt;Menu&amp;lt;/tt&amp;gt; дескрипторы (Handles), и будет выглядеть и действовать так же, как и меню API, основанное на панельном API.&lt;br /&gt;
&lt;br /&gt;
=Обратные вызовы (callbacks)=&lt;br /&gt;
==Краткий обзор==&lt;br /&gt;
Меню базируются на системе обратных вызовов. Каждый обратный вызов предоставляет собой действие, которые происходят во время ''цикла отображения меню''. Цикл состоит из множества уведомлений:&lt;br /&gt;
*Начало уведомления.&lt;br /&gt;
**Уведомление об отображении, если меню может быть отображено клиенту.&lt;br /&gt;
**Уведомление о выборе пункта или кнопки отмены.&lt;br /&gt;
*Конец уведомления.&lt;br /&gt;
&lt;br /&gt;
Так как ''End'' обозначает конец полного цикла отображения, то обычно его используют для уничтожения временных меню.&lt;br /&gt;
&lt;br /&gt;
==Спецификация==&lt;br /&gt;
Детальное объяснение этих событий ниже. Для C++, &amp;lt;tt&amp;gt;IBaseMenu&amp;lt;/tt&amp;gt; указатель всегда доступен. Для SourcePawn, &amp;lt;tt&amp;gt;Menu&amp;lt;/tt&amp;gt; хандл и &amp;lt;tt&amp;gt;MenuAction&amp;lt;/tt&amp;gt; всегда установлены в &amp;lt;tt&amp;gt;MenuHandler&amp;lt;/tt&amp;gt; callback. В отличии от C++, SourcePawn API позволяет вызвать лишь некоторые действия, если они были запрошены во время создания меню. Это сделано в целях оптимизации. Однако, эти действия не могут быть не вызваны.&lt;br /&gt;
&lt;br /&gt;
*'''Start'''. Меню было признано. Это не означает, что меню будет отображено; однако, это гарантирует, что событие &amp;quot;OnMenuEnd&amp;quot; будет вызвано.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuStart()&amp;lt;/tt&amp;gt; в C++.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Start&amp;lt;/tt&amp;gt; в SourcePawn. Не будет вызвано, если не было запрошено.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Игнорируется (всегда 0).&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Игнорируется (всегда 0).&lt;br /&gt;
*'''Display'''.  Меню отобразилось клиенту.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuDisplay()&amp;lt;/tt&amp;gt; в C++. &amp;lt;tt&amp;gt;IMenuPanel&amp;lt;/tt&amp;gt; доступны указатель и индекс клиента.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Display&amp;lt;/tt&amp;gt; в SourcePawn. Не будет вызвано, если не было запрошено.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Индекс клиента.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Хандл меню.&lt;br /&gt;
*'''Select'''. Пункт был выбран. Будет дана позиция пункта в меню, а не нажатая кнопка (если меню не является панелью) &lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuSelect()&amp;lt;/tt&amp;gt; в C++. Передаются индекс клиента и позиция пункта.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Select&amp;lt;/tt&amp;gt; в SourcePawn. Это действие всегда вызывается, вне зависимости от запроса.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Индекс клиента.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Позиция пункта.&lt;br /&gt;
*'''Cancel'''.  Отображение меню у одного из клиентов было закрыто.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuCancel()&amp;lt;/tt&amp;gt; в C++. Доступна причина закрытия.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Cancel&amp;lt;/tt&amp;gt; в SourcePawn. Это действие всегда вызывается, вне зависимости от запроса.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Индекс клиента.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Код причины закрытия меню.&lt;br /&gt;
*'''End'''. Цикл отображения меню закончился; это означает, что &amp;quot;Start&amp;quot; действие было, и одно из действий &amp;quot;Select&amp;quot; или &amp;quot;Cancel&amp;quot; так же произошло. Обычно в этом месте отчищаются ресурсы меню или само меню удаляется.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuEnd()&amp;lt;/tt&amp;gt; в C++.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt; в SourcePawn. Это действие всегда вызывается, вне зависимости от запроса.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Причина завершения меню.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: если param1 == MenuEnd_Cancelled, то здесь содержится код причины закрытия меню.&lt;br /&gt;
&lt;br /&gt;
==Панели==&lt;br /&gt;
Для панелей цикл жизни другой. Панели могут вызывать лишь два callback'а из написанных выше, и гарантируется, что один из них точно будет вызван для данного цикла отображения. Для C++, &amp;lt;tt&amp;gt;IBaseMenu&amp;lt;/tt&amp;gt; указатель будет всегда &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. Для SourcePawn, меню Handle будет всегда &amp;lt;tt&amp;gt;INVALID_HANDLE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*'''Select'''.  Кнопка была нажата. Этой кнопкой может быть любое число. Например, если в панели у вас 2 пункта, то клиент может вызвать это событие, нажав &amp;quot;43&amp;quot;.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuSelect()&amp;lt;/tt&amp;gt; в C++. Передаются индекс клиента и нажатая кнопка.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Select&amp;lt;/tt&amp;gt; в SourcePawn.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Индекс клиента.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Номер нажатой клавиши.&lt;br /&gt;
*'''Cancel'''. Отображение меню у одного из клиентов было закрыто.&lt;br /&gt;
**&amp;lt;tt&amp;gt;OnMenuCancel()&amp;lt;/tt&amp;gt; в C++. Доступна причина закрытия.&lt;br /&gt;
**&amp;lt;tt&amp;gt;MenuAction_Cancel&amp;lt;/tt&amp;gt; в SourcePawn.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;: Индекс клиента.&lt;br /&gt;
***&amp;lt;tt&amp;gt;param2&amp;lt;/tt&amp;gt;: Код причины закрытия меню.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Примеры=&lt;br /&gt;
Для начала попробуем сделать очень простое меню:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Вы любите яблоки?&lt;br /&gt;
1. Да&lt;br /&gt;
2. Нет&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сделаем это как меню и как панель, чтобы увидеть различия в их API.&lt;br /&gt;
&lt;br /&gt;
==Простое меню==&lt;br /&gt;
Сперва напишем наш пример через API Меню. Для пошагового руководства смотрите [[Menus Step By Step (SourceMod Scripting)]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	// зарегистрировали консольную команду menu_test1 для открытия меню.&lt;br /&gt;
	RegConsoleCmd(&amp;quot;menu_test1&amp;quot;, Menu_Test1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// хандл меню&lt;br /&gt;
int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)&lt;br /&gt;
{&lt;br /&gt;
	/* Если был выбран какой-либо пункт, то сообщим клиенту о его выборе. */&lt;br /&gt;
	if (action == MenuAction_Select)&lt;br /&gt;
	{&lt;br /&gt;
		char info[32]; // переменная для хранения выбора&lt;br /&gt;
		bool found = GetMenuItem(menu, param2, info, sizeof(info)); // получаем информацию о выбранном в меню пункте&lt;br /&gt;
		PrintToConsole(param1, &amp;quot;Вы нажали: %d (найдено? %d информация: %s)&amp;quot;, param2, found, info); // пишем клиенту в консоль&lt;br /&gt;
	}&lt;br /&gt;
	/* Если меню было отменено, то сообщим об этом серверу. */&lt;br /&gt;
	else if (action == MenuAction_Cancel)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToServer(&amp;quot;Клиент %d' закрыл меню.  Причина: %d&amp;quot;, param1, param2);&lt;br /&gt;
	}&lt;br /&gt;
	/* Если меню &amp;quot;закончилось&amp;quot;, то удалим его из памяти */&lt;br /&gt;
	else if (action == MenuAction_End)&lt;br /&gt;
	{&lt;br /&gt;
		delete menu;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action Menu_Test1(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	new Handle:menu = CreateMenu(MenuHandler1);&lt;br /&gt;
	SetMenuTitle(menu, &amp;quot;Вы любите яблоки?&amp;quot;);&lt;br /&gt;
	AddMenuItem(menu, &amp;quot;да&amp;quot;, &amp;quot;да&amp;quot;);&lt;br /&gt;
	AddMenuItem(menu, &amp;quot;нет&amp;quot;, &amp;quot;нет&amp;quot;);&lt;br /&gt;
	SetMenuExitButton(menu, false);&lt;br /&gt;
	DisplayMenu(menu, client, 20);&lt;br /&gt;
	&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Несколько очень важных замечаний о этом примере:&lt;br /&gt;
*Одно из &amp;lt;tt&amp;gt;Select&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;Cancel&amp;lt;/tt&amp;gt; событий всегда будет отослано обработчику действий (action handler).&lt;br /&gt;
*&amp;lt;tt&amp;gt;End&amp;lt;/tt&amp;gt; всегда будет отослано обработчику действий (action handler).&lt;br /&gt;
*Мы удаляем наше меню в &amp;lt;tt&amp;gt;End&amp;lt;/tt&amp;gt; действии, потому что наш дескриптор (Handle) нам больше не нужен. Если бы мы удалили его после &amp;lt;tt&amp;gt;DisplayMenu&amp;lt;/tt&amp;gt;, это бы отменило отображение меню клиенту.&lt;br /&gt;
*Меню по умолчанию имеет кнопку выхода. В нашем примере мы его отключили.&lt;br /&gt;
*Наше меню будет отображаться 20 секунд. Это означает, что если клиент ничего не выбрал в течении 20 секунд, то меню будет закрыто. Это обычно необходимо для меню с голосованиями. В отличии от AMX Mod X, вам не нужно создавать таймер, чтобы быть увереным, что меню &amp;quot;закончилось&amp;quot;.&lt;br /&gt;
*Мы создали и уничтожили новый дескриптор меню (Menu Handle), однако мы можем этого и не делать. Вполне допустимо создать дескриптор (Handle) один раз для всего времени жизни плагина.&lt;br /&gt;
*Чтобы нормально отображались русские буквы, кодировка файла должна быть UTF-8 (без BOOM), иначе будут квадратики вместо русских букв.&lt;br /&gt;
&lt;br /&gt;
Наше законченное меню и приложенный вывод в консоли выглядит как на картинке ниже (был выбран ответ &amp;quot;Да&amp;quot;, и картинка взята с англ вики, прим. переводчика).&lt;br /&gt;
&lt;br /&gt;
[[Image:Basic_menu_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
==Базовая панель==&lt;br /&gt;
Теперь давайте перепишем наш пример с использованием Панели вместо Меню.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	// зарегистрировали консольную команду panel_test1 для открытия меню.&lt;br /&gt;
	RegConsoleCmd(&amp;quot;panel_test1&amp;quot;, Panel_Test1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public PanelHandler1(Handle:menu, MenuAction:action, param1, param2)&lt;br /&gt;
{&lt;br /&gt;
	if (action == MenuAction_Select)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(param1, &amp;quot;Вы выбрали: %d&amp;quot;, param2);&lt;br /&gt;
	} else if (action == MenuAction_Cancel) {&lt;br /&gt;
		PrintToServer(&amp;quot;Клиент %d' закрыл панель. Причина: %d&amp;quot;, param1, param2);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:Panel_Test1(client, args)&lt;br /&gt;
{&lt;br /&gt;
	new Handle:panel = CreatePanel();&lt;br /&gt;
	SetPanelTitle(panel, &amp;quot;Вы любите яблоки?&amp;quot;);&lt;br /&gt;
	DrawPanelItem(panel, &amp;quot;Да&amp;quot;);&lt;br /&gt;
	DrawPanelItem(panel, &amp;quot;Нет&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
	SendPanelToClient(panel, client, PanelHandler1, 20);&lt;br /&gt;
&lt;br /&gt;
	CloseHandle(panel);&lt;br /&gt;
	&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как вы можете заметить, Панели сильно отличаются от Меню:&lt;br /&gt;
*Мы можем удалить Панель как только закончим его отображать. Мы можем создать Панель один раз, и продолжать использовать его много раз, однако мы можем удалить его в любой момент, без нарушения цикла отображения клиентского меню.&lt;br /&gt;
*Обработчик Панели (Handler) получает гораздо меньше информации. Так как Панели разрабатывались как грубый вывод текста, была сохранена возможность добавления информации без занятия слота. Поэтому обработчик может знать лишь об отмене или о нажатии любой клавиши с номером.&lt;br /&gt;
*Отсутствует автоматизация. Вы не можете добавить больше определенного числа выбираемых пунктов и добавить нумерацию. Автоматический контроль требует использования тяжелого объектного API Меню.&lt;br /&gt;
&lt;br /&gt;
Наше законченная панель и приложеный вывод в консоли выглядит как на картинке ниже (был выбран ответ &amp;quot;Да&amp;quot;, и картинка взята с англ вики, прим. переводчика):&lt;br /&gt;
&lt;br /&gt;
[[Image:Basic_panel_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
==Базовое меню с нумерацией==&lt;br /&gt;
Теперь сделаем пример с большим функционалом -- нумерацией. Попробуем сделать меню для смены карты. Самый простой путь - прочесть &amp;lt;tt&amp;gt;maplist.txt&amp;lt;/tt&amp;gt; файл в начале плагина и создать меню по этому файла.&lt;br /&gt;
&lt;br /&gt;
Так как чтение и парсинг файла довольно долгая операция, мы будем делать это только раз за карту. Поэтому мы построим меню в &amp;lt;tt&amp;gt;OnMapStart&amp;lt;/tt&amp;gt;, и мы не будем вызывать &amp;lt;tt&amp;gt;CloseHandle&amp;lt;/tt&amp;gt; до события &amp;lt;tt&amp;gt;OnMapEnd&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исходный код:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new Handle:g_MapMenu = INVALID_HANDLE&lt;br /&gt;
&lt;br /&gt;
public OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegConsoleCmd(&amp;quot;menu_changemap&amp;quot;, Command_ChangeMap);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnMapStart()&lt;br /&gt;
{&lt;br /&gt;
	g_MapMenu = BuildMapMenu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnMapEnd()&lt;br /&gt;
{&lt;br /&gt;
	if (g_MapMenu != INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		CloseHandle(g_MapMenu);&lt;br /&gt;
		g_MapMenu = INVALID_HANDLE;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Handle:BuildMapMenu()&lt;br /&gt;
{&lt;br /&gt;
	/* открываем файл */&lt;br /&gt;
	new Handle:file = OpenFile(&amp;quot;maplist.txt&amp;quot;, &amp;quot;rt&amp;quot;);&lt;br /&gt;
	if (file == INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		return INVALID_HANDLE;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/* создаем хандл меню */&lt;br /&gt;
	new Handle:menu = CreateMenu(Menu_ChangeMap);&lt;br /&gt;
	new String:mapname[255];&lt;br /&gt;
	while (!IsEndOfFile(file) &amp;amp;&amp;amp; ReadFileLine(file, mapname, sizeof(mapname)))&lt;br /&gt;
	{&lt;br /&gt;
		if (mapname[0] == ';' || !IsCharAlpha(mapname[0]))&lt;br /&gt;
		{&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
		/* выбрасываем все пробелы из названия */&lt;br /&gt;
		new len = strlen(mapname);&lt;br /&gt;
		for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
		{&lt;br /&gt;
			if (IsCharSpace(mapname[i]))&lt;br /&gt;
			{&lt;br /&gt;
				mapname[i] = '\0';&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		/* проверяем карту на валидность */&lt;br /&gt;
		if (!IsMapValid(mapname))&lt;br /&gt;
		{&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
		/* добавляем карту в меню */&lt;br /&gt;
		AddMenuItem(menu, mapname, mapname);&lt;br /&gt;
	}&lt;br /&gt;
	/* не забываем закрыть файл! */&lt;br /&gt;
	CloseHandle(file);&lt;br /&gt;
	&lt;br /&gt;
	/* наконец, устанавливаем заглавие меню */&lt;br /&gt;
	SetMenuTitle(menu, &amp;quot;Выберите карту:&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	return menu;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Menu_ChangeMap(Handle:menu, MenuAction:action, param1, param2)&lt;br /&gt;
{&lt;br /&gt;
	if (action == MenuAction_Select)&lt;br /&gt;
	{&lt;br /&gt;
		new String:info[32];&lt;br /&gt;
&lt;br /&gt;
		/* получаем информацию о пункте */&lt;br /&gt;
		new bool:found = GetMenuItem(menu, param2, info, sizeof(info));&lt;br /&gt;
&lt;br /&gt;
		/* говорим об этом клиенту */&lt;br /&gt;
		PrintToConsole(param1, &amp;quot;Вы выбрали: %d (найдено? %d информация: %s)&amp;quot;, param2, found, info);&lt;br /&gt;
&lt;br /&gt;
		/* меняем карту */&lt;br /&gt;
		ServerCommand(&amp;quot;changelevel %s&amp;quot;, info);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:Command_ChangeMap(client, args)&lt;br /&gt;
{&lt;br /&gt;
	if (g_MapMenu == INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToConsole(client, &amp;quot;Файл maplist.txt не был найден!&amp;quot;);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}	&lt;br /&gt;
	&lt;br /&gt;
	DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER);&lt;br /&gt;
	&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результатом такого меню будет множество пунктов (&amp;lt;tt&amp;gt;maplist.txt&amp;lt;/tt&amp;gt; файл содержал примерно 18 карт). Таким образом, конечное меню содержит три страницы, которые идут друг за другом, и выглядят вот так:&lt;br /&gt;
&lt;br /&gt;
[[Image:Basic_menu_2_page1.PNG]]&lt;br /&gt;
[[Image:Basic_menu_2_page2.PNG]]&lt;br /&gt;
[[Image:Basic_menu_2_page3.PNG]]&lt;br /&gt;
&lt;br /&gt;
Сообщение в консоль будет выведено до смены карты, например, если выбрали &amp;lt;tt&amp;gt;cs_office&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;Вы выбрали: 8 (найдено? 1 информация: cs_office)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Отображение и разработка этого меню через &amp;lt;tt&amp;gt;ShowMenu&amp;lt;/tt&amp;gt; сообщение или &amp;lt;tt&amp;gt;Панельный&amp;lt;/tt&amp;gt; API занимает много времени и является довольно сложной задачей. Придется отслеживать все пункты в массиве большого размера, страницы, которые пользователь просматривает, и написать функцию, которая будет вычислять, на основе текущей странице, пункт, который был выбран и какую кнопку нажали. Меню системы это всё делает за вас.&lt;br /&gt;
&lt;br /&gt;
'''Заметки:'''&lt;br /&gt;
*Пункты управления, которые не доступны, не рисуются. Например, на первой странице вы не можете нажать &amp;quot;назад&amp;quot;, а на последней странице вы не можете нажать &amp;quot;вперед&amp;quot;. Несмотря на это, меню пытается удерживать каждый интерфейс последовательно. Таким образом, визуально, каждая навигационная клавиша всегда на одной и той же позиции.&lt;br /&gt;
*Если указать таймаут меню, то переключение между страницами не воздействует на общее время открытия меню. Например, если мы установим таймаут на 20 секунд, то каждое листание страницы будет устанавливать таймайт равный (20 - время, уже затраченное на просмотр). Только переоткрытие меню позволит вернуть таймаут времени на 20 секунд.&lt;br /&gt;
*Если отключить кнопку выхода, то не смотря на это, пункты 8 и 9 будут всё так же &amp;quot;назад&amp;quot; и вперед, соответственно.&lt;br /&gt;
*Мы не освобождаем дескриптор (Handle) меню в &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt;, потому что наше меню глобальное/статическое, и нам не нужно пересоздавать его каждый раз.&lt;br /&gt;
*На изображении отображена кнопка &amp;quot;Назад&amp;quot;. В SourceMod версии 1011 и выше, кнопка &amp;quot;Назад&amp;quot; была переименована в &amp;quot;Предыдующая&amp;quot;, и &amp;quot;Назад&amp;quot; зарезервированно для &amp;quot;ExitBack&amp;quot; функциональности. (актуально для ENG версии, на ру вроде бы оба пункта &amp;quot;назад&amp;quot;. прим. переводчик)&lt;br /&gt;
&lt;br /&gt;
=Голосование=&lt;br /&gt;
SourceMod также имеет API для отображения меню как голосования для больше чем одного клиента. SourceMod автоматически обрабатываем выбранные пункты and randomly picking a tie-breaker (не знаю как перевести. прим. переводчика). Так же API голосования добавляет два новых значения для &amp;lt;tt&amp;gt;MenuAction&amp;lt;/tt&amp;gt;, которые во время отображения меню всегда вызываются.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tt&amp;gt;MenuAction_VoteStart&amp;lt;/tt&amp;gt;: Вызывается после &amp;lt;tt&amp;gt;MenuAction_Start&amp;lt;/tt&amp;gt;, когда голосование оффициально началось.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MenuAction_VoteEnd&amp;lt;/tt&amp;gt;: Вызывается после того, как все клиенты проголосовали или отменили свои меню голосований. Выбранный предмет может быть получен через &amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;. Вызывается '''перед''' &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt;. Важно заметить, что это не замена &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt;, это разные вещи. Нельзя освобождать меню в &amp;lt;tt&amp;gt;MenuAction_VoteEnd&amp;lt;/tt&amp;gt;. '''Заметка:''' не вызывается, если используется &amp;lt;tt&amp;gt;SetVoteResultCallback&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*&amp;lt;tt&amp;gt;MenuAction_VoteCancel&amp;lt;/tt&amp;gt;: Вызывается, если меню было отмеено в процессе голосования. Если вызвалось, то &amp;lt;tt&amp;gt;MenuAction_VoteEnd&amp;lt;/tt&amp;gt; или обратный вызов (callback) для результата голосований не будет вызваны, но &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt; будет после этого.  Причина отмены голосования находится в &amp;lt;tt&amp;gt;param1&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Система меню - это то же самое меню, только с двумя дополнительными свойствами:&lt;br /&gt;
*Только одно голосование может быть активно. Вы должны проверять, не запущено ли голосование (&amp;lt;tt&amp;gt;IsVoteInProgress&amp;lt;/tt&amp;gt;()), иначе &amp;lt;tt&amp;gt;VoteMenu&amp;lt;/tt&amp;gt;() не сработает.&lt;br /&gt;
*Если клиент во время голосования отключится, то его голос будет недействительным. &lt;br /&gt;
&lt;br /&gt;
Пример внизу показывает, как создать функцию &amp;lt;tt&amp;gt;DoVoteMenu()&amp;lt;/tt&amp;gt;, которая будет спрашивать, хотят ли они сменить карту на предложенную.&lt;br /&gt;
&lt;br /&gt;
==Простое Голосование==&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2)&lt;br /&gt;
{&lt;br /&gt;
	if (action == MenuAction_End)&lt;br /&gt;
	{&lt;br /&gt;
		/* Вызывается после VoteEnd */&lt;br /&gt;
		CloseHandle(menu);&lt;br /&gt;
	} else if (action == MenuAction_VoteEnd) {&lt;br /&gt;
		/* 0=да, 1=нет */&lt;br /&gt;
		if (param1 == 0)&lt;br /&gt;
		{&lt;br /&gt;
			new String:map[64];&lt;br /&gt;
			GetMenuItem(menu, param1, map, sizeof(map));&lt;br /&gt;
			ServerCommand(&amp;quot;changelevel %s&amp;quot;, map);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
DoVoteMenu(const String:map[])&lt;br /&gt;
{&lt;br /&gt;
	if (IsVoteInProgress())&lt;br /&gt;
	{&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	new Handle:menu = CreateMenu(Handle_VoteMenu);&lt;br /&gt;
	SetMenuTitle(menu, &amp;quot;Сменить карту на: %s?&amp;quot;, map);&lt;br /&gt;
	AddMenuItem(menu, map, &amp;quot;да&amp;quot;);&lt;br /&gt;
	AddMenuItem(menu, &amp;quot;no&amp;quot;, &amp;quot;нет&amp;quot;);&lt;br /&gt;
	SetMenuExitButton(menu, false);&lt;br /&gt;
	VoteMenuToAll(menu, 20);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Продвинутое Голосование==&lt;br /&gt;
Если вам нужно больше информации о результатах голосовании, чем вам дает &amp;lt;tt&amp;gt;MenuAction_VoteEnd&amp;lt;/tt&amp;gt;, вы можете указать отдельный обратный вызов (callback). Новый обратный вызов будет давать больше информации, но за опреденную цену: &amp;lt;tt&amp;gt;MenuAction_VoteEnd&amp;lt;/tt&amp;gt; не будет вызвано, и вам придется самим решать, как обработать результат. Это делается с помощью &amp;lt;tt&amp;gt;SetVoteResultCallback&amp;lt;/tt&amp;gt;().&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2)&lt;br /&gt;
{&lt;br /&gt;
	if (action == MenuAction_End)&lt;br /&gt;
	{&lt;br /&gt;
		/* Вызывается после VoteEnd */&lt;br /&gt;
		CloseHandle(menu);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Handle_VoteResults(Handle:menu, &lt;br /&gt;
			num_votes, &lt;br /&gt;
			num_clients, &lt;br /&gt;
			const client_info[][2], &lt;br /&gt;
			num_items, &lt;br /&gt;
			const item_info[][2])&lt;br /&gt;
{&lt;br /&gt;
	/* Проверяем, нет ли сразу двух победителей */&lt;br /&gt;
	new winner = 0;&lt;br /&gt;
	if (num_items &amp;gt; 1&lt;br /&gt;
	    &amp;amp;&amp;amp; (item_info[0][VOTEINFO_ITEM_VOTES] == item_info[1][VOTEINFO_ITEM_VOTES]))&lt;br /&gt;
	{&lt;br /&gt;
		winner = GetRandomInt(0, 1);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	new String:map[64];&lt;br /&gt;
	GetMenuItem(menu, item_info[winner][VOTEINFO_ITEM_INDEX], map, sizeof(map));&lt;br /&gt;
	ServerCommand(&amp;quot;changelevel %s&amp;quot;, map);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
DoVoteMenu(const String:map[])&lt;br /&gt;
{&lt;br /&gt;
	if (IsVoteInProgress())&lt;br /&gt;
	{&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	new Handle:menu = CreateMenu(Handle_VoteMenu);&lt;br /&gt;
	SetVoteResultCallback(menu, Handle_VoteResults);&lt;br /&gt;
	SetMenuTitle(menu, &amp;quot;Сменить карту на: %s?&amp;quot;, map);&lt;br /&gt;
	AddMenuItem(menu, map, &amp;quot;Yes&amp;quot;);&lt;br /&gt;
	AddMenuItem(menu, &amp;quot;no&amp;quot;, &amp;quot;No&amp;quot;);&lt;br /&gt;
	SetMenuExitButton(menu, false);&lt;br /&gt;
	VoteMenuToAll(menu, 20);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=ExitBack=&lt;br /&gt;
ExitBack - специальный термин для обозначения &amp;quot;ExitBack Кнопки&amp;quot;. По умолчанию эта кнопка отключена.  Обычно нумерованные меню не имеют пункта &amp;quot;Назад&amp;quot; для первой страници. Если &amp;quot;ExitBack&amp;quot; кнопка включена, появится кнопка &amp;quot;Назад&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Выбор опции &amp;quot;ExitBack&amp;quot; для меню в обратном вызове будет в действии &amp;lt;tt&amp;gt;MenuCancel_ExitBack&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;MenuEnd_ExitBack&amp;lt;/tt&amp;gt;. Функциональность этого такая же, как и у простого выхода из меню; дополнительная функциональность должна быть определена через обратный вызов.&lt;br /&gt;
&lt;br /&gt;
=Освобождение Дескрипторов (Handle) меню=&lt;br /&gt;
Важно закрывать дескриптор меню в &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;MenuAction_End&amp;lt;/tt&amp;gt; вызывается когда меню закрылось и больше не нужно.&lt;br /&gt;
&lt;br /&gt;
=Переводы=&lt;br /&gt;
Есть возможность динамически переводить меню для каждого игрока через &amp;lt;tt&amp;gt;MenuAction_DisplayItem&amp;lt;/tt&amp;gt; callback. Специальный натив, &amp;lt;tt&amp;gt;RedrawMenuItem&amp;lt;/tt&amp;gt;, используется чтобы преобразовать текст внутри вызова. Давайте переделаем наш пример голосования с переводами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Handle_VoteMenu(Handle:menu, MenuAction:action, param1, param2)&lt;br /&gt;
{&lt;br /&gt;
	if (action == MenuAction_End)&lt;br /&gt;
	{&lt;br /&gt;
		/* Вызывается после VoteEnd */&lt;br /&gt;
		CloseHandle(menu);&lt;br /&gt;
	} else if (action == MenuAction_VoteEnd) {&lt;br /&gt;
		/* 0=да, 1=нет */&lt;br /&gt;
		if (param1 == 0)&lt;br /&gt;
		{&lt;br /&gt;
			new String:map[64];&lt;br /&gt;
			GetMenuItem(menu, param1, map, sizeof(map));&lt;br /&gt;
			ServerCommand(&amp;quot;changelevel %s&amp;quot;, map);&lt;br /&gt;
		}&lt;br /&gt;
	} else if (action == MenuAction_DisplayItem) {&lt;br /&gt;
		/* Получаем отображаемую строку, будем использовать как фразу перевода */&lt;br /&gt;
		decl String:display[64];&lt;br /&gt;
		GetMenuItem(menu, param2, &amp;quot;&amp;quot;, 0, _, display, sizeof(display));&lt;br /&gt;
&lt;br /&gt;
		/* Переводим строку на язык клиента */&lt;br /&gt;
		decl String:buffer[255];&lt;br /&gt;
		Format(buffer, sizeof(buffer), &amp;quot;%T&amp;quot;, display, param1);&lt;br /&gt;
&lt;br /&gt;
		/* Перерисовываем текст */&lt;br /&gt;
		return RedrawMenuItem(buffer);&lt;br /&gt;
	} else if (action == MenuAction_Display) {&lt;br /&gt;
		/* Дескриптор панели будет вторым параметром */&lt;br /&gt;
		new Handle:panel = Handle:param2;&lt;br /&gt;
		&lt;br /&gt;
		/* Get the map name we're changing to from the first item */&lt;br /&gt;
		/* Получаем название карты, на которую меняем, из первого пункта */&lt;br /&gt;
		decl String:map[64];&lt;br /&gt;
		GetMenuItem(menu, 0, map, sizeof(map));&lt;br /&gt;
		&lt;br /&gt;
		/* Переводим нашу фразу */&lt;br /&gt;
		decl String:buffer[255];&lt;br /&gt;
		Format(buffer, sizeof(buffer), &amp;quot;%T&amp;quot;, &amp;quot;Change map to?&amp;quot;, client, map);&lt;br /&gt;
&lt;br /&gt;
		SetPanelTitle(panel, buffer);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
DoVoteMenu(const String:map[])&lt;br /&gt;
{&lt;br /&gt;
	if (IsVoteInProgress())&lt;br /&gt;
	{&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	new Handle:menu = CreateMenu(Handle_VoteMenu, MenuAction_DisplayItem|MenuAction_Display);&lt;br /&gt;
	SetMenuTitle(menu, &amp;quot;Сменить карту на: %s?&amp;quot;, map);&lt;br /&gt;
	AddMenuItem(menu, map, &amp;quot;Yes&amp;quot;);&lt;br /&gt;
	AddMenuItem(menu, &amp;quot;no&amp;quot;, &amp;quot;No&amp;quot;);&lt;br /&gt;
	SetMenuExitButton(menu, false);&lt;br /&gt;
	VoteMenuToAll(menu, 20);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>HolyHender</name></author>
		
	</entry>
</feed>