Как создать свой первый SourceMod плагин, вам расскажет эта статья. После прочтения, вы научитесь писать свои просты SourceMod плагины, SourceMod плагины написаны на языке SourcePawn, рекомендуем вам с ним ознакомиться. Что понадобиться для созданиея SourceMod плагина? Вам понадобиться Notepad + + или Crimson Editor, знания SourcePawn языка. Что же давайте начнем создавать свой первый SourceMod плагин. Большенство SourceMod плагинов имеет следющиюю структуру: # Включение <sourcemod>
public Plugin:myinfo = {
name = "Мой первый плагин", author = "Me", description = " Мой первый плагин изучение", version = "1.0.0.0", url = "http://csske.ru/" };
public OnPluginStart() {
/ / Выполнение разовых задач, запуск ... }
| Информационная часть представляет собой специальную конструкцию синтаксиса. В не можете поменять не одно ключевое слово, или общества Plugin: MyInfo декларации. Лучше всего, чтобы скопируйте и вставьте этот скелетной структуры и изменения строк, чтобы начать.В основном плагины SourceMod включают в себя:Для работы языка требуется включать файлы, так же, как в языке C требует заголовочных файлов. Включать файлы перечислить все структуры, функции, обратные вызовы и теги, которые доступны. Есть три типа файлов включают в себя: Core - sourcemod.inc и все, что он включает в себя. Они все предоставляемые Основные SourceMod автора. Extension - дает зависимость от определенного расширения.А plugin - передает превязанность от определенного плагина. Включютья файлы с помощью # включить директивы компилятора.В нашем первом плагине администратор будет бить игрока :DВо-первых, давайте посмотрим на то, что администратор команды требуется. Администратор команды регистрируются с помощью RegAdminCmd функции. Они требуют названия, функция обратного вызова, и флаги администратора по умолчанию. Функция обратного вызова является то, что вызывается каждый раз команда используется. Пример:public OnPluginStart() { RegAdminCmd("sm_myslap", Command_MySlap, ADMFLAG_SLAY) }
public Action:Command_MySlap(client, args) { }
| Теперь мы успешно реализовали команды, но это еще не все.у нас будет вылетать ошибка "Unknown command", если вы используете его! Причина в том, из-за действий тега. Любая команда, которую вы вводите в консоли, даже если оно зарегистрировано SourceMod, будет отправлен на двигателе должны быть обработаны. Потому что у нас не было SourceMod блокировать эту функцию еще, двигатель отвечает с "Неизвестная команда", поскольку он не является допустимым командой двигателя. public Action:Command_MySlap(client, args) { return Plugin_Handled; }
| Теперь команда будет сообщать никакой ошибки, но все равно ничего не будет делать. Это потому, что возвращение "PLUGIN_HANDLED" в команду обратного вызова позволит предотвратить двигатель от обработки команды. Двигатель никогда не сможет даже увидеть, что команда была выполнена. Это то, что вам нужно будет сделать, если вы регистрируете совершенно новую команду через SourceMod.Как это сделать? Очень просто Давайте решим, что команда будет выглядеть. Давайте возмем команду sm_slap по умолчанию: sm_myslap <name|#userid> [damage]
| Чтобы осуществить это, нам нужно несколько шагов: 1 - Разрешить ввод с консоли. Мы используем GetCmdArg для этого () . 2 - Найти соответствующий плеер. Используем сразу FindTarget () . 3 - Ударить игрока. Для этого мы используем команду SlapPlayer () , которая нуждается в sdktools, это расширение идет вкомплекте с SourceMod. 4 - Если админ то... Тогда пользуемся командой ReplyToCommand () . Полный пример: #include <sourcemod> #include <sdktools>
public Plugin:myinfo = { name = "My First Plugin", author = "Me", description = "My first plugin ever", version = "1.0.0.0", url = "http://www.sourcemod.net/" }
public OnPluginStart() { RegAdminCmd("sm_myslap", Command_MySlap, ADMFLAG_SLAY) }
public Action:Command_MySlap(client, args) { new String:arg1[32], String:arg2[32] new damage
/* Get the first argument */ GetCmdArg(1, arg1, sizeof(arg1))
/* If there are 2 or more arguments, and the second argument fetch * is successful, convert it to an integer. */ if (args >= 2 && GetCmdArg(2, arg2, sizeof(arg2))) { damage = StringToInt(arg2) }
/* Try and find a matching player */ new target = FindTarget(client, arg1) if (target == -1) { /* FindTarget() automatically replies with the * failure reason. */ return Plugin_Handled; }
SlapPlayer(target, damage)
new String:name[MAX_NAME_LENGTH]
GetClientName(target, name, sizeof(name)) ReplyToCommand(client, "[SM] You slapped %s for %d damage!", name, damage)
return Plugin_Handled; }
| Для получения дополнительной информации о том,% S и% D являются, см. Функции формата класса . Обратите внимание, что вам никогда не придется отменить или удалить администратора команды. Когда плагин выгружается, SourceMod очищает его и для вас.Работа с ConVars:ConVars, также известный как CVARS, являются глобальные переменные консоли на Source Engine. Они могут иметь целый, дробный, или строковые значения. ConVar Доступ осуществляется с помощью ручки . С ConVars являются глобальными, вам не нужно, чтобы закрыть ConVar ручки (на самом деле, вы не можете). Удобная особенность ConVars является то, что они легки для пользователей, чтобы настроить. Из можно разместить в любой. CFG файлов, таких как server.cfg или sourcemod.cfg. Для облегчения этой задачи, SourceMod имеет AutoExecConfig () функцию. Эта функция автоматически построить по умолчанию. CFG файл, содержащий все ваши CVARS, аннотированный с комментариями, для пользователей. Мы настоятельно рекомендуем, чтобы вы называете это если у вас есть настраиваемой ConVars. Давайте расширим предыдущий пример с новым ConVar. Наши ConVar будет sm_myslap_damage и укажет кто-то умолчанию ущерб ударил ибо, если не был причинен ущерб уточняется.new Handle:sm_myslap_damage = INVALID_HANDLE
public OnPluginStart() { RegAdminCmd("sm_myslap", Command_MySlap, ADMFLAG_SLAY)
sm_myslap_damage = CreateConVar("sm_myslap_damage", "5", "Default slap damage") AutoExecConfig(true, "plugin_myslap") }
public Action:Command_MySlap(client, args) { new String:arg1[32], String:arg2[32] new damage = GetConVarInt(sm_myslap_damage)
/* The rest remains unchanged! */
| Отображение активности, логирование:Почти все команды администратора должны войти свою деятельность, команды администратора обязаны показать свою активность в игре клиентов. Вы можете сделать это через LogAction () или ShowActivity2 () команды, функции. Точная функциональность ShowActivity2 () определяется sm_show_activity квар. Например, давайте перепишем несколько последних строк нашего убойного плагина команду:SlapPlayer(target, damage)
new String:name[MAX_NAME_LENGTH]
GetClientName(target, name, sizeof(name))
ShowActivity2(client, "[SM] ", "Slapped %s for %d damage!", name, damage) LogAction(client, target, "\"%L\" slapped \"%L\" (damage %d)", client, target, damage)
return Plugin_Handled; }
| Один ко многим: Чтобы полностью завершить нашу пощечину демонстрации, давайте сделаем его поддерживают несколько целей. SourceMod в системы наведения является весьма прогрессивным, поэтому его использование вам покажется очень сложным на первый взгляд.
Функция мы используем ProcessTargetString () . Он принимает ввод с консоли, возвратит список клиентов. Она также возвращает существительное, которое будет идентифицировать либо одного клиента или описать список клиентов. Идея состоит в том, что каждый клиент затем обрабатывается, но активность показали всем игрокам обрабатывается только один раз. Это снижает экрана спама.
Этот метод целевой обработки используется почти для каждого администратора команды в SourceMod, где в реальности FindTarget () всего лишь упрощенная версия.
Полный, последний пример:#include <sourcemod> #include <sdktools>
new Handle:sm_myslap_damage = INVALID_HANDLE
public Plugin:myinfo = { name = "My First Plugin", author = "Me", description = "My first plugin ever", version = "1.0.0.0", url = "http://www.sourcemod.net/" }
public OnPluginStart() { LoadTranslations("common.phrases") RegAdminCmd("sm_myslap", Command_MySlap, ADMFLAG_SLAY)
sm_myslap_damage = CreateConVar("sm_myslap_damage", "5", "Default slap damage") AutoExecConfig(true, "plugin_myslap") }
public Action:Command_MySlap(client, args) { new String:arg1[32], String:arg2[32] new damage = GetConVarInt(sm_myslap_damage)
/* Get the first argument */ GetCmdArg(1, arg1, sizeof(arg1))
/* If there are 2 or more arguments, and the second argument fetch * is successful, convert it to an integer. */ if (args >= 2 && GetCmdArg(2, arg2, sizeof(arg2))) { damage = StringToInt(arg2) }
/** * target_name - stores the noun identifying the target(s) * target_list - array to store clients * target_count - variable to store number of clients * tn_is_ml - stores whether the noun must be translated */ new String:target_name[MAX_TARGET_LENGTH] new target_list[MAXPLAYERS], target_count new bool:tn_is_ml
if ((target_count = ProcessTargetString( arg1, client, target_list, MAXPLAYERS, COMMAND_FILTER_ALIVE, /* Only allow alive players */ target_name, sizeof(target_name), tn_is_ml)) <= 0) { /* This function replies to the admin with a failure message */ ReplyToTargetError(client, target_count); return Plugin_Handled; }
for (new i = 0; i < target_count; i++) { SlapPlayer(target_list[i], damage) LogAction(client, target_list[i], "\"%L\" slapped \"%L\" (damage %d)", client, target_list[i], damage) }
if (tn_is_ml) { ShowActivity2(client, "[SM] ", "Slapped %t for %d damage!", target_name, damage) } else { ShowActivity2(client, "[SM] ", "Slapped %s for %d damage!", target_name, damage) }
return Plugin_Handled; }
|
Клиент и Entity индексы:
Одним из главных степени смешения с Half-Life 2 представляет собой разницу между следующими вещами: Клиент индекс Сущность индексов Userid
Первым ответом является то, что клиенты лиц. Получается,что номер клиента и номер объекта одно и то же. А во время того когда SourceMod начинает запрашивть новый индекс некоторого объекта, номер пользователя может быть назначен. Когда SourceMod функция запрашивает индекс пользователя и это означает, что номер пользователя может быть указан.
Быстрый способ проверить, если индекс объекта является клиент проверяет ли это между одним и GetMaxClients () (включивши). Если сервер клиента N слотов максимум, то лиц от 1 до числа N, всегда заблокированы для ползователей. Обратите внимание, что 0 является допустимым индексом лица; это мир лицом (Worldspawn).
Идентификатор пользователя, с другой стороны, это совершенно другое. Сервер поддерживает глобальную "соединение счета" номер, и он начинается с 1. Каждый раз, когда клиент подключается, подключение счетчика увеличивается, и клиент получает новый номер как свой идентификатор пользователя.
Например, первый клиент для подключения имеет идентификатор 2. Если он выходит и возвращается, его значение(идентифицирующие) будет 3 (а например если какой, нибудь другой клиент присоединяется между ними). Так как клиенты отключаются от mapchange, их идентификаторами изменить. UserIds очень удобный способ для проверки состояния соединения клиента изменились.
SourceMod предоставляет две функции для идентификаторами пользователей: GetClientOfUserId () и GetClientUserId () .
События
События являются информационные сообщения уведомлений, передаваемых между объектами на сервере. Многие из них также перекидываються от сервера к пользователю. Они определены в. Файлов разрешения в соответствии с hl2/resource папки и папки ресурсов конкретной моды.
Важно отметить несколько понятий о событиях: Они почти всегда информационной. То есть, блокирование player_death не остановить игрока от смерти. Он может блокировать HUD сообщение или консоль или что-то еще несовершеннолетний. Они почти всегда используют идентификаторами, а не клиент индексов. Просто потому, что он находится в ресурсах незначит, что он никогда не называл, или работает так, как вы ожидаете. Моды Как известно, при не правильной документирование их функциональных возможностей событий.
Например нахождения, когда игрок умирает: общественных OnPluginStart () {HookEvent ("player_death", = GetEventInt (события, "UserID") новый attacker_id = GetEventInt (события, "Злоумышленник") новую жертву = GetClientOfUserId (victim_id) новый атакующий = GetClientOfUserId (attacker_id) / * код * /} Обратный заказов и сопряжение
SourceMod имеет ряд встроенных функций обратного вызова о состоянии сервера и плагинов. Некоторые из них парные специальными способами которая в заблуждение пользователей. Спаривание
Спаривание SourceMod терминологии. Примерами этого являются: OnMapEnd () не может быть вызван без OnMapStart (), и если OnMapStart () вызывается, он не может быть вызван снова без OnMapEnd (). OnClientConnected (N) для данного клиента N будет вызываться только один раз, пока OnClientDisconnected (N) для того же клиента N называется (которая гарантированно случится).
Существует формальное определение спаривания SourceMod автора. Для двух функций X и Y, как с входом, выполняются следующие условия: Если X вызывается с входом, он не может быть вызван снова с тем же вход, если Y называется с участием А. Если X вызывается с входом, это гарантирует, что Y будет, в какой-то момент, можно назвать с участием А. Y не может быть вызван с любого входа, если X был назван первым с входом А. Отношения описывается как "X работает в паре с Y» и «Y сопряжена с X." Генеральный Callbacks
Эти обратные вызовы перечислены в порядке их еще называют, в жизни плагинов и сервер. AskPluginLoad () - вызывается один раз, сразу после того, как плагин загружается с диска. OnPluginStart () - вызывается один раз, после того, плагин был полностью инициализирован и может приступить к загрузке. Любые ошибки во время выполнения этой функции приведет к тому, плагин не загружается. Это в паре с OnPluginEnd (). OnMapStart () - Вызывается каждый раз, когда карта нагрузки. Если плагин загружен поздно, и карта уже началась, эта функция вызывается в любом случае после нагрузки, в целях сохранения спаривания. Эта функция вместе с OnMapEnd (). OnConfigsExecuted () - вызывается один раз за карту изменения после servercfgfile (обычно server.cfg), sourcemod.cfg, и все файлы конфигурации плагина закончили выполнение. Если плагин загружается после того, как это произошло, обратный вызов во всяком случае, в целях сохранения спаривания. Данная функция sourcemod идет вместе с OnMapEnd (). На данный момент, большинство обратных вызовов игре может произойти, например, события и обратные привлекая клиентов (или другие вещи, такие как OnGameFrame). OnMapEnd () - Вызывается, когда карта подходит к концу. На данный момент, все клиенты будут отключены, но TIMER_NO_MAPCHANGE таймеров еще не уничтожены.И данная также функция идет вместе с OnMapStart (). OnPluginEnd () - вызывается один раз, непосредственно перед плагин выгружается Эта функция работает в паре с OnPluginStart ().. Обратных вызовов клиента
Эти обратные вызовы, перечисленные в каких-либо конкретных целях, однако, их документация справедливо как для поддельными и реальных клиентов. OnClientConnect () - Вызывается, когда игрок инициирует соединение Это в паре с OnClientDisconnect () для успешного соединения только.. OnClientAuthorized () - Вызывается, когда игрок получает Steam ID. Важно отметить, что это никогда не может быть названо. Это может произойти в любое время в период между подключать и отключать. Не полагайтесь на это, если вы пишете что-то, что должно Паровая идентификаторы, и даже тогда вы должны использовать OnClientPostAdminCheck (). OnClientPutInServer () - означает, что игрок находится в игре и IsClientInGame () вернет правда. OnClientPostAdminCheck () - Вызывается после того, как игрок уполномоченным и в игре. То есть, как OnClientAuthorized () и OnClientPutInServer () была вызвана. Это лучший обратного вызова для проверки административного доступа после подключения. OnClientDisconnect () -. Вызывается при отключении игрока заканчивается Это в паре с OnClientConnect (). Часто задаваемые вопросы Являются ли плагины перезагружается каждые mapchange?
Плагины, по умолчанию, не перегружены на mapchange, если их изменения временной метки. Это функция, поэтому плагин авторы имеют больше гибкости с состоянием их плагины. Нужно ли мне звонить CloseHandle в OnPluginEnd?
Номер SourceMod автоматически закрывает ваши ручки, когда ваш плагин выгружается, в целях предотвращения ошибок памяти. Нужно ли включать # каждого человека. Inc?
Номер # включить даст вам 95%. ПНС. Кроме того, # включить включает в себя все, начиная с . Почему бы не некоторые события огня?
Существует никакой гарантии, что события будут стрелять. Мероприятие перечень не является спецификацией, это список событий, что игра способна стрелять. Если игра на самом деле срабатывает них до клапана или разработчика. Нужно ли CloseHandle таймеры?
Нет, в самом деле, это может привести к ошибкам. Таймеры естественно умереть на своей собственной, если они не бесконечна таймеры, в этом случае вы можете использовать KillTimer () или умереть красиво, возвращаясь Plugin_Stop в функции обратного вызова. Клиенты отключены от mapchange?
Все клиенты будут полностью отключены до смены карты. Все они подключены после очередного карта начинается.
|