/*****************************************************************************
1. Настроить сколько игроков выводить в список
2. Настроить минимальное количество игроков для вывода
3. Настроить с какого раунда выводить
5. Мгновенное закрытие меню по нажатию на клавиши цифр
6. Отключение показа через команду /damage
7. Помимо урона рядом выводит также количество убийств
8. Префикс перед сообщением в чате
9. Настроить сколько денег давать лучшему игроку раунда
10. Возможность отключения выдачи награды
Только на реапи, без реапи делать не буду, не вижу смысла
Vaqtincha - за куски кода, идею и помощь по коду
Ссылка на оригинал плагина: https://dev-cs.ru/threads/75/
1.0.1 добавлена возможность выдавать денежную награду лучшему игроку
1.0.3 перенес проверку на минимальное количество игроков с fnCompareDamage() в RoundEnd() и изменен подсчет наносимого урона
1.0.4 убрал вывод заголовка меню, если никто в раунде никого не ранил
*****************************************************************************/
/* не трогать всё что ниже*/
new g_arrData[MAX_PLAYERS + 1][ePlayerData];
new g_iPlayerDmg[MAX_PLAYERS + 1];
new g_iPlayerKills[MAX_PLAYERS + 1];
new bool:g_bIsSwitch[MAX_PLAYERS + 1];
register_plugin(PLUGIN, VERSION, AUTHOR);
register_clcmd("say /damage", "cmdTopDamageSwitch");
register_clcmd("say_team /damage", "cmdTopDamageSwitch");
RegisterHookChain(RG_CSGameRules_RestartRound, "CSGameRules_RestartRound_Pre", false);
RegisterHookChain(RG_CBasePlayer_TakeDamage, "CBasePlayer_TakeDamage", true);
RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", true);
RegisterHookChain(RG_RoundEnd, "RoundEnd", true);
register_menucmd(register_menuid("TopDmg"), MENU_KEYS, "fnTopDmgHandler");
g_iMaxPlayers = get_member_game(m_nMaxPlayers);
public client_putinserver(id)
// начальные значения зашедшему игроку
public cmdTopDamageSwitch(id)
g_bIsSwitch[id] = !g_bIsSwitch[id];
formatex(szSwitch, charsmax(szSwitch), "%s", g_bIsSwitch[id] ? "включили" : "отключили");
client_print_color(id, print_team_default,
"%s ^1Вы %s показ ^4[топ-%d по урону] ^1за раунд!",
CHAT_PREFIX, szSwitch, TOP_PLAYERS
public CSGameRules_RestartRound_Pre()
if(get_member_game(m_bCompleteReset))
// чистка массивов с данными
ClearArr(g_iPlayerKills);
for(new i = 1; i <= g_iMaxPlayers; i++)
arrayset(g_arrData[i], 0, ePlayerData);
public CBasePlayer_TakeDamage(const pevVictim, pevInflictor, const pevAttacker, Float:flDamage, bitsDamageType)
if(pevVictim == pevAttacker || !IsPlayer(pevAttacker) || (bitsDamageType & DMG_BLAST))
if(rg_is_player_can_takedamage(pevVictim, pevAttacker))
g_iPlayerDmg[pevAttacker] += floatround(flDamage);
public CBasePlayer_Killed(const Victim, Attacker)
if(!is_user_connected(Victim) || Victim == Attacker || !IsPlayer(Attacker) || get_member(Victim, m_iTeam) == get_member(Attacker, m_iTeam))
g_iPlayerKills[Attacker]++;
new iPlayers[MAX_PLAYERS], iNum, iPlayer;
new szName[MAX_NAME_LENGTH], pBestPlayerId, pBestPlayerDamage;
get_players(iPlayers, iNum, "h");
// цикл сбора инфы по всем игрокам
for(new i; i < iNum; i++)
g_arrData[i][PLAYER_ID] = iPlayer;
g_arrData[i][DAMAGE] = _:g_iPlayerDmg[iPlayer];
g_arrData[i][KILLS] = _:g_iPlayerKills[iPlayer];
SortCustom2D(g_arrData, sizeof(g_arrData), "SortRoundDamage");
// получение ид лучшего игрока после сортировки (1й элемент массива)
pBestPlayerId = g_arrData[0][PLAYER_ID];
// также получение урона лучшего игрока
pBestPlayerDamage = g_arrData[0][DAMAGE];
// проверки на валидность данного игрока и урон (если урон 0, то не давать награду)
if(IsPlayer(pBestPlayerId) && is_user_connected(pBestPlayerId) && pBestPlayerDamage >= 1)
get_user_name(pBestPlayerId, szName, charsmax(szName));
rg_add_account(pBestPlayerId, GIVE_MONEY, AS_ADD, true);
client_print_color(0, print_team_default,
"%s ^3%s ^1нанес больше всего урона [^4%d^1] и получает [^4%d^3$^1].",
CHAT_PREFIX, szName, pBestPlayerDamage, GIVE_MONEY
// функция сравнения для сортировки
public SortRoundDamage(const elem1[], const elem2[])
return (elem1[DAMAGE] < elem2[DAMAGE]) ? 1 : (elem1[DAMAGE] > elem2[DAMAGE]) ? -1 : 0;
if(g_iRoundCounter >= ROUND_NUMBER)
new iPlayers[MAX_PLAYERS], iNum;
get_players(iPlayers, iNum, "h");
// если игроков меньше чем выставленное значение MIN_PLAYERS, то прерываем
// таск с задежкой для сравнения урона игроков (без него будет неточность последнего попадания)
// при игре 1х1 и убийстве противника с одного патрона думаю станет ясно, что это значит и для чего таск
set_task(0.1, "fnCompareDamage");
// таск на отображение списка
set_task(0.2, "fnShowStats");
new iPlayers[MAX_PLAYERS], iNum, szMenu[512], szName[MAX_NAME_LENGTH], iLen, iPlayer;
get_players(iPlayers, iNum, "h");
iLen = formatex(szMenu, charsmax(szMenu), "\w#. \r[\yУрон\r] [\yФраги\r] \wза раунд:^n^n");
// проверка если игроков на сервере меньше чем выставлено TOP_PLAYERS
// то не делаем лишних итераций до TOP_PLAYERS
for(new i; i < iNum; i++)
// для тех, кому надо выводить игроков с 0 уроном, закомментировать 2 строки ниже
if(g_arrData[i][DAMAGE] <= 0)
get_user_name(g_arrData[i][PLAYER_ID], szName, charsmax(szName));
// форматирование красивого меню в столбик
if(0 <= g_arrData[i][DAMAGE] < 10)
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y00%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
else if(10 <= g_arrData[i][DAMAGE] < 100)
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y0%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
// пробегаем лучших игроков до TOP_PLAYERS
for(new i; i < TOP_PLAYERS; i++)
// для тех, кому надо выводить игроков с 0 уроном, закомментировать 2 строки ниже
if(g_arrData[i][DAMAGE] <= 0)
get_user_name(g_arrData[i][PLAYER_ID], szName, charsmax(szName));
// форматирование красивого меню в столбик
if(0 <= g_arrData[i][DAMAGE] < 10)
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y00%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
else if(10 <= g_arrData[i][DAMAGE] < 100)
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y0%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y%d\r] [\y%d\r] \w%s^n", i + 1, g_arrData[i][DAMAGE], g_arrData[i][KILLS], szName);
// если есть игроки в раунде с уроном
// показ всем игрокам список лучших игроков
for(new i; i < iNum; i++)
// если игрок не выключил показ, то показываем
show_menu(iPlayer, MENU_KEYS, szMenu, SHOW_TIME, "TopDmg");
// обработчик нажатия цифр для закрытия меню моментально
public fnTopDmgHandler(id, iKey)
if(iKey >= 0 || iKey <= 9)