Difference between revisions of "Ru:Events (SourceMod Scripting)"

From AlliedModders Wiki
Jump to: navigation, search
(Hooking Events)
 
(One intermediate revision by the same user not shown)
Line 53: Line 53:
 
*Вы не должны вызывать <tt>CloseHandle()</tt>, <tt>FireEvent()</tt> сделает это за вас.
 
*Вы не должны вызывать <tt>CloseHandle()</tt>, <tt>FireEvent()</tt> сделает это за вас.
 
*Даже если "userid" и "attacker" являются shorts, мы отсылаем их в качестве ints.  Термин "short" используется только для того, чтобы сказать движку сколько байт числа необходимо для отправки.
 
*Даже если "userid" и "attacker" являются shorts, мы отсылаем их в качестве ints.  Термин "short" используется только для того, чтобы сказать движку сколько байт числа необходимо для отправки.
*It is possible for event creation to fail; this can happen if the event does not exist, or nothing is hooking the eventThus, you should always make sure <tt>CreateEvent</tt> calls return a valid Handle.
+
*Событие может и не создастся; это происходит если событие не существует или никто не перехватывает егоПоэтому вы должны убедиться, что вызов <tt>CreateEvent</tt> возвращает правильный Handle.
*Most events use client userids instead of client indexes.
+
*Большинство событий используют userids вместо индекса.
*By default, <tt>FireEvent()</tt> broadcasts messages to clientsThis can be prevented by passing <tt>dontBroadcast</tt> as true.
+
*По умолчанию, <tt>FireEvent()</tt> посылает сообщения к клиентуЭто можно отключить установив <tt>dontBroadcast</tt> в true.
  
=Hooking Events=
+
=Перехват Событий=
When hooking an event, there are three modes to choose from:
+
Существует три режима перехвата событий:
*<tt>Pre</tt> - Hook the event before it is fired.
+
*<tt>Pre</tt> - Перехват события до выполнения.
*<tt>Post</tt> - Hook the event after it is fired.
+
*<tt>Post</tt> - Перехват события после выполнения.
*<tt>Post_NoCopy</tt> - Hook the event, but do not save any of its information (special optimization).
+
*<tt>Post_NoCopy</tt> - Перехват события, но не сохраняется любая информация об этом событии (специальная оптимизация).
  
Hooking an event is usually done for one of the following goalsTo get an idea of which mode to use, see the list below each goal:
+
Перехват событий обычно делается для одной из этих целейДля того, чтоб понять какой режим использовать, смотрите ниже список целей:
*Blocking the event (preventing it from being fired)
+
*Блокировка события (предотвращение выполнения)
**'''Always <tt>Pre</tt>'''
+
**'''Всегда <tt>Pre</tt>'''
*Rewriting the event (changing its parameters)
+
*Изменение события (изменение параметров)
**'''Always <tt>Pre</tt>'''
+
**'''Всегда <tt>Pre</tt>'''
*Acting upon the event (doing something once the event is completed)
+
*Выполнить после события (сделать что-то после того как событие произошло)
**'''<tt>Pre</tt>''' if your action must come before the mod's action.
+
**'''<tt>Pre</tt>''' если ваши действия должны произойти перед выполнением мода.
**'''<tt>Post</tt>''' if your action must come after the mod's action.
+
**'''<tt>Post</tt>''' если ваши действия должны произойти после выполнением мода.
**'''<tt>PostNoCopy</tt>''' if your action is <tt>Post</tt> and only requires the event name.
+
**'''<tt>PostNoCopy</tt>''' если подходит <tt>Post</tt> и требуется только имя события.
  
As always, you do not need to unhook events when your plugin unloadsThey are automatically removed.
+
Как всегда вы не должны убирать перехват события, когда происходит выгрузка плагинаОни удаляются автоматически.
  
==Blocking Events==
+
==Блокировка Событий==
Blocking events is the easiest thing to doLet's say we want to block death events that are headshots:
+
Блокировку событий сделать очень простоНапример мы хотим заблокировать событие смерти если смерть произошла от попадания в голову:
  
 
<pawn>public OnPluginStart()
 
<pawn>public OnPluginStart()
Line 92: Line 92:
 
}</pawn>
 
}</pawn>
  
==Rewriting Events==
+
==Изменение Событий==
Rewriting events is just as easy -- events can be modified in pre hooksFor example, say we want to remove headshots from all events:
+
Измененить событий тоже очень просто -- события могут быть изменены в режиме перед выполнением событияНапример мы хотим убрать попадание в голову со всех событий:
  
 
<pawn>public OnPluginStart()
 
<pawn>public OnPluginStart()
Line 106: Line 106:
 
}</pawn>
 
}</pawn>
  
==Post Hooks==
+
==Post Перехват==
Post hooks are default, and will usually be the most common usageFor example, say we want to print a message to every client that dies:
+
По умолчанию используется перехват после события и как правило наиболее используемыйНапример мы хотим послать сообщение всем игрокам, которые умерли:
  
 
<pawn>public OnPluginStart()
 
<pawn>public OnPluginStart()
Line 134: Line 134:
 
}</pawn>
 
}</pawn>
  
This will print a message to a player's console telling them who killed them, with what weapon, and whether it was a headshot or not.
+
Это будет писать игроку в консоли кто его убил, с каким оружием и было ли попадание в голову.
  
Note that the return value for post hooks is ignored, so the <tt>Action</tt> tag is not needed.
+
Обратите внимание, что возвращение значений с перехвата после события игнорируется, поэтому тег <tt>Action</tt> ненужен.
  
==PostNoCopy Hooks==
+
==PostNoCopy Перехват==
Lastly, there are some hooks where the only piece of information needed is the name of the event.  <tt>PostNoCopy</tt> is a special optimization for this caseWhen transitioning from <tt>Pre</tt> to <tt>Post</tt>, SourceMod must duplicate the event and all of its key/value pairs.  <tt>PostNoCopy</tt> prevents that sequence from happening.
+
Наконец есть перехваты где требуется только имя события.  <tt>PostNoCopy</tt> специальная оптимизация для этогоПри переходе от <tt>Pre</tt> к <tt>Post</tt>, SourceMod должен дублировать событие и все значения.  <tt>PostNoCopy</tt> предотвращает это.
  
For example, let's say we want to find when a certain sequence of events is called.
+
Например мы хотим найти когда происходят определенные события.
  
 
<pawn>public OnPluginStart()
 
<pawn>public OnPluginStart()
Line 156: Line 156:
 
}</pawn>
 
}</pawn>
  
Note that like normal <tt>Post</tt> hooks, there is no return value neededHowever, the <tt>event</tt> parameter for <tt>PostNoCopy</tt> will '''always''' be equal to <tt>INVALID_HANDLE</tt>.  Thus, the <tt>name</tt> parameter must be used instead of <tt>GetEventName</tt>.
+
Обратите внимание, что как и обычный <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.

Введение

События описаны в .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.