Top damage round

amxx Top damage round 1.0.6

Нет прав для скачивания
Для CS 1.6
Автор
Dager* *.* -G-
Исходный код
C++:
/*****************************************************************************
   Возможности:
1. Настроить сколько игроков выводить в список
2. Настроить минимальное количество игроков для вывода
3. Настроить с какого раунда выводить
4. Время показа
5. Мгновенное закрытие меню по нажатию на клавиши цифр
6. Отключение показа через команду /damage
7. Помимо урона рядом выводит также количество убийств (отключаемо)
8. Префикс перед сообщением в чате
9. Настроить сколько денег давать лучшему игроку раунда
10. Возможность отключения выдачи награды
11. Сохранение статуса отображения с помощью nvault
12. Не показывать топ, если у игрока открыто какое-либо меню

Только на реапи, без реапи делать не буду, не вижу смысла

Благодарности:
Vaqtincha - за куски кода, идею и помощь по коду
Ссылка на оригинал плагина: https://dev-cs.ru/threads/75/

Версии:
v.1.0.0
    - Релиз
v.1.0.1
    - Добавлена возможность выдавать денежную награду лучшему игроку
v.1.0.2
    - Рефаторинг кода
v.1.0.3
    - Перенес проверку на минимальное количество игроков с fnCompareDamage() в RoundEnd() и изменен подсчет наносимого урона
v.1.0.4
    - Убрал вывод заголовка меню, если никто в раунде никого не ранил
v.1.0.5
    - Рефакторинг кода
    - Добавлен конфиг файл
    - Добавлен LANG-файл с поддержкой русского, английского языков
    - Убрал вывод топа если произойдет рестарт или гейм комменсинг
    - Добавлен квар переключения показа топа с убийствами и без них
    - Добавлена проверка на открытые меню и если у игрока открыто какое-либо меню, то ему не будет показываться топ за раунд
    - Добавлена возможность сохранения статуса отображения с помощью nvault
v.1.0.6
    - Исправление бага, когда список мог не показываться

*****************************************************************************/

#include <amxmodx>
#include <amxmisc>
#include <reapi>
#include <nvault>

#if AMXX_VERSION_NUM < 183
    #include <colorchat>
    #define MAX_PLAYERS 32
    #define MAX_NAME_LENGTH 32
    new MaxClients;
#endif

new const PLUGIN[] = "[ReAPI] TopRoundDamage";
new const VERSION[] = "1.0.6";
new const AUTHOR[] = "Dager* *.* -G-";

new const FILE_CFG[] = "damage_round.cfg";
new const FILE_VAULT[] = "damage_round";

#define IsPlayer(%1) (1 <= %1 <= MaxClients)
#define ClearArr(%1) arrayset(_:%1, _:0.0, sizeof(%1))
#define MENU_KEYS    (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)

enum _:ePlayerData
{
    PLAYER_ID,
    DAMAGE,
    KILLS
};

new g_aData[MAX_PLAYERS + 1][ePlayerData],
    g_iPlayerDmg[MAX_PLAYERS + 1],
    g_iPlayerKills[MAX_PLAYERS + 1],
    g_iRoundCount,
    bool:g_bSwitch[MAX_PLAYERS + 1],
    g_szAuthID[MAX_PLAYERS + 1][35],
    g_hVault;

new g_pTopPlayers,
    g_pMinPlayers,
    g_pRoundNumber,
    g_pShowTime,
    g_pGiveAward,
    g_pGiveMoney,
    g_pShowKills,
    g_pPruneDays;

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR);
    register_dictionary("damage_round.txt");

    g_pTopPlayers  = register_cvar("dmgr_top_players",  "5");
    g_pMinPlayers  = register_cvar("dmgr_min_players",  "2");
    g_pRoundNumber = register_cvar("dmgr_round_number", "1");
    g_pShowTime    = register_cvar("dmgr_show_time",    "5");
    g_pGiveAward   = register_cvar("dmgr_give_award",   "1");
    g_pGiveMoney   = register_cvar("dmgr_give_money",   "500");
    g_pShowKills   = register_cvar("dmgr_show_kills",   "1");
    g_pPruneDays   = register_cvar("dmgr_prune_days",   "30");
 
    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");
 
#if AMXX_VERSION_NUM < 183
    MaxClients = get_member_game(m_nMaxPlayers);
#endif
}

public plugin_cfg()
{
    new szCfgPath[64], szFileName[128];
    get_configsdir(szCfgPath, charsmax(szCfgPath));
    formatex(szFileName, charsmax(szFileName), "%s/%s", szCfgPath, FILE_CFG);

    if (!file_exists(szFileName))
    {
        log_amx("Config %s/%s not found", szCfgPath, FILE_CFG);
        return;
    }

    server_cmd("exec %s/%s", szCfgPath, FILE_CFG);
    server_exec();

    g_hVault = nvault_open(FILE_VAULT);

    if (g_hVault != INVALID_HANDLE)
        nvault_prune(g_hVault, 0, get_systime() - (get_pcvar_num(g_pPruneDays) * 86400));
    else
        set_fail_state("Opening nVault file failed!");
}

public client_authorized(id)
{
    get_user_authid(id, g_szAuthID[id], charsmax(g_szAuthID[]));
}

public LoadData(id)
{
    new szKey[30], szData[3], iDataExists, iTimestamp;
    formatex(szKey, charsmax(szKey), "%s_TDR", g_szAuthID[id]);
    iDataExists = nvault_lookup(g_hVault, g_szAuthID[id], szData, charsmax(szData), iTimestamp);

    if (iDataExists)
    {
        g_bSwitch[id] = bool:nvault_get(g_hVault, szKey);
        // обновление данных (если нашли стимид, значит игрок активный)
        nvault_set(g_hVault, szKey, g_bSwitch[id] ? "1" : "0");
    }
    else
        g_bSwitch[id] = true;
}

public client_putinserver(id)
{
    if (!is_user_bot(id) || !is_user_hltv(id))
        LoadData(id);
 
    g_iPlayerDmg[id] = 0;
    g_iPlayerKills[id] = 0;
}

public cmdTopDamageSwitch(id)
{
    g_bSwitch[id] = !g_bSwitch[id];

    new szSwitch[30], szKey[30];
    formatex(szKey, charsmax(szKey), "%s_TDR", g_szAuthID[id]);
    nvault_set(g_hVault, szKey, g_bSwitch[id] ? "1" : "0");
 
    formatex(szSwitch, charsmax(szSwitch), "%L", id, g_bSwitch[id] ? "CHAT_DMG_ROUND_SWITCH_ON" : "CHAT_DMG_ROUND_SWITCH_OFF");

    client_print_color(id, print_team_default, "%L %L",
        id, "CHAT_DMG_ROUND_PREFIX",
        id, "CHAT_DMG_ROUND_SWITCH",
        szSwitch, get_pcvar_num(g_pTopPlayers)
    );
 
    return PLUGIN_CONTINUE;
}

public CSGameRules_RestartRound_Pre()
{
    if (get_member_game(m_bCompleteReset))
        g_iRoundCount = 0;
 
    g_iRoundCount++;
 
    ClearArr(g_iPlayerDmg);
    ClearArr(g_iPlayerKills);
 
    for (new i = 1; i <= MaxClients; i++)
        arrayset(g_aData[i], 0, ePlayerData);
}

public CBasePlayer_TakeDamage(const pevVictim, pevInflictor, const pevAttacker, Float:flDamage, bitsDamageType)
{
    if (!IsPlayer(pevAttacker) || pevVictim == pevAttacker || (bitsDamageType & DMG_BLAST))
        return HC_CONTINUE;
 
    if (rg_is_player_can_takedamage(pevVictim, pevAttacker))
        g_iPlayerDmg[pevAttacker] += floatround(flDamage);
 
    return HC_CONTINUE;
}

public CBasePlayer_Killed(const pevVictim, pevAttacker)
{
    if (!is_user_connected(pevAttacker) || pevVictim == pevAttacker)
        return HC_CONTINUE;
 
    g_iPlayerKills[pevAttacker]++;
 
    return HC_CONTINUE;
}

public RoundEnd(WinStatus:status, ScenarioEventEndRound:event)
{
    if (event == ROUND_GAME_COMMENCE || event == ROUND_GAME_RESTART)
        return HC_CONTINUE;

    if (g_iRoundCount >= get_pcvar_num(g_pRoundNumber))
    {
        new iPlayers[MAX_PLAYERS], iNum;
        get_players(iPlayers, iNum, "h");
     
        if (iNum >= get_pcvar_num(g_pMinPlayers))
            set_task(0.1, "fnShowTopRound");
    }

    return HC_CONTINUE;
}

public fnShowTopRound()
{
    new iPlayers[MAX_PLAYERS], iNum, pPlayer;
    new szName[MAX_NAME_LENGTH], pBestPlayerId, pBestPlayerDamage;
    new szMenu[512], iLen, iTop, iShowKills;
    new bool:bMenuDmgShow;

    get_players(iPlayers, iNum, "h");
 
    for (new i = 0; i < iNum; i++)
    {
        pPlayer = iPlayers[i];
     
        g_aData[i][PLAYER_ID] = pPlayer;
        g_aData[i][DAMAGE] = _:g_iPlayerDmg[pPlayer];
        g_aData[i][KILLS] = _:g_iPlayerKills[pPlayer];
    }
 
    SortCustom2D(g_aData, sizeof(g_aData), "SortRoundDamage");
 
    if (get_pcvar_num(g_pGiveAward))
    {
        pBestPlayerId = g_aData[0][PLAYER_ID];
        pBestPlayerDamage = g_aData[0][DAMAGE];
     
        if (IsPlayer(pBestPlayerId) && is_user_connected(pBestPlayerId) && pBestPlayerDamage > 0)
        {
            get_user_name(pBestPlayerId, szName, charsmax(szName));
            rg_add_account(pBestPlayerId, get_pcvar_num(g_pGiveMoney), AS_ADD, true);
         
            client_print_color(0, print_team_default, "%L %L",
                LANG_PLAYER, "CHAT_DMG_ROUND_PREFIX",
                LANG_PLAYER, "CHAT_DMG_ROUND_BEST_PLAYER",
                szName, pBestPlayerDamage, get_pcvar_num(g_pGiveMoney)
            );
        }
    }

    iShowKills = get_pcvar_num(g_pShowKills);
    iTop = get_pcvar_num(g_pTopPlayers);
 
    if (iShowKills)
        iLen = formatex(szMenu, charsmax(szMenu), "%L^n^n", LANG_PLAYER, "MENU_DMG_ROUND_TITLE1");
    else
        iLen = formatex(szMenu, charsmax(szMenu), "%L^n^n", LANG_PLAYER, "MENU_DMG_ROUND_TITLE2");

    for (new i = 0; i < iTop; i++)
    {
        if (g_aData[i][DAMAGE] <= 0)
            continue;
     
        get_user_name(g_aData[i][PLAYER_ID], szName, charsmax(szName));
     
        if (iShowKills)
        {
            switch (g_aData[i][DAMAGE])
            {
                case 1..9:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y00%d\r] [\y%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], g_aData[i][KILLS], szName
                    );
                case 10..99:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y0%d\r] [\y%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], g_aData[i][KILLS], szName
                    );
                default:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y%d\r] [\y%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], g_aData[i][KILLS], szName
                    );
            }
        }
        else
        {
            switch (g_aData[i][DAMAGE])
            {
                case 1..9:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y00%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], szName
                    );
                case 10..99:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y0%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], szName
                    );
                default:
                    iLen += formatex(szMenu[iLen], charsmax(szMenu) - iLen, "\w%d. \r[\y%d\r] \w%s^n",
                        i + 1, g_aData[i][DAMAGE], szName
                    );
            }
        }
     
        bMenuDmgShow = true;
    }
 
    if (bMenuDmgShow)
    {
        for (new i = 0; i < iNum; i++)
        {
            pPlayer = iPlayers[i];
         
            if (g_bSwitch[pPlayer] && !InMenu(pPlayer))
                show_menu(pPlayer, MENU_KEYS, szMenu, get_pcvar_num(g_pShowTime), "TopDmg");
        }
    }
 
    return PLUGIN_HANDLED;
}

public SortRoundDamage(const elem1[], const elem2[])
{
    return (elem1[DAMAGE] < elem2[DAMAGE]) ? 1 : (elem1[DAMAGE] > elem2[DAMAGE]) ? -1 : 0;
}

public fnTopDmgHandler(id, iKey)
{
    if (iKey >= 0 || iKey <= 9)
        return PLUGIN_CONTINUE;
 
    return PLUGIN_HANDLED;
}

stock InMenu(id)
{
    new Menu, New;
    new MenuUP = player_menu_info(id, Menu, New);
 
    if (MenuUP || Menu)
        return true;

    return false;
}

public plugin_end()
{
    if (g_hVault != INVALID_HANDLE)
        nvault_close(g_hVault);
}
Поддержка русского языка
Да
Совместимость
  1. HLDS
  2. REHLDS
Сверху Снизу