<?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=Simon+Logic</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=Simon+Logic"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Simon_Logic"/>
	<updated>2026-04-17T20:48:51Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6863</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6863"/>
		<updated>2009-01-28T10:46:43Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Redirecting to Список изменений в AMX Mod X 1.8.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Список изменений в AMX Mod X 1.8.1]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_AMX_Mod_X_1.8.1&amp;diff=6862</id>
		<title>Список изменений в AMX Mod X 1.8.1</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_AMX_Mod_X_1.8.1&amp;diff=6862"/>
		<updated>2009-01-28T10:45:08Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Russian  AMX Mod X 1.8.1 является, по большому счету, работой над ошибками.  *Добавлено {{amb|1762}}: Македонский ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.8.1 является, по большому счету, работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Македонский язык (спаисбо z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: Нативная функция ns_remove_upgrade().&lt;br /&gt;
*Добавлено {{amb|1604}}: Нативная функция unregister_message().&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives для ассоциативных хранилищ.&lt;br /&gt;
*Добавлено {{amb|1365}}: Словацкий язык (спасибо Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Обработчик Invalid_Array в cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: Новый флаг 'k' в файле users.ini, который указывает, что имена/тэги кланов чувствительны к регистру.&lt;br /&gt;
*Добавлено {{amb|1167}}: Нативная функция menu_addtext().&lt;br /&gt;
*Исправлено {{amb|1648}}: Опечатка в validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Координаты браша неверно читались.&lt;br /&gt;
*Исправлено {{amb|1643}}: В TFC stats.amxx была опция, которая не поддерживалась конфигурационным меню статистики.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE в файле stats.sma для TFC.&lt;br /&gt;
*Исправлено {{amb|1632}}: Некоторые значения mp_roundtime могли конфликтовать со StatsX.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX выделял недостаточную облать памяти для csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() имел неконсистентные эвристики.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat по-мелочи не соответствовал cmdaccess.ini (патч от Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity игнорировала последнего клиента.&lt;br /&gt;
*Исправлено {{amb|1456}}: Неверный языковой ключ в режиме голосования за кик/бан.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() выдавал неверные объекты.&lt;br /&gt;
*Исправлено {{amb|1389}}: Функция client_changeteam() из модуля NS имела перевернутый список аргументов интерфейса.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() неверно вызывала vformat().&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() не работала из-за опечатки.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich имел опечатку для мода Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Обход ошибки HLDS при парсинге ключей localinfo.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip не показывал время (патч от James).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager вызывал сбой если файл cmdaccess.ini не был доступен для записи.&lt;br /&gt;
*Исправлено {{amb|1218}}: В файле ns.inc была опечатка.&lt;br /&gt;
*Исправлено {{amb|1199}}: Неверный комментарий для Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: Новый модуль и плагин не добавлялись в пакет дополнений.&lt;br /&gt;
*Исправлено {{amb|1163}}: Распечатка значений с плавающей запятой была некорректной для больших значений.&lt;br /&gt;
*Исправлено {{amb|1143}}: Опечатка в SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu не следовали cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Удалена неиспользуемая cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: Использование dod_set_model() приводило к сбою.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ранжирование игроков по IP приводило сервер к застопорению.&lt;br /&gt;
*Исправлено {{amb|1079}}: Потоковые запросы к СУБД сзапросом результатов могли сбоить.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault не загружался на некоторых Linux серверах.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip выдавал сообщение дважды.&lt;br /&gt;
*Исправлено {{amb|1080}}: Опечатка в немецком языке.&lt;br /&gt;
*Исправлено {{amb|1049}}: Небрежно были названы объекты TraceResult.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6861</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6861"/>
		<updated>2009-01-28T10:43:41Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.8.1 является, по большому счету, работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Македонский язык (спаисбо z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: Нативная функция ns_remove_upgrade().&lt;br /&gt;
*Добавлено {{amb|1604}}: Нативная функция unregister_message().&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives для ассоциативных хранилищ.&lt;br /&gt;
*Добавлено {{amb|1365}}: Словацкий язык (спасибо Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Обработчик Invalid_Array в cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: Новый флаг 'k' в файле users.ini, который указывает, что имена/тэги кланов чувствительны к регистру.&lt;br /&gt;
*Добавлено {{amb|1167}}: Нативная функция menu_addtext().&lt;br /&gt;
*Исправлено {{amb|1648}}: Опечатка в validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Координаты браша неверно читались.&lt;br /&gt;
*Исправлено {{amb|1643}}: В TFC stats.amxx была опция, которая не поддерживалась конфигурационным меню статистики.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE в файле stats.sma для TFC.&lt;br /&gt;
*Исправлено {{amb|1632}}: Некоторые значения mp_roundtime могли конфликтовать со StatsX.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX выделял недостаточную облать памяти для csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() имел неконсистентные эвристики.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat по-мелочи не соответствовал cmdaccess.ini (патч от Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity игнорировала последнего клиента.&lt;br /&gt;
*Исправлено {{amb|1456}}: Неверный языковой ключ в режиме голосования за кик/бан.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() выдавал неверные объекты.&lt;br /&gt;
*Исправлено {{amb|1389}}: Функция client_changeteam() из модуля NS имела перевернутый список аргументов интерфейса.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() неверно вызывала vformat().&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() не работала из-за опечатки.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich имел опечатку для мода Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Обход ошибки HLDS при парсинге ключей localinfo.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip не показывал время (патч от James).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager вызывал сбой если файл cmdaccess.ini не был доступен для записи.&lt;br /&gt;
*Исправлено {{amb|1218}}: В файле ns.inc была опечатка.&lt;br /&gt;
*Исправлено {{amb|1199}}: Неверный комментарий для Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: Новый модуль и плагин не добавлялись в пакет дополнений.&lt;br /&gt;
*Исправлено {{amb|1163}}: Распечатка значений с плавающей запятой была некорректной для больших значений.&lt;br /&gt;
*Исправлено {{amb|1143}}: Опечатка в SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu не следовали cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Удалена неиспользуемая cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: Использование dod_set_model() приводило к сбою.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ранжирование игроков по IP приводило сервер к застопорению.&lt;br /&gt;
*Исправлено {{amb|1079}}: Потоковые запросы к СУБД сзапросом результатов могли сбоить.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault не загружался на некоторых Linux серверах.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip выдавал сообщение дважды.&lt;br /&gt;
*Исправлено {{amb|1080}}: Опечатка в немецком языке.&lt;br /&gt;
*Исправлено {{amb|1049}}: Небрежно были названы объекты TraceResult.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6409</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6409"/>
		<updated>2008-11-10T08:18:14Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Perfect Hashing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение глобальных и локальных переменных, переменные в циклах ===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение статических переменных и глобальных ===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
=== Константы ===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
=== Таблицы поиска ===&lt;br /&gt;
Есть такое правило: все что можно заранее вычислить - вычисляйте и запоминайте.  Например, вам необходимо сопоставить индекс оружия его имени (т.е. по номеру найти имя):&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Если не учитывать, что в AMX Mod X есть функция &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt;, то такой код считается неэффективным. Мы можем запросто сделать сопоставление индексов именам заранее:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..от 0 до CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..от CSW_AK47+1 до TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Идеальное хэширование ===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6408</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6408"/>
		<updated>2008-11-10T08:17:30Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Lookup Tables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение глобальных и локальных переменных, переменные в циклах ===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение статических переменных и глобальных ===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
=== Константы ===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
=== Таблицы поиска ===&lt;br /&gt;
Есть такое правило: все что можно заранее вычислить - вычисляйте и запоминайте.  Например, вам необходимо сопоставить индекс оружия его имени (т.е. по номеру найти имя):&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Если не учитывать, что в AMX Mod X есть функция &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt;, то такой код считается неэффективным. Мы можем запросто сделать сопоставление индексов именам заранее:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..от 0 до CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..от CSW_AK47+1 до TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6407</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6407"/>
		<updated>2008-11-10T08:11:12Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Constant variables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение глобальных и локальных переменных, переменные в циклах ===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение статических переменных и глобальных ===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
=== Константы ===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6406</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6406"/>
		<updated>2008-11-10T08:10:52Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Static vs Global */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение глобальных и локальных переменных, переменные в циклах ===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение статических переменных и глобальных ===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6405</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6405"/>
		<updated>2008-11-10T08:10:17Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Global vs Local and Variables in Loops */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
=== Сравнение глобальных и локальных переменных, переменные в циклах ===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6404</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6404"/>
		<updated>2008-11-10T08:00:44Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Switch instead of If */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Switch вместо If ===&lt;br /&gt;
Если возможно, лучше использовать &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; вместо &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X&amp;diff=6398</id>
		<title>AMX Mod X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X&amp;diff=6398"/>
		<updated>2008-11-08T13:17:07Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Feature List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:{{owned_project|project=AMX Mod X|website=www.amxmodx.org}}&lt;br /&gt;
==Introduction==&lt;br /&gt;
AMX Mod X is a [[Metamod]] plugin for [[Half-Life 1]].  It provides comprehensive scripting for the game engine and its mods.  Scripts can intercept network messages, log events, commands, client commands, set cvars, modify entities, and more.  AMX Mod X also has a system for extending native scripting through [[AMX Mod X Modules|modules]], leading to outside support for things like MySQL and Sockets.  The AMX Mod X scripting language is called [[Pawn]] (formerly &amp;quot;Small&amp;quot;), and is officially maintained by [http://www.compuphase.com/ ITB CompuPhase].&lt;br /&gt;
&lt;br /&gt;
==Feature List==&lt;br /&gt;
*Creating client and server-side commands and variables&lt;br /&gt;
*Default and customizable server administration tools&lt;br /&gt;
**Kicking/Banning&lt;br /&gt;
**Slot Reservation&lt;br /&gt;
**Text file or MySQL enabled admin system&lt;br /&gt;
**Voting&lt;br /&gt;
**Management Commands (chat, map changing, cvar changing, etc)&lt;br /&gt;
**Flood Protection&lt;br /&gt;
**Weapon Restriction&lt;br /&gt;
**Statistics&lt;br /&gt;
*Scriptability through large function library&lt;br /&gt;
**Inter-plugin communication&lt;br /&gt;
**Event listening&lt;br /&gt;
**Network message hooking&lt;br /&gt;
**Entity and engine modification&lt;br /&gt;
**Gamedll and engine function call hooking&lt;br /&gt;
**Sockets&lt;br /&gt;
**Mod-specific extra support for:&lt;br /&gt;
***Counter-Strike, Condition Zero&lt;br /&gt;
***Day of Defeat&lt;br /&gt;
***Natural Selection&lt;br /&gt;
***Team Fortress Classic&lt;br /&gt;
***The Specialists&lt;br /&gt;
***Earth's Special Forces&lt;br /&gt;
**Regular Expressions&lt;br /&gt;
**Menu Creation&lt;br /&gt;
**Debugger&lt;br /&gt;
*Modularity&lt;br /&gt;
**Comprehensive M/DK for interacting with scripts&lt;br /&gt;
**Easily attach and use Metamod&lt;br /&gt;
**Plug 'n Use - MDK requires almost no modification to compile&lt;br /&gt;
**Written in C/C++ - total flexibility&lt;br /&gt;
[[Image:Example.jpg]]&lt;br /&gt;
&lt;br /&gt;
==History==&lt;br /&gt;
The original AMX Mod project started in 2002 authored by [[OLO|Aleksander &amp;quot;OLO&amp;quot; Naszko]].  While the same scripting language ([[Small]]) was used as its predecessor admin tool, [[Admin-Mod]], the style itself is very different, most likely to correct various confusing or inadequate design decisions.  For example:&lt;br /&gt;
*Focus was on modifying the game, rather than only providing admin tools&lt;br /&gt;
*Easier native syntaxes&lt;br /&gt;
*Easier string manipulation&lt;br /&gt;
*Greater flexibility for hooking game events and commands&lt;br /&gt;
*Greater flexibility for manipulating engine/game&lt;br /&gt;
*Module support for developers to extend native language&lt;br /&gt;
*Easier syntax in general (for example, dropping semicolon requirement)&lt;br /&gt;
&lt;br /&gt;
AMX Mod was originally coupled with [[dJeyL]]'s &amp;quot;[[MetaSmall]]&amp;quot;, although this was eventually dropped and the two combined into one binary.&lt;br /&gt;
&lt;br /&gt;
Around January of 2004, various high-ranking members of the AMX Mod community decided the project was in an inactive and dead state.  Neither OLO nor dJeyL could be contacted, and [[SniperBeamer|Felix &amp;quot;SniperBeamer&amp;quot; Geyer]] decided to found a continuation project named [[AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
==Milestones==&lt;br /&gt;
''For a full list of AMX Mod X and AMX Mod changes, see the [[AMX Mod X Changelog]].''&lt;br /&gt;
===0.10-alpha===&lt;br /&gt;
The first release of AMX Mod X presented the core new features and organization policies of the overall package, native library, and forums.&lt;br /&gt;
&lt;br /&gt;
===0.16-beta===&lt;br /&gt;
This was the first and most widely used version of AMX Mod X considered to be stable.  It contained cleaned up code, inter-plugin communication, a rewritten internal events system, and more.&lt;br /&gt;
&lt;br /&gt;
===1.00===&lt;br /&gt;
Jumped from 0.20, AMX Mod X became a truly different product with a new, advanced module API and many code rewrites, as well as the first Metamod plugin with AMD64 support.  AMX Mod X also became the project to port [[Small]] to AMD64.  It also gained a very powerful subsystem and module for engine hacking called [[Fakemeta]].&lt;br /&gt;
&lt;br /&gt;
===1.50===&lt;br /&gt;
AMX Mod X followed the renaming of [[Small]] to [[Pawn]] by [[CompuPhase]].  It also added dynamic natives and featured a new debugger.&lt;br /&gt;
&lt;br /&gt;
==Development Team==&lt;br /&gt;
===Original===&lt;br /&gt;
The AMX Mod X development team, founded by SniperBeamer, was:&lt;br /&gt;
*[[SniperBeamer|Felix &amp;quot;SniperBeamer&amp;quot; Geyer]] - Manager, Plugins/Documentation Maintainer, Web Dev&lt;br /&gt;
*[[PM OnoTo|Pavol &amp;quot;PM OnoTo&amp;quot; Marko]] - Lead Developer, Core/VM/Compiler Maintainer&lt;br /&gt;
*[[User:BAILOPAN|David &amp;quot;BAILOPAN&amp;quot; Anderson]] - General Development, Engine Module, Release Technician&lt;br /&gt;
*[[Johnny Got His Gun|Johnny &amp;quot;JGHG&amp;quot; Bergström]] - Cstrike module, Fun module&lt;br /&gt;
*[[SidLuke|Lukasz &amp;quot;SidLuke&amp;quot; Wlasinski]] - Stats modules and extra mod support (TFC, DoD, TFC, TS) ''note - SidLuke joined Jul 17, 2005&lt;br /&gt;
&lt;br /&gt;
===Current===&lt;br /&gt;
After 1.0 (Nov 15, 2004), the AMX Mod X development team informally disbanded.  On January 4, 2006, the development team was officially restructured to continue to maintain and improve AMX Mod X.&lt;br /&gt;
*[[User:BAILOPAN|David &amp;quot;BAILOPAN&amp;quot; Anderson]] - Manager, Core/VM/Compiler Maintainer, Release Technician&lt;br /&gt;
*[[User:Basic-Master|Christian &amp;quot;Basic-Master&amp;quot; Hammacher]] - AMXX Studio, AMXX Installer, GabenMod&lt;br /&gt;
*[[User:faluco|Borja &amp;quot;faluco&amp;quot; Ferrer]] - General Maintenance/Development, Multi-Lingual Maintenance&lt;br /&gt;
*[[User:Damaged Soul|Scott &amp;quot;Damaged Soul&amp;quot; Ehlert]] - General Maintenance/Development&lt;br /&gt;
*[[User:sawce|Steve &amp;quot;sawce&amp;quot; Dudenhoeffer]] - General Maintenance/Development&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
For full documentation on AMX Mod X, see [[AMX Mod X Documentation]].&lt;br /&gt;
&lt;br /&gt;
==The Future==&lt;br /&gt;
AMX Mod X is, for the most part, a finished product.  The future holds maintenance, optimizing, further expanding the community as possible, and bug fixing.  Features will also usually be added on request.&lt;br /&gt;
&lt;br /&gt;
==License==&lt;br /&gt;
AMX Mod X is licensed under the [[GNU General Public License]], the parent license of [[Metamod]].  AMX Mod X also requires that plugins be licensed under the GPL, unless you are granted an [[AMX Mod X License Exception]].&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://www.amxmodx.org/ The AMX Mod X Website]&lt;br /&gt;
*[http://www.metamod.org/ The Metamod Website]&lt;br /&gt;
*[http://www.amxmod.net/ The Original AMX Mod Website]&lt;br /&gt;
*[http://www.amxmodx.org/forums AMX Mod X Forums]&lt;br /&gt;
&lt;br /&gt;
[[Category:AMX Mod X]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6397</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6397"/>
		<updated>2008-11-07T16:24:28Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Always Save Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
=== Всегда запоминайте результаты ===&lt;br /&gt;
Рассмотрим следующий пример:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
В жизни такой участок кода не слишком ресурсоемкий, однако на его примере вполне эффектно можно рассмотреть метод оптимизации плагина. Когда компилятор генерирует псевдокод для исполнения непосредственно интерпретатором, он будет выглядеть примерно так:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Заметили проблему? Мы вызвали функцию &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; два лишних раза. Возвращаемый результат этих функций не будет меняться, поэтому нам следует его запомнить однократно. Теперь сравните:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Компилятор в этот раз сгенерирует следующий псевдокод:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Если бы функция &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; была ресурсоемкой операцией, мы бы вычисляли результат каждый раз при выполненнии условия &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Switch instead of If===&lt;br /&gt;
If you can, you should use &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; cases instead of &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6396</id>
		<title>Ru:Optimizing Plugins (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6396"/>
		<updated>2008-11-07T16:13:28Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Redirecting to Оптимизация Плагинов (AMX Mod X Scripting)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Оптимизация Плагинов (AMX Mod X Scripting)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6395</id>
		<title>Optimizing Plugins (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6395"/>
		<updated>2008-11-07T16:11:57Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LanguageSwitch}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
[[Admin-Mod]] and [[AMX Mod X]] became very popular because of their easy to use scripting language.  However, the words &amp;quot;scripting language&amp;quot; come with a lot of loaded preconceptions.  Most people assume that because it's scripted:&lt;br /&gt;
*You can't possibly make it any faster&lt;br /&gt;
*It's pre-compiled, so it's already quite fast&lt;br /&gt;
*Details don't matter, as it's only &amp;quot;scripting&amp;quot; anyway&lt;br /&gt;
&lt;br /&gt;
Especially, with [[Pawn]] (formerly Small), none of these are true.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
===Terms===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
===Always Save Results===&lt;br /&gt;
Observe the example code snippet below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This is a mild example of &amp;quot;cache your results&amp;quot;.  When the compiler generates assembly for this code, it will (in pseudo code) generate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice the problem?  We have called &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; an extra two times than necessary.  The result doesn't change, so we can save it.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Now, the compiler will only generate this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; were an expensive operation (it's relatively cheap), we would have recalculated the entire result each branch of the &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.&lt;br /&gt;
&lt;br /&gt;
===Switch instead of If===&lt;br /&gt;
If you can, you should use &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; cases instead of &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6394</id>
		<title>Optimizing Plugins (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Optimizing_Plugins_(AMX_Mod_X_Scripting)&amp;diff=6394"/>
		<updated>2008-11-07T16:11:29Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: added langswitch template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LanguageSwitch}}&lt;br /&gt;
==Introduction==&lt;br /&gt;
[[Admin-Mod]] and [[AMX Mod X]] became very popular because of their easy to use scripting language.  However, the words &amp;quot;scripting language&amp;quot; come with a lot of loaded preconceptions.  Most people assume that because it's scripted:&lt;br /&gt;
*You can't possibly make it any faster&lt;br /&gt;
*It's pre-compiled, so it's already quite fast&lt;br /&gt;
*Details don't matter, as it's only &amp;quot;scripting&amp;quot; anyway&lt;br /&gt;
&lt;br /&gt;
Especially, with [[Pawn]] (formerly Small), none of these are true.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
===Terms===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
===Always Save Results===&lt;br /&gt;
Observe the example code snippet below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This is a mild example of &amp;quot;cache your results&amp;quot;.  When the compiler generates assembly for this code, it will (in pseudo code) generate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice the problem?  We have called &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; an extra two times than necessary.  The result doesn't change, so we can save it.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Now, the compiler will only generate this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; were an expensive operation (it's relatively cheap), we would have recalculated the entire result each branch of the &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.&lt;br /&gt;
&lt;br /&gt;
===Switch instead of If===&lt;br /&gt;
If you can, you should use &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; cases instead of &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Fundamental_Basics_of_AMX_Mod_X_Scripting&amp;diff=6392</id>
		<title>Ru:Fundamental Basics of AMX Mod X Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Fundamental_Basics_of_AMX_Mod_X_Scripting&amp;diff=6392"/>
		<updated>2008-11-07T15:59:24Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Ru Fundamental Basics of AMX Mod X Scripting moved to Ru:Fundamental Basics of AMX Mod X Scripting: To accompany a langswitch template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
=Фундаментальные основы AMX Mod X скриптинга=&lt;br /&gt;
&lt;br /&gt;
Данная статья не дает готовых &amp;quot;рецептов&amp;quot; по [[AMX Mod X]] скриптингу, но раскрывает его фундаментальные основы. Это и типы данных, и прототипы функций и многое другое, без знания чего невозможно писать AMX Mod X плагины.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Введение=&lt;br /&gt;
&lt;br /&gt;
Прежде чем начинать писать AMX Mod X плагины, в первую очередь необходимо разобраться в основах [[Pawn]].&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Pawn – это скриптовый язык, созданный компанией [http://www.compuphase.com ITB CompuPhase]. Ранее Pawn назывался Small, но с версии 3.0 языку было решено дать более характерное название. Т.к. &amp;quot;pawn&amp;quot; в переводе с английского языка означает &amp;quot;пешка&amp;quot;, можно догадаться, что основной характерной чертой данного языка является простота.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Если вы владеете английским языком, рекомендуется ознакомиться с полным руководством по Pawn - [http://www.compuphase.com/pawn/pawn-lang.pdf Pawn The Language].&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Код плагина представляет собой текст (как правило, заключенный в файл типа *.sma), включающий множество элементов языка: комментарии, переменные, функции и др. Поэтому для оформления кода потребуется текстовый редактор. Из простейших можно выделить, например, Microsoft Notepad. Также существует AMXX-Studio – специализированый редактор для AMX Mod X плагинов, позволяющий максимально эффективно работать в соответствующей среде. Последняя версия данного редактора может быть найдена в секции [http://www.amxmodx.org/downloads.php downloads] официального сайта AMX Mod X.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Чтобы позволить AMX Mod X выполнять код, файл с кодом необходимо откомпилировать с помощью компилятора AMXXPC (AMX Mod X Pawn Compiler). Операция компилирования преобразовывает набор текстовых инструкций в последовательность инструкций абстрактной машины (от англ. abstract machine), она же AMX, а также интерпретатор (от англ. interpreter).&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Откомпилированый код обычно помещается в файл типа *.amxx, имеющий двоичный формат. Такой файл называют AMX Mod X плагином (от англ. plugin).&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Для ознакомления с инструкциями по компилированию и установке плагинов смотрите [[Ru Compiling Plugins (AMX Mod X)]] и [[Ru Configuring AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Pawn=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Уровни кода==&lt;br /&gt;
&lt;br /&gt;
В основе любого кода лежит уровневая структура. Причиной этому является нелинейность инструкций.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Т.н. &amp;quot;нулевой уровень&amp;quot; или &amp;quot;глобальное пространство&amp;quot; является неотъемлемой частью любого кода. Как только вы приступаете к написанию нового кода, вы оказываетесь в его глобальном пространстве. Оно же в свою очередь будет включать в себя пространства с более низкими уровнями.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Обычно глобальное пространство содержит всю общую информацию, которая может потребоваться в ходе выполнения кода пространствам более низкого уровня. Примером такой информации могут служить общие константы, переменные, списки, макросы.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Комментарии==&lt;br /&gt;
&lt;br /&gt;
Комментарий – это, как правило, текст информативного характера. Например, чтобы дать описание плагину можно использовать многострочный комментарий:&amp;lt;pawn&amp;gt;/* здесь вы помещаете&lt;br /&gt;
необходимую информацию */&amp;lt;/pawn&amp;gt;Как видно из примера, многострочный комментарий ограничивается символами /* и */, отмечающими начало и конец комментария соответственно. Недопустимо открывать последующий комментарий, не закрыв при этом предыдущий.&lt;br /&gt;
&amp;lt;BR&amp;gt;Примером однострочного комментария может быть:&amp;lt;pawn&amp;gt;/* ваш комментарий */&amp;lt;/pawn&amp;gt;Хотя, можно упростить конструкцию:&amp;lt;pawn&amp;gt;// ваш комментарий&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Как видно из последнего примера, комментарий начинается с двойного симовола обратного слеша //. Заканчивается такой комментарий вместе с концом текущей строки, поэтому не требует закрывающих символов. Такие комментарии могут быть только однострочными. Не обязательно комментарий должен начинаться с новой строки. Например, /* ... */ комментарий может быть расположен непосредственно в самом коде.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Т.к. комментарии не считаются кодом, они исключаются из обработки. Данная особенность позволяет при необходимости исключать части кода путем комментирования, что может быть использовано, например, при отладке кода.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Типы данных==&lt;br /&gt;
&lt;br /&gt;
Технически основой всех типов данных в Pawn является т.н. &amp;quot;cell&amp;quot; – ячейка памяти, состоящая из последовательности определенного количества бит. Количество бит в такой ячейке постоянно для определенной платформы. Так для 32х битной платформы оно будет составлять 32, а для 64х битной – 64.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Т.к. технически все данные не имеют отличия, для обозначения их типа применяются т.н. &amp;quot;тэги&amp;quot;. Если при создании переменной тэг не указан, то переменная является целым числом:&amp;lt;pawn&amp;gt;new ivar // создана целочисленная переменная с именем &amp;quot;ivar&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Если при создании переменной ей не присваивается какое-либо конкретное значение, то переменная будет равна нулю. Таким образом, вышеприведенный пример технически соответствует:&amp;lt;pawn&amp;gt;new ivar = 0&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Чтобы создать дробную переменную, необходимо использовать тэг &amp;quot;Float&amp;quot;:&amp;lt;pawn&amp;gt;new Float:fvar&amp;lt;/pawn&amp;gt;Переменная fvar также будет равна нулю, но ввиду соответствия типу данных это будет 0.0, т.е. технический аналог примера будет:&amp;lt;pawn&amp;gt;new Float:fvar = 0.0&amp;lt;/pawn&amp;gt;Таким образом, мы обеспечиваем типовое соответствие &amp;quot;левой&amp;quot; и &amp;quot;правой&amp;quot; части.&lt;br /&gt;
&amp;lt;BR&amp;gt;Одним из особых типов данных является т.н. &amp;quot;булевые&amp;quot; переменные, которые технически могут иметь только два значение, логически интерпретируемые как &amp;quot;истина&amp;quot; и &amp;quot;ложь&amp;quot; (true и false). Чтобы создать булевую переменную, необходимо использовать тэг &amp;quot;bool&amp;quot;:&amp;lt;pawn&amp;gt;new bool:bvar&amp;lt;/pawn&amp;gt;Т.к. численно false является нулем, то технический аналог примера будет выглядеть как:&amp;lt;pawn&amp;gt;new bool:bvar = false&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Примечание: чтобы запретить изменение значения переменной, необходимо использовать атрибут const, например:&amp;lt;pawn&amp;gt;new const var = 1&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Pawn также позволяет создавать массивы данных, представляющие собой набор значений определенного типа. Так примером простого массива, содержащего два целочисленных значения будет:&amp;lt;pawn&amp;gt;new array[2]&amp;lt;/pawn&amp;gt;Технически данный пример выглядит следующим образом:&amp;lt;pawn&amp;gt;new array[2] = {0, 0}&amp;lt;/pawn&amp;gt;Технические аналоги для Float и bool массивов выглядят как:&amp;lt;pawn&amp;gt;new Float:farray[2] = {0.0, 0.0}&lt;br /&gt;
new bool:barray[2] = {false, false}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Также существует особый тип данных, называемый &amp;quot;строка&amp;quot;, технически являющийся массивом целых чисел. Каждое целое число в строковом массиве соответствует числовому ASCII коду символа. Например, код 32 соответствует пробелу. Таким образом,&amp;lt;pawn&amp;gt;new string[3] = {'h', 'i', '^0'}&amp;lt;/pawn&amp;gt;является символьным представлением строкового массива&amp;lt;pawn&amp;gt;new string[3] = &amp;quot;hi&amp;quot;&amp;lt;/pawn&amp;gt;Обратите внимание на наличие специального символа '^0'. Это обязательный элемент строки, указывающий на ее окончание (численно равен нулю).&lt;br /&gt;
&amp;lt;BR&amp;gt;Также Pawn поддерживает многоуровневые массивы, например:&amp;lt;pawn&amp;gt;new multiarray[2][2]&amp;lt;/pawn&amp;gt;Технически такой массив равен:&amp;lt;pawn&amp;gt;new multiarray[2][2] = {{0, 0}, {0, 0}}&amp;lt;/pawn&amp;gt;Максимальное количество уровней массива равно 3.&lt;br /&gt;
&amp;lt;BR&amp;gt;Для любого явно заданного массива его размер может не указываться, например:&amp;lt;pawn&amp;gt;new array[] = {1, 2, 3} // размер массива равен 3&lt;br /&gt;
new string[] = &amp;quot;hello&amp;quot; // размер массива равен 6, т.к. помимо 5 символов также включает в себя символ окончания строки '^0'&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Чтобы инициализировать все элементы массива каким-либо конкретным значением, можно использовать символ троеточия ..., например:&amp;lt;pawn&amp;gt;new bool:is_active[16] = {true, ...}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Прекомпиляция==&lt;br /&gt;
&lt;br /&gt;
На начальной стадии компилирования Pawn компилятор обрабатывает т.н. &amp;quot;статическую&amp;quot; часть кода. К ней можно отнести директивы, глобальные константы, списки и др.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Директивы являются специальными инструкциями компилятора. Одна из самых широко используемых директив – это &amp;quot;include&amp;quot;. Пример ее использования может быть следующим:&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&amp;lt;/pawn&amp;gt;Директива как бы &amp;quot;влаживает&amp;quot; содержимое указанного файла в текущую позицию. В данном случае указывается файл amxmodx.inc, который обычно расположен в amxmodx\scripting\include директории, и декларирует основные AMX Mod X функции.&lt;br /&gt;
&amp;lt;BR&amp;gt;Другая директива, позволяющая конструировать т.н. &amp;quot;макросы&amp;quot;, имеет название &amp;quot;define&amp;quot;. Макрос удобен тем, что способен заменять простые блоки кода. Один из простейших макросов – это т.н. &amp;quot;макроконстанта&amp;quot;, например:&amp;lt;pawn&amp;gt;#define VALUE 1&amp;lt;/pawn&amp;gt;В названиях макросов принято использовать буквы только верхнего регистра.&lt;br /&gt;
&amp;lt;BR&amp;gt;Нетехническим аналогом вышеприведенной макроконстанты является т.н. &amp;quot;глобальная константа&amp;quot;:&amp;lt;pawn&amp;gt;stock const value = 1&amp;lt;/pawn&amp;gt;stock атрибут позволяет не включать константу в плагин, если она не используется в коде.&lt;br /&gt;
&amp;lt;BR&amp;gt;Т.н. &amp;quot;список&amp;quot; – это набор нумерованных элементов определенного типа. Например:&amp;lt;pawn&amp;gt;enum {zero, one, two} // соответствует 0, 1, 2&lt;br /&gt;
enum {elem1 = 1, elem2, elem3} // соответствует 1, 2, 3&lt;br /&gt;
enum steeps {steep1 = 10, steep2 = 20} // соответствует 10, 20&amp;lt;/pawn&amp;gt;Тип списка (в вышеприведенном примере типом списка является steeps) – необязательный атрибут, по сути является тэгом, указывающим тип элементов, поэтому следующий пример является верным:&amp;lt;pawn&amp;gt;new steeps:steep = steep2&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Функции==&lt;br /&gt;
&lt;br /&gt;
Существует несколько типов функций.&lt;br /&gt;
*т.н. &amp;quot;'''обычная'''&amp;quot; – обычно т.н. &amp;quot;вспомогательная&amp;quot; функция; может быть вызвана непосредственно только другими функциями данного плагина; не может быть вызвана непосредственно AMX Mod X либо его модулями.&lt;br /&gt;
*'''public''' – обычно функция, вызываемая непосредственно AMX Mod X либо его модулями; может быть также вызвана непосредственно другими функциями данного плагина.&lt;br /&gt;
*'''native''' – функция, имеющая т.н. &amp;quot;глобальный&amp;quot; характер; может быть вызвана AMX Mod X плагинами.&lt;br /&gt;
*'''forward''' - функция, имеющая т.н. &amp;quot;глобальный&amp;quot; характер; при наличии в плагине public функции с соответствующим именем функция будет вызываться AMX Mod X или его модулями.&lt;br /&gt;
*'''stock''' – обычно функция, состоящая в т.н. &amp;quot;библиотеке&amp;quot; функций; не включается в плагин, если не используется в коде.&lt;br /&gt;
&amp;lt;BR&amp;gt;В общем виде заголовок, а также прототип любой функции условно выглядит следующим образом (символами треуголных скобок &amp;lt;&amp;gt; ограничены обязательные элементы, символами квадратных скобок [] ограничены необязательные элементы, которые могут быть опущены в определенных случаях):&amp;lt;pawn&amp;gt;[type] [tag]:&amp;lt;name&amp;gt;([[param1], [param2], ..., [paramN]])&amp;lt;/pawn&amp;gt;, где&lt;br /&gt;
*[type] – соответствует типу функции (для обычной функции тип не указывается)&lt;br /&gt;
*[tag] – соответствует типу данных возвращаемого результата функции&lt;br /&gt;
*&amp;lt;name&amp;gt; - соответствует имени функции&lt;br /&gt;
*([...]) – соответствует набору параметров функции; количество параметров может быть от нуля (параметры отсутствуют) до N, где N – целое положительное число&lt;br /&gt;
&amp;lt;BR&amp;gt;За заголовком функции следует т.н. &amp;quot;тело&amp;quot; функции, ограниченное символами фигурных скобок {}. Таким образом, примером простейшей функции является:&amp;lt;pawn&amp;gt;function()&lt;br /&gt;
{&lt;br /&gt;
	// это пустое тело функции, имеющей имя &amp;quot;function&amp;quot;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;Технически данная функция не выполняет никаких действий, т.к. в своем теле содержит только комментарий. Обратите внимание, что комментарий как бы сдвинут вправо относительно заголовка функции. В данном случае функция инициализирует новый уровень кода. Каждый уровень кода в целях удобочитаемости принято оформлять с соответствующим отступом. Чем более низкий уровень кода, тем больший отступ он будет иметь. Обычно в качестве отступа принято использовать символ табуляции, т.к. многие редакторы позволяют задавать видимую ширину табулированого отступа.&lt;br /&gt;
&amp;lt;BR&amp;gt;Существует два способа передачи параметров функции. Т.н. &amp;quot;основной&amp;quot; способ заключается в том, что при передаче данные дублируются путем создания соответствующих копий в памяти. Т.н. способ передачи параметров &amp;quot;по ссылке&amp;quot; (от англ. by reference) состоит в том, что данные передаются &amp;quot;как есть&amp;quot;, т.е. их дублирования не осуществляется, что позволяет функции изменять оригинальные данные непосредственно.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Для параметров функции все типы массивов, в том числе и строковые, могут передаваться исключительно по ссылке. Передача остальных данных по умолчанию осуществляется основным способом. Чтобы произвести передачу параметра функции по ссылке, в заголовке функции перед параметром необходимо добавлять символ амперсанда &amp;amp;, например:&amp;lt;pawn&amp;gt;function(&amp;amp;Float:fparam)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Параметры функции могут иметь значения по умолчанию, например:&amp;lt;pawn&amp;gt;function(param = 1)&amp;lt;/pawn&amp;gt;Таким образом, чтобы вызвать данную функцию с параметром по умолчанию, параметр можно не указывать:&amp;lt;pawn&amp;gt;function()&amp;lt;/pawn&amp;gt;Также в таких случаях можно использовать символ подчеркивания _:&amp;lt;pawn&amp;gt;function(_)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Чтобы запретить функции изменение передаваемых данных, необходимо использовать атрибут const, например:&amp;lt;pawn&amp;gt;function(const array[])&amp;lt;/pawn&amp;gt;Таким образом, можно утверждать, что в данном случае целью функции не является изменение данных массива, чего нельзя утверждать о следующей функции:&amp;lt;pawn&amp;gt;swaparray(array[2])&amp;lt;/pawn&amp;gt;Исходя из названия функции, типа параметра, его размера и отсутствия запрета на изменение, можно сделать предположение о том, что данная функция меняет элементы массива местами.&lt;br /&gt;
&amp;lt;BR&amp;gt;Важным свойством функции является способность возвращать результат, значение которого имеет определенный тип, например:&amp;lt;pawn&amp;gt;bool:is_true()&lt;br /&gt;
{&lt;br /&gt;
	return true&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Чтобы указать допустимые типы параметра функции, в заголовке функции перед параметром необходимо добавлять конструкцию, которая условно выглядит как {tag1, tag2, ..., tagN}:, т.е. представляет собой набор тэгов, количество которых может быть от одного до N, где N – целое положительное число, например:&amp;lt;pawn&amp;gt;get_integer({bool, _}:value)&lt;br /&gt;
{&lt;br /&gt;
	return _:value // возвращается значение типа &amp;quot;целое число&amp;quot;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;Смысл вышеприведенной функции заключается в том, что она принимает параметр как типа &amp;quot;целое число&amp;quot;, так и булевого типа, в результате возвращая значение параметра в числовой форме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=AMX Mod X=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Функции==&lt;br /&gt;
&lt;br /&gt;
При написании AMX Mod X плагинов важно уметь понимать назначение и принцип действия AMX Mod X функций.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Прототипы функций, а также используемые ими константы и списки заключены в файлы типа *.inc, т.н. &amp;quot;инклуды&amp;quot; (от англ. include), которые обычно расположены в amxmodx\scripting\include директории.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Иногда одни инклуды включают в себя другие. Так основные AMX Mod X функции (т.н. функции AMX Mod X &amp;quot;ядра&amp;quot;) продекларированы в файле amxmodx.inc, который также включает векторные и другие инклуды, декларирующие функции, константы и списки, также имеющие непосредственное отношение к AMX Mod X ядру.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Одной из основных функций AMX Mod X является forward функция plugin_init. Если в коде плагина имеется public функция plugin_init, она будет вызвана AMX Mod X после загрузки карты на сервере. Обычно в plugin_init регистрируют сам плагин, его команды, переменные и т.п.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Плагин регистрируют с помощью native функции register_plugin. Т.к. прототип register_plugin соответствует:&amp;lt;pawn&amp;gt;native register_plugin(const plugin_name[], const version[], const author[])&amp;lt;/pawn&amp;gt;, можно понять, что в качестве параметров функция принимает три строковых массива, соответствующих названию плагина, номеру его версии и автору плагина.&lt;br /&gt;
&amp;lt;BR&amp;gt;Итак, примером простого AMX Mod X плагина является:&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	register_plugin(&amp;quot;Test&amp;quot;, &amp;quot;0.1&amp;quot;, &amp;quot;VEN&amp;quot;)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;По сути данный плагин не выполняет каких-либо действий, но регистрирует себя в AMX Mod X с указанными данными.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Системы функционирования==&lt;br /&gt;
&lt;br /&gt;
AMX Mod X предоставляет большое количество определенных систем функционирования. Так одна из основных систем – это система контроля уровней доступа. Здесь имеют место соответствующие функции, например get_user_flags, а также константы стандартных уровней доступа типа ADMIN_*.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Система регистрирования и контроля консольных команд также &amp;quot;пересекается&amp;quot; с системой контроля уровней доступа и использует такие функции, как например register_concmd и cmd_access.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Также существует множество других систем, среди которых имеется система регистрирования и контроля серверных консольных переменных (англ.: Server CVars), клиентских меню и др.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Как правило, системы регистрирования используют т.н. &amp;quot;handle&amp;quot; (или &amp;quot;hook&amp;quot;) функции, которые вызываются системой в необходимый момент.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Так после регистрирования консольной команды &amp;quot;action&amp;quot;:&amp;lt;pawn&amp;gt;register_concmd(&amp;quot;action&amp;quot;, &amp;quot;action_handler&amp;quot;)&amp;lt;/pawn&amp;gt;при исполнении данной команды из консоли сервера или клиента система попытается найти и выполнить public функцию action_handler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Система строкового форматирования==&lt;br /&gt;
&lt;br /&gt;
Многие AMX Mod X функции используют систему строкового форматирования. Например, это все *_print функции.&lt;br /&gt;
&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;Такие функции принимают практически неограниченное количество параметров, которые используются при форматировании соответствующей строковой конструкции. Для наглядности рассмотрим пример:&amp;lt;pawn&amp;gt;server_print(&amp;quot;Formatted string: %d %f %s %c&amp;quot;, 1, 1.234567, &amp;quot;hello&amp;quot;, '!')&amp;lt;/pawn&amp;gt;Функция server_print отформатирует строковую конструкцию &amp;quot;Formatted string: %d %f %s %c&amp;quot;, используя переданные параметры, и выведет в серверной консоли строку:&amp;lt;pawn&amp;gt;Formatted string: 1 1.234567 hello !&amp;lt;/pawn&amp;gt;Таким образом, %d, %f, %s, %c – специальные элементы, используемые для форматирования целого числа, дробного числа, строки и символа соответственно.&lt;br /&gt;
&amp;lt;BR&amp;gt;Опасно при использовании функций, поддерживающих форматирование, передавать строковую переменную непосредственно в параметр строковой конструкции, например:&amp;lt;pawn&amp;gt;server_print(string)&amp;lt;/pawn&amp;gt;Безопасный вариант выглядит, следующим образом:&amp;lt;pawn&amp;gt;server_print(&amp;quot;%s&amp;quot;, string)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Т.к. символ процента % является, т.н. &amp;quot;специальным символом&amp;quot;, для его форматирования в строковой конструкции необходимо использовать двойной символ процента %%, например:&amp;lt;pawn&amp;gt;server_print(&amp;quot;This is a single symbol of percent: %%&amp;quot;)&amp;lt;/pawn&amp;gt;выведет в серверной консоли:&amp;lt;pre&amp;gt;This is a single symbol of percent: %&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;Также существует т.н. &amp;quot;контрольный символ&amp;quot; (от англ. control character), позволяющий использовать т.н. &amp;quot;специальные символы форматирования&amp;quot;. Контрольным символом по умолчанию является символ ^, который может быть изменен директивой pragma ctrlchar, например:&amp;lt;pre&amp;gt;#pragma ctrlchar '\'&amp;lt;/pre&amp;gt;изменит контрольный символ на \.&lt;br /&gt;
&amp;lt;BR&amp;gt;Примеры некоторых специальных символов форматирования приведены ниже:&lt;br /&gt;
*^t – табуляция&lt;br /&gt;
*^n – новая строка&lt;br /&gt;
*^xHH – символ, представленный в шестнадцатиричном формате, где HH – двойное число, представленное в шестнадцатиричном формате&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting&amp;diff=6393</id>
		<title>Ru Fundamental Basics of AMX Mod X Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting&amp;diff=6393"/>
		<updated>2008-11-07T15:59:24Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Ru Fundamental Basics of AMX Mod X Scripting moved to Ru:Fundamental Basics of AMX Mod X Scripting: To accompany a langswitch template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Ru:Fundamental Basics of AMX Mod X Scripting]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Small&amp;diff=6391</id>
		<title>Ru:Small</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Small&amp;diff=6391"/>
		<updated>2008-11-07T15:58:06Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
Small - это бывшее название скриптового языка [[Pawn Tutorial|Pawn]], разработанного фирмой [http://www.compuphase.com/ ITB CompuPhase]. Имя было изменено, начиная с версии 3.0 в июле 2005 года, чтобы сделать его более уникальным.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Small&amp;diff=6390</id>
		<title>Small</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Small&amp;diff=6390"/>
		<updated>2008-11-07T15:57:30Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: + LanguageSwitch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Scripting (AMX Mod X)]]&lt;br /&gt;
{{LanguageSwitch}}&lt;br /&gt;
Small was the former name of the [[Pawn Tutorial|Pawn]] scripting language provided by [http://www.compuphase.com/ ITB CompuPhase].  The name was changed with version 3.0 in July, 2005, to make the name more unique.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Small&amp;diff=6389</id>
		<title>Ru:Small</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Small&amp;diff=6389"/>
		<updated>2008-11-07T15:56:36Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Ru:Scripting (AMX Mod X) Small - это бывшее наимнование скриптового языка Pawn, разработанного фирмой...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
Small - это бывшее наимнование скриптового языка [[Pawn Tutorial|Pawn]], разработанного фирмой [http://www.compuphase.com/ ITB CompuPhase]. Имя было изменено, начиная с версии 3.0 в июле 2005 года, чтобы сделать его более уникальным.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6388</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6388"/>
		<updated>2008-11-07T15:48:55Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
== Введение ==&lt;br /&gt;
[[Admin-Mod]] и [[AMX Mod X]] стали очень поплулярными из-за используемого в них скриптового языка, который прост в изучении. Однако, словосочетание &amp;quot;скриптовый язык&amp;quot; обычно ассоциируется со следующими устойчивыми понятиями:&lt;br /&gt;
*Невозможно сделать его быстрее&lt;br /&gt;
*Он прекомпилируемый, значит уже быстрый в исполнении&lt;br /&gt;
*Детали и мелочи не важны, т.к. это всего лишь &amp;quot;скрипт&amp;quot;&lt;br /&gt;
&lt;br /&gt;
В отношении [[Pawn]] (ранее известный как [[Small]]), особенно, ничто из вышеперечисленного верно.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
=== Термины ===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
===Always Save Results===&lt;br /&gt;
Observe the example code snippet below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This is a mild example of &amp;quot;cache your results&amp;quot;.  When the compiler generates assembly for this code, it will (in pseudo code) generate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice the problem?  We have called &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; an extra two times than necessary.  The result doesn't change, so we can save it.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Now, the compiler will only generate this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; were an expensive operation (it's relatively cheap), we would have recalculated the entire result each branch of the &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.&lt;br /&gt;
&lt;br /&gt;
===Switch instead of If===&lt;br /&gt;
If you can, you should use &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; cases instead of &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6387</id>
		<title>Оптимизация Плагинов (AMX Mod X Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=%D0%9E%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%9F%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2_(AMX_Mod_X_Scripting)&amp;diff=6387"/>
		<updated>2008-11-07T15:42:16Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: fixed category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
==Introduction==&lt;br /&gt;
[[Admin-Mod]] and [[AMX Mod X]] became very popular because of their easy to use scripting language.  However, the words &amp;quot;scripting language&amp;quot; come with a lot of loaded preconceptions.  Most people assume that because it's scripted:&lt;br /&gt;
*You can't possibly make it any faster&lt;br /&gt;
*It's pre-compiled, so it's already quite fast&lt;br /&gt;
*Details don't matter, as it's only &amp;quot;scripting&amp;quot; anyway&lt;br /&gt;
&lt;br /&gt;
Especially, with [[Pawn]] (formerly Small), none of these are true.  The compiler, in fact, is very poor at optimizing, and you can '''greatly''' increase the speed and efficiency of your plugins by keeping a few rules in mind.  Remember - it's more important to minimize instructions than it is to minimize lines of code.&lt;br /&gt;
&lt;br /&gt;
===Terms===&lt;br /&gt;
To read this document, you will need to understand a few concepts beforehand:&lt;br /&gt;
*&amp;lt;tt&amp;gt;BRANCHING&amp;lt;/tt&amp;gt; - When the processor takes a different path of code.  For example, to call a function or to use an if statement, the processor will &amp;quot;branch&amp;quot;.  Modern processors attempt to predict pathways with &amp;quot;branch prediction&amp;quot;, but it's best to avoid branching a lot if possible.&lt;br /&gt;
*&amp;lt;tt&amp;gt;STACK ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, all local data is stored on the stack, a big chunk of continuous memory.  Whenever you create a variable on the stack, it is automatically written with zeroes.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HEAP ALLOCATION&amp;lt;/tt&amp;gt; - In Pawn, temporary data that needs to be referenced by a native is stored on the heap, another area of contiguous, but less restrictive memory.&lt;br /&gt;
*&amp;lt;tt&amp;gt;DATA SECTION&amp;lt;/tt&amp;gt; - This is an area of memory built into your .amxx file.  In fact, it &amp;quot;becomes&amp;quot; the heap at load time.  All your strings and arrays are hardcoded into this area.&lt;br /&gt;
*&amp;lt;tt&amp;gt;EXPENSIVENESS&amp;lt;/tt&amp;gt; - To be &amp;quot;expensive&amp;quot; in computer science means an operation requires a lot of CPU processing.  It usually does not refer to memory size, only to processing cycles and time.  Addition is inexpensive, floating power operations are expensive.  However, both are inexpensive in comparison to writing a file.  An inexpensive operation can also be called &amp;quot;cheap&amp;quot;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;BIG-OH NOTATION&amp;lt;/tt&amp;gt; - O(*) notation refers to the expensiveness of an algorithm.  If something is O(n), it occurs in linear time -- meaning that for N items, it will complete relative to N.  O(N^2) means with N items, it will complete relative to N^2.  O(1) means &amp;quot;constant time&amp;quot; - no matter what N is, it will run in the same amount of time.&lt;br /&gt;
&lt;br /&gt;
==Compiler Optimizations==&lt;br /&gt;
These optimizations have to do with changing how your code is compiled.  While the syntax may remain the same, you are not only increasing compile time, but increasing your plugin's efficiency and speed at run time.&lt;br /&gt;
&lt;br /&gt;
===Always Save Results===&lt;br /&gt;
Observe the example code snippet below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (get_user_team(player) == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (get_user_team(player) == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This is a mild example of &amp;quot;cache your results&amp;quot;.  When the compiler generates assembly for this code, it will (in pseudo code) generate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice the problem?  We have called &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; an extra two times than necessary.  The result doesn't change, so we can save it.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
if (team == TEAM_T)&lt;br /&gt;
{&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_CT) {&lt;br /&gt;
    //...code&lt;br /&gt;
} else if (team == TEAM_SPECTATOR) {&lt;br /&gt;
    //...code&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Now, the compiler will only generate this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
  COMPARE+BRANCH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If &amp;lt;tt&amp;gt;get_user_team&amp;lt;/tt&amp;gt; were an expensive operation (it's relatively cheap), we would have recalculated the entire result each branch of the &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.&lt;br /&gt;
&lt;br /&gt;
===Switch instead of If===&lt;br /&gt;
If you can, you should use &amp;lt;tt&amp;gt;switch&amp;lt;/tt&amp;gt; cases instead of &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.  This is because for an if statement, the compiler must branch to each consecutive &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; case.  Using the example from above, observe the switch version:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new team = get_user_team(player)&lt;br /&gt;
switch (team)&lt;br /&gt;
{&lt;br /&gt;
  case TEAM_T:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_CT:&lt;br /&gt;
     //code...&lt;br /&gt;
  case TEAM_SPECTATOR:&lt;br /&gt;
     //code...&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will generate what's called a &amp;quot;case table&amp;quot;.  Rather than worm through displaced &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; tests, the compiler generates a table of possible values, which the virtual machine knows to browse through:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CALL get_user_team&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
  COMPARE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Don't Re-index Arrays===&lt;br /&gt;
A common practice in Small is to &amp;quot;save space&amp;quot; by re-indexing arrays.  There are a few myths behind this, such as saving memory, assuming the compiler does it for you, or readability.  Fact: none of these are true.  Observe the code below:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new players[32], num, team&lt;br /&gt;
get_players(players, num)&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   if (!is_user_connected(players[i]))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(players[i])&lt;br /&gt;
   set_user_frags(players[i], 0)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
For this, the compiler generates code similar to:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
See what happened?  The compiler does not cache array indexing.  Because we've used &amp;lt;tt&amp;gt;players[i]&amp;lt;/tt&amp;gt; each time, every instance generates 4-6 (or more) instructions which load &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;, the address of &amp;lt;tt&amp;gt;players&amp;lt;/tt&amp;gt;, computes the final location, and then grabs the data out of memory.  It is much faster to do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   if (!is_user_connected(player))&lt;br /&gt;
      continue;&lt;br /&gt;
   team = get_user_team(player)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Not only is this more readable, but look at how much cruft we've shaved off the compiler's generated code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:LOOP_BEGIN&lt;br /&gt;
   LOAD i&lt;br /&gt;
   LOAD players&lt;br /&gt;
   CALC&lt;br /&gt;
   LOAD players[i]&lt;br /&gt;
   STORE player&lt;br /&gt;
   CALL is_user_connected&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL get_user_team&lt;br /&gt;
   LOAD player&lt;br /&gt;
   CALL set_user_frags&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In a large loop you can drastically reduce codesize in this manner.&lt;br /&gt;
&lt;br /&gt;
===Global vs Local and Variables in Loops===&lt;br /&gt;
It is important to realize that every variable in [[Pawn]] is automatically zeroed.  For global variables, they are static and permanent, thus they are zeroed when your plugin is loaded.  Variables in functions, however, must be zeroed dynamically.  This is a slow and tedious operation, and you should not only avoid relying on it when necessary, but you should keep that fact in mind when using arrays.&lt;br /&gt;
&lt;br /&gt;
[[Arrays]] in [[Pawn]] are &amp;quot;cells&amp;quot; of data.  Each cell is four or eight bytes, depending on whether your processor is 32bit or 64bit.  To create an array of 4096 cells, for example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new array[4096]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The compiler generates code to manually zero every single one of the 16,384 bytes in that location.  Normally, this isn't too bad -- but it can be absolutely deadly in a function which is called quite often.  For example, &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is called on every [[server tick]] in [[AMX Mod X]].  To declare an array of that size in &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; is highly unnecessary.  Instead, you can take advantage of the fact that not only are globals free of charge, but &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; does not need to be re-entrant.  That is, you will never call &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt; inside of &amp;lt;tt&amp;gt;server_frame&amp;lt;/tt&amp;gt;, so making the variable global will not bring up the problem of one instance of the function overwriting data from another instance of the same function.  Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_serverframe_array[4096]&lt;br /&gt;
public server_frame()&lt;br /&gt;
{&lt;br /&gt;
  //...code that uses g_serverframe_array&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will execute conseridably faster.  You can do this with smaller arrays too.&lt;br /&gt;
&lt;br /&gt;
Likewise, it is equally important to avoid declaring arrays inside of loops.  Consider the following block of code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   new message[255], name[32], player&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If there are 32 players, this loop will actually resize and zero out over 1K of memory thirty two times in a row.  Not good!  However, on the other hand, it's nice that the message is zeroed out for us each time.  &amp;lt;tt&amp;gt;Tip:&amp;lt;/tt&amp;gt; you often only need to zero out the first character of a string.  This will make the entire string empty.  The code below is much more efficient:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new message[255], name[32], player&lt;br /&gt;
for (new i=0; i&amp;lt;num; i++)&lt;br /&gt;
{&lt;br /&gt;
   player = players[i]&lt;br /&gt;
   name[0] = '^0'&lt;br /&gt;
   message[0] = '^0'&lt;br /&gt;
   get_user_name(player, name, 31)&lt;br /&gt;
   format(message, 254, &amp;quot;Hello, %s&amp;quot;, name)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This has the effect of safely making the string empty beforehand, as well as largely reducing a lot of run-time overhead.&lt;br /&gt;
&lt;br /&gt;
===Static vs Global===&lt;br /&gt;
An alternative to global variables is static variables, which are internally the same but easier to work with for programming.&lt;br /&gt;
&lt;br /&gt;
A variable declared with the keyword &amp;quot;static&amp;quot; instead of &amp;quot;new&amp;quot; operates in the same way a global does (it is created only once) but the variable is local to the function; this means the code is much easier to read, while drastically improving speed just like a global variable.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock SomeBigFunction()&lt;br /&gt;
{&lt;br /&gt;
   static gaben[255];&lt;br /&gt;
   format(gaben, &amp;quot;%L&amp;quot;, LANG_SERVER, &amp;quot;STUFF&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has the same effect as declaring &amp;lt;tt&amp;gt;gaben&amp;lt;/tt&amp;gt; as global, except only &amp;lt;tt&amp;gt;SomeBigFunction&amp;lt;/tt&amp;gt; can use it.  &lt;br /&gt;
&lt;br /&gt;
{{qnotice|Be careful of re-entrancy!}}&lt;br /&gt;
When a variable is static, it has the same re-entrancy problems of a global variable.  That means, if your function might be called recursively, or twice in the same stack frame, you should not use static variables.  This is most often the case for API provided to other plugins or helper functions.  Triggered events are usually never called twice on the same execution chain.&lt;br /&gt;
&lt;br /&gt;
===Constant variables===&lt;br /&gt;
You can declare a variable &amp;quot;constant&amp;quot; by adding the &amp;quot;const&amp;quot; keyword before the variable name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does is prevents the variable from being changed; essentially, you've locked the variable to a certain value. In this way, a constant can offer a type safe method of simplifying code, unlike a define, which is not type safe.&lt;br /&gt;
&lt;br /&gt;
In addition, constant variables are often optimized out, resulting in quicker and smaller code.&lt;br /&gt;
&lt;br /&gt;
===For Loop Comparisons===&lt;br /&gt;
A common mistake is to write code like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
for (new i=0; i&amp;lt;strlen(string); i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This plays off a similar principle from before: cache results.  The compiler will actually recompute your string length on each iteration of the loop.  This will have even worse effects if your string changes mid-loop.  A more sensible method is:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new string[256] = &amp;quot;something long&amp;quot;&lt;br /&gt;
new len = strlen(string)&lt;br /&gt;
for (new i=0; i&amp;lt;len; i++)&lt;br /&gt;
   //...code&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tips and Tricks==&lt;br /&gt;
===Lookup Tables===&lt;br /&gt;
Precompute what can be precomputed.  For example, say you have a mapping of weapon indices to names:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (weapon == CSW_AK47)&lt;br /&gt;
   copy(name, len, &amp;quot;weapon_ak47&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Ignoring the fact that we have &amp;lt;tt&amp;gt;get_weapon_name&amp;lt;/tt&amp;gt; in [[AMX Mod X]], this is inefficient.  We could precompute this result in a table:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_WeaponNamesTable[TOTAL_WEAPONS][] = {&lt;br /&gt;
   //..0 to CSW_AK47-1&lt;br /&gt;
   &amp;quot;weapon_ak47&amp;quot;,&lt;br /&gt;
   //..CSW_AK47+1 to TOTAL_WEAPONS-1&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Perfect Hashing===&lt;br /&gt;
:TODO: explain this&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Local Strings===&lt;br /&gt;
The [[Pawn]] compiler does not optimize the DATA section, which stores all hardcoded strings and global arrays.  If you reference the same hardcoded string 500 times in your plugin, it will appear 500 different times.  If this seems bad enough, it actually does this with all strings.  For example, the empty string (&amp;quot;&amp;quot;) appears everywhere in the include files, usually used as a default parameter to many natives.  This too is copied into the data section for each unique reference.  &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_cvar_num(&amp;quot;amx_gaben&amp;quot;, get_cvar_num(&amp;quot;amx_gaben&amp;quot;) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This will create two copies of &amp;quot;amx_gaben&amp;quot; in the DATA section.  While this doesn't really hurt, it does increase the size of your plugin.  &lt;br /&gt;
&lt;br /&gt;
Similarly, this has the same problem:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define AMX_GABEN &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
The only way to avoid this mess is to use global variables.  As stated earlier, they're basically free storage.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, while not necessary, this will reduce your plugin's size in memory and on disk.  If you're already using defines, you can make this switch easily.&lt;br /&gt;
&lt;br /&gt;
In order to prevent this from changing, you may want to declare it constant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new const AMX_GABEN[] = &amp;quot;amx_gaben&amp;quot;&lt;br /&gt;
set_cvar_num(AMX_GABEN, get_cvar_num(AMX_GABEN) + 1)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it is a perfectly safe method of storage.&lt;br /&gt;
&lt;br /&gt;
==Faster Natives==&lt;br /&gt;
AMX Mod X replaces many of the old AMX Mod natives with faster versions.  Read below to discover them.&lt;br /&gt;
&lt;br /&gt;
===Cvar Pointers===&lt;br /&gt;
As of AMX Mod X 1.70, you can cache &amp;quot;cvar pointers&amp;quot;.  These are direct accesses to cvars, rather than named access.  This is a critical optimization which is dozens of times faster.  For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new g_enabled = register_cvar(&amp;quot;csdm_enabled&amp;quot;, &amp;quot;1&amp;quot;)&lt;br /&gt;
//OR&lt;br /&gt;
new g_enabled = get_cvar_pointer(&amp;quot;csdm_enabled&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
stock SetCSDM(num)&lt;br /&gt;
   set_pcvar_num(g_enabled, num)&lt;br /&gt;
&lt;br /&gt;
stock GetCSDM()&lt;br /&gt;
   return get_pcvar_num(g_enabled)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
All of the cvar* functions (except for set_cvar_string) are mapped to [get|set]_pcvar_*.  You can get a cached cvar pointer with get_cvar_pointer() or register_cvar().&lt;br /&gt;
&lt;br /&gt;
===FormatEX===&lt;br /&gt;
As of AMX Mod X 1.70, there is an ultra high-speed version of format() called formatex().  It skips copy-back checking, unlike format().  formatex() cannot be used if a source input is the same as the output buffer.  For example, these are invalid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new buffer[255]&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
formatex(buffer, 254, buffer);&lt;br /&gt;
formatex(buffer, 254, &amp;quot;%d %s&amp;quot;, buffer[2]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be noted that format() will behave the same as formatex() if it detects that there will be no copy-back needed.  However, formatex() does not check this, and thus is slightly faster for situations where the coder is sure of its usage.&lt;br /&gt;
&lt;br /&gt;
===File Writing===&lt;br /&gt;
As of AMX Mod X 1.70, there are new natives for file writing.  Read_file and write_file are O(n^2) functions for consecutive read/writes.  fopen(), fgets(), fputs(), and fclose() are O(n) (or better) depending on how you use them.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_Compiling_Plugins_(AMX_Mod_X)&amp;diff=6386</id>
		<title>Ru Compiling Plugins (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_Compiling_Plugins_(AMX_Mod_X)&amp;diff=6386"/>
		<updated>2008-11-07T15:40:11Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Ru:Compiling Plugins (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Compiling_Plugins_(AMX_Mod_X)&amp;diff=6385</id>
		<title>Ru:Compiling Plugins (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Compiling_Plugins_(AMX_Mod_X)&amp;diff=6385"/>
		<updated>2008-11-07T15:39:40Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Russian Category:Ru:Scripting (AMX Mod X) Просмотреть оригинал статьи (англ.): Compiling Plugins (AMX Mod X)  =Компилировани...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
Просмотреть оригинал статьи (англ.): [[Compiling Plugins (AMX Mod X)]]&lt;br /&gt;
&lt;br /&gt;
=Компилирование плагинов=&lt;br /&gt;
&lt;br /&gt;
Эта статья описывает, как компилировать [[AMX Mod X]] плагины из [[Ru:source code|исходного кода]] (.sma).&lt;br /&gt;
&lt;br /&gt;
Для всех случаев вы должны поместить .sma файл в директорию addons/amxmodx/scripting.&lt;br /&gt;
&lt;br /&gt;
=Windows=&lt;br /&gt;
&lt;br /&gt;
==Метод перетаскивания==&lt;br /&gt;
#Перетащите .sma файл на &amp;quot;compile.exe&amp;quot;.&lt;br /&gt;
#Откомпилированный .amxx файл будет находиться в директории compiled.&lt;br /&gt;
&lt;br /&gt;
==Компилирование всех плагинов==&lt;br /&gt;
#Дважды щелкните на compile.exe, чтобы откомпилировать все плагины и поместить их в директорию compiled.&lt;br /&gt;
==Командная строка==&lt;br /&gt;
#Зайдите в &amp;quot;Пуск&amp;quot;, &amp;quot;Выполнить&amp;quot;, введите &amp;quot;cmd&amp;quot;, нажмите Ok.&lt;br /&gt;
#Используйте cd, чтобы сменить директорию, например: &amp;lt;pre&amp;gt;cd c:\hlserver\cstrike\addons\amxmodx\scripting&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Используйте amxxpc, чтобы откомпилировать плагин: &amp;lt;pre&amp;gt;amxxpc.exe myplugin.sma&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Откомпилированный плагин будет в этой же директории.&lt;br /&gt;
&lt;br /&gt;
=Linux=&lt;br /&gt;
&lt;br /&gt;
Сперва перейдите в scripting директорию в вашей оболочке следующим образом: &amp;lt;pre&amp;gt;cd addons/amxmodx/scripting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Компилирование всех плагинов==&lt;br /&gt;
#Запустите скрипт compile.sh одним из способов: &amp;lt;pre&amp;gt;sh compile.sh&amp;lt;/pre&amp;gt; или &amp;lt;pre&amp;gt;chmod +x compile.sh&lt;br /&gt;
        ./compile.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Компилирование одиночного плагина==&lt;br /&gt;
#Запустите amxxpc, например: &amp;lt;pre&amp;gt;./amxxpc myplugin.sma&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Откомпилированный плагин будет в этой же директории.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Ru:Scripting_(AMX_Mod_X)&amp;diff=6384</id>
		<title>Category:Ru:Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Ru:Scripting_(AMX_Mod_X)&amp;diff=6384"/>
		<updated>2008-11-07T15:32:51Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
[[AMX Mod X]] позволяет расширять функциональность игры плагинами. Ниже приведен список некторых статей, которые помогут вам писать плагины используя [[Pawn]] (ранее называвшийся [[Small]]).&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6383</id>
		<title>Ru:Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6383"/>
		<updated>2008-11-06T10:34:38Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Руководство по Subversion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
Добро пожаловать в AMWiki, единый и совместный проект документаций AlliedModders, который объединяет такие проекты, как [[AMX Mod X]], [[Metamod:Source]], и [[SourceMod]].&lt;br /&gt;
&lt;br /&gt;
С чего вам начать? Смотрите ниже, для получения общего представления. Зайдите в [[Help:Contents|Справка]] и ознакомтесь с основными принципами и правилами wiki. Или, если вы что-то ищите, просто используйте поиск в левом меню сайта!&lt;br /&gt;
&lt;br /&gt;
=Основные Статьи=&lt;br /&gt;
&lt;br /&gt;
==Разработка SourceMod==&lt;br /&gt;
[[:Category:SourceMod Development|SourceMod]] вышел! Хотите узнать подробнее о разработке плагинов и расширений? Посетите [[:Category:SourceMod Development|Категорию Разработки SourceMod]] исчерпывающих статей о SourceMod, мощи C++ и Pawn API.&lt;br /&gt;
&lt;br /&gt;
==Изменения AMX Mod X: 1.8.0==&lt;br /&gt;
Выпуск [[AMX Mod X]] 1.8.0 состоялся и содержит ряд интересных изменений, таких как динамическое количество администраторов, сущности функций перехвата и динамические массивы. Каждый, кто используюет AMX Mod X, должен свериться с новой статьей, [[AMX_Mod_X_1.8.0_Changes|AMX Mod X 1.8.0]].&lt;br /&gt;
&lt;br /&gt;
==Руководство по Subversion==&lt;br /&gt;
AlliedModders перешел от CVS к Subversion, которое лучше организует исходный код. Заинтерисованы его работой и хотите скачать с SVN репозитория? Просмотрите [[Subversion Tutorial|Руководство по Subversion]]!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;border:0px;&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
=Проекты=&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''SourceMod'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Sm_small.gif|left]] [[SourceMod]] - оптимизированая и широко расширяемая скриптами среда для [[Half-Life 2]].&lt;br /&gt;
* [[:Category:SourceMod Documentation|Документация]]&lt;br /&gt;
* [[:Category:SourceMod Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''AMX Mod X'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Amxxsmall.gif|left]] [[AMX Mod X]] - мощная, расширяемая скриптами среда для [[Half-Life 1]].&lt;br /&gt;
* [[:Category:Documentation (AMX Mod X)|Документация]]&lt;br /&gt;
* [[:Category:Scripting (AMX Mod X)|Скриптинг]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''Metamod:Source'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Mms.jpg|left]][[Metamod:Source]], мощный API плагин для [[Half-Life 2]], функции перехвата интерфейсов и универсальный API плагин.&lt;br /&gt;
* [[:Category:Metamod:Source Documentation|Документация]]&lt;br /&gt;
* [[:Category:Metamod:Source Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
=Новости=&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| AMX Mod X 1.8.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2008-08-16'': Выпущена новая версия [[AMX Mod X]], отличается в основном отсутствием большого количества ошибок.  Смотрите [[Ru:AMX Mod X 1.8.1 Changes|Изменения AMX Mod X: 1.8.1]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Metamod:Source 1.4.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-05-16'': Новая версия [[Metamod:Source|SourceMM]] была выпущена как большой патч исправляющий ошибки в 1.4 версиях. Посетите [http://www.sourcemm.net/ домашнюю страницу] для более подробной информации.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Сборки SourceMod&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-03-17'': [[SourceMod]] теперь публично доступна ночными сборками. Заинтерисованы в разработке? Смотрите [[SourceMod SDK]] и [http://www.sourcemod.net/ сайт SourceMod].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6382</id>
		<title>Ru:Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6382"/>
		<updated>2008-11-06T10:33:17Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Изменения AMX Mod X: 1.8.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
Добро пожаловать в AMWiki, единый и совместный проект документаций AlliedModders, который объединяет такие проекты, как [[AMX Mod X]], [[Metamod:Source]], и [[SourceMod]].&lt;br /&gt;
&lt;br /&gt;
С чего вам начать? Смотрите ниже, для получения общего представления. Зайдите в [[Help:Contents|Справка]] и ознакомтесь с основными принципами и правилами wiki. Или, если вы что-то ищите, просто используйте поиск в левом меню сайта!&lt;br /&gt;
&lt;br /&gt;
=Основные Статьи=&lt;br /&gt;
&lt;br /&gt;
==Разработка SourceMod==&lt;br /&gt;
[[:Category:SourceMod Development|SourceMod]] вышел! Хотите узнать подробнее о разработке плагинов и расширений? Посетите [[:Category:SourceMod Development|Категорию Разработки SourceMod]] исчерпывающих статей о SourceMod, мощи C++ и Pawn API.&lt;br /&gt;
&lt;br /&gt;
==Изменения AMX Mod X: 1.8.0==&lt;br /&gt;
Выпуск [[AMX Mod X]] 1.8.0 состоялся и содержит ряд интересных изменений, таких как динамическое количество администраторов, сущности функций перехвата и динамические массивы. Каждый, кто используюет AMX Mod X, должен свериться с новой статьей, [[AMX_Mod_X_1.8.0_Changes|AMX Mod X 1.8.0]].&lt;br /&gt;
&lt;br /&gt;
==Руководство по Subversion==&lt;br /&gt;
AlliedModders перешел от CVS к Subversion, которые лучше организуют исходный код. Заинтерисованы работой, и хотите скачать с SVN репозитория? Просмотрите [[Subversion Tutorial|Руководство по Subversion]]!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;border:0px;&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
=Проекты=&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''SourceMod'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Sm_small.gif|left]] [[SourceMod]] - оптимизированая и широко расширяемая скриптами среда для [[Half-Life 2]].&lt;br /&gt;
* [[:Category:SourceMod Documentation|Документация]]&lt;br /&gt;
* [[:Category:SourceMod Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''AMX Mod X'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Amxxsmall.gif|left]] [[AMX Mod X]] - мощная, расширяемая скриптами среда для [[Half-Life 1]].&lt;br /&gt;
* [[:Category:Documentation (AMX Mod X)|Документация]]&lt;br /&gt;
* [[:Category:Scripting (AMX Mod X)|Скриптинг]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''Metamod:Source'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Mms.jpg|left]][[Metamod:Source]], мощный API плагин для [[Half-Life 2]], функции перехвата интерфейсов и универсальный API плагин.&lt;br /&gt;
* [[:Category:Metamod:Source Documentation|Документация]]&lt;br /&gt;
* [[:Category:Metamod:Source Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
=Новости=&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| AMX Mod X 1.8.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2008-08-16'': Выпущена новая версия [[AMX Mod X]], отличается в основном отсутствием большого количества ошибок.  Смотрите [[Ru:AMX Mod X 1.8.1 Changes|Изменения AMX Mod X: 1.8.1]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Metamod:Source 1.4.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-05-16'': Новая версия [[Metamod:Source|SourceMM]] была выпущена как большой патч исправляющий ошибки в 1.4 версиях. Посетите [http://www.sourcemm.net/ домашнюю страницу] для более подробной информации.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Сборки SourceMod&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-03-17'': [[SourceMod]] теперь публично доступна ночными сборками. Заинтерисованы в разработке? Смотрите [[SourceMod SDK]] и [http://www.sourcemod.net/ сайт SourceMod].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_Using_New_Menu_System&amp;diff=6381</id>
		<title>Ru Using New Menu System</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_Using_New_Menu_System&amp;diff=6381"/>
		<updated>2008-11-06T10:31:00Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Ru:Using_New_Menu_System]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Using_New_Menu_System&amp;diff=6380</id>
		<title>Ru:Using New Menu System</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Using_New_Menu_System&amp;diff=6380"/>
		<updated>2008-11-06T10:30:21Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Russian Category:Ru:Scripting (AMX Mod X)  = Введение = Это статья поможет вам разобраться в новой системе меню.  = ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
&lt;br /&gt;
= Введение =&lt;br /&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;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Глобальные переменные ===&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new g_Menu;	// Переменная обработки главного меню&lt;br /&gt;
new g_Votes[3];	// Сохраняем голосования Да как 1, No как 2&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь мы создали 2 глобальные переменные. Одна будет содержать указатель на ваше меню, другая будет хранить результаты голосования. Голоса 'За' будут сохранены в g_Votes[1], а 'Против' - в g_Votes[2]. g_Votes[0] - не используется(?).&lt;br /&gt;
&lt;br /&gt;
=== Регистрируем Плагин и Меню ===&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	// Регистрируем ваш плагин&lt;br /&gt;
	register_plugin(&amp;quot;Vote Menu&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Freecode&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Регистрируем меню смены карты&lt;br /&gt;
	g_Menu = menu_create(&amp;quot;Change Level?&amp;quot;,&amp;quot;menu_handle&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	register_clcmd(&amp;quot;amx_startvote&amp;quot;,&amp;quot;startvote&amp;quot;,ADMIN_CFG,&amp;quot;Gaben&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Теперь нам надо создать наше меню&lt;br /&gt;
	build_menu();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lets break this down. &lt;br /&gt;
&lt;br /&gt;
*Регистрирует ваш плагин&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_plugin(&amp;quot;Vote Menu&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Freecode&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*g_Menu - Указатель на ваше меню. Это будет установлено после вызова menu_create.&lt;br /&gt;
&amp;lt;pawn&amp;gt;g_Menu = menu_create(&amp;quot;Change Level?&amp;quot;,&amp;quot;menu_handle&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
//menu_create ( title[], handler[], ml=0 )&lt;br /&gt;
//title[] - Заголовок меню&lt;br /&gt;
//handler[] - Эта функция будет вызвана когда будет нажата клавиша в вашем меню.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Мы добавили эту команду. Она начинает ваше голосование.&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_clcmd(&amp;quot;amx_startvote&amp;quot;,&amp;quot;startvote&amp;quot;,ADMIN_CFG,&amp;quot;Gaben&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Это вызов функции. build_menu() функция создает ваше меню.&lt;br /&gt;
&amp;lt;pawn&amp;gt;build_menu();&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Создение меню ===&lt;br /&gt;
Конструирование заключается в добавлении пунктов в ваше меню. Прежде чем начали добавлять пункты, мы должны взглянуть на &lt;br /&gt;
menu_additem .&lt;br /&gt;
&amp;lt;pawn&amp;gt;menu_additem ( menu, const name[], const command[], paccess=0, callback=-1 )&amp;lt;/pawn&amp;gt;&lt;br /&gt;
* menu - указатель на меню. Это указывает menu_additem меню к которому нужно добавить пункты.&lt;br /&gt;
* const name[] - имя пункта меню. Это то что будет показано в меню.&lt;br /&gt;
* const command[] - информация пункта меню.&lt;br /&gt;
&lt;br /&gt;
Теперь давайте приступим к созданию нашего меню. Как уже говорилось, это простое голосование смены карты. Так что нам надо всего 2 пункта меню. А именно &amp;quot;Да&amp;quot; и &amp;quot;Нет&amp;quot;.&lt;br /&gt;
&amp;lt;pawn&amp;gt;build_menu()&lt;br /&gt;
{&lt;br /&gt;
	menu_additem(g_Menu, &amp;quot;Yes&amp;quot;, &amp;quot;1&amp;quot;);&lt;br /&gt;
	menu_additem(g_Menu, &amp;quot;No&amp;quot;, &amp;quot;2&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	menu_setprop(g_Menu, MPROP_PERPAGE, 0);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;Примечание&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Как вы можете видеть вместо command[] я указал числа. Это необходимо для более простой идентификации пунктов меню.&lt;br /&gt;
** Я так-же добавил menu_setprop. Это говорит нашему меню что оно не имеет страниц. Для дополнительной информации смотрите в amxconst.inc&lt;br /&gt;
&lt;br /&gt;
=== Показывает меню голосования ===&lt;br /&gt;
Для того что-бы показать меню мы должны использовать menu_display.&lt;br /&gt;
&amp;lt;pawn&amp;gt;menu_display ( id, menu, page )&amp;lt;/pawn&amp;gt;&lt;br /&gt;
* id - id пользователя которому надо показать это меню.&lt;br /&gt;
* menu - тут указываем хэндл меню которое показываем пользователю.&lt;br /&gt;
* page - какая страница (номер страницы меню) с которой начинаем. Страницы меню начинаются с 0.&lt;br /&gt;
&lt;br /&gt;
Ok теперь посмотрим на наш код.&lt;br /&gt;
&amp;lt;pawn&amp;gt;public startvote(id)&lt;br /&gt;
{&lt;br /&gt;
	for(new i = 0; i &amp;lt; 33; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if( is_user_alive(i) )&lt;br /&gt;
		{&lt;br /&gt;
			menu_display(i, g_Menu, 0);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return PLUGIN_HANDLED;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;Примечание:&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;b&amp;gt;3&amp;lt;/b&amp;gt; переменные которые передаются в функцию.&lt;br /&gt;
* id - id пользователя&lt;br /&gt;
* menu - открытое меню у пользователя&lt;br /&gt;
* item - тут выбор пункта меню пользователем&lt;br /&gt;
&lt;br /&gt;
Далее мы объявляем несколько специальных переменных таких как меню выхода.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define MENU_EXIT	-3&lt;br /&gt;
#define	MENU_BACK	-2&lt;br /&gt;
#define MENU_MORE	-1&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь нам надо проверить если пункт меню выбран и он не является специальной переменной&lt;br /&gt;
&amp;lt;pawn&amp;gt;if( item &amp;lt; 0 ) return PLUGIN_CONTINUE;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующим шагом мы получаем информацию о выбранном пункте меню. Все что мы ищем это номер пункта меню. (Да = 1, Нет = 2).&lt;br /&gt;
Для этого надо использовать menu_item_getinfo.&lt;br /&gt;
&amp;lt;pawn&amp;gt;menu_item_getinfo ( menu, item, &amp;amp;access, command[], cmdlen, name[]=&amp;quot;&amp;quot;, namelen=0, &amp;amp;callback )&amp;lt;/pawn&amp;gt;&lt;br /&gt;
* menu - меню в котором находится пункт меню.&lt;br /&gt;
* item - the item itself&lt;br /&gt;
* &amp;amp;access - (edit)&lt;br /&gt;
* command[] - (edit)(это то где сохраняются идентификационные номера меню)&lt;br /&gt;
* cmdlen - размер command[]&lt;br /&gt;
* name[] - имя пункта меню&lt;br /&gt;
* namelen - размер name[]&lt;br /&gt;
* &amp;amp;callback - (edit)&lt;br /&gt;
&lt;br /&gt;
После того как мы получили информацию о пуектах меню, надо взять из command[] номера выбранных меню(это должно быть 1 или 2). &lt;br /&gt;
Теперь надо добавить в g_Votes теми голосами что были сделаны.&lt;br /&gt;
Вот как завершонная функция должна выглядеть:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public menu_handle(id, menu, item)&lt;br /&gt;
{&lt;br /&gt;
	if( item &amp;lt; 0 ) return PLUGIN_CONTINUE;&lt;br /&gt;
	&lt;br /&gt;
	// Get item info&lt;br /&gt;
	new cmd[3];&lt;br /&gt;
	new access, callback;&lt;br /&gt;
	&lt;br /&gt;
	menu_item_getinfo(menu, item, access, cmd,2,_,_, callback);&lt;br /&gt;
	&lt;br /&gt;
	new iChoice = str_to_num(cmd);&lt;br /&gt;
	&lt;br /&gt;
	g_Votes[iChoice]++;&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;
Ну вот и все. Вы завершили Урок по созданию меню. Используя новую систему меню, можно создать более удобное управление. В следующем уроке вы увидите более сложную систему меню, которая будет использовать callbacks, уничтожение меню и его создание. Вот итоговый код, который должен получиться у вас после выполнения всех действий урока.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
new g_Menu;	// Переменная обработки главного меню&lt;br /&gt;
new g_Votes[3];	// Сохраняем голосования Да как 1, No как 2&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	// Регистрируем ваш плагин&lt;br /&gt;
	register_plugin(&amp;quot;Vote Menu&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Freecode&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Регистрируем меню смены карты&lt;br /&gt;
	g_Menu = menu_create(&amp;quot;Change Level?&amp;quot;,&amp;quot;menu_handle&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	register_clcmd(&amp;quot;amx_startvote&amp;quot;,&amp;quot;startvote&amp;quot;,ADMIN_CFG,&amp;quot;Gaben&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Теперь нам надо создать наше меню&lt;br /&gt;
	build_menu();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
build_menu()&lt;br /&gt;
{&lt;br /&gt;
	menu_additem(g_Menu, &amp;quot;Yes&amp;quot;, &amp;quot;1&amp;quot;);&lt;br /&gt;
	menu_additem(g_Menu, &amp;quot;No&amp;quot;, &amp;quot;2&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	menu_setprop(g_Menu, MPROP_PERPAGE, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public startvote(id)&lt;br /&gt;
{&lt;br /&gt;
	for(new i = 0; i &amp;lt; 33; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if( is_user_alive(i) )&lt;br /&gt;
		{&lt;br /&gt;
			menu_display(i, g_Menu, 0);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return PLUGIN_HANDLED;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public menu_handle(id, menu, item)&lt;br /&gt;
{&lt;br /&gt;
	if( item &amp;lt; 0 ) return PLUGIN_CONTINUE;&lt;br /&gt;
	&lt;br /&gt;
	// Получаем информацию о пункте&lt;br /&gt;
	new cmd[3];&lt;br /&gt;
	new access, callback;&lt;br /&gt;
	&lt;br /&gt;
	menu_item_getinfo(menu, item, access, cmd,2,_,_, callback);&lt;br /&gt;
	&lt;br /&gt;
	new iChoice = str_to_num(cmd);&lt;br /&gt;
	&lt;br /&gt;
	g_Votes[iChoice]++;&lt;br /&gt;
	&lt;br /&gt;
	return PLUGIN_HANDLED;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_Button_constants_(AMX_Mod_X)&amp;diff=6379</id>
		<title>Ru Button constants (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_Button_constants_(AMX_Mod_X)&amp;diff=6379"/>
		<updated>2008-11-06T10:25:41Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Ru:Button_constants_(AMX_Mod_X)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Button_constants_(AMX_Mod_X)&amp;diff=6378</id>
		<title>Ru:Button constants (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Button_constants_(AMX_Mod_X)&amp;diff=6378"/>
		<updated>2008-11-06T10:24:48Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Russian Category:Ru:Scripting (AMX Mod X) =Кнопочные константы=  Просмотреть оригинал статьи (англ.): [[Button constants (AM...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:Scripting (AMX Mod X)]]&lt;br /&gt;
=Кнопочные константы=&lt;br /&gt;
&lt;br /&gt;
Просмотреть оригинал статьи (англ.): [[Button constants (AMX Mod X)]]&lt;br /&gt;
&lt;br /&gt;
=Использование=&lt;br /&gt;
&lt;br /&gt;
Кнопочные константы обычно используются для того, чтобы &amp;quot;поймать&amp;quot; момент, когда игрок пытается совершить какое-либо действие, нажимая на кнопки, &amp;quot;привязанные&amp;quot; к таким командам, как +attack, +use и так далее с помощью команды [[cmd_bind|bind]]. Метод используется потому, что HL &amp;quot;движок&amp;quot;  не может &amp;quot;поймать&amp;quot; +/-команды стандартным регистрированием, если их реализация выполнена в самом движке.&lt;br /&gt;
&lt;br /&gt;
Например, это будет работать:&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_concmd(&amp;quot;+explode&amp;quot;,&amp;quot;explode&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
А это - нет:&lt;br /&gt;
&amp;lt;pawn&amp;gt;register_concmd(&amp;quot;+attack&amp;quot;,&amp;quot;hook_attack&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Константы=&lt;br /&gt;
&lt;br /&gt;
Полный список всех констант вы можете найти [http://amxmodx.org/funcwiki.php?go=module&amp;amp;id=3#const_buttons здесь].&lt;br /&gt;
&lt;br /&gt;
=Реализация=&lt;br /&gt;
&lt;br /&gt;
Вот, например, один из вариантов, как определить, нажимает ли игрок кнопку атаки или нет:&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
#include &amp;lt;engine&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	register_plugin(&amp;quot;Attack Test&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Hawk552&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public client_PreThink(id)&lt;br /&gt;
{&lt;br /&gt;
	if(entity_get_int(id, EV_INT_BUTTON) &amp;amp; IN_ATTACK)&lt;br /&gt;
	{&lt;br /&gt;
		// do something&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что используется битовый оператор &amp;amp;, в отличии от логического оператора &amp;amp;&amp;amp;. Оператор &amp;amp; проверяет, содержится ли бит после оператора в бите до него, т.е. в данном случае проверяется, есть ли среди нажатых кнопок игрока кнопка IN_ATTACK.&lt;br /&gt;
&lt;br /&gt;
Чтобы заставить игрока эмулировать нажатие кнопки, можно поступить следующим образом:&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
#include &amp;lt;engine&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	register_plugin(&amp;quot;Attack Test&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Hawk552&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public client_PreThink(id)&lt;br /&gt;
{&lt;br /&gt;
	entity_set_int(id,EV_INT_button,entity_get_int(id,EV_INT_button) | IN_ATTACK);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Этот пример будет выставлять флаг кнопки &amp;quot;атака&amp;quot; в положение &amp;quot;ВКЛ&amp;quot; каждый раз, когда рендерится entity игрока. Т.е. мы получаем все кнопки, нажатые в данный момент, и как бы прибавляем кнопку атаки.&lt;br /&gt;
&lt;br /&gt;
Чтобы &amp;quot;поймать&amp;quot; кнопки игрока, а потом &amp;quot;вычесть&amp;quot; какую либо кнопку, можно использовать следующий метод:&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
#include &amp;lt;engine&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
	register_plugin(&amp;quot;Attack Test&amp;quot;,&amp;quot;1.0&amp;quot;,&amp;quot;Hawk552&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public client_PreThink(id)&lt;br /&gt;
{&lt;br /&gt;
	entity_set_int(id,EV_INT_button,entity_get_int(id,EV_INT_button) &amp;amp; ~IN_ATTACK);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Например, клиент прыгает (IN_JUMP) и атакует (IN_ATTACK) одновременно, функция entity_get_int(id,EV_INT_button) будет возвращать бит сумму IN_ATTACK и IN_JUMP. Используя конструкцию &amp;amp; ~БИТ мы как бы удаляем конкретное значение бита, в данном случае IN_ATTACK. Таким образом, в итоге получим только IN_JUMP.&lt;br /&gt;
&lt;br /&gt;
=Замечания=&lt;br /&gt;
&lt;br /&gt;
Важно понимать, что нажатие какой-либо кнопки не всегда означает, что в это время происходит конкретное действие. Например, если выстрелить из пистолета и не отпускать кнопку атаки - пуля вылетит, атака закончится и не возобновится, т.к. пистолет не является автоматическим оружием, но, т.к. кнопка все еще будет нажата, то, используя вышеприведенный метод, мы получим активное состояние кнопки IN_ATTACK, хотя атаки как таковой в данный момент не осуществляется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Более наглядный пример с прыжком. Представьте, что вы прыгнули и, не отпуская кнопки прыжка, опустились на землю. Второго прыжка не произойдет, т.к. для этого нужно отпустить кнопку и нажать ее снова. Таким образом, нажатая кнопка прыжка не говорит о том, что в данный момент вы находитесь в состоянии прыжка. Как уже было отмечено, это относится и к другим кнопкам. Поэтому, в подавляющем большинстве случаев вы не должны делать проверку на наличие нажатой кнопки, если хотите определить, совершает ли игрок соответствующее действие или нет, для этого существуют другие методы.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
По большому счету метод, описанный в данной статье, может быть эффективен только для блокировки или эмуляции атаки, хотя для этого есть еще более эффективные методы. Описанный метод не может быть применим к блокировке подавляющего большинства кнопок: для этого существуют другие методы ''(TODO: указать здесь ссылку на эти методы)''.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6377</id>
		<title>Ru:Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6377"/>
		<updated>2008-11-06T10:18:18Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[AMX Mod X]] позволяет расширить функциональность игры с помощью плагинов. Перейдите в категорию [http://wiki.amxmodx.org/index.php/Category:Ru:Scripting_%28AMX_Mod_X%29 Ru:Scripting (AMX Mod X)], чтобы просмотреть список некторых статей, которые помогут вам разработать свои (или доработать чужие) плагины, используя язык [[Pawn]] (известный ранее как [[Small]]).&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6376</id>
		<title>Ru:Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6376"/>
		<updated>2008-11-06T10:18:08Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
{{LanguageSwitch}}&lt;br /&gt;
[[AMX Mod X]] позволяет расширить функциональность игры с помощью плагинов. Перейдите в категорию [http://wiki.amxmodx.org/index.php/Category:Ru:Scripting_%28AMX_Mod_X%29 Ru:Scripting (AMX Mod X)], чтобы просмотреть список некторых статей, которые помогут вам разработать свои (или доработать чужие) плагины, используя язык [[Pawn]] (известный ранее как [[Small]]).&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_Scripting_(AMX_Mod_X)&amp;diff=6375</id>
		<title>Ru Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_Scripting_(AMX_Mod_X)&amp;diff=6375"/>
		<updated>2008-11-06T10:17:28Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Redirecting to Ru:Scripting (AMX Mod X)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Ru:Scripting (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6374</id>
		<title>Ru:Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Scripting_(AMX_Mod_X)&amp;diff=6374"/>
		<updated>2008-11-06T10:16:42Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: Category:Russian  AMX Mod X позволяет расширить функциональность игры с помощью плагинов. Перейдите в категор...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]] &lt;br /&gt;
[[AMX Mod X]] позволяет расширить функциональность игры с помощью плагинов. Перейдите в категорию [http://wiki.amxmodx.org/index.php/Category:Ru:Scripting_%28AMX_Mod_X%29 Ru:Scripting (AMX Mod X)], чтобы просмотреть список некторых статей, которые помогут вам разработать свои (или доработать чужие) плагины, используя язык [[Pawn]] (известный ранее как [[Small]]).&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6340</id>
		<title>Ru:Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Main_Page&amp;diff=6340"/>
		<updated>2008-10-09T21:55:28Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Новости */ 1.8.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
Добро пожаловать в AMWiki, единый и совместный проект документаций AlliedModders, который объединяет такие проекты, как [[AMX Mod X]], [[Metamod:Source]], и [[SourceMod]].&lt;br /&gt;
&lt;br /&gt;
С чего вам начать? Смотрите ниже, для получения общего представления. Зайдите в [[Help:Contents|Справка]] и ознакомтесь с основными принципами и правилами wiki. Или, если вы что-то ищите, просто используйте поиск в левом меню сайта!&lt;br /&gt;
&lt;br /&gt;
=Основные Статьи=&lt;br /&gt;
&lt;br /&gt;
==Разработка SourceMod==&lt;br /&gt;
[[:Category:SourceMod Development|SourceMod]] вышел! Хотите узнать подробнее о разработке плагинов и расширений? Посетите [[:Category:SourceMod Development|Категорию Разработки SourceMod]] исчерпывающих статей о SourceMod, мощи C++ и Pawn API.&lt;br /&gt;
&lt;br /&gt;
==Изменения AMX Mod X: 1.8.0==&lt;br /&gt;
[[AMX Mod X]] 1.8.0 состоялся и содержит ряд интересных изменений, таких как динмаические администраторы, сущности функций перехвата, и динамические массивы. Каждый, использующий AMX Mod X должен свериться с новой статьей, [[AMX_Mod_X_1.8.0_Changes|AMX Mod X 1.8.0]].&lt;br /&gt;
&lt;br /&gt;
==Руководство по Subversion==&lt;br /&gt;
AlliedModders перешел от CVS к Subversion, которые лучше организуют исходный код. Заинтерисованы работой, и хотите скачать с SVN репозитория? Просмотрите [[Subversion Tutorial|Руководство по Subversion]]!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;border:0px;&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
=Проекты=&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''SourceMod'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Sm_small.gif|left]] [[SourceMod]] - оптимизированая и широко расширяемая скриптами среда для [[Half-Life 2]].&lt;br /&gt;
* [[:Category:SourceMod Documentation|Документация]]&lt;br /&gt;
* [[:Category:SourceMod Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''AMX Mod X'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Amxxsmall.gif|left]] [[AMX Mod X]] - мощная, расширяемая скриптами среда для [[Half-Life 1]].&lt;br /&gt;
* [[:Category:Documentation (AMX Mod X)|Документация]]&lt;br /&gt;
* [[:Category:Scripting (AMX Mod X)|Скриптинг]]&lt;br /&gt;
|}&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| '''Metamod:Source'''&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
|[[Image:Mms.jpg|left]][[Metamod:Source]], мощный API плагин для [[Half-Life 2]], функции перехвата интерфейсов и универсальный API плагин.&lt;br /&gt;
* [[:Category:Metamod:Source Documentation|Документация]]&lt;br /&gt;
* [[:Category:Metamod:Source Development|Разработка]]&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
=Новости=&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| AMX Mod X 1.8.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2008-08-16'': Выпущена новая версия [[AMX Mod X]], отличается в основном отсутствием большого количества ошибок.  Смотрите [[Ru:AMX Mod X 1.8.1 Changes|Изменения AMX Mod X: 1.8.1]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Metamod:Source 1.4.1&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-05-16'': Новая версия [[Metamod:Source|SourceMM]] была выпущена как большой патч исправляющий ошибки в 1.4 версиях. Посетите [http://www.sourcemm.net/ домашнюю страницу] для более подробной информации.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
{| cellpadding=&amp;quot;6&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Сборки SourceMod&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ''2007-03-17'': [[SourceMod]] теперь публично доступна ночными сборками. Заинтерисованы в разработке? Смотрите [[SourceMod SDK]] и [http://www.sourcemod.net/ сайт SourceMod].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6339</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6339"/>
		<updated>2008-10-09T21:31:19Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.8.1 является по большому счету работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Македонский язык (спаисбо z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: Нативная функция ns_remove_upgrade().&lt;br /&gt;
*Добавлено {{amb|1604}}: Нативная функция unregister_message().&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives для ассоциативных хранилищ.&lt;br /&gt;
*Добавлено {{amb|1365}}: Словацкий язык (спасибо Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Обработчик Invalid_Array в cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: Новый флаг 'k' в файле users.ini, который указывает, что имена/тэги кланов чувствительны к регистру.&lt;br /&gt;
*Добавлено {{amb|1167}}: Нативная функция menu_addtext().&lt;br /&gt;
*Исправлено {{amb|1648}}: Опечатка в validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Координаты браша неверно читались.&lt;br /&gt;
*Исправлено {{amb|1643}}: В TFC stats.amxx была опция, которая не поддерживалась конфигурационным меню статистики.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE в файле stats.sma для TFC.&lt;br /&gt;
*Исправлено {{amb|1632}}: Некоторые значения mp_roundtime могли конфликтовать со StatsX.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX выделял недостаточную облать памяти для csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() имел неконсистентные эвристики.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat по-мелочи не соответствовал cmdaccess.ini (патч от Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity игнорировала последнего клиента.&lt;br /&gt;
*Исправлено {{amb|1456}}: Неверный языковой ключ в режиме голосования за кик/бан.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() выдавал неверные объекты.&lt;br /&gt;
*Исправлено {{amb|1389}}: Функция client_changeteam() из модуля NS имела перевернутый список аргументов интерфейса.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() неверно вызывала vformat().&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() не работала из-за опечатки.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich имел опечатку для мода Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Обход ошибки HLDS при парсинге ключей localinfo.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip не показывал время (патч от James).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager вызывал сбой если файл cmdaccess.ini не был доступен для записи.&lt;br /&gt;
*Исправлено {{amb|1218}}: В файле ns.inc была опечатка.&lt;br /&gt;
*Исправлено {{amb|1199}}: Неверный комментарий для Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: Новый модуль и плагин не добавлялись в пакет дополнений.&lt;br /&gt;
*Исправлено {{amb|1163}}: Распечатка значений с плавающей запятой была некорректной для больших значений.&lt;br /&gt;
*Исправлено {{amb|1143}}: Опечатка в SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu не следовали cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Удалена неиспользуемая cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: Использование dod_set_model() приводило к сбою.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ранжирование игроков по IP приводило сервер к застопорению.&lt;br /&gt;
*Исправлено {{amb|1079}}: Потоковые запросы к СУБД сзапросом результатов могли сбоить.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault не загружался на некоторых Linux серверах.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip выдавал сообщение дважды.&lt;br /&gt;
*Исправлено {{amb|1080}}: Опечатка в немецком языке.&lt;br /&gt;
*Исправлено {{amb|1049}}: Небрежно были названы объекты TraceResult.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6338</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6338"/>
		<updated>2008-10-09T21:28:53Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.8.1 является по большому счету работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Македонский язык (спаисбо z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: Нативная функция ns_remove_upgrade().&lt;br /&gt;
*Добавлено {{amb|1604}}: Нативная функция unregister_message().&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives для ассоциативных хранилищ.&lt;br /&gt;
*Добавлено {{amb|1365}}: Словацкий язык (спасибо Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Обработчик Invalid_Array в cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: Новый флаг 'k' в файле users.ini, который указывает, что имена/тэги кланов чувствительны к регистру.&lt;br /&gt;
*Добавлено {{amb|1167}}: Нативная функция menu_addtext().&lt;br /&gt;
*Исправлено {{amb|1648}}: Опечатка в validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Координаты браша неверно читались.&lt;br /&gt;
*Исправлено {{amb|1643}}: В TFC stats.amxx была опция, которая не поддерживалась конфигурационным меню статистики.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE в файле stats.sma для TFC.&lt;br /&gt;
*Исправлено {{amb|1632}}: Некоторые значения mp_roundtime могли конфликтовать со StatsX.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX выделял недостаточную облать памяти для csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() имел неконсистентные эвристики.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat по-мелочи не соответствовал cmdaccess.ini (патч от Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity игнорировала последнего клиента.&lt;br /&gt;
*Исправлено {{amb|1456}}: Неверный языковой ключ в режиме голосования за кик/бан.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() выдавал неверные объекты.&lt;br /&gt;
*Исправлено {{amb|1389}}: Функция client_changeteam() из модуля NS имела перевернутый список аргументов интерфейса.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() неверно вызывала vformat().&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() не работала из-за опечатки.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich имел опечатку для мода Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Обход ошибки HLDS при парсинге ключей localinfo.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip не показывал время (патч от James).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager вызывал сбой если файл cmdaccess.ini не был доступен для записи.&lt;br /&gt;
*Исправлено {{amb|1218}}: В файле ns.inc была опечатка.&lt;br /&gt;
*Исправлено {{amb|1199}}: Неверный комментарий для Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: Новый модуль и плагин не добавлялись в пакет дополнений.&lt;br /&gt;
*Исправлено {{amb|1163}}: Распечатка значений с плавающей запятой была некорректной для больших значений.&lt;br /&gt;
*Исправлено {{amb|1143}}: Опечатка в SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu не следовали cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Удалена неиспользуемая cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: Использование dod_set_model() приводило к сбою.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ранжирование игроков по IP приводило сервер к застопорению.&lt;br /&gt;
*Исправлено {{amb|1079}}: Потоковые запросы к СУБД сзапросом результатов могли сбоить.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault не загружался на некоторых Linux серверах.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip message printed twice.&lt;br /&gt;
*Исправлено {{amb|1080}}: Опечатка в немецком языке.&lt;br /&gt;
*Исправлено {{amb|1049}}: Небрежно были названы объекты TraceResult.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Alternative_Language&amp;diff=6337</id>
		<title>Ru:Alternative Language</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Alternative_Language&amp;diff=6337"/>
		<updated>2008-10-09T20:59:05Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Translations]]&lt;br /&gt;
&lt;br /&gt;
Если вы желаете составить документацию на языке отличном от английского, пожалуйста, начните отсюда. Приветствуется содержимое на любом языке.&lt;br /&gt;
&lt;br /&gt;
Другие языки не обязательно должны быть &amp;quot;зеркалом&amp;quot; английской документации. &lt;br /&gt;
Приветствуется не только перевод документации с английского языка, но и дополнения к ней.&lt;br /&gt;
&lt;br /&gt;
= Выбор языка =&lt;br /&gt;
&lt;br /&gt;
Переключение осуществляется подстановкой префикс-кода языка.&lt;br /&gt;
&lt;br /&gt;
* [[Alternative_Language|English]]&lt;br /&gt;
* [[ru:Alternative_Language|Russian]]&lt;br /&gt;
&lt;br /&gt;
Быстрый и эффективный способ добавления переключателя нового языка - это использование шаблона&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{LanguageSwitch}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
где-либо в статье (рекомендуется добавлять вверху, либо в самом низу). Данный код добавит маленькое меню, которое выглядит следующим образом:&lt;br /&gt;
{{LanguageSwitch}}&lt;br /&gt;
&lt;br /&gt;
После того, как новый язык добавлен в wiki, данный темплейт будет изменен автоматически. Таким образом, все страницы, которые его используют, будут также автоматически обновлены.&lt;br /&gt;
&lt;br /&gt;
= Как перевести страницу =&lt;br /&gt;
&lt;br /&gt;
# Перейдите на страницу, которую вы желаете перевести.&lt;br /&gt;
# Вверху страницы выберите &amp;quot;edit&amp;quot;(править), затем сверху добавьте переключатель языка, если такового не существует.&lt;br /&gt;
# Скопируйте весь текст темплейта страницы.&lt;br /&gt;
# Сохраните (чтобы сохранился переключатель языка).&lt;br /&gt;
# Теперь вверху страницы должен появиться переключатель языка, как на этой странице.&lt;br /&gt;
# Выберите нажатием язык, на который вы желаете осуществить перевод.&lt;br /&gt;
# Вставьте текст, который вы скопировали, в текстовую область.&lt;br /&gt;
# Осуществите перевод, после чего сохраните его.&lt;br /&gt;
&lt;br /&gt;
Вышеприведенные инструкции позволят создать версию текущего документа на вашем языке. Существует возможность перевода любых страниц.&lt;br /&gt;
&lt;br /&gt;
= Ресурсы =&lt;br /&gt;
&lt;br /&gt;
* Список 2х-буквенных кодов языков можно найти тут: http://www.w3.org/WAI/ER/IG/ert/iso639.htm&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:Alternative_Language&amp;diff=6336</id>
		<title>Ru:Alternative Language</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:Alternative_Language&amp;diff=6336"/>
		<updated>2008-10-09T20:57:36Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Translations]]&lt;br /&gt;
&lt;br /&gt;
Если вы желаете составить документацию на языке отличном от английского, пожалуйста, начните отсюда. Приветствуется содержимое на любом языке.&lt;br /&gt;
&lt;br /&gt;
Другие языки не обязательно должны быть &amp;quot;зеркалом&amp;quot; английской документации. &lt;br /&gt;
Приветствуется не только перевод документации с английского языка, но и дополнения к ней.&lt;br /&gt;
&lt;br /&gt;
= Выбор языка =&lt;br /&gt;
&lt;br /&gt;
Переключение осуществляется подстановкой префикс-кода языка.&lt;br /&gt;
&lt;br /&gt;
* [[Alternative_Language|English]]&lt;br /&gt;
* [[ru:Alternative_Language|Russian]]&lt;br /&gt;
&lt;br /&gt;
Быстрый и эффективный способ добавления переключателя нового языка - это использование шаблона&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{LanguageSwitch}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
где-либо в статье (рекомендуется добавлять вверху, либо в самом низу). Данный код добавит маленькое меню, которое выглядит следующим образом:&lt;br /&gt;
{{LanguageSwitch}}&lt;br /&gt;
&lt;br /&gt;
После того, как новый язык добавлен в wiki, данный темплейт будет изменен автоматически. Таким образом, все страницы, которые его используют, будут также автоматически обновлены.&lt;br /&gt;
&lt;br /&gt;
= Как перевести страницу =&lt;br /&gt;
&lt;br /&gt;
1) Перейдите на страницу, которую вы желаете перевести.&lt;br /&gt;
&lt;br /&gt;
2) Вверху страницы выберите &amp;quot;edit&amp;quot;(править), затем сверху добавьте переключатель языка, если такового не существует.&lt;br /&gt;
&lt;br /&gt;
3) Скопируйте весь текст темплейта страницы.&lt;br /&gt;
&lt;br /&gt;
4) Сохраните (чтобы сохранился переключатель языка).&lt;br /&gt;
&lt;br /&gt;
5) Теперь вверху страницы должен появиться переключатель языка, как на этой странице.&lt;br /&gt;
&lt;br /&gt;
6) Выберите нажатием язык, на который вы желаете осуществить перевод.&lt;br /&gt;
&lt;br /&gt;
7) Вставьте текст, который вы скопировали, в текстовую область.&lt;br /&gt;
&lt;br /&gt;
8) Осуществите перевод, после чего сохраните его.&lt;br /&gt;
&lt;br /&gt;
Вышеприведенные инструкции позволят создать версию текущего документа на вашем языке. Существует возможность перевода любых страниц.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Ресурсы:'''&lt;br /&gt;
&lt;br /&gt;
* Список 2х-буквенных кодов языков можно найти тут: http://www.w3.org/WAI/ER/IG/ert/iso639.htm&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6335</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6335"/>
		<updated>2008-10-09T20:55:40Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMX Mod X 1.8.1 является по большому счету работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: ns_remove_upgrade() native.&lt;br /&gt;
*Добавлено {{amb|1604}}: unregister_message() native.&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives for associative storage.&lt;br /&gt;
*Добавлено {{amb|1365}}: Slovak translation (thanks Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Invalid_Array handle in cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: A new flag in users.ini, 'k' implies name/tags are case sensitive.&lt;br /&gt;
*Добавлено {{amb|1167}}: menu_addtext() native.&lt;br /&gt;
*Исправлено {{amb|1648}}: Typo in validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Brush origin retrieval was wrong.&lt;br /&gt;
*Исправлено {{amb|1643}}: TFC's stats.amxx added an option it did not support to the stats config menu.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE in tfc stats.sma.&lt;br /&gt;
*Исправлено {{amb|1632}}: Certain mp_roundtime values could conflict with statsx.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX was allocating a buffer too small for csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() had inconsistent heuristics.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat sundry details did not obey cmdaccess.ini (patch from Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity was ignoring the last client.&lt;br /&gt;
*Исправлено {{amb|1456}}: Wrong language key in vote kick/ban.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() was giving wrong items.&lt;br /&gt;
*Исправлено {{amb|1389}}: NS module's client_changeteam() had a reversed syntax.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() had a messed up vformat() call.&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() broken due to typo.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich had a typo for Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Workaround for a bug with HLDS's parsing of localinfo keys.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip did not show time (patch from &amp;quot;James&amp;quot;).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager caused a crash if the cmdaccess.ini was not writable.&lt;br /&gt;
*Исправлено {{amb|1218}}: ns.inc had a typo.&lt;br /&gt;
*Исправлено {{amb|1199}}: Incorrect comment for Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: New module and plugin did not get added to addon packages.&lt;br /&gt;
*Исправлено {{amb|1163}}: float printing broke on large values.&lt;br /&gt;
*Исправлено {{amb|1143}}: Typo in SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu now follows cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Removed unused cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: dod_set_model() crashed.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ranking by IP caused the server to freeze.&lt;br /&gt;
*Исправлено {{amb|1079}}: Threaded queries with results would crash.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault wouldn't load on some Linux servers.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip message printed twice.&lt;br /&gt;
*Исправлено {{amb|1080}}: German translation typo.&lt;br /&gt;
*Исправлено {{amb|1049}}: Sloppy TraceResult namings.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;br /&gt;
&lt;br /&gt;
[[Category:Russian]]&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.1_Changes&amp;diff=6334</id>
		<title>AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.1_Changes&amp;diff=6334"/>
		<updated>2008-10-09T20:54:44Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LanguageSwitch}}&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.8.1 is a bug-fix release.&lt;br /&gt;
&lt;br /&gt;
*Added {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L).&lt;br /&gt;
*Added {{amb|1635}}: ns_remove_upgrade() native.&lt;br /&gt;
*Added {{amb|1604}}: unregister_message() native.&lt;br /&gt;
*Added {{amb|1600}}: Trie natives for associative storage.&lt;br /&gt;
*Added {{amb|1365}}: Slovak translation (thanks Centaury).&lt;br /&gt;
*Added {{amb|1290}}: Invalid_Array handle in cellarray.inc.&lt;br /&gt;
*Added {{amb|1263}}: A new flag in users.ini, 'k' implies name/tags are case sensitive.&lt;br /&gt;
*Added {{amb|1167}}: menu_addtext() native.&lt;br /&gt;
*Fixed {{amb|1648}}: Typo in validate_menu_text.&lt;br /&gt;
*Fixed {{amb|1647}}: Brush origin retrieval was wrong.&lt;br /&gt;
*Fixed {{amb|1643}}: TFC's stats.amxx added an option it did not support to the stats config menu.&lt;br /&gt;
*Fixed {{amb|1642}}: RTE in tfc stats.sma.&lt;br /&gt;
*Fixed {{amb|1632}}: Certain mp_roundtime values could conflict with statsx.&lt;br /&gt;
*Fixed {{amb|1596}}: CSX was allocating a buffer too small for csstats.amxx.&lt;br /&gt;
*Fixed {{amb|1565}}: CCmdManager::gotAccess() had inconsistent heuristics.&lt;br /&gt;
*Fixed {{amb|1564}}: amx_chat sundry details did not obey cmdaccess.ini (patch from Teyut).&lt;br /&gt;
*Fixed {{amb|1545}}: show_activity was ignoring the last client.&lt;br /&gt;
*Fixed {{amb|1456}}: Wrong language key in vote kick/ban.&lt;br /&gt;
*Fixed {{amb|1452}}: ns_give_item() was giving wrong items.&lt;br /&gt;
*Fixed {{amb|1389}}: NS module's client_changeteam() had a reversed syntax.&lt;br /&gt;
*Fixed {{amb|1343}}: show_activity() had a messed up vformat() call.&lt;br /&gt;
*Fixed {{amb|1315}}: fread_blocks() broken due to typo.&lt;br /&gt;
*Fixed {{amb|1313}}: Hamsandwich had a typo for Sven Co-op.&lt;br /&gt;
*Fixed {{amb|1293}}: Workaround for a bug with HLDS's parsing of localinfo keys.&lt;br /&gt;
*Fixed {{amb|1288}}: amx_banip did not show time (patch from &amp;quot;James&amp;quot;).&lt;br /&gt;
*Fixed {{amb|1267}}: FlagManager caused a crash if the cmdaccess.ini was not writable.&lt;br /&gt;
*Fixed {{amb|1218}}: ns.inc had a typo.&lt;br /&gt;
*Fixed {{amb|1199}}: Incorrect comment for Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Fixed {{amb|1175}}: New module and plugin did not get added to addon packages.&lt;br /&gt;
*Fixed {{amb|1163}}: float printing broke on large values.&lt;br /&gt;
*Fixed {{amb|1143}}: Typo in SetClientKeyValue().&lt;br /&gt;
*Fixed {{amb|1139}}: Menufront/plmenu now follows cmdaccess.ini changes for its additions.&lt;br /&gt;
*Fixed {{amb|1134}}: Removed unused cvar.&lt;br /&gt;
*Fixed {{amb|1126}}: dod_set_model() crashed.&lt;br /&gt;
*Fixed {{amb|1096}}: Ranking by IP caused the server to freeze.&lt;br /&gt;
*Fixed {{amb|1079}}: Threaded queries with results would crash.&lt;br /&gt;
*Fixed {{amb|1077}}: nVault wouldn't load on some Linux servers.&lt;br /&gt;
*Fixed {{amb|1089}}: amx_banip message printed twice.&lt;br /&gt;
*Fixed {{amb|1080}}: German translation typo.&lt;br /&gt;
*Fixed {{amb|1049}}: Sloppy TraceResult namings.&lt;br /&gt;
*CS and NS did not have plmenu and slapdamage amounts in their amxx.cfg.&lt;br /&gt;
*Plugin menu now ignores immunity if executed on self.&lt;br /&gt;
*Mod-specific modules no longer load on mods they don't support.&lt;br /&gt;
*AMX Mod X now uses Visual Studio 2005.&lt;br /&gt;
*Linux builds no longer use -fPIC (smaller, slightly faster binaries).&lt;br /&gt;
*Updated GeoIP database to August 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1&amp;diff=6333</id>
		<title>Ru:AMX Mod X 1.8.1</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1&amp;diff=6333"/>
		<updated>2008-10-09T20:53:50Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: Removing all content from page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6332</id>
		<title>Ru:AMX Mod X 1.8.1 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1_Changes&amp;diff=6332"/>
		<updated>2008-10-09T20:53:46Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: AMX Mod X 1.8.1 является по большому счету работой над ошибками.  *Добавлено {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L). *Д...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMX Mod X 1.8.1 является по большому счету работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: ns_remove_upgrade() native.&lt;br /&gt;
*Добавлено {{amb|1604}}: unregister_message() native.&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives for associative storage.&lt;br /&gt;
*Добавлено {{amb|1365}}: Slovak translation (thanks Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Invalid_Array handle in cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: A new flag in users.ini, 'k' implies name/tags are case sensitive.&lt;br /&gt;
*Добавлено {{amb|1167}}: menu_addtext() native.&lt;br /&gt;
*Исправлено {{amb|1648}}: Typo in validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Brush origin retrieval was wrong.&lt;br /&gt;
*Исправлено {{amb|1643}}: TFC's stats.amxx added an option it did not support to the stats config menu.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE in tfc stats.sma.&lt;br /&gt;
*Исправлено {{amb|1632}}: Certain mp_roundtime values could conflict with statsx.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX was allocating a buffer too small for csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() had inconsistent heuristics.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat sundry details did not obey cmdaccess.ini (patch from Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity was ignoring the last client.&lt;br /&gt;
*Исправлено {{amb|1456}}: Wrong language key in vote kick/ban.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() was giving wrong items.&lt;br /&gt;
*Исправлено {{amb|1389}}: NS module's client_changeteam() had a reversed syntax.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() had a messed up vformat() call.&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() broken due to typo.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich had a typo for Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Workaround for a bug with HLDS's parsing of localinfo keys.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip did not show time (patch from &amp;quot;James&amp;quot;).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager caused a crash if the cmdaccess.ini was not writable.&lt;br /&gt;
*Исправлено {{amb|1218}}: ns.inc had a typo.&lt;br /&gt;
*Исправлено {{amb|1199}}: Incorrect comment for Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: New module and plugin did not get added to addon packages.&lt;br /&gt;
*Исправлено {{amb|1163}}: float printing broke on large values.&lt;br /&gt;
*Исправлено {{amb|1143}}: Typo in SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu now follows cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Removed unused cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: dod_set_model() crashed.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ranking by IP caused the server to freeze.&lt;br /&gt;
*Исправлено {{amb|1079}}: Threaded queries with results would crash.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault wouldn't load on some Linux servers.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip message printed twice.&lt;br /&gt;
*Исправлено {{amb|1080}}: German translation typo.&lt;br /&gt;
*Исправлено {{amb|1049}}: Sloppy TraceResult namings.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1&amp;diff=6331</id>
		<title>Ru:AMX Mod X 1.8.1</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru:AMX_Mod_X_1.8.1&amp;diff=6331"/>
		<updated>2008-10-09T20:51:20Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: New page: AMX Mod X 1.8.1 является по большому счету работой над ошибками.  *Добавлено {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L). *Д...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMX Mod X 1.8.1 является по большому счету работой над ошибками.&lt;br /&gt;
&lt;br /&gt;
*Добавлено {{amb|1762}}: Macedonian translation (thanks z3r0Lev3L).&lt;br /&gt;
*Добавлено {{amb|1635}}: ns_remove_upgrade() native.&lt;br /&gt;
*Добавлено {{amb|1604}}: unregister_message() native.&lt;br /&gt;
*Добавлено {{amb|1600}}: Trie natives for associative storage.&lt;br /&gt;
*Добавлено {{amb|1365}}: Slovak translation (thanks Centaury).&lt;br /&gt;
*Добавлено {{amb|1290}}: Invalid_Array handle in cellarray.inc.&lt;br /&gt;
*Добавлено {{amb|1263}}: A new flag in users.ini, 'k' implies name/tags are case sensitive.&lt;br /&gt;
*Добавлено {{amb|1167}}: menu_addtext() native.&lt;br /&gt;
*Исправлено {{amb|1648}}: Typo in validate_menu_text.&lt;br /&gt;
*Исправлено {{amb|1647}}: Brush origin retrieval was wrong.&lt;br /&gt;
*Исправлено {{amb|1643}}: TFC's stats.amxx added an option it did not support to the stats config menu.&lt;br /&gt;
*Исправлено {{amb|1642}}: RTE in tfc stats.sma.&lt;br /&gt;
*Исправлено {{amb|1632}}: Certain mp_roundtime values could conflict with statsx.&lt;br /&gt;
*Исправлено {{amb|1596}}: CSX was allocating a buffer too small for csstats.amxx.&lt;br /&gt;
*Исправлено {{amb|1565}}: CCmdManager::gotAccess() had inconsistent heuristics.&lt;br /&gt;
*Исправлено {{amb|1564}}: amx_chat sundry details did not obey cmdaccess.ini (patch from Teyut).&lt;br /&gt;
*Исправлено {{amb|1545}}: show_activity was ignoring the last client.&lt;br /&gt;
*Исправлено {{amb|1456}}: Wrong language key in vote kick/ban.&lt;br /&gt;
*Исправлено {{amb|1452}}: ns_give_item() was giving wrong items.&lt;br /&gt;
*Исправлено {{amb|1389}}: NS module's client_changeteam() had a reversed syntax.&lt;br /&gt;
*Исправлено {{amb|1343}}: show_activity() had a messed up vformat() call.&lt;br /&gt;
*Исправлено {{amb|1315}}: fread_blocks() broken due to typo.&lt;br /&gt;
*Исправлено {{amb|1313}}: Hamsandwich had a typo for Sven Co-op.&lt;br /&gt;
*Исправлено {{amb|1293}}: Workaround for a bug with HLDS's parsing of localinfo keys.&lt;br /&gt;
*Исправлено {{amb|1288}}: amx_banip did not show time (patch from &amp;quot;James&amp;quot;).&lt;br /&gt;
*Исправлено {{amb|1267}}: FlagManager caused a crash if the cmdaccess.ini was not writable.&lt;br /&gt;
*Исправлено {{amb|1218}}: ns.inc had a typo.&lt;br /&gt;
*Исправлено {{amb|1199}}: Incorrect comment for Ham_DOD_RoundRespawnEnt.&lt;br /&gt;
*Исправлено {{amb|1175}}: New module and plugin did not get added to addon packages.&lt;br /&gt;
*Исправлено {{amb|1163}}: float printing broke on large values.&lt;br /&gt;
*Исправлено {{amb|1143}}: Typo in SetClientKeyValue().&lt;br /&gt;
*Исправлено {{amb|1139}}: Menufront/plmenu now follows cmdaccess.ini changes for its additions.&lt;br /&gt;
*Исправлено {{amb|1134}}: Removed unused cvar.&lt;br /&gt;
*Исправлено {{amb|1126}}: dod_set_model() crashed.&lt;br /&gt;
*Исправлено {{amb|1096}}: Ranking by IP caused the server to freeze.&lt;br /&gt;
*Исправлено {{amb|1079}}: Threaded queries with results would crash.&lt;br /&gt;
*Исправлено {{amb|1077}}: nVault wouldn't load on some Linux servers.&lt;br /&gt;
*Исправлено {{amb|1089}}: amx_banip message printed twice.&lt;br /&gt;
*Исправлено {{amb|1080}}: German translation typo.&lt;br /&gt;
*Исправлено {{amb|1049}}: Sloppy TraceResult namings.&lt;br /&gt;
*CS и NS не содержали plmenu и slapdamage значения в amxx.cfg.&lt;br /&gt;
*Меню плагинов теперь игнорирует признак иммунитета, когда действие применяется на самом себе.&lt;br /&gt;
*Модули, специфичные для модов, больше не загружаются под модами, которые они не поддреживают.&lt;br /&gt;
*AMX Mod X теперь использует Visual Studio 2005 (речь о бинарнике под windows).&lt;br /&gt;
*Бинарники под Linux теперь не используют -fPIC (стали меньше, немного быстрее).&lt;br /&gt;
*Обновлена база GeoIP на август 2008.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6096</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6096"/>
		<updated>2008-08-02T10:34:40Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Почему клиент не получает права админа по IP? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
=== Я перевел на русский языковой файл плагина, а текст в игре отображается криво ===&lt;br /&gt;
: Скорее всего вы не сохранили файл в UTF-8 кодировке. Даже если вы это сделали, проверьте что в начале файле нет маркера кодировки, потому что некоторые редакторы его вставляют без предупреждения. Для этого надо использовать редактор или режим, который НЕ понимает UTF-8, потому что unicode редактор не отображает такой маркер.&lt;br /&gt;
: Имейте в виду, что в консоли сервера, работающего в режиме ''-console'', переведенный текст не будет отображаться по-русски.&lt;br /&gt;
&lt;br /&gt;
=== Как называется статистика, встроенная в AMXX? ===&lt;br /&gt;
: Называется &amp;quot;StatsX&amp;quot;, реализована в виде плагинов ''statsx.amxx'', ''statscfg.amxx'', ''stats_logging.amxx'', а также в модуле ''csx''. О последнем многие забывают, полагая, что можно просто изменить алгоритм учета статистики на уровне плагинов AMXX.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''STEAM_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана для всех(!) активных AMXX плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
=== Как очистить статистику StatsX? ===&lt;br /&gt;
: Удалите файл ''$AMXMODX/data/csstats.dat''.&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6095</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6095"/>
		<updated>2008-08-02T10:23:37Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: + Как очистить статистику StatsX?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
=== Я перевел на русский языковой файл плагина, а текст в игре отображается криво ===&lt;br /&gt;
: Скорее всего вы не сохранили файл в UTF-8 кодировке. Даже если вы это сделали, проверьте что в начале файле нет маркера кодировки, потому что некоторые редакторы его вставляют без предупреждения. Для этого надо использовать редактор или режим, который НЕ понимает UTF-8, потому что unicode редактор не отображает такой маркер.&lt;br /&gt;
: Имейте в виду, что в консоли сервера, работающего в режиме ''-console'', переведенный текст не будет отображаться по-русски.&lt;br /&gt;
&lt;br /&gt;
=== Как называется статистика, встроенная в AMXX? ===&lt;br /&gt;
: Называется &amp;quot;StatsX&amp;quot;, реализована в виде плагинов ''statsx.amxx'', ''statscfg.amxx'', ''stats_logging.amxx'', а также в модуле ''csx''. О последнем многие забывают, полагая, что можно просто изменить алгоритм учета статистики на уровне плагинов AMXX.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''VALVE_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана для всех(!) активных AMXX плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
=== Как очистить статистику StatsX? ===&lt;br /&gt;
: Удалите файл ''$AMXMODX/data/csstats.dat''.&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6094</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6094"/>
		<updated>2008-08-02T10:17:35Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: + Как называется статистика, встроенная в AMXX?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
=== Я перевел на русский языковой файл плагина, а текст в игре отображается криво ===&lt;br /&gt;
: Скорее всего вы не сохранили файл в UTF-8 кодировке. Даже если вы это сделали, проверьте что в начале файле нет маркера кодировки, потому что некоторые редакторы его вставляют без предупреждения. Для этого надо использовать редактор или режим, который НЕ понимает UTF-8, потому что unicode редактор не отображает такой маркер.&lt;br /&gt;
: Имейте в виду, что в консоли сервера, работающего в режиме ''-console'', переведенный текст не будет отображаться по-русски.&lt;br /&gt;
&lt;br /&gt;
=== Как называется статистика, встроенная в AMXX? ===&lt;br /&gt;
: Называется &amp;quot;StatsX&amp;quot;, реализована в виде плагинов ''statsx.amxx'', ''statscfg.amxx'', ''stats_logging.amxx'', а также в модуле ''csx''. О последнем многие забывают, полагая, что можно просто изменить алгоритм учета статистики на уровне плагинов AMXX.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''VALVE_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана для всех(!) активных AMXX плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6093</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6093"/>
		<updated>2008-08-02T09:40:04Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Как узнать, в каком плагине зарегистрирована та или иная переменная? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
=== Я перевел на русский языковой файл плагина, а текст в игре отображается криво ===&lt;br /&gt;
: Скорее всего вы не сохранили файл в UTF-8 кодировке. Даже если вы это сделали, проверьте что в начале файле нет маркера кодировки, потому что некоторые редакторы его вставляют без предупреждения. Для этого надо использовать редактор или режим, который НЕ понимает UTF-8, потому что unicode редактор не отображает такой маркер.&lt;br /&gt;
: Имейте в виду, что в консоли сервера, работающего в режиме ''-console'', переведенный текст не будет отображаться по-русски.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''VALVE_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана для всех(!) активных AMXX плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6092</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6092"/>
		<updated>2008-08-02T09:32:17Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Почему клиент не получает права админа по IP? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''VALVE_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана для всех(!) активных AMXX плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6091</id>
		<title>Ru AMX Mod X FAQ</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Ru_AMX_Mod_X_FAQ&amp;diff=6091"/>
		<updated>2008-08-02T09:31:41Z</updated>

		<summary type="html">&lt;p&gt;Simon Logic: /* Почему клиент не получает права админа по IP? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Russian]]&lt;br /&gt;
[[Category:Ru:AMX Mod X]]&lt;br /&gt;
&lt;br /&gt;
= Общие положения, термины, сокращения и условные обозначения =&lt;br /&gt;
:* HL или HL1 - аббревиатура от [[Half-Life 1|Half-Life]] (часть первая);&lt;br /&gt;
:* Mod - &amp;quot;мод&amp;quot;, модификация - дополнение к чему-либо, как правило, расширяющее/изменяющее функциональность;&lt;br /&gt;
:* HL Engine - &amp;quot;движок&amp;quot; Half-Life - &amp;quot;центральный модуль&amp;quot;, осуществляющий выполнение базовых &amp;quot;общемодовых&amp;quot; задач;&lt;br /&gt;
:* MM - [[Metamod]] - сторонний мод особого типа, является промежуточным звеном в системе &amp;quot;HL движок - HL мод&amp;quot;;&lt;br /&gt;
:* AMXX - аббревиатура от [[AMX Mod X]] - Metamod plugin (&amp;quot;плагин&amp;quot;), своего рода Metamod мод;&lt;br /&gt;
:* Map - &amp;quot;карта&amp;quot; - определяет внешний вид территории, на которой происходит игровое действие;&lt;br /&gt;
:* World - &amp;quot;мир&amp;quot; - все пространство, которое занимает карта, а также область, находящаяся за картой;&lt;br /&gt;
:* Spawn - &amp;quot;спавн&amp;quot; - момент, когда игрок появляется в мире, обретая физическое тело;&lt;br /&gt;
:* SinglePlayer - &amp;quot;синглплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать только один игрок;&lt;br /&gt;
:* MultiPlayer - &amp;quot;мультиплеер&amp;quot; - игровой тип, когда одновременно в игре может участвовать несколько игроков;&lt;br /&gt;
:* DM - аббревиатура от Death Match - динамичный мультиплеер тип игры, когда после &amp;quot;смерти&amp;quot; игрока происходит его скорый спавн (&amp;quot;респавн&amp;quot;);&lt;br /&gt;
:* HLDM - аббревиатура от Half-Life Death Match - оригинальный HL мод DM типа;&lt;br /&gt;
:* CS - аббревиатура от [[Counter-Stirke]] - наиболее популярный HL мод;&lt;br /&gt;
:* VALVE - [[VALVe Software|корпорация, разработчик HL и CS]], также редко используется как синоним HLDM, подчеркивая название директории мода (&amp;quot;valve&amp;quot;);&lt;br /&gt;
:* $MODDIR - способ условного обозначения корневой директории мода, например: ''cstrike'', ''valve'';&lt;br /&gt;
:* $MMDIR - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории Metamod, по-умолчанию: ''addons/metamod'';&lt;br /&gt;
:* $AMXMODX - способ условного обозначения относительного пути (относительно пути к $MODDIR) к корневой директории AMX Mod X, по-умолчанию: ''addons/amxmodx''.&lt;br /&gt;
&lt;br /&gt;
= Общие вопросы =&lt;br /&gt;
=== Где скачать последнюю версию AMX Mod X? ===&lt;br /&gt;
: Последнюю версию всегда можно скачать на официальном сайте AMX Mod X в [http://www.amxmodx.org/downloads.php разделе закачек].&lt;br /&gt;
&lt;br /&gt;
=== А что именно качать? ===&lt;br /&gt;
: Качайте либо инсталлятор (AMX Mod X Full Installer), который включает базовый AMX Mod X пакет, все AMX Mod X дополнения для HL модов, а также AMXX-Studio (специализированный редактор AMX Mod X плагинов), либо, если готовы произвести установку AMX Mod X вручную, а также не желаете закачивать все существующие AMX Mod X дополнения для HL модов, качайте базовый архив (AMX Mod X Base), а затем дополнение для интересующего вас HL мода. Сама по себе базовая поставка практически во всех случаях будет достаточна только для HLDM мода.&lt;br /&gt;
&lt;br /&gt;
=== Чем отличается AMX Mod X от AMX Mod? ===&lt;br /&gt;
: Буквой X ;). На самом деле отличий очень много:&lt;br /&gt;
:* AMXX поддерживается до сих пор, а поддержка AMX Mod была завершена примерно в 2006 году;&lt;br /&gt;
:* функциональность AMXX значительно превосходит AMX Mod, это также касается и расширенной поддержки других модов, в то время как AMX Mod поддерживал только HLDM, CS и CZ;&lt;br /&gt;
:* AMXX принято считать быстрее AMX Mod;&lt;br /&gt;
:* плагины AMXX не совместимы с плагинами AMX Mod;&lt;br /&gt;
:* плагины AMX Mod 0.9.9 совместимы с AMXX, если последний работает в режиме совместимости(?);&lt;br /&gt;
:* плагины для AMX Mod имеют расширение .amx, а плагины AMXX - .amxx;&lt;br /&gt;
:* ''TODO: дополнить список''&lt;br /&gt;
&lt;br /&gt;
=== Как запустить два различных сервера AMX Mod X? ===&lt;br /&gt;
: К примеру, вы хотите запустить два различных сервера из одной ''cstrike'' директории на базе различных AMX Mod X/Metamod плагинов, настроек и прочего. Это решаемо. Один из примеров для win32 системы приведен ниже:&lt;br /&gt;
:* Создать отдельную AMX Mod X директорию с необходимыми файлами, например: ''addons/amxmodx2''&lt;br /&gt;
:* В ''addons/amxmodx2/configs/core.ini'' везде изменить &amp;quot;amxmodx&amp;quot; на &amp;quot;amxmodx2&amp;quot;&lt;br /&gt;
:* Создать отдельный файл загрузки Metamod плагинов, например: ''addons/metamod/plugins2.ini''&lt;br /&gt;
:* В созданный ''plugins2.ini'' файл вписать: ''win32 addons\amxmodx2\dlls\amxmodx_mm.dll''&lt;br /&gt;
:* Создать в директории ''cstrike'' файл, например, с именем ''amxmodx2.cfg'', его содержимое должно быть следующим:&lt;br /&gt;
&amp;lt;pre&amp;gt;localinfo mm_pluginsfile &amp;quot;addons/metamod/plugins2.ini&amp;quot;&lt;br /&gt;
localinfo amxx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amxx_cfg &amp;quot;addons/amxmodx2/configs/core.ini&amp;quot;&lt;br /&gt;
localinfo amxx_configsdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amxx_customdir &amp;quot;addons/amxmodx2/custom&amp;quot;&lt;br /&gt;
localinfo amxx_datadir &amp;quot;addons/amxmodx2/data&amp;quot;&lt;br /&gt;
localinfo amxx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_logs &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amxx_modules &amp;quot;addons/amxmodx2/configs/modules.ini&amp;quot;&lt;br /&gt;
localinfo amxx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amxx_plugins &amp;quot;addons/amxmodx2/configs/plugins.ini&amp;quot;&lt;br /&gt;
localinfo amxx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&lt;br /&gt;
localinfo amxx_vault &amp;quot;addons/amxmodx2/data/vault.ini&amp;quot;&lt;br /&gt;
localinfo csstats &amp;quot;addons/amxmodx2/data/csstats.dat&amp;quot;&lt;br /&gt;
localinfo csstats_score &amp;quot;addons/amxmodx2/data/csstats.amxx&amp;quot;&lt;br /&gt;
localinfo amx_basedir &amp;quot;addons/amxmodx2&amp;quot;&lt;br /&gt;
localinfo amx_configdir &amp;quot;addons/amxmodx2/configs&amp;quot;&lt;br /&gt;
localinfo amx_langdir &amp;quot;addons/amxmodx2/data/amxmod-lang&amp;quot;&lt;br /&gt;
localinfo amx_logdir &amp;quot;addons/amxmodx2/logs&amp;quot;&lt;br /&gt;
localinfo amx_modulesdir &amp;quot;addons/amxmodx2/modules&amp;quot;&lt;br /&gt;
localinfo amx_pluginsdir &amp;quot;addons/amxmodx2/plugins&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
:* Теперь второй сервер необходимо будет запускать с параметром командной строки: ''+exec amxmodx2.cfg''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по плагинам =&lt;br /&gt;
== Общие вопросы ==&lt;br /&gt;
=== Где и как искать плагины? ===&lt;br /&gt;
: Предварительно отметим, что условно AMX Mod X плагины можно разделить на следующие категории: стандартные, официально одобренные, официально отклоненные и неофициальные. Одобренные плагины можно искать [http://www.amxmodx.org/compiler.php здесь], или, используя [http://forums.alliedmods.net/search.php поисковую систему официального форума]. В поле '''Search in Forum(s)''' отметьте '''Approved Plugins''', также, зажав клавишу Ctrl, можно отметить интересующие вас секции из подраздела '''High-Traffic Plugins'''. Чтобы искать неофициальные плагины, следует также воспользоваться [http://forums.alliedmods.net/search.php поисковой системой официального форума], правда, в поле '''Search in Forum(s)''' необходимо выбрать '''Unapproved/Old Plugins'''. Если для вас не имеет значения статус плагина, и вы склонны к экспериментам, осуществляйте поиск по категории '''Plugins''', которая включает в себя одобренные, отклоненные, недавно опубликованные, вполне возможно, &amp;quot;сырые&amp;quot; плагины, а также темы-запросы, в которых могут быть &amp;quot;быстро написанные&amp;quot; плагины.  Особенность поиска на официальных форумах еще состоит в том, что при вводе слова система ищет именно слова (без учета регистра), т.е. фрагменты, разделенные слева и справа пробелами. Т.о., к примеру, набрав для поиска слово ''FCOS'' вы не найдете нужного вам плагина, хотя есть тема, в которой присутствует текст ''[fcos]''. Для этого надо использовать в поиске строку ''*FCOS*''. Немного поработав с поисковой формой форума, вы легко освоите эту систему. Единственное возможное для некоторых неудобство - практически все описания плагинов написаны на английcком языке. Неофициальные плагины также можно попробовать искать с помощью общеизвестных поисковых систем: Google, Yandex, Rambler и др.&lt;br /&gt;
&lt;br /&gt;
=== Сколько плагинов сейчас выпущено под AMX Mod X? ===&lt;br /&gt;
: &amp;quot;Тонны&amp;quot; плагинов. Но, к сожалению, качеством и надежностью б'''о'''льшая половина из них не белещет. К тому же некоторые плагины, &amp;quot;заброшены&amp;quot; авторами и не обновляются, что приводит даже к несовместимости с новыми версиями AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
=== Как устанавливать плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Как удалять плагины? ===&lt;br /&gt;
: Обратитесь к [[Ru Configuring AMX Mod X|этой]] статье.&lt;br /&gt;
&lt;br /&gt;
=== Что такое стандартные плагины? ===&lt;br /&gt;
: Это плагины, которые входят в стандартную поставку AMX Mod X. Они находятся в папке $AMXMODX\scripting.&lt;br /&gt;
&lt;br /&gt;
=== Как узнать, в каком плагине зарегистрирована та или иная переменная? ===&lt;br /&gt;
: В серверной консоли наберите команду ''amxx cvars''. Выделите текст, скопируйте в файл, там сделайте поиск искомой переменной. В правой колонке будет стоять имя плагина, в котором она и зарегистрирована.&lt;br /&gt;
&lt;br /&gt;
== Вопросы по стандартным плагинам ==&lt;br /&gt;
=== Как увеличить число карт в стандартном голосовании? ===&lt;br /&gt;
: Откройте файл $AMXMODX\scripting\mapchooser.sma, замените число 3 в строке&lt;br /&gt;
 #define SELECTMAPS  3&lt;br /&gt;
: на требуемое, затем [[#Как компилировать плагины?|откомпилируйте]] плагин и замените исходный.&lt;br /&gt;
&lt;br /&gt;
=== Как увеличить число администраторов? ===&lt;br /&gt;
: В файле ''admin.sma'' замените число 64 на требуемое значение в строке:&lt;br /&gt;
 #define MAX_ADMINS 64&lt;br /&gt;
: Не ставьте слишком большие значения. Не забудьте [[#Как компилировать плагины?|перекомпилировать]] плагин и заменить исходный новым.&lt;br /&gt;
: В AMXX 1.8.X и выше такая проблема не стоит, т.к. там реализован динамический список админов.&lt;br /&gt;
&lt;br /&gt;
=== Почему клиент не получает права админа по IP? ===&lt;br /&gt;
:Данная проблема возникает на публичных Non-Steam (патченных) интернет-серверах c sv_lan = 0 при подключении Steam/Non-Steam клиентов.&lt;br /&gt;
: Сначала убедитесь, что у вас нединамический внешний IP. Динамический IP означает, что каждый раз, подключась к Интернету, вам назначается новый внешний IP (обычно из какого-то фиксированного диапазона). Для этого обратитесь к вашему провайдеру. Далее необходимо сверить, правильно ли вы прописали доступ в файле users.ini. Для этого проверьте свой внешний IP на страничке [http://myip.ru/ myip.ru]. Запомните его. Откройте файл user.ini и убедитесь что там есть такая запись:&lt;br /&gt;
 &amp;quot;&amp;lt;ваш_ip&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваш_пароль&amp;gt;&amp;quot; &amp;quot;&amp;lt;ваши_флаги&amp;gt;&amp;quot; &amp;quot;d&amp;lt;другие_модификаторы&amp;gt;&amp;quot;&lt;br /&gt;
:В поле ''&amp;lt;ваш_ip&amp;gt;'' должен быть вбит запомненный ранее IP. Обратите внимание на модификатор '''d'''. Без него проверка на IP проводиться НЕ будет. При указании IP старайтесь не использовать номер порта (знак двоеточия и то, что справа от него).&lt;br /&gt;
: Если все правильно, а вы все равно не становитесь администратором на сервере, то, скорее всего, проблема в том, что вы не прошли авторизацию на сервере. Для этого выполните команду ''users'' или ''stat'' в консоли сервера и обратите внимание на значение в колонке ''userid''. Если напротив потенциального админа стоит '''VALVE_ID_PENDING''', то это означает, что сервер криво заломан, и он не авторизовал данного игрока. В свою очередь это значит, что функция ''client_authorized(id)'' не была вызвана из всех AMXX активных плагинов. Если открыть файл ''admin.sma'', то можно увидеть следующее:&lt;br /&gt;
 public client_authorized(id)&lt;br /&gt;
   return get_cvar_num(&amp;quot;amx_mode&amp;quot;) ? accessUser(id) : PLUGIN_CONTINUE&lt;br /&gt;
: Это и есть проверка клиента на админа. Чтобы эта функция вызывалась всегда, ''client_authorized'' надо переименовать в ''client_putinserver'', а существующую функцию ''client_putinserver'' либо удалить, либо [[Ru_Fundamental_Basics_of_AMX_Mod_X_Scripting#Комментарии|закомментировать]].&lt;br /&gt;
&lt;br /&gt;
=== Как заставить команду amx_who выводить IP вместо ID? ===&lt;br /&gt;
: В файле ''admincmd.sma'' в указанном ниже месте &lt;br /&gt;
 public cmdWho(id, level, cid)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess) &lt;br /&gt;
  for (new a = 0; a &amp;lt; inum; ++a)&lt;br /&gt;
  {&lt;br /&gt;
   get_user_authid(players[a], authid, 31)&lt;br /&gt;
   ...&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
:замените &lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;authid&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: на&lt;br /&gt;
 console_print(id, &amp;quot;^n%s:^n #  %-16.15s %-20s %-8s %-4.3s %-4.3s %s&amp;quot;, cl_on_server, &amp;quot;nick&amp;quot;, &amp;quot;ip&amp;quot;, &amp;quot;userid&amp;quot;, lImm, lRes, lAccess)&lt;br /&gt;
: а также&lt;br /&gt;
 get_user_authid(players[a], authid, 31)&lt;br /&gt;
: на&lt;br /&gt;
 get_user_ip(players[a], authid, 31, 1)&lt;br /&gt;
: Сохраните файл и [[#Как компилировать плагины?|перекомпилируйте]] плагин.&lt;br /&gt;
&lt;br /&gt;
=== А как дать всем доступ к команде amx_who? ===&lt;br /&gt;
: По умолчанию, команда доступна только игрокам с правами '''y''' (т.е. это признак админа). Чтобы разрешить пользоваться ею всем игрокам, надо открыть файл ''admincmd.sma'', и в строке&lt;br /&gt;
 register_concmd(&amp;quot;amx_who&amp;quot;, &amp;quot;cmdWho&amp;quot;, ADMIN_ADMIN, &amp;quot;- displays who is on server&amp;quot;)&lt;br /&gt;
: заменить ''ADMIN_ADMIN'' на ''ADMIN_ALL'' и [[#Как компилировать плагины?|перекомпилировать]] плагин.&lt;br /&gt;
: В AMX 1.8.X и выше доступны стандартные средства переопределения прав доступа к командам без исправления самих плагинов (''TODO: ссылка?'').&lt;br /&gt;
&lt;br /&gt;
= Вопросы по компилированию =&lt;br /&gt;
=== Что такое компиляция? ===&lt;br /&gt;
: Это процесс, который переводит текстовые файлы (*.sma), содержащие исходный код (т.е. инструкции для AMX Mod X, который их исполняет), в формат, более пригодный для исполнения.  За счет этого скорость выполнения плагинов возрастает многократно, упрощается разработка &amp;quot;движка&amp;quot;, который эти плагины исполняет, а также в некотором смысле защищается авторский код. Почему в &amp;quot;некотором смысле&amp;quot;? Потому что все AMX Mod X плагины должны публиковаться под лицензией GNU General Public License. В случае публикации плагина лицензия обязывает также публиковать и его исходный код. Откомпилированные плагины имеют расширение .amxx. Именно файлы этого типа, а не .sma, должны указываться в файле plugins.ini для последующей корректной загрузки плагина.&lt;br /&gt;
&lt;br /&gt;
=== Как компилировать плагины? ===&lt;br /&gt;
: Базовую информацию вы можете найти на [[Ru Compiling Plugins (AMX Mod X)|этой]] странице.&lt;br /&gt;
&lt;br /&gt;
=== Как упростить процесс компилирования? ===&lt;br /&gt;
: Можно написать стороннюю программу или скрипт, например такой, как пакетный batch файл. Например, создайте файл make.bat со следующим содержимым:&lt;br /&gt;
 @amxxpc.exe %1 -i.\include -o.\compiled\%1&lt;br /&gt;
: Чтобы с помощью него откомпилировать плагин, необходимо выполнить следующую команду:&lt;br /&gt;
 make.bat my_plugin.sma&lt;br /&gt;
: В итоге откомпилированный файл будет помещен в каталог ''compiled'' текущей директории. Если его там нет, значит в процессе компилирования возникли фатальные ошибки, которые выводятся на экран.&lt;br /&gt;
: Если вам необходимо (например, в случае ошибок) отправить кому-нибудь результат компиляции, можете перенаправить вывод информации о процессе компилирования в файл, например таким образом:&lt;br /&gt;
 make.bat my_plugin.sma &amp;gt; my_plugin.log&lt;br /&gt;
&lt;br /&gt;
=== Компилятор выводит &amp;quot;max. usage is unknown, due to recursion&amp;quot; ===&lt;br /&gt;
: Ничего страшного - просто компилятор не может вычислить предполагаемый объем памяти, используемый вашим плагином.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Вопросы по скриптингу =&lt;br /&gt;
=== С чего начать? ===&lt;br /&gt;
: С со статьи [[Ru Fundamental Basics of AMX Mod X Scripting|Фундаментальные основы AMX Mod X скриптинга]].&lt;br /&gt;
&lt;br /&gt;
=== А стоит ли вообще начинать? ===&lt;br /&gt;
: В зависимости от того, какую цель вы преследуете, а также от вашего желания и потенциала. Знание английского языка (чтение) будет огромным плюсом во время обучения, иначе постигать азы будет очень сложно. CS является закрытым проектом без исходных кодов, поэтому могие новые (неизученные) элементы приходится постигать через проведение экспериментов.&lt;/div&gt;</summary>
		<author><name>Simon Logic</name></author>
		
	</entry>
</feed>