Участник
- Сообщения
- 2,491
- Реакции
- 2,794
- Помог
- 61 раз(а)
Итак, на старте мы имеем плагин https://dev-cs.ru/threads/2953/
Как же нам переделать его на ReAPI + AmxModX 1.8.3, а также исправить множество баг и косяков?
Для начала давайте отформатируем код и переименуем все переменные на более красивые и понятные
Можно заметить, что модуль cstrike и инклуд amxmisc нигде по коду не используются. Проверить это легко: закомментируем две строчки и пробуем откомпилить. Если компилятор не выдал ошибки, значит их можно убрать.
Далее уберем include колорчата, так как он уже есть в AmxModX 1.8.3. Для этого достаточно
В AES 0.5 версии новый include aes_v вместо aes_main. Заменяем. Также в новой версии убрали натив aes_add_player_exp. Для этого используем связку
Посмотрим на цикл
Стоит отметить что тут присутствует бага. Слотов на сервере максимально 32. Но в данном примере мы никогда не обнулим последний 32-ой слот. А значит со временем игрок под этим индексом всегда будет в топе. Потому стоит заменить
Избавляемся от захардкодженного числа 32. В 1.8.3 присутствует глобальная переменная MaxClients которая равна максимальному числу слотов на сервере и идентична результату get_maxplayers. Еще один момент это начальный индекс, игроки начинаются с 1 вместо 0. Теперь мы можем проходить не все 33 элемента, а только те, которые реально нужны.
Далее нам не нужен внутренний цикл. Ведь у нас есть замечательный натив arrayset
То же самое проделываем и с хуком дисконнекта игрока
Движемся дальше. Для отправки всем игрокам сообщения в чат. Достаточно указать вместо id игрока 0. Убираем цикл.
Компилятор подсказывает, что мы больше нигде не используем переменную
Переходим к коду расчета топа по урону. Тут есть множество багов.
Во-первых, используя get_players в переменной num, мы получаем количество игроков в массиве players, которое нам возвращает натив. И, оно, как правило ниже числа 32, значит мы всегда обходим много невалидных игроков. Во вторых, массив players содержит индексы игроков и использовать переменную итерации i - грубая ошибка. Дополнительно для get_players укажем флаг h, который пропустит HLTV (ведь он не может нанести урон). Исправляем
Заодно видим что в plugin_init присутствует
Теперь переходим к самому ReAPI. Малой кровью нам удастся заменить хук TakeDamage.
Достаточно RegisterHam заменить на RegisterHookChain и Ham_TakeDamage на RG_CBasePlayer_TakeDamage. Не стоит забывать, что у HAM модуля в хуке вторым аргументом указывается classname, а в ReAPI указывать класс player не нужно.
Также стоит исправить недочет автора плагина, который делает PRE хук. Так как нанесение урона может быть заблокировано другим плагином, то нам обязательно нужен POST хук. Для этого последним аргументом указываем true. Также заменяем
Также сразу исправим баг с невалидным атакующим. Для этого достаточно добавить проверку is_user_conencted, и, если он не валиден, завершаем функцию через return.
Еще одна бага получится у нас, если игрок сам себе нанесет урон (например падение с высоты). Такой урон не должен учитываться. Чтобы исключить такое, достаточно проверить совпадает ли ID игрока с ID атакующего.
Давайте сразу же избавимся от модуля fakemeta, который используется только в одном месте. В ReAPI есть уже отличный натив для проверки класснейма FClassnameIs. Тем самым мы упрощаем наш код до следующего:
Но мы пойдем еще дальше, и вместо сравнения класснеймов мы воспользуемся проверкой битсумы damagebits на присутствие бита DMG_GRENADE.
Дело осталось за малым. Проверка на попадание в голову. Для этого есть мембер m_LastHitGroup.
Убираем модули fakemeta и hamsandwich, так как больше они нигде не используются, а также добавляем ReAPI.
Теперь давайте заменим хук конца раунда на хук из ReAPI.
Тут сразу возможна оптимизация: вместо обнуления в новом раунде всех игроков, мы можем в хуке конца раунда добавить обнуление.
Осталось отловить событие смерти игрока. Нам достаточно использовать хук RG_CBasePlayer_Killed. Заодно добавляем проверки на валидного атакующего, чтобы избежать такую же багу, как и в случае TakeDamage.
Ну и последние штрихи.
Оптимизируем
В итоге конечный код выглядит так:
Подитожим:
Спасибо d3m37r4 за исправление ошибок
Как же нам переделать его на ReAPI + AmxModX 1.8.3, а также исправить множество баг и косяков?
Код:
#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <hamsandwich>
#include <fakemeta>
#include <ColorChat>
#include <aes_main>
enum _:score
{
frags,
Float:dmg,
hs
}
new niceP[33][score]
new Aesopt
new g_iMaxPlayers
public plugin_init()
{
register_plugin("BestAes", "1.0", "") //Исходник [*J*]
RegisterHam(Ham_TakeDamage, "player", "hook_TakeDamage")
register_event("DeathMsg", "Event_DeathMessage", "a")
register_logevent("event_round_end", 2, "1=Round_End")
register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
Aesopt = register_cvar("nkiller_aes", "10")
g_iMaxPlayers = get_maxplayers()
return 0;
}
public event_round_end ()
{
new Players[32], num, tmpf, Float:tmpd, tmpid
get_players( Players, num )
for( new i; i < 32; i++)
{
if ( niceP[i][frags] > tmpf )
{
tmpid = i
tmpf = niceP[i][frags]
tmpd = niceP[i][dmg]
}
else if ( niceP[i][frags] == tmpf && niceP[i][dmg] > tmpd)
{
tmpid = i
tmpf = niceP[i][frags]
tmpd = niceP[i][dmg]
}
}
if ( tmpf > 0 )
{
new name[32]
get_user_name(tmpid, name, 31);
aes_add_player_exp(tmpid, tmpf*get_pcvar_num(Aesopt) )
for(new ids = 1; ids <= g_iMaxPlayers; ids++)
{
ColorChat( ids, NORMAL, "[^x4Сервер^x1] Самый лучший игрок раунда ^x3%s^x1 получил^x4 %d^x1 опыта, убив ^x4%d^x1 игроков!", name, tmpf * get_pcvar_num(Aesopt), tmpf)
}
}
}
public hook_TakeDamage(Victim, inflictor, Attacker, Float:damage, damagebits)
{
if( inflictor == Attacker )
niceP[Attacker][dmg] += damage
else
{
static classname[32]
pev (inflictor, pev_classname, classname, 31)
if( equal (classname, "grenade") )
niceP[Attacker][dmg] += damage
}
if ( get_pdata_int(Victim, 75, 5) == HIT_HEAD )
niceP[Attacker][hs]++
return HAM_IGNORED
}
public Event_DeathMessage()
niceP[read_data(1)][frags]++
public event_round_start ( )
for (new i; i < 32; i++)
for ( new j; j < 3; j++)
niceP[i][j] = 0
public client_disconnected(id)
for ( new j; j < 3; j++)
niceP[id][j] = 0
Diff:
- #include < amxmodx >
- #include < amxmisc >
- #include < cstrike >
- #include < hamsandwich >
- #include < fakemeta >
- #include < ColorChat >
- #include < aes_main >
+ #include <amxmodx>
+ #include <amxmisc>
+ #include <cstrike>
+ #include <hamsandwich>
+ #include <fakemeta>
+ #include <ColorChat>
+ #include <aes_main>
- enum _:score
- {
+ enum _:score {
frags,
Float:dmg,
hs
}
- new niceP[33][score]
+ new g_PlayersData[33][score];
- new Aesopt
- new g_iMaxPlayers
+ new pcv_Aesopt;
+ new g_iMaxPlayers;
- public plugin_init()
- {
- register_plugin("BestAes", "1.0", "") //Исходник [*J*]
+ public plugin_init(){
+ register_plugin("BestAes", "1.0", "");
- RegisterHam(Ham_TakeDamage, "player", "hook_TakeDamage")
- register_event("DeathMsg", "Event_DeathMessage", "a")
- register_logevent("event_round_end", 2, "1=Round_End")
- register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
- Aesopt = register_cvar("nkiller_aes", "10")
- g_iMaxPlayers = get_maxplayers()
+ RegisterHam(Ham_TakeDamage, "player", "hook_TakeDamage");
+ register_event("DeathMsg", "Event_DeathMessage", "a");
+ register_logevent("event_round_end", 2, "1=Round_End");
+ register_event("HLTV", "event_round_start", "a", "1=0", "2=0");
+ pcv_Aesopt = register_cvar("nkiller_aes", "10");
+ g_iMaxPlayers = get_maxplayers();
return 0;
-
}
- public event_round_end ()
- {
- new Players[32], num, tmpf, Float:tmpd, tmpid
- get_players( Players, num )
+ public event_round_end () {
+ new players[32], num, tmpf, Float:tmpd, tmpid;
+ get_players(players, num);
- for( new i; i < 32; i++)
- {
- if ( niceP[i][frags] > tmpf )
- {
- tmpid = i
- tmpf = niceP[i][frags]
- tmpd = niceP[i][dmg]
- }
- else if ( niceP[i][frags] == tmpf && niceP[i][dmg] > tmpd)
- {
+ for (new i; i < 32; i++) {
+ if (g_PlayersData[i][frags] > tmpf) {
+ tmpid = i;
+ tmpf = g_PlayersData[i][frags];
+ tmpd = g_PlayersData[i][dmg];
+ } else if (g_PlayersData[i][frags] == tmpf && g_PlayersData[i][dmg] > tmpd) {
tmpid = i;
- tmpf = niceP[i][frags];
- tmpd = niceP[i][dmg];
+ tmpf = g_PlayersData[i][frags];
+ tmpd = g_PlayersData[i][dmg];
}
}
- if ( tmpf > 0 )
- {
- new name[32]
+ if (tmpf > 0) {
+ new name[32];
get_user_name(tmpid, name, 31);
-
- aes_add_player_exp(tmpid, tmpf*get_pcvar_num(Aesopt) )
- for(new ids = 1; ids <= g_iMaxPlayers; ids++)
- {
- ColorChat( ids, NORMAL, "[^x4Сервер^x1] Самый лучший игрок раунда ^x3%s^x1 получил^x4 %d^x1 опыта, убив ^x4%d^x1 игроков!", name, tmpf * get_pcvar_num(Aesopt), tmpf)
+
+ aes_add_player_exp(tmpid, tmpf * get_pcvar_num(pcv_Aesopt));
+ for (new id = 1; id <= g_iMaxPlayers; id++) {
+ ColorChat(id, NORMAL, "[^x4Сервер^x1] Самый лучший игрок раунда ^x3%s^x1 получил^x4 %d^x1 опыта, убив ^x4%d^x1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
}
-
+
}
}
- public hook_TakeDamage(Victim, inflictor, Attacker, Float:damage, damagebits)
- {
- if( inflictor == Attacker )
- niceP[Attacker][dmg] += damage
- else
- {
- static classname[32]
- pev (inflictor, pev_classname, classname, 31)
- if( equal (classname, "grenade") )
- niceP[Attacker][dmg] += damage
+ public hook_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
+ if (inflictor == attacker ) {
+ g_PlayersData[attacker][dmg] += damage;
+ } else {
+ static classname[32];
+ pev (inflictor, pev_classname, classname, 31);
+ if (equal (classname, "grenade")) {
+ g_PlayersData[attacker][dmg] += damage;
+ }
}
- if ( get_pdata_int(Victim, 75, 5) == HIT_HEAD )
- niceP[Attacker][hs]++
+ if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
+ g_PlayersData[attacker][hs]++;
+ }
- return HAM_IGNORED
+ return HAM_IGNORED;
}
- public Event_DeathMessage()
- niceP[read_data(1)][frags]++
+ public Event_DeathMessage() {
+ g_PlayersData[read_data(1)][frags]++;
+ }
- public event_round_start ( )
- for (new i; i < 32; i++)
- for ( new j; j < 3; j++)
- niceP[i][j] = 0
+ public event_round_start() {
+ for (new i; i < 32; i++) {
+ for (new j; j < 3; j++) {
+ g_PlayersData[i][j] = 0;
+ }
+ }
+ }
- public client_disconnected(id)
- for ( new j; j < 3; j++)
- niceP[id][j] = 0
+ public client_disconnected(id) {
+ for (new j; j < 3; j++) {
+ g_PlayersData[id][j] = 0;
+ }
+ }
Diff:
- #include <amxmisc>
- #include <cstrike>
ColorChat(id, color, message[])
заменить на client_print_color(id, color, message[])
. Стоит учесть, что цвет задается через enum или указывается id игрока
Diff:
- #include <ColorChat>
- ColorChat(id, NORMAL, "[^x4Сервер^x1] Самый лучший игрок раунда ^x3%s^x1 получил^x4 %d^x1 опыта, убив ^x4%d^x1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
+ client_print_color(id, print_team_default, "[^4Сервер^1] Самый лучший игрок раунда ^3%s^1 получил^x4 %d^1 опыта, убив ^4%d^1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
aes_set_player_exp(id, aes_get_player_exp(id) + amount)
Diff:
- #include <aes_main>
+ #include <aes_v>
- aes_add_player_exp(tmpid, tmpf * get_pcvar_num(pcv_Aesopt));
+ aes_set_player_exp(tmpid, aes_get_player_exp(tmpid) + tmpf * get_pcvar_num(pcv_Aesopt));
Код:
for (new i; i < 32; i++) {
for (new j; j < 3; j++) {
g_PlayersData[i][j] = 0;
}
}
i < 32
на i <= 32
Избавляемся от захардкодженного числа 32. В 1.8.3 присутствует глобальная переменная MaxClients которая равна максимальному числу слотов на сервере и идентична результату get_maxplayers. Еще один момент это начальный индекс, игроки начинаются с 1 вместо 0. Теперь мы можем проходить не все 33 элемента, а только те, которые реально нужны.
Diff:
- for (new i; i < 32; i++) {
+ for (new i = 1; i <= MaxClients; i++) {
for (new j; j < 3; j++) {
g_PlayersData[i][j] = 0;
}
}
Diff:
for (new i = 1; i <= MaxClients; i++) {
- for (new j; j < 3; j++) {
- g_PlayersData[i][j] = 0;
- }
+ arrayset(g_PlayersData[i], 0, score);
}
Diff:
public client_disconnected(id) {
- for (new j; j < 3; j++) {
- g_PlayersData[id][j] = 0;
- }
+ arrayset(g_PlayersData[id], 0, score);
}
Diff:
- for (new id = 1; id <= g_iMaxPlayers; id++) {
- client_print_color(id, print_team_default, "[^4Сервер^x1] Самый лучший игрок раунда ^3%s^1 получил^4 %d^1 опыта, убив ^4%d^1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
- }
+ client_print_color(0, print_team_default, "[^4Сервер^x1] Самый лучший игрок раунда ^3%s^1 получил^4 %d^1 опыта, убив ^4%d^1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
g_iMaxPlayers
. Убираем.
Diff:
- new g_iMaxPlayers;
- g_iMaxPlayers = get_maxplayers();
Код:
new players[32], num, tmpf, Float:tmpd, tmpid;
get_players(players, num);
for (new i; i < 32; i++) {
if (g_PlayersData[i][frags] > tmpf) {
tmpid = i;
tmpf = g_PlayersData[i][frags];
tmpd = g_PlayersData[i][dmg];
} else if (g_PlayersData[i][frags] == tmpf && g_PlayersData[i][dmg] > tmpd) {
tmpid = i;
tmpf = g_PlayersData[i][frags];
tmpd = g_PlayersData[i][dmg];
}
}
Diff:
new players[32], num, tmpf, Float:tmpd, tmpid;
- get_players(players, num);
+ get_players(players, num, "h");
- for (new i; i < 32; i++) {
- if (g_PlayersData[i][frags] > tmpf) {
- tmpid = i;
- tmpf = g_PlayersData[i][frags];
- tmpd = g_PlayersData[i][dmg];
- } else if (g_PlayersData[i][frags] == tmpf && g_PlayersData[i][dmg] > tmpd) {
- tmpid = i;
- tmpf = g_PlayersData[i][frags];
- tmpd = g_PlayersData[i][dmg];
+ for (new i, player; i < num; i++) {
+ player = players[i];
+ if (g_PlayersData[player][frags] > tmpf) {
+ tmpid = player;
+ tmpf = g_PlayersData[player][frags];
+ tmpd = g_PlayersData[player][dmg];
+ } else if (g_PlayersData[player][frags] == tmpf && g_PlayersData[player][dmg] > tmpd) {
+ tmpid = player;
+ tmpf = g_PlayersData[player][frags];
+ tmpd = g_PlayersData[player][dmg];
}
}
return 0;
. Он там не нужен, Убираем
Diff:
- return 0;
Достаточно RegisterHam заменить на RegisterHookChain и Ham_TakeDamage на RG_CBasePlayer_TakeDamage. Не стоит забывать, что у HAM модуля в хуке вторым аргументом указывается classname, а в ReAPI указывать класс player не нужно.
Также стоит исправить недочет автора плагина, который делает PRE хук. Так как нанесение урона может быть заблокировано другим плагином, то нам обязательно нужен POST хук. Для этого последним аргументом указываем true. Также заменяем
return HAM_IGNORED
на return HC_CONTINUE
. Сразу переименуем callback хука с hook_TakeDamage на CBasePlayer_TakeDamage.
Diff:
- RegisterHam(Ham_TakeDamage, "player", "hook_TakeDamage");
+ RegisterHookChain(RG_CBasePlayer_TakeDamage, "CBasePlayer_TakeDamage", true);
- public hook_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
+ public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
if (inflictor == attacker ) {
g_PlayersData[attacker][dmg] += damage;
} else {
static classname[32];
pev (inflictor, pev_classname, classname, 31);
if (equal (classname, "grenade")) {
g_PlayersData[attacker][dmg] += damage;
}
}
if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
- return HAM_IGNORED;
+ return HC_CONTINUE;
}
Еще одна бага получится у нас, если игрок сам себе нанесет урон (например падение с высоты). Такой урон не должен учитываться. Чтобы исключить такое, достаточно проверить совпадает ли ID игрока с ID атакующего.
Diff:
public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
+ if (!is_user_connected(attacker) || victim == attacker) {
+ return HC_CONTINUE;
+ }
+
if (inflictor == attacker ) {
g_PlayersData[attacker][dmg] += damage;
} else {
static classname[32];
pev (inflictor, pev_classname, classname, 31);
if (equal (classname, "grenade")) {
g_PlayersData[attacker][dmg] += damage;
}
}
if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
return HC_CONTINUE;
}
Diff:
public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
if (!is_user_connected(attacker) || victim == attacker) {
return HC_CONTINUE;
}
if (inflictor == attacker ) {
g_PlayersData[attacker][dmg] += damage;
- } else {
- static classname[32];
- pev (inflictor, pev_classname, classname, 31);
- if (equal (classname, "grenade")) {
- g_PlayersData[attacker][dmg] += damage;
- }
+ } else if (FClassnameIs(inflictor, "grenade")) {
+ g_PlayersData[attacker][dmg] += damage;
}
if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
return HC_CONTINUE;
}
Diff:
public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
if (!is_user_connected(attacker) || victim == attacker) {
return HC_CONTINUE;
}
- if (inflictor == attacker ) {
- g_PlayersData[attacker][dmg] += damage;
- } else if (FClassnameIs(inflictor, "grenade")) {
- g_PlayersData[attacker][dmg] += damage;
- }
+ if (inflictor == attacker || damagebits & DMG_GRENADE) {
+ g_PlayersData[attacker][dmg] += damage;
+ }
if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
return HC_CONTINUE;
}
Diff:
public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
if (!is_user_connected(attacker) || victim == attacker) {
return HC_CONTINUE;
}
if (inflictor == attacker || damagebits & DMG_GRENADE) {
g_PlayersData[attacker][dmg] += damage;
}
- if (get_pdata_int(victim, 75, 5) == HIT_HEAD) {
+ if (get_member(victim, m_LastHitGroup) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
return HC_CONTINUE;
}
Diff:
- #include <hamsandwich>
- #include <fakemeta>
+ #include <reapi>
Diff:
- register_logevent("event_round_end", 2, "1=Round_End");
+ RegisterHookChain(RG_RoundEnd, "RoundEnd", true);
- public event_round_end () {
+ public RoundEnd () {
// ...
}
Diff:
- register_event("HLTV", "event_round_start", "a", "1=0", "2=0");
-
public RoundEnd () {
new players[32], num, tmpf, Float:tmpd, tmpid;
get_players(players, num, "h");
for (new i, player; i < num; i++) {
player = players[i];
if (g_PlayersData[player][frags] > tmpf) {
tmpid = player;
tmpf = g_PlayersData[player][frags];
tmpd = g_PlayersData[player][dmg];
} else if (g_PlayersData[player][frags] == tmpf && g_PlayersData[player][dmg] > tmpd) {
tmpid = palyer;
tmpf = g_PlayersData[player][frags];
tmpd = g_PlayersData[player][dmg];
}
}
if (tmpf > 0) {
new name[32];
get_user_name(tmpid, name, 31);
aes_set_player_exp(tmpid, aes_get_player_exp(tmpid) + tmpf * get_pcvar_num(pcv_Aesopt));
client_print_color(0, print_team_default, "[^4Сервер^1] Самый лучший игрок раунда ^3%s^1 получил^x4 %d^1 опыта, убив ^4%d^1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
}
+ for (new i = 1; i <= MaxClients; i++) {
+ arrayset(g_PlayersData[i], 0, score);
+ }
}
- public event_round_start() {
- for (new i = 1; i <= MaxClients; i++) {
- arrayset(g_PlayersData[i], 0, score);
- }
- }
Diff:
- register_event("DeathMsg", "Event_DeathMessage", "a");
+ RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", true);
- public Event_DeathMessage() {
- g_PlayersData[read_data(1)][frags]++;
+ public CBasePlayer_Killed(id, attacker) {
+ if (id != attacker && is_user_connected(attacker)) {
+ g_PlayersData[attacker][frags]++;
+ }
}
Diff:
- new g_PlayersData[33][score];
+ new g_PlayersData[MAX_PLAYERS + 1][score];
Diff:
- new name[32];
+ new name[MAX_NAME_LENGTH];
- get_user_name(tmpid, name, 31);
+ get_user_name(tmpid, name, charsmax(name));
Diff:
+ new bonus = tmpf * get_pcvar_num(pcv_Aesopt);
- aes_set_player_exp(tmpid, aes_get_player_exp(tmpid) + tmpf * get_pcvar_num(pcv_Aesopt));
+ aes_set_player_exp(tmpid, aes_get_player_exp(tmpid) + bonus);
- client_print_color(0, print_team_default, "[^4Сервер^1] Самый лучший игрок раунда ^3%s^1 получил^x4 %d^1 опыта, убив ^4%d^1 игроков!", name, tmpf * get_pcvar_num(pcv_Aesopt), tmpf);
+ client_print_color(0, print_team_default, "[^4Сервер^1] Самый лучший игрок раунда ^3%s^1 получил^x4 %d^1 опыта, убив ^4%d^1 игроков!", name, bonus, tmpf);
Diff:
for (new i, player; i < num; i++) {
player = players[i];
- if (g_PlayersData[player][frags] > tmpf) {
+ if (g_PlayersData[player][frags] > tmpf || (g_PlayersData[player][frags] == tmpf && g_PlayersData[player][dmg] > tmpd)) {
tmpid = player;
tmpf = g_PlayersData[player][frags];
tmpd = g_PlayersData[player][dmg];
- } else if (g_PlayersData[player][frags] == tmpf && g_PlayersData[player][dmg] > tmpd) {
- tmpid = player;
- tmpf = g_PlayersData[player][frags];
- tmpd = g_PlayersData[player][dmg];
}
}
Код:
#include <amxmodx>
#include <reapi>
#include <aes_v>
enum _:score {
frags,
Float:dmg,
hs
}
new g_PlayersData[MAX_PLAYERS + 1][score];
new pcv_Aesopt;
public plugin_init(){
register_plugin("BestAes", "1.0", "");
RegisterHookChain(RG_CBasePlayer_TakeDamage, "CBasePlayer_TakeDamage", true);
RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", true);
RegisterHookChain(RG_RoundEnd, "RoundEnd", true);
pcv_Aesopt = register_cvar("nkiller_aes", "10");
}
public RoundEnd () {
new players[32], num, tmpf, Float:tmpd, tmpid;
get_players(players, num, "h");
for (new i, player; i < num; i++) {
player = players[i];
if (g_PlayersData[player][frags] > tmpf || (g_PlayersData[player][frags] == tmpf && g_PlayersData[player][dmg] > tmpd)) {
tmpid = player;
tmpf = g_PlayersData[player][frags];
tmpd = g_PlayersData[player][dmg];
}
}
if (tmpf > 0) {
new name[MAX_NAME_LENGTH];
get_user_name(tmpid, name, charsmax(name));
new bonus = tmpf * get_pcvar_num(pcv_Aesopt);
aes_set_player_exp(tmpid, aes_get_player_exp(tmpid) + bonus);
client_print_color(0, print_team_default, "[^4Сервер^1] Самый лучший игрок раунда ^3%s^1 получил^x4 %d^1 опыта, убив ^4%d^1 игроков!", name, bonus, tmpf);
}
for (new i = 1; i <= MaxClients; i++) {
arrayset(g_PlayersData[i], 0, score);
}
}
public CBasePlayer_TakeDamage(victim, inflictor, attacker, Float:damage, damagebits) {
if (!is_user_connected(attacker) || victim == attacker) {
return HC_CONTINUE;
}
if (inflictor == attacker || damagebits & DMG_GRENADE) {
g_PlayersData[attacker][dmg] += damage;
}
if (get_member(victim, m_LastHitGroup) == HIT_HEAD) {
g_PlayersData[attacker][hs]++;
}
return HC_CONTINUE;
}
public CBasePlayer_Killed(id, attacker) {
if (id != attacker && is_user_connected(attacker)) {
g_PlayersData[attacker][frags]++;
}
}
public client_disconnected(id) {
arrayset(g_PlayersData[id], 0, score);
}
Подитожим:
- Мы научились переводить плагины на ReAPI.
- На практике поняли, почему ReAPI + AmxModx 1.8.3 - отличный выбор.
- Исправили множество багов.
- Увидели типичные ошибки в плагинах.
12 Июн 2018
Последнее редактирование: