События спавна(появления) игрока и начала/конца/нового раунда следует определять по вызову public функции, например назовем ее "event", которая регистрируется следующим образом:- Для спавна игрока:
Code
RegisterHam(Ham_Spawn, "player", "event", 1)
- Для нового раунда (начало freezetime):
Code
register_event("HLTV", "event", "a", "1=0", "2=0")
- Для начала раунда (конец freezetime):
Code
register_logevent("event", 2, "1=Round_Start")
- Для конца раунда:
Code
register_logevent("event", 2, "1=Round_End")
В случае спавна игрока в функцию также будет передаваться параметр индекса появляющегося игрока, т.е. заголовок функции будет иметь вид: event(id). По крайней мере, для Counter-Strike мода также в теле данной функции необходимо осуществлять проверку типа is_user_alive(id), т.к. зарегистрированная функция также будет вызываться во время вхождения игрока на сервер, когда он еще является всего лишь наблюдателем, а не фактическим игроком. Для Counter-Strike мода также имеется возможность использовать Ham_CS_RoundRespawn - в отличие от Ham_Spawn, не вызывается после входа игрока на сервер (поэтому is_user_alive проверки не требуется), и, что важно отметить, функция также не будет вызвана при первом спавне игрока (после его входа на сервер). Для Half-Life Death Match (HLDM мод, файлы которого обычно находятся в папке "valve") is_user_alive проверки не требуется, а напротив - она "отсеит", по крайней мере, момент первого спавна игрока (после его входа на сервер).
Регистирование события спавна игрока осуществляется посредством "Ham Sandwich" модуля, который поставляется с AMX Mod X, начиная с версии 1.80. На данный момент указанный модуль поддерживает следующие моды: cstrike, czero, valve, dod, tfc, ns, nsp, ts, svencoop, esf, esf_openbeta. Если тип используемого вами мода не находится в указанном списке, или у вас не установлен "Ham Sandwich" модуль, имеется возможность использовать иной метод, представляющий собой регистрирование ResetHUD сообщения.
Отмечу, что использование ResetHUD метода в некоторых случаях может привести к "падению" сервера. Это может случиться, например, в случае выполнения над игроком в момент его спавна функции strip_user_weapons(). Данное поведение связано с тем, что ResetHUD вызывается не в конце спавна игрока, как в вышеприведенном "Ham Sandwich" методе, а именно в процессе спавна.
Многие регистрируют ResetHUD сообщение, не подозревая, что оно отсылается не только в случае спавна игрока. Некоторые даже интерпретируют ResetHUD как событие начала/нового раунда, что, очевидно, не является верным. Заблуждения многих писателей плагинов относительно использования ResetHUD связаны с пережитками AMX Mod периода. В свое время я заметил, что очень многие сриптеры не понимают, при каких обстоятельствах следует использовать ResetHUD событие, а при каких - нет. И, чтобы исправить это закоренелое плачевное положение, на официальном AMX Mod X форуме мной была выложена подробная статья на тему событий спавна игрока и начала/конца/нового раунда (на английском языке).
Итак, в каких же случаях, кроме спавна игрока, вызывается ResetHUD? В момент выполнения на стороне клиента консольной команды "fullupdate", которая также вызывается автоматически в момент начала записи клиентом игрового демо-файла. Также, по крайней мере, для Counter-Strike мода данное событие вызывается в момент вхождения игрока на сервер. К тому же, именно для данного мода ResetHUD будет вызываться для живых игроков в момент начала выполнения отложенного задания рестарта раунда (примерно спустя секунду после установки положительного значения одной из следующих серверных консольных переменных: "sv_restartround" / "sv_restart").
Таким образом, для определения момента спавна игрока в случае с ResetHUD методом необходимо не только регистрирование данного события, но и последующее отсеивание вышерассмотренных событий, никак не связанных со спавном. Пример наиболее эффективного на данный момент метода такового отсеивания приведен ниже:
Code
#include <amxmodx>
#include <fakemeta>
#define MAX_CLIENTS 32
new bool:g_bPlayerNonSpawnEvent[MAX_CLIENTS + 1]
new g_iFwFmClientCommandPost
public plugin_init() {
register_event("ResetHUD", "fwEvResetHUD", "b")
register_event("TextMsg", "fwEvGameWillRestartIn", "a", "2=#Game_will_restart_in")
register_clcmd("fullupdate", "fwCmdClFullupdate")
}
public fwEvResetHUD(iPlayerId) {
if (!is_user_alive(iPlayerId))
return
if (g_bPlayerNonSpawnEvent[iPlayerId]) {
g_bPlayerNonSpawnEvent[iPlayerId] = false
return
}
fwPlayerSpawn(iPlayerId)
}
public fwEvGameWillRestartIn() {
static iPlayers[32], iPlayersNum, i
get_players(iPlayers, iPlayersNum, "a")
for (i = 0; i < iPlayersNum; ++i)
g_bPlayerNonSpawnEvent[iPlayers[i]] = true
}
public fwCmdClFullupdate(iPlayerId) {
g_bPlayerNonSpawnEvent[iPlayerId] = true
static const szFwFmClientCommandPost[] = "fwFmClientCommandPost"
g_iFwFmClientCommandPost = register_forward(FM_ClientCommand, szFwFmClientCommandPost, 1)
return PLUGIN_CONTINUE
}
public fwFmClientCommandPost(iPlayerId) {
unregister_forward(FM_ClientCommand, g_iFwFmClientCommandPost, 1)
g_bPlayerNonSpawnEvent[iPlayerId] = false
return FMRES_HANDLED
}
public fwPlayerSpawn(iPlayerId) {
// событие спавна игрока
}
Как видно из кода, при регистрировании ResetHUD не используется флаг "e", но осуществляется is_user_alive проверка непосредственно в самой зарегистрированной функции. Это сделано для того, чтобы избежать бага для версий AMX Mod X меньше 1.80, когда обработчик пропускет вызовы зарегистрированной функции не только для живых игроков.
Также не осуществляется блокировка клиентской консольной команды "fullupdate", т.к. данное действие не является необходимым, и даже более того - не рекомендуется по причине необходимости данной команды для обновления HUD-дисплея в момент начала записи клиентом игрового демо-файла. Вместо блокировки клиентской консольной команды "fullupdate" в коде используется метод одиночного игнорирования ResetHUD события в момент вызова данной команды.
Нужно также отметить, что раунд после смены карты или запуска сервера считается как бы "нулевым", поэтому функция, зарегестрированная для события нового раунда (начало freezetime), вызвана не будет.