Первые шаги

Сообщения
494
Реакции
341
Помог
11 раз(а)
Да не статьи по изучению языка, хотя я знаю, что от С отличается немного. Я про основные моменты, при создании проекта )
"Pawn" - кастрированный "С". И написание плагина сложно назвать проектом.
ну там я уже глянул, что основная функция нужна plugin_init
Не совсем верно. Открываешь "amxmodx.inc" и читаешь:
Код:
/**
 * Called just after server activation.
 *
 * @note Good place to initialize most of the plugin, such as registering
 *       cvars, commands or forwards, creating data structures for later use, or
 *       generating and loading other required configurations.
 *
 * @noreturn
 */
forward plugin_init();
По такой же аналогии читай какие есть форварды и нативы для использования.

Тот же "amxmodx.inc" не даст тебе полноценных возможностей для работы. Например, для хука неглобальных событий, в основном касающихся исключительно энтити, изучай модуль "hamsandwich", для установки свойств "fakemeta"/"engine" (engine достаточно устарел если что).
Если всё это нужно совмещать, то "reapi" - самый "свежий" модуль, но он не может полноценно заменить вышеописанные модули, они более узконаправленные. Впрочем, вообще всё зависит от поставленной задачи.

Открываешь сурсы различных плагинов и изучаешь.
По-моему стоит изначально ставить перед собой задачу, а уже в процессе выполнения этой задачи обращаться к сурсам по мере необходимости. Так будет в голове более правильная логика вещей, нежели он просто будет что-то изучать и смотреть, не имея перед собой конкретной цели и понимая что и зачем нужно.
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
bizon, хм, ну я вот настроил VSC, вроде бы компилит плагины.

А смотрю я инклуды сейчас, нужно ведь их изучить, это ведь часть SDK ?
Установил ReAPI и тоже инклуды смотрю.

Как я уже понял, plugin_init() просто регистрирует события, все функции и т.д. Запускается один раз в момент загрузки карты.
"Pawn" - кастрированный "С". И написание плагина сложно назвать проектом.
+/- синтаксис понятен, так как немного отличается от Си/С++
Вообще стараюсь левые плагины небольшие открывать и смотреть, чтобы понять алгоритм написания.
 

d3m37r4

111111
Сообщения
1,451
Реакции
1,177
Помог
10 раз(а)
Как я уже понял, plugin_init() просто регистрирует события, все функции и т.д.
Нет. Читай описание форварда в инклуде, там вполне ясно всё описано. Форвард ничего не регистрирует, в нём можно регистрировать события, загружать конфиги и пр.
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
в нём можно регистрировать события, загружать конфиги и пр.
я это и сказал)
Всё равно спасибо, читаю сижу. Почему-то отличаются инклуды с Гитхаба и те, которые скачал для компиляции вместе с Амх модом.
Внутри не нашёл client_disconnected, а на Гитхабе есть описание. Конечно по переводу логично что происходит, но всё же странно.
 
Сообщения
494
Реакции
341
Помог
11 раз(а)
ncux0Zz, читать инклуды не можно, а нужно - в них описаны нативы и форварды, а также параметры, которые передаются вместе с функциями.

Функция "plugin_init" имеет тип "forward", функции такого типа вызываются из модулей metamod/либо из других плагинов (есть возможность создавать их с помощью функции "CreateMultiForward" и вызвать через "ExecuteForward", но это уже совсем другая история). То есть они в основном просто вызываются в определенный момент и могут передавать какие-то параметры (plugin_init ничего не передает, читай параметры).
А вот функции типа "native" ты уже используешь в нужный момент события (в том же форварде, например), передавая свои данные, а не используя пришедшие, как в форварде.

Например, при старте сервера вызывается форвард plugin_init:
Код:
public plugin_init()
{
    // code
}
Имеем следующий натив (простой элементарный пример):
Код:
/**
 * Sets informations about the calling plugin.
 *
 * @param plugin_name   Name of the plugin
 * @param version       Version of the plugin
 * @param author        Author of the plugin
 *
 * @return              Plugin id of the calling plugin
 */
native register_plugin(const plugin_name[], const version[], const author[]);
Из описания натива мы понимаем, что он "регистрирует" плагин и должен передавать три параметра:
1. Название плагина
2. Версия плагина
3. Автор плагина
Все три параметра имеют тип "string".

Используя полученные знания применяем их на практике:

Код:
#include <amxmodx> // Подключаем библиотеку amxmodx, ибо используемый форвард и натив описаны именно там

public plugin_init() // Ловим в своём плагине вызов форварда
{
    register_plugin("Name Plugin", "ver. 1.0", "6u3oH"); // Натив, регистрирующий плагин (параметры описал выше)
}
Компилируем, закидываем на сервер, запускаем сервер/меняем карту, вводим в консоль сервера команду "amxx plugins" (без кавычек), которая выводит список плагинов и смотрим в списке плагинов свой (смотри во вложении результат).
То есть цепочка такова: ловим нужное событие (plugin_init) - выполняем свои действия (register_plugin). Таким образом всё в павне и происходит.
22 Фев 2022
Всё равно спасибо, читаю сижу. Почему-то отличаются инклуды с Гитхаба и те, которые скачал для компиляции вместе с Амх модом.
Могут быть разные версии, либо ты просто не нашёл.

Внутри не нашёл client_disconnected, а на Гитхабе есть описание. Конечно по переводу логично что происходит, но всё же странно.
Возможно, у тебя старая версия, где событие имело имя "client_disconnect". В версии >= 1.9.0 всё на месте:

Код:
/**
 * Called when a client is disconnected from the server.
 *
 * @note This will be called in some additional cases that client_disconnect doesn't cover,
 *       most notably when a client aborts the connection process. It is guaranteed to pair
 *       with the client_connect() forward.
 * @note When this fires the player entity is still valid (e.g. is_user_connected(id) will
 *       return true), but no networked commands will reach the client.
 *
 * @param id         Client index
 * @param drop       If true, the game has explicitly dropped the client
 * @param message    If drop is true, a writable buffer containing the disconnect info message
 * @param maxlen     Maximum size of buffer
 *
 * @noreturn
 */
forward client_disconnected(id, bool:drop, message[], maxlen);
 

Вложения

  • 27.7 KB Просмотры: 16
Сообщения
190
Реакции
16
Помог
1 раз(а)
bizon, да я подумал про версию уже, у меня 1.8.2.
Можно попробовать dev 1.9.0 установить, там она есть.

Так то, всё что ты описал я понимаю.
Про native и forward не знал отличия, так что спасибо.

Ещё не могу найти от куда берётся "pPlayer".
Я так понимаю, это указатель на игрока. Но описание не нашёл. Вот пример кода из левого плагина:

Код:
public client_disconnected(pPlayer) {
    if(is_user_hltv(pPlayer) || is_user_bot(pPlayer)) {
        return;
    }
Тут же видим client_disconnected. Но описание я уже нашёл на Гитхабе.
 
Сообщения
494
Реакции
341
Помог
11 раз(а)
ncux0Zz, я же писал, читай описание функций, выше я даже скинул описание функции client_disconnected. Обрати внимание на эту строчку:
Код:
* @param id         Client index
Параметр, который передается в функцию client_disconnected - индекс игрока.
Если тебя смущает, что в описании "id", а в примере ты увидел "pPlayer", то это всего лишь разные названия переменных.
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
bizon, d3m37r4, а что такое хуки и с чем их едят? Где можно почитать?
22 Фев 2022
Параметр, который передается в функцию client_disconnected - индекс игрока.
Если тебя смущает, что в описании "id", а в примере ты увидел "pPlayer", то это всего лишь разные названия переменных
Я понимаю, что это id название разных переменных. Но pPlayer это произвольное название переменной в функции, как я понял, просто автор заменил её на свою и всё? При обращении она инициализируется, при отсоединении игрока в переменную pPlayer передаются его данные. А вообще там функция принимает ряд данных, тогда в pPlayer передаётся набор данных (структура или массив).
 
Сообщения
494
Реакции
341
Помог
11 раз(а)
ncux0Zz, если в двух словах, то "хук" - это отлов события. От англ. hook - крюк, ловушка, зацеп, грубо говоря, мы "цепляем" это событие или если вернее переводить на русский семантически - ловим.
В модуле hamsandwich есть функция RegisterHam.
Код:
/**
* Hooks the virtual table for the specified entity class.
* An example would be: RegisterHam(Ham_TakeDamage, "player", "player_hurt");
* Look at the Ham enum for parameter lists.
*
* @param function        The function to hook.
* @param EntityClass    The entity classname to hook.
* @param callback        The forward to call.
* @param post            Whether or not to forward this in post.
* @param specialbot    Whether or not to enable support for bot without "player" classname.
* @return                 Returns a handle to the forward.  Use EnableHamForward/DisableHamForward to toggle the forward on or off.
*/
native HamHook:RegisterHam(Ham:function, const EntityClass[], const Callback[], Post=0, bool:specialbot = false);
Параметры:
1. Событие типа Ham_*
2. Класснэйм с которым ловим событие (игрок имеет имя класса "player")
3. Функция, которая будет вызвана во время хука события
4. Pre=0/Post=1. Pre - вызывается до момента исполнения события, Post - после. Вся разница в том, что Pre используется для того, чтобы была возможно заблокировать это событие, Post - просто для получения информации после исполнении события.
5. Поддержка не имитирующих классэйм ботов. На это пока можешь вообще не обращать внимание.

Например, нужно "хукнуть" спавн игрока, другими словами - отловить событие, когда игрок спавнится, тогда:
Код:
#include <amxmodx>
#include <hamsandwich>

public plugin_init()
{
    RegisterHam(Ham_Spawn, "player", "fwHam_PlayerSpawn_Post", 1); // хукаем событие
}

public fwHam_PlayerSpawn_Post(pPlayer) // обрабатываем хукнутое событие
{
    client_print(pPlayer, print_chat, "Вы возродились"); // Выводим в чат информацию о спавне
}
Список этих самых событий ищи в "ham_const.inc", там же есть описание параметров, которые передаются.
Для Ham_Spawn:
Код:
    /**
     * Description:        This is typically called whenever an entity is created.
     *                    It is the virtual equivilent of spawn from the engine.
     *                    Some mods call this on player spawns too.
     * Forward params:    function(this)
     * Return type:        None.
     * Execute params:    ExecuteHam(Ham_Spawn, this);
     */
    Ham_Spawn = 0,
Аналог в reapi: RegisterHookChain. Описание смотри в инклудах.

P. S. RegisterHam/RegisterHookChain просто как примеры.
 
Последнее редактирование:

d3m37r4

111111
Сообщения
1,451
Реакции
1,177
Помог
10 раз(а)
А вообще там функция принимает ряд данных, тогда в pPlayer передаётся набор данных (структура или массив).
То, что она "принимает" и что передает, две разные вещи. В твоем случае там просто засылается индекс игрока, который вышел с сервера. В следующих далее аргументах другая информация, опять же см. описание возвращаемых аргументов.
 

RockTheStreet

Саппорт года
Сообщения
1,743
Реакции
344
Помог
40 раз(а)
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Внутри не нашёл client_disconnected
Потому что не нужно старые версии AmxModX качать.
Как я уже понял, plugin_init() просто регистрирует события, все функции и т.д. Запускается один раз в момент загрузки карты.
Стандартные форварды вызываются в определённым порядке. Соответственно, можно выбрать для себя в какой форвард пихать регистрацию конфигов, событий, и тому подобное.
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
Я тут ReAPI глянул, как я понял, там есть Хуки, которые способны отлавливать события. То есть в АМХ стандартно ограничен лишь готовыми функциями. Когда в то время, с помощью ReAPI хуков можно отловить события, которые происходят в рамках самого движка или ReGameDll?
Например, смерть игрока. Может что-то путаю, пытаюсь через переводчик читать)) с Английским не всё так гладко. Описание к сожалению там краткое и примеров нет)
23 Фев 2022
Выше почитал комменты ещё раз, вроде бы понятно, а на деле туплю)

Вообще лучше вначале изучить ReAPI? а потом Amx ?
Так как слышал, что есть устаревшие функции в Amx, типа в ReAPI лучше использовать.
 
Сообщения
3,583
Реакции
1,572
Помог
138 раз(а)
ncux0Zz, по функционалу хуки почти те же самые, что и в Ham или Fakemeta. Даже наоборот, некоторых нет в reapi
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
В каком инклуде и где можно найти нажатие игроком той или иной кнопки? Например, хочу отловить прыжок, или приседание или стрельбу, или когда шифт зажат и т.д. А по срабатыванию, например, события прыжок 3 раза у меня выполняется действие. Типа пытаюсь такое реализовать сейчас.
23 Фев 2022
ncux0Zz, по функционалу хуки почти те же самые, что и в Ham или Fakemeta. Даже наоборот, некоторых нет в reapi
Понял спасибо, а можешь сказать, что в Амх устарело и лучше не смотреть, чтобы не забивать голову?
 
Сообщения
494
Реакции
341
Помог
11 раз(а)
ncux0Zz, странный ты, вроде пришёл учиться, а будто бы и не читал, что я тебе писал.
Вот я тебе показал пример как через hamsandwich поймать событие спавна игрока, далее пояснил, что все иные события ты можешь найти в ham_const.inc.
Прыжок: Ham_Player_Jump
Приседание: Ham_Player_Duck
Стрельба: Ham_Weapon_PrimaryAttack (ЛКМ)/Ham_Weapon_SecondaryAttack (ПКМ).
Эти события вызываются, пока игрок зажимает определённую кнопку. Плюс hamsandwich позволяет блокировать эти события.

Ловить нажатие кнопок такое себе, ибо нужно в достаточно часто вызываемых событиях проверять битсуммы нажатых кнопок, но всё же это возможно (fakemeta & FM_PlayerPreThink просто для примера):
Код:
#include <amxmodx>
#include <fakemeta>

public plugin_init()
{
    register_forward(FM_PlayerPreThink, "fwd_PlayerPreThink", 1);
}

public fwd_PlayerPreThink(pPlayer)
{
    if(pev(pPlayer, pev_button) & IN_JUMP) {} // прыжок
    if(pev(pPlayer, pev_button) & IN_DUCK) {} // приседание
    if(pev(pPlayer, pev_button) & IN_ATTACK) {} // лкм
    if(pev(pPlayer, pev_button) & IN_ATTACK2) {} // пкм
}
Доступные IN_* кнопки для отлова ищи в hlsdk.inc

Касательно reapi. Ранее, чтоб отловить игровые события, приходилось использовать костыли и самые различные функции, reapi позволяет это делать намного проще (глобально, через одну функцию), плюс блокировать, если нужно. И опять же я тебе уже писал выше, что он не может полноценно заменять другие модули. Изучи сперва hamsandwich + fakemeta, потому как он объединяет в себе их принцип работы.
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
hamsandwich + fakemeta, потому как он объединяет в себе их принцип работы.
хорошо, спасибо.
Доступные IN_* кнопки для отлова ищи в hlsdk.inc
то что надо)
странный ты, вроде пришёл учиться, а будто бы и не читал, что я тебе писал.
да тупанул я, перечитал уже
 
Сообщения
494
Реакции
341
Помог
11 раз(а)
Учти, что такой способ не самый лучший для реализации, лучше через hamsandwich ловить нажатие кнопок, если это возможно. Я просто показал грубый пример.
Если используешь pev_button в операндах не единожды, то функцию кэшируй в переменную.
Код:
if(pev(pPlayer, pev_button) & IN_JUMP && pev(pPlayer, pev_button) & IN_DUCK)
->
Код:
static iButton; iButton = pev(pPlayer, pev_button);
if(iButton & IN_JUMP && IN_JUMP & IN_DUCK);
К слову, помимо pev_button есть еще pev_oldbuttons - нажатая кнопка до pev_button (или, если вернее, нажатая в предыдущем кадре Think'а).
 
Сообщения
190
Реакции
16
Помог
1 раз(а)
Привет всем, может кто объяснить и помочь разобраться?
Я пытаюсь понять, где брать описание и источники, чтобы понять какая функция и что делает, например:
C++:
HC_CBasePlayer_TakeDamage_Post
В includ'ах не нашёл.
 
Сообщения
1,042
Реакции
206
Предупреждения
1
Помог
6 раз(а)
ncux0Zz, смотри исходники regamedll и reapi
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу