Русское сообщество по скриптингу

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

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

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

Сообщение DJ_WEST » 07 сен 2009, 16:02

Источник: wiki.alliedmods.net
Перевод: DJ_WEST


Введение
AMX Mod X плагин может понимать четыре типа функций:

  • public (публичная) - это значит, что данный тип функций виден и доступен движку AMX Mod X.
  • native (внутренняя) - функция, которая объявлена или в модуле, или в ядре AMXX.
  • регулярная - функция, которая объявлена без всяких атрибутов.
  • forward - функция, которая вызывается после того, как произойдет какое-либо действие.

Любой плагин в AMX Mod X должен начинаться с инициализирующей функции:
Код: Выделить всё
// include - включает native функции из файла includes\amxmodx.inc
#include <amxmodx>
 
// Определение трех строковых констант
#define PLUGIN "AMXX Demo"
#define AUTHOR "AMX-X.RU"
#define VERSION "1.0"
 
// Это публичная функция, которая необходимо для инициализации плагина под AMXX.
// У функции нет параметров и она запускается после загрузки карты.
public plugin_init()
{
     // Регистрация функции в AMX Mod X и передача некоторой информации (название плагина, его автор и версия)
     register_plugin(PLUGIN, VERSION, AUTHOR)
}
 


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

Код: Выделить всё
#include <amxmodx>
#include <amxmisc> // Здесь содержится функция для проверки доступа игрока
#include <fun> // Здесь содержится функция для изменения количества жизни
 
#define PLUGIN "Change Health"
#define AUTHOR "AMX-X.RU"
#define VERSION "1.0"
 
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 функцию. Третий аргумент - необходимый уровень доступа. Последний - описание для данной команды, которое можно посмотреть, например, через amx_help. Затем мы написали публичную функцию cmd_hp с тремя параметрами. Параметр id содержит id игрока, который запустил данную функцию, level - содержит флаг доступа к команде и cid содержит внутренний id команды.
Поговорим насчет PLUGIN_HANDLED. Есть два основных значения возврата функции, которых вы коснетесь. PLUGIN_CONTINUE - означает "продолжать дальнейшую операцию" и PLUGIN_HANDLED - "блокировать дальнейшую операцию". Различия маленькие, но важные. К примеру, при создании консольной команды вы не должны возвращать PLUGIN_CONTINUE. Но с другой стороны, если вы вернете PLUGIN_HANDLED при создании "say" команды, то это заблокирует сообщение игрока от отображения. Вы должны быть внимательны при использовании данных значений. На большинство вещей возврат никак не влияет (к примеру, task (задачи), events (события) и другие).
Теперь необходимо проверить, что у пользователя есть ADMIN_SLAY доступ:
Код: Выделить всё
public cmd_hp(id, level, cid)
{
     if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED

     return PLUGIN_HANDLED
} 

Функция cmd_access() проверяет информацию о команде (пользователь, доступ и id) и дает нам убедиться в том, что данный пользователь имеет нужный доступ и через команду передано необходимое количество аргументов. Мы указали 3, потому что команда имеет вид: amx_hp <цель> <количество>. Следовательно, состоит из трех частей (аргументов): amx_hp, цель, количество. Если cmd_access вернул ложный ответ, то мы прекращаем выполнение функции через возвращение PLUGIN_HANDLED.
Следующее, что нам необходимо сделать - это обработать два последних параметра. "Количество" нужно из строкового типа перевести в целочисленный. И параметр "цель", который указывает на игроков из трех типов:
  • @CT или @T - CT или T команда
  • @ALL - всем
  • цель - часть имени игрока
Код: Выделить всё

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
          
// Функция get_players заполянет переменную players[32]
          // существующими id игроков. 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 {
          // Находим id игрока, который соответствует указанному части имени
          // Аргумент 1 означает, что мы не берем во внимание игроков с флагом иммунитета
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
               // Показываем сообщение игроку, который выполнил админскую команду
               // %s - означает строку
               // %d или %i - означает число
               // %f - означает число с плавающей точкой
               // Например, для правильного отображения строки "Hello %s, I am %d years old"
               // ей необходима строка и число
               console_print(id, "Sorry, player %s could not be found or targetted!", Arg1)
               return PLUGIN_HANDLED
          
} else {
               set_user_health(player, Health)
          }
     }
 
     return PLUGIN_HANDLED
} 

В результате полноценный плагин будет выглядеть так:
Код: Выделить всё
#include <amxmodx>
#include <amxmisc>
#include <fun>
 
#define PLUGIN "Change Health"
#define AUTHOR "AMX-X.RU"
#define VERSION "1.0"
 
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
          
// Проверяем, какая команда была указана
          // Начинаем с элемента [1], потому что символ @ нам не нужен
          if (equali(Arg1[1], "CT"))
          {
               Team = 2
          
} else if (equali(Arg1[1], "T")) 
          
{
               Team = 1
          
}

          new players[32], num
          
// Функция get_players заполянет переменную players[32]
          // существующими id игроков. 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 {
          // Находим id игрока, который соответствует указанному части имени
          // Аргумент 1 означает, что мы не берем во внимание игроков с флагом иммунитета
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
               // Показываем сообщение игроку, который выполнил админскую команду
               // %s - означает строку
               // %d или %i - означает число
               // %f - означает число с плавающей точкой
               // Например, для правильного отображения строки "Hello %s, I am %d years old"
               // ей необходима строка и число
               console_print(id, "Sorry, player %s could not be found or targetted!", Arg1)
               return PLUGIN_HANDLED
          
} else {
               set_user_health(player, Health)
          }
     }

     return PLUGIN_HANDLED
} 


Серверные команды (CVAR)
CVAR - это серверская комнада, к примеру, "mp_startmoney" - это Counter-Strike CVAR, который содержит количество денег, которые игроки будут получать в первом раунде. Вы можете сделать свои cvar, зарегистрировав их в plugin_init(). Давайте попробуем сделать аналог mp_startmoney.
Код: Выделить всё
#include <amxmodx>
#include <cstrike>
 
public plugin_init
()
{
     register_plugin("CVAR Test", "1.0", "AMX-X.RU")
     // 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 можно использовать числа, числа с плавающей точкой и строки.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

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

Сообщение ranzez » 10 апр 2011, 13:36

У меня вопрос:
необходимо каждые 120 секунд по центру выводить hud_message. Как отсчитывать именно эти 120 секунд?

Спасибо
Аватара пользователя
ranzez
 
Сообщения: 1
Зарегистрирован: 10 апр 2011, 13:35
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Team Fortress II
Left 4 Dead

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

Сообщение ejik » 10 апр 2011, 13:46

Аватара пользователя
ejik
 
Сообщения: 249
Зарегистрирован: 01 июл 2010, 14:07
Благодарил (а): 83 раз.
Поблагодарили: 83 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6

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

Сообщение Factor » 06 авг 2011, 17:51

Как установить последовательность звуков, то есть, чтобы звуки воспроизводились так - в начале ЗВУК\музыка, после его окончания следующий ЗВУК\музыка. А то у меня получается, что всё одновременно воспроизводится. :(
Аватара пользователя
Factor
 
Сообщения: 222
Зарегистрирован: 25 июн 2011, 15:14
Откуда: +4:00 GMT
Благодарил (а): 59 раз.
Поблагодарили: 10 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Counter-Strike 1.6

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

Сообщение Factor » 07 авг 2011, 17:15

:shout:
Аватара пользователя
Factor
 
Сообщения: 222
Зарегистрирован: 25 июн 2011, 15:14
Откуда: +4:00 GMT
Благодарил (а): 59 раз.
Поблагодарили: 10 раз.
Опыт программирования: Около 3 месяцев
Языки программирования: Counter-Strike 1.6

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

Сообщение Chuvi » 14 янв 2012, 17:40

CL0NE писал(а):
Серверские команды (CVAR)

Вроде бы как серверные

И вроде как "переменные", а не "комманды".
Во всяком случае я CVAR воспринимаю как Constant VARiable. Если не прав-поправьте. :-[
Плагинами на заказ не занимаюсь.
Своих дел хватает.
Аватара пользователя
Chuvi
Модератор
 
Сообщения: 2253
Зарегистрирован: 24 ноя 2011, 08:03
Благодарил (а): 127 раз.
Поблагодарили: 562 раз.

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

Сообщение ejik » 14 янв 2012, 23:11

Console VARiable
Constant VARiable
как Переменная можеть постоянной?
Аватара пользователя
ejik
 
Сообщения: 249
Зарегистрирован: 01 июл 2010, 14:07
Благодарил (а): 83 раз.
Поблагодарили: 83 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6

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

Сообщение Chuvi » 14 янв 2012, 23:26

ejik писал(а):Console VARiable
Constant VARiable
как Переменная можеть постоянной?

Скажем так. "Переменные, которы постоянно хранятся где-нибудь". Например в конфигах. Это не всмысле "константа".
Плагинами на заказ не занимаюсь.
Своих дел хватает.
Аватара пользователя
Chuvi
Модератор
 
Сообщения: 2253
Зарегистрирован: 24 ноя 2011, 08:03
Благодарил (а): 127 раз.
Поблагодарили: 562 раз.

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

Сообщение trololost » 01 фев 2012, 01:56

Код: Выделить всё
     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)
                    }
               }
          }

а я вот это не понял.
Зачем в коде выше здоровье устанавливается и там и в противном случае.

И !team - что это еще такое?
[Не принимаю заказы]
Аватара пользователя
trololost
 
Сообщения: 923
Зарегистрирован: 05 ноя 2011, 02:25
Благодарил (а): 104 раз.
Поблагодарили: 358 раз.

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

Сообщение DJ_WEST » 01 фев 2012, 09:54

И !team - что это еще такое?

Отрицание, другими словами если team = 0, то выполняется условие. Чуть выше идет проверка:
[pawn]
  1. if (Arg1[0] == '@')
[/pawn]
Затем инициализация переменной Team. Дальше идут проверки CT и T, то есть если ты написал @ALL, выдать здоровье всем, то Team = 0. И сработает:
[pawn]
  1. if (!Team)

  2.                {

  3.                     // Устанавливаем игроку количество жизни

  4.                    set_user_health(players[i], Health)

  5.                }
[/pawn]
Что выдаст здоровье всем, иначе выдаст здоровье только CT или T.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

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

Сообщение trololost » 01 фев 2012, 21:39

понятно. А если будет вот так: @BLABLABLA ? То тоже всем здоровье выдаст? ну судя по коду?
[Не принимаю заказы]
Аватара пользователя
trololost
 
Сообщения: 923
Зарегистрирован: 05 ноя 2011, 02:25
Благодарил (а): 104 раз.
Поблагодарили: 358 раз.

Пред.След.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5