Ru Intro to AMX Mod X Scripting

From AlliedModders Wiki
Revision as of 11:07, 31 December 2006 by VEN (talk | contribs) (added the link to the upcoming "Ru:Fundamental Basics of the AMX Mod X Scripting")
Jump to: navigation, search

Просмотреть оригинал статьи (англ.): Intro to AMX Mod X Scripting


Введение в AMX Mod X скриптинг

Это руководство позволит разобраться в основах скриптинга AMX Mod X плагинов.

Обзор

Значит, вы хотите создать плагин? Вы должны иметь хорошее представление о том, как работает Pawn, скриптинг язык, который используется для написания AMX Mod X плагинов. Поэтому в первую очередь настоятельно рекомендуется ознакомиться с фундаментальными основами Pawn и AMX Mod X скриптинга: Ru:Fundamental Basics of the AMX Mod X Scripting. Желательно читать данную статью, сидя за компьютером с текстовым редактором и Pawn компилятором под рукой - хорошее подспорье для эффективного обучения. Конечно же, вы не будете сразу писать большие плагины типа WC3, Matrix Mod и CSDM, но все же статья даст вам "толчок" в мир моддинга AMX Mod X. Хороший редактор с поддержкой Pawn - это AMXX-Studio, который можно найти в секции AMX Mod X downloads.

Вам необходимо знать, как компилировать плагины. Обратитесь к секции Ru:Compiling Plugins (AMX Mod X) для ознакомления. Также, чтобы проверить и отладить ваш плагин, вы должны знать, как устанавливать плагины. Для этого обратитесь к секции Ru:Configuring AMX Mod X.

Введение

AMX Mod X плагин может иметь четыре главных типа функций. Первый - "public" функция. Это означает, что функция доступна для AMX Mod X "движка". Второй тип - "native" функция, которая располагается в модуле или в ядре AMX Mod X. Третий тип - обычные пользовательские функции, которые прописываются без каких-либо специальных атрибутов. Четвертый тип - это "forward" функция, которая вызывается каждый раз, когда происходит какое-то определенное событие (forward функция также является и public). AMX Mod X плагин должен начинаться с функции, инициализирующей плагин:

//Это делает возможным использование функций AMX Mod X ядра
//Это "влаживает" native "определители"(заголовки) из includes\amxmodx.inc
#include <amxmodx>
 
//Объявляем три строковых переменных
new PLUGIN[]="AMXX Demo"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"
 
//Это public функция.
//Необходимо инициализировать ваш скрипт для AMX Mod X.
//Эта функция не содержит параметров, вызывается сразу после загрузки карты.
public plugin_init()
{
     //Это функция, которая "берет" три строки.
     //Она регистрирует ваш плагин в AMX Mod X и присваивает некоторую основную информацию.
     register_plugin(PLUGIN, VERSION, AUTHOR)
}

Попробуйте откомпилировать скрипт, приведенный выше. Он будет очень мал, т.к. не делает ничего особенного. Однако, если вы загрузите этот скрипт и напишите "amxx plugins" в серверной консоли, вы должны увидеть новую запись в листе плагинов.

Создание админ-комманд

AMX Mod X предоставляет возможность простого добавления консольных админ-команд. Каждая команда "регистрируется" как консольная команда. При регистрировании команды вы должны указать четыре свойства: имя консольной команды; функцию, которая будет вызываться при использовании команды; уровень доступа, необходимый для использования команды; короткое описание команды.

Для демонстрации давайте сделаем плагин, который позволит вам изменить количество жизней игрока на сервере с помощью команды "amx_hp".

Для начала нам понадобится сделать две вещи: первая - нам нужно зарегистрировать команду в консоли. Т.к. мы "привязываем" команду к public функции, мы должны убедиться, что функция существует.

#include <amxmodx>
#include <amxmisc> //Это содержит некоторые полезные функции
#include <fun>     //Это содержит функцию для изменения жизней
 
new PLUGIN[]="Change Health"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"
 
public plugin_init()
{
     register_plugin(PLUGIN, VERSION, AUTHOR)
     register_concmd("amx_hp", "cmd_hp", ADMIN_SLAY, "<target> ")
}
 
public cmd_hp(id, level, cid)
{
     return PLUGIN_HANDLED
}

Первая новая функция - это "register_concmd", которая берет четыре параметра. Первый - название команды, которую необходимо набрать в консоли. Второй - название public функции, которая будет контролировать команду. Третий - уровень доступа, который необходим для вашей команды. И последний - строка, описывающая, как использовать вашу команду.

Далее мы создаем public функцию для контроля amx_hp команды. Обратите внимание, что мы даем ей три параметра. Эти параметры будут содержать специальные данные, когда команду будет использована. id будет содержать индекс(номер) игрока, который запустил команду, level будет содержать уровень доступа команды (вы должны сами осуществить проверку уровня доступа), cid будет содержать внутренний индекс(номер) команды.

Также обратите внимание на PLUGIN_HANDLED. Существует два главных return значения. PLUGIN_CONTINUE как бы означает "продолжить с нормальным выполнением", PLUGIN_HANDLED означает "блокировать дальнейшее выполнение". Разница сложно уловима, но важна. К примеру, если вы делаете "привязку" к своей команде, вы не должны возвращать PLUGIN_CONTINUE. Но если вы возвращаете PLUGIN_HANDLED, при привязанной "say" команде, это полностью заблокирует say-текст. Вы должны быть внимательны с тем, что вы выбираете для возврата в различных ситуациях. Однако, многие вещи "безразличны" к возвращаемому значению. Например, таймеры(tasks), события(events) и другие вещи, с которыми вы встретитесь позже.

Итак, как же мы убедимся, что данный пользователь - это админ, который имеет ADMIN_SLAY уровень доступа?

public cmd_hp(id, level, cid)
{
     if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED
     return PLUGIN_HANDLED
}

cmd_access() функция проверит информацию команды (пользователя, уровень доступа и индекс) и проверяет две вещи: что пользователь имеет доступ, и что было дано минимальное количество параметров. Мы указали три, потому что команда будет выглядеть как: amx_hp <target> <amount>, и в действительности сама команда также считается как параметр. Если cmd_access откажет, мы сразу прекращаем выполнение команды.

Следующее, что нужно решить: мы должны взять два параметра и преобразовать их. "amount" параметр прост - мы просто конвертируем его из строки в число. Другой же параметр будет по сложнее, т.к. мы хотим иметь возможность указывать на три различных типа людей:

  • @CT или @T - (контр-террористы или террористы)
  • @ALL - (все)
  • <target> - частичное имя игрока
public cmd_hp(id, level, cid)
{
     if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED
 
     new Arg1[24]
     new Arg2[4]
 
     //Берем аргументы команды из консоли
     read_argv(1, Arg1, 23)
     read_argv(2, Arg2, 3)
 
     //Конвертируем количество жизней из строки в число
     new Health = str_to_num(Arg2)
 
     //Является ли первый символ @ символом?
     if (Arg1[0] == '@')
     {
          new Team = 0
          //Проверяем, какая команда была указана.
          //Заметьте, что мы начинаем с [1]
          // это означает, что @ не входит
          if (equali(Arg1[1], "CT"))
          {
               Team = 2
          } else if (equali(Arg1[1], "T")) {
               Team = 1
          }
          new players[32], num
          //Эта функция заполнит players[32] переменную
          // верными индексами игроков. num будет содержать количество
          // игроков, которые действительны.
          get_players(players, num)
          new i
          for (i=0; i<num; i++)
          {
               if (!Team)
               {
                    //Устанавливаем количество жизней этого игрока
                    set_user_health(players[i], Health)
               } else {
                    if (get_user_team(players[i]) == Team)
                    {
                         set_user_health(players[i], Health)
                    }
               }
          }
     } else {
          //находит индекс игрока, который соответствует части указанного имени
          //1 означает, что игрок с "иммунитетом" не будет учтен
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
               //это напечатает сообщение пользователю, который запускал команду
               //Формат для этой команды называется "format()" стиль,
               // где первая строка форматирует сообщение соответственно
               // любому количеству следующих параметров:
               //  %s означает строка
               //  %d или %i означает целое число
               //  %f означает дробное число
               // поэтому "Privet %s, mne %d let" будет требовать
               //  чтобы следовали параметры строки и целого числа
               console_print(id, "Izvinite, igrok %s ne mojet bit naiden ili ispol'zovan v kachestve ob'ekta!", Arg1)
               return PLUGIN_HANDLED
          } else {
               set_user_health(player, Health)
          }
     }
 
     return PLUGIN_HANDLED
}

Таким образом, наша финальная версия amx_hp плагина будет выглядеть следующим образом:

#include <amxmodx>
#include <fun>
 
new PLUGIN[]="Change Health"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"
 
public plugin_init()
{
     register_plugin(PLUGIN, VERSION, AUTHOR)
     register_concmd("amx_hp", "cmd_hp", ADMIN_SLAY, "<target> <hp>")
}
 
public cmd_hp(id, level, cid)
{
     if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED
 
     new Arg1[24]
     new Arg2[4]
 
     //Берем аргументы команды из консоли
     read_argv(1, Arg1, 23)
     read_argv(2, Arg2, 3)
 
     //Конвертируем количество жизней из строки в число
     new Health = str_to_num(Arg2)
 
     //Является ли первый символ @ символом?
     if (Arg1[0] == '@')
     {
          new Team = 0
          if (equali(Arg1[1], "CT"))
          {
               Team = 2
          } else if (equali(Arg1[1], "T")) {
               Team = 1
          }
          new players[32], num
          get_players(players, num)
          new i
          for (i=0; i<num; i++)
          {
               if (!Team)
               {
                    set_user_health(players[i], Health)
               } else {
                    if (get_user_team(players[i]) == Team)
                    {
                         set_user_health(players[i], Health)
                    }
               }
          }
     } else {
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
               console_print(id, "Izvinite, igrok %s ne mojet bit naiden ili ispol'zovan v kachestve ob'ekta!", Arg1)
               return PLUGIN_HANDLED
          } else {
               set_user_health(player, Health)
          }
     }
 
     return PLUGIN_HANDLED
}

Консольные переменные

CVar - это консольная переменная. Существуют клиентские и серверные CVar'ы. К примеру, "mp_startmoney" - Counter-Strike серверная CVar, содержащая число, указывающее, сколько денег дается игрокам, когда они заходят на сервер. Вы можете создавать свои серверные CVar'ы путем их регистрирования. Давайте создадим свою amx_startmoney CVar.

#include <amxmodx>
#include <cstrike>
 
public plugin_init()
{
     register_plugin("CVAR Test", "1.0", "BAILOPAN")
     //регистрируем amx_startmoney CVar
     // и устанавливаем для нее значение по умолчанию 500
     register_cvar("amx_startmoney", "500")
}
 
//это вызывается, когда клиент заходит непосредственно на сервер
public client_putinserver(id)
{
     if (get_cvar_num("amx_startmoney") > 0)
     {
          cs_set_user_money(id, get_cvar_num("amx_startmoney"))
     } else {
          cs_set_user_money(id, get_cvar_num("mp_startmoney"))
     }
}

Вы можете устанавливать дробные, целые или строковые значения как для своих CVar, так и для любых других.

Дополнительно

Чтобы узнать больше о скриптинге для AMX Mod X вам следует взглянуть на native прототипы в описаниях функий или в *.inc файлах ("инклудах"). Инклуды по большому счету придерживаются двух форматов. Они имеют название в соответствии с модулем или определенным предназначением. _const добавляется, если они содержат предопределенные числа или списки. _stocks добавляется, если они содержат "помогающие" или полезные "функции-обертки". Помните, что stocks компилируются только, если вы используете их, поэтому без опаски можно "включать" файлы, содержащие большое количество stocks.

Вы также можете посетить Форум и задать вопросы или найти больше информации.