Difference between revisions of "Ru:Events (SourceMod Scripting)"
m |
(→Hooking Events) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | :'' | + | :''Для просмотра всех событий, нажмите [[Game Events (Source)|здесь]].'' |
− | + | События это короткие сообщения с именем, посылаемые сервером. Хотя они используются для внутренней передачи сообщений, они также посылаются клиентам. | |
− | + | Все нативные события можно найти в <tt>plugins/include/events.inc</tt>. | |
− | = | + | =Введение= |
− | + | События описаны в <tt>.res</tt> файлах мода в папке <tt>resource</tt>. "Стандартные" события находятся в <tt>hl2/resource/gameevents.res</tt> и <tt>hl2/resource/serverevents.res</tt>. Мод может расширить эти события с помощью расширений. | |
− | + | Для примера посмотрим на <tt>player_death</tt> из <tt>hl2/resource/gameevents.res</tt>: | |
<pre>"player_death" | <pre>"player_death" | ||
{ | { | ||
− | "userid" "short" // user ID | + | "userid" "short" // user ID убитого |
− | "attacker" "short" // user ID | + | "attacker" "short" // user ID убийцы |
}</pre> | }</pre> | ||
− | Counter-Strike:Source | + | Counter-Strike:Source расширяет это описание в <tt>cstrike/resource/modevents.res</tt>: |
<pre>"player_death" | <pre>"player_death" | ||
{ | { | ||
− | "userid" "short" // user ID | + | "userid" "short" // user ID убитого |
− | "attacker" "short" // user ID | + | "attacker" "short" // user ID убийцы |
− | "weapon" "string" // | + | "weapon" "string" // название оружие, которым убил убийца |
− | "headshot" "bool" // | + | "headshot" "bool" // сигнал попадания в голову |
}</pre> | }</pre> | ||
− | + | Обратите внимание, что событие состоит в следующем формате: | |
<pre>"name" | <pre>"name" | ||
{ | { | ||
Line 32: | Line 32: | ||
}</pre> | }</pre> | ||
− | = | + | =Посылка сообщений= |
− | + | Послать сообщенмя очень просто. Например мы хотим послать сообщение смерти используя событие <tt>player_death</tt> описанное выше. Для Counter-Strike:Source, это будет иметь вид: | |
<pawn>SendDeathMessage(attacker, victim, const String:weapon[], bool:headshot) | <pawn>SendDeathMessage(attacker, victim, const String:weapon[], bool:headshot) | ||
Line 50: | Line 50: | ||
}</pawn> | }</pawn> | ||
− | + | Примечания: | |
− | * | + | *Вы не должны вызывать <tt>CloseHandle()</tt>, <tt>FireEvent()</tt> сделает это за вас. |
− | * | + | *Даже если "userid" и "attacker" являются shorts, мы отсылаем их в качестве ints. Термин "short" используется только для того, чтобы сказать движку сколько байт числа необходимо для отправки. |
− | * | + | *Событие может и не создастся; это происходит если событие не существует или никто не перехватывает его. Поэтому вы должны убедиться, что вызов <tt>CreateEvent</tt> возвращает правильный Handle. |
− | * | + | *Большинство событий используют userids вместо индекса. |
− | * | + | *По умолчанию, <tt>FireEvent()</tt> посылает сообщения к клиенту. Это можно отключить установив <tt>dontBroadcast</tt> в true. |
− | = | + | =Перехват Событий= |
− | + | Существует три режима перехвата событий: | |
− | *<tt>Pre</tt> - | + | *<tt>Pre</tt> - Перехват события до выполнения. |
− | *<tt>Post</tt> - | + | *<tt>Post</tt> - Перехват события после выполнения. |
− | *<tt>Post_NoCopy</tt> - | + | *<tt>Post_NoCopy</tt> - Перехват события, но не сохраняется любая информация об этом событии (специальная оптимизация). |
− | + | Перехват событий обычно делается для одной из этих целей. Для того, чтоб понять какой режим использовать, смотрите ниже список целей: | |
− | * | + | *Блокировка события (предотвращение выполнения) |
− | **''' | + | **'''Всегда <tt>Pre</tt>''' |
− | * | + | *Изменение события (изменение параметров) |
− | **''' | + | **'''Всегда <tt>Pre</tt>''' |
− | * | + | *Выполнить после события (сделать что-то после того как событие произошло) |
− | **'''<tt>Pre</tt>''' | + | **'''<tt>Pre</tt>''' если ваши действия должны произойти перед выполнением мода. |
− | **'''<tt>Post</tt>''' | + | **'''<tt>Post</tt>''' если ваши действия должны произойти после выполнением мода. |
− | **'''<tt>PostNoCopy</tt>''' | + | **'''<tt>PostNoCopy</tt>''' если подходит <tt>Post</tt> и требуется только имя события. |
− | + | Как всегда вы не должны убирать перехват события, когда происходит выгрузка плагина. Они удаляются автоматически. | |
− | == | + | ==Блокировка Событий== |
− | + | Блокировку событий сделать очень просто. Например мы хотим заблокировать событие смерти если смерть произошла от попадания в голову: | |
<pawn>public OnPluginStart() | <pawn>public OnPluginStart() | ||
Line 92: | Line 92: | ||
}</pawn> | }</pawn> | ||
− | == | + | ==Изменение Событий== |
− | + | Измененить событий тоже очень просто -- события могут быть изменены в режиме перед выполнением события. Например мы хотим убрать попадание в голову со всех событий: | |
<pawn>public OnPluginStart() | <pawn>public OnPluginStart() | ||
Line 106: | Line 106: | ||
}</pawn> | }</pawn> | ||
− | ==Post | + | ==Post Перехват== |
− | + | По умолчанию используется перехват после события и как правило наиболее используемый. Например мы хотим послать сообщение всем игрокам, которые умерли: | |
<pawn>public OnPluginStart() | <pawn>public OnPluginStart() | ||
Line 134: | Line 134: | ||
}</pawn> | }</pawn> | ||
− | + | Это будет писать игроку в консоли кто его убил, с каким оружием и было ли попадание в голову. | |
− | + | Обратите внимание, что возвращение значений с перехвата после события игнорируется, поэтому тег <tt>Action</tt> ненужен. | |
− | ==PostNoCopy | + | ==PostNoCopy Перехват== |
− | + | Наконец есть перехваты где требуется только имя события. <tt>PostNoCopy</tt> специальная оптимизация для этого. При переходе от <tt>Pre</tt> к <tt>Post</tt>, SourceMod должен дублировать событие и все значения. <tt>PostNoCopy</tt> предотвращает это. | |
− | + | Например мы хотим найти когда происходят определенные события. | |
<pawn>public OnPluginStart() | <pawn>public OnPluginStart() | ||
Line 156: | Line 156: | ||
}</pawn> | }</pawn> | ||
− | + | Обратите внимание, что как и обычный <tt>Post</tt> перехват, он не требует возврата значений. Однако, параметр <tt>event</tt> для <tt>PostNoCopy</tt> '''всегда''' должен быть равным <tt>INVALID_HANDLE</tt>. Таким образом параметр <tt>name</tt> должен использоваться вместо <tt>GetEventName</tt>. | |
[[Category:Ru:SourceMod Scripting]] | [[Category:Ru:SourceMod Scripting]] |
Latest revision as of 22:16, 24 December 2010
- Для просмотра всех событий, нажмите здесь.
События это короткие сообщения с именем, посылаемые сервером. Хотя они используются для внутренней передачи сообщений, они также посылаются клиентам.
Все нативные события можно найти в plugins/include/events.inc.
Contents
Введение
События описаны в .res файлах мода в папке resource. "Стандартные" события находятся в hl2/resource/gameevents.res и hl2/resource/serverevents.res. Мод может расширить эти события с помощью расширений.
Для примера посмотрим на player_death из hl2/resource/gameevents.res:
"player_death" { "userid" "short" // user ID убитого "attacker" "short" // user ID убийцы }
Counter-Strike:Source расширяет это описание в cstrike/resource/modevents.res:
"player_death" { "userid" "short" // user ID убитого "attacker" "short" // user ID убийцы "weapon" "string" // название оружие, которым убил убийца "headshot" "bool" // сигнал попадания в голову }
Обратите внимание, что событие состоит в следующем формате:
"name" { "key1" "valueType1" "key2" "valueType2" ... }
Посылка сообщений
Послать сообщенмя очень просто. Например мы хотим послать сообщение смерти используя событие player_death описанное выше. Для Counter-Strike:Source, это будет иметь вид:
SendDeathMessage(attacker, victim, const String:weapon[], bool:headshot) { new Handle:event = CreateEvent("player_death") if (event == INVALID_HANDLE) { return } SetEventInt(event, "userid", GetClientUserId(victim)) SetEventInt(event, "attacker", GetClientUserId(attacker)) SetEventString(event, "weapon", weapon) SetEventBool(event, "headshot", headshot) FireEvent(event) }
Примечания:
- Вы не должны вызывать CloseHandle(), FireEvent() сделает это за вас.
- Даже если "userid" и "attacker" являются shorts, мы отсылаем их в качестве ints. Термин "short" используется только для того, чтобы сказать движку сколько байт числа необходимо для отправки.
- Событие может и не создастся; это происходит если событие не существует или никто не перехватывает его. Поэтому вы должны убедиться, что вызов CreateEvent возвращает правильный Handle.
- Большинство событий используют userids вместо индекса.
- По умолчанию, FireEvent() посылает сообщения к клиенту. Это можно отключить установив dontBroadcast в true.
Перехват Событий
Существует три режима перехвата событий:
- Pre - Перехват события до выполнения.
- Post - Перехват события после выполнения.
- Post_NoCopy - Перехват события, но не сохраняется любая информация об этом событии (специальная оптимизация).
Перехват событий обычно делается для одной из этих целей. Для того, чтоб понять какой режим использовать, смотрите ниже список целей:
- Блокировка события (предотвращение выполнения)
- Всегда Pre
- Изменение события (изменение параметров)
- Всегда Pre
- Выполнить после события (сделать что-то после того как событие произошло)
- Pre если ваши действия должны произойти перед выполнением мода.
- Post если ваши действия должны произойти после выполнением мода.
- PostNoCopy если подходит Post и требуется только имя события.
Как всегда вы не должны убирать перехват события, когда происходит выгрузка плагина. Они удаляются автоматически.
Блокировка Событий
Блокировку событий сделать очень просто. Например мы хотим заблокировать событие смерти если смерть произошла от попадания в голову:
public OnPluginStart() { HookEvent("player_death", Event_PlayerDeath, EventHookMode_Pre) } public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) { if (GetEventBool(event, "headshot")) { return Plugin_Handled } return Plugin_Continue }
Изменение Событий
Измененить событий тоже очень просто -- события могут быть изменены в режиме перед выполнением события. Например мы хотим убрать попадание в голову со всех событий:
public OnPluginStart() { HookEvent("player_death", Event_PlayerDeath, EventHookMode_Pre) } public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) { SetEventBool(event, "headshot", false) return Plugin_Continue }
Post Перехват
По умолчанию используется перехват после события и как правило наиболее используемый. Например мы хотим послать сообщение всем игрокам, которые умерли:
public OnPluginStart() { HookEvent("player_death", Event_PlayerDeath) } public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) { decl String:weapon[64] new victimId = GetEventInt(event, "userid") new attackerId = GetEventInt(event, "attacker") new bool:headshot = GetEventBool(event, "headshot") GetEventString(event, "weapon", weapon, sizeof(weapon)) decl String:name[64] new victim = GetClientOfUserId(victimId) new attacker = GetClientOfUserId(attackerId) GetClientName(attacker, name, sizeof(name)) PrintToConsole(victim, "You were killed by \"%s\" (weapon \"%s\") (headshot \"%d\")", name, weapon, headshot) }
Это будет писать игроку в консоли кто его убил, с каким оружием и было ли попадание в голову.
Обратите внимание, что возвращение значений с перехвата после события игнорируется, поэтому тег Action ненужен.
PostNoCopy Перехват
Наконец есть перехваты где требуется только имя события. PostNoCopy специальная оптимизация для этого. При переходе от Pre к Post, SourceMod должен дублировать событие и все значения. PostNoCopy предотвращает это.
Например мы хотим найти когда происходят определенные события.
public OnPluginStart() { HookEvent("game_newmap", GameEvents, EventHookMode_PostNoCopy) HookEvent("game_start", GameEvents, EventHookMode_PostNoCopy) HookEvent("game_end", GameEvents, EventHookMode_PostNoCopy) HookEvent("game_message", GameEvents, EventHookMode_PostNoCopy) } public GameEvents(Handle:event, const String:name[], bool:dontBroadcast) { PrintToServer("Event has been fired (event \"%s\") (nobcast \"%d\")", name, dontBroadcast) }
Обратите внимание, что как и обычный Post перехват, он не требует возврата значений. Однако, параметр event для PostNoCopy всегда должен быть равным INVALID_HANDLE. Таким образом параметр name должен использоваться вместо GetEventName.