Куплю плагин WarMix Half Round frag save" (1.0.0) by FrozDark.

shuoumaaa423

Участник
Сообщения
1
Реакции
0
Так же интересуют и другие полезные плагины для cw/mix сервера.
 

ravskiy1

Участник
Сообщения
206
Реакции
83
Могу помочь с плагином, и в целом с доработкой WarMix.

Если интересно пиши в ЛС или t.me/ravskiy1
 

Alex777

Участник
Сообщения
36
Реакции
1
Держи,тестируй. Не все допилено - но вроде работает)
🎮 Основные функции для игроков
1. Система сбора игроков
Автоматическая готовность при входе на сервер
Ручная готовность через !ready или !r
Снятие готовности через !unready или !ur
Счётчик игроков в hostname: [Ожидание 5] CSrating | Mix server
2. Выбор команд
Автоматический выбор 2 капитанов из готовых игроков
Капитаны по очереди выбирают игроков в команды
Меню выбора с никами игроков (нельзя выбрать себя)
Для режима 1v1 - автоматическое распределение без выбора
3. Управление матчем
!pause - поставить паузу (2 на команду)
!unpause - снять паузу
!sub - запросить замену (капитан выбирает замену из спектров)
!score - показать текущий счёт
!match - информация о матче
4. Меню команд
!menu или !help - открывает главное меню
Быстрый доступ ко всем функциям
Админские команды в меню (только для админов)
⚙️ Настройки матча (для админов)
Форматы игры:
1v1 (2 игрока) - без выбора капитанов, авто-старт
2v2 (4 игрока)
3v3 (6 игроков)
5v5 (10 игроков) - по умолчанию
Форматы раундов:
MR9 (18 раундов)
MR12 (24 раунда)
MR15 (30 раундов) - по умолчанию
Админские команды:
sm_start - принудительный старт матча
sm_restart - рестарт матча
sm_cancel - отмена матча
sm_setscore <CT> <T> - установить счёт
sm_forcepause - принудительная пауза
sm_matchsettings - меню настроек матча
🔄 Автоматические функции
1. Управление AllTalk
Лобби/сбор: sv_alltalk 1 (все слышат всех)
Матч: sv_alltalk 0 (только своя команда)
Конец матча: sv_alltalk 1 (возврат)
2. Смена сторон
Автоматическая смена сторон после первого перерыва (MR15 - после 15 раундов)
Используется mp_switchteams 1
3. Овертайм
Автоматический запуск при ничьей после основных раундов
6 раундов за один овертайм (настраивается)
4. Автоотмена матча
1v1: если игрок вышел - матч сразу отменяется
Другие режимы: если осталось меньше 70% игроков - матч отменяется
5. Голосование за карту
Запускается автоматически через 10 секунд после окончания матча
Использует mapchooser.smx если установлен
Иначе - встроенное меню голосования
Реклама и уведомления
Система рекламы:
Настраиваемая реклама в чате
Интервал: 60 секунд между сообщениями
Цвета: {red}, {lightgreen}, {default}
Конфиг: csrating_adverts.cfg
Уведомления:
Приветствие новым игрокам с подсказкой !menu
Сообщения о готовности игроков
Сообщения о выборе капитанов и игроков
Предупреждения о паузах, заменах
Информация о победителе в конце матча
 

Вложения

  • csrating_mix.zip
    20.3 КБ · Просмотры: 15

khood

Участник
Сообщения
274
Реакции
95
Держи,тестируй. Не все допилено - но вроде работает)
🎮 Основные функции для игроков
1. Система сбора игроков
Автоматическая готовность при входе на сервер
Ручная готовность через !ready или !r
Снятие готовности через !unready или !ur
Счётчик игроков в hostname: [Ожидание 5] CSrating | Mix server
2. Выбор команд
Автоматический выбор 2 капитанов из готовых игроков
Капитаны по очереди выбирают игроков в команды
Меню выбора с никами игроков (нельзя выбрать себя)
Для режима 1v1 - автоматическое распределение без выбора
3. Управление матчем
!pause - поставить паузу (2 на команду)
!unpause - снять паузу
!sub - запросить замену (капитан выбирает замену из спектров)
!score - показать текущий счёт
!match - информация о матче
4. Меню команд
!menu или !help - открывает главное меню
Быстрый доступ ко всем функциям
Админские команды в меню (только для админов)
⚙️ Настройки матча (для админов)
Форматы игры:
1v1 (2 игрока) - без выбора капитанов, авто-старт
2v2 (4 игрока)
3v3 (6 игроков)
5v5 (10 игроков) - по умолчанию
Форматы раундов:
MR9 (18 раундов)
MR12 (24 раунда)
MR15 (30 раундов) - по умолчанию
Админские команды:
sm_start - принудительный старт матча
sm_restart - рестарт матча
sm_cancel - отмена матча
sm_setscore <CT> <T> - установить счёт
sm_forcepause - принудительная пауза
sm_matchsettings - меню настроек матча
🔄 Автоматические функции
1. Управление AllTalk
Лобби/сбор: sv_alltalk 1 (все слышат всех)
Матч: sv_alltalk 0 (только своя команда)
Конец матча: sv_alltalk 1 (возврат)
2. Смена сторон
Автоматическая смена сторон после первого перерыва (MR15 - после 15 раундов)
Используется mp_switchteams 1
3. Овертайм
Автоматический запуск при ничьей после основных раундов
6 раундов за один овертайм (настраивается)
4. Автоотмена матча
1v1: если игрок вышел - матч сразу отменяется
Другие режимы: если осталось меньше 70% игроков - матч отменяется
5. Голосование за карту
Запускается автоматически через 10 секунд после окончания матча
Использует mapchooser.smx если установлен
Иначе - встроенное меню голосования
Реклама и уведомления
Система рекламы:
Настраиваемая реклама в чате
Интервал: 60 секунд между сообщениями
Цвета: {red}, {lightgreen}, {default}
Конфиг: csrating_adverts.cfg
Уведомления:
Приветствие новым игрокам с подсказкой !menu
Сообщения о готовности игроков
Сообщения о выборе капитанов и игроков
Предупреждения о паузах, заменах
Информация о победителе в конце матча
Исходник можно?
И для чего делать прототип вармикса
 

Alex777

Участник
Сообщения
36
Реакции
1
Исходник можно?
И для чего делать прототип вармикса
Меньше настроек и гемора. Делал для себя- так что не принуждаю использовать
Исходник:
/**
 * CSrating Match Plugin для CS:Source
 * Версия: 3.3 - РУССКИЙ ЯЗЫК CS:S
 */

#include <sourcemod>
#include <sdktools>
#include <cstrike>

#pragma semicolon 1

#define PLUGIN_VERSION "3.3.0"
#define MAX_ADVERTS 50

enum MatchState
{
    STATE_LOBBY = 0,
    STATE_CAPTAIN_PICK,
    STATE_PLAYER_PICK,
    STATE_LIVE,
    STATE_HALFTIME,
    STATE_OVERTIME,
    STATE_FINISHED
}

new MatchState:g_iMatchState;
new g_iCTScore;
new g_iTScore;
new g_iCurrentRound;
new g_iOvertimeCount;
new g_iCaptainTeam;
new g_iPickOrder;
new g_iPlayersReady;
new g_iPauseCount[2];
new bool:g_bIsPaused;
new bool:g_bPlayerReady[MAXPLAYERS + 1];
new g_iPlayerTeam[MAXPLAYERS + 1];
new g_iCaptains[2];
new g_iTeamSize[2];
new g_iSubRequests[MAXPLAYERS + 1];
char g_sOriginalHostname[256];

new g_iMatchAdmin;

new g_iAdvertCount;
new g_iCurrentAdvert;
char g_sAdvertText[MAX_ADVERTS][256];

new Handle:g_hDatabase;

new g_iMaxRounds;
new g_iRoundsPerHalf;
new g_iOvertimeRounds;
new g_iPlayersPerTeam;

public Plugin:myinfo =
{
    name = "CSrating Match System",
    author = "CSrating.ru",
    description = "Система матчмейкинга для CS:Source",
    version = PLUGIN_VERSION,
    url = "https://csrating.ru"
};

public OnPluginStart()
{
    RegConsoleCmd("sm_ready", Command_Ready, "Готовность");
    RegConsoleCmd("sm_r", Command_Ready, "Готовность");
    RegConsoleCmd("sm_unready", Command_Unready, "Не готов");
    RegConsoleCmd("sm_ur", Command_Unready, "Не готов");
    RegConsoleCmd("sm_pause", Command_Pause, "Пауза");
    RegConsoleCmd("sm_unpause", Command_Unpause, "Снять паузу");
    RegConsoleCmd("sm_score", Command_Score, "Счет");
    RegConsoleCmd("sm_sub", Command_Sub, "Замена");
    RegConsoleCmd("sm_match", Command_MatchInfo, "Инфо");
    RegConsoleCmd("sm_menu", Command_Menu, "Меню");
    RegConsoleCmd("sm_help", Command_Menu, "Помощь");
    
    RegAdminCmd("sm_start", Command_Start, ADMFLAG_GENERIC, "Старт");
    RegAdminCmd("sm_restart", Command_Restart, ADMFLAG_GENERIC, "Рестарт");
    RegAdminCmd("sm_setscore", Command_SetScore, ADMFLAG_GENERIC, "Счет");
    RegAdminCmd("sm_forcepause", Command_ForcePause, ADMFLAG_GENERIC, "Пауза");
    RegAdminCmd("sm_cancel", Command_Cancel, ADMFLAG_GENERIC, "Отмена");
    RegAdminCmd("sm_matchsettings", Command_MatchSettings, ADMFLAG_GENERIC, "Настройки");
    
    AutoExecConfig(true, "csrating_match");
    
    ServerCommand("sv_timeout 65");
    ServerCommand("sv_kick_bots 0");
    
    ConnectToDatabase();
    LoadAdverts();
    
    char hostname[256];
    ConVar cvHostname = FindConVar("hostname");
    if (cvHostname != null)
    {
        GetConVarString(cvHostname, hostname, sizeof(hostname));
        if (strlen(hostname) > 0)
        {
            strcopy(g_sOriginalHostname, sizeof(g_sOriginalHostname), hostname);
        }
        else
        {
            strcopy(g_sOriginalHostname, sizeof(g_sOriginalHostname), "CSrating Server");
        }
    }
    
    HookEvent("player_disconnect", Event_PlayerDisconnect);
    HookEvent("round_start", Event_RoundStart);
    HookEvent("round_end", Event_RoundEnd);
    
    g_iMatchState = STATE_LOBBY;
    g_iCTScore = 0;
    g_iTScore = 0;
    g_iCurrentRound = 0;
    g_iOvertimeCount = 0;
    g_iPlayersReady = 0;
    g_bIsPaused = false;
    g_iTeamSize[0] = 0;
    g_iTeamSize[1] = 0;
    g_iMatchAdmin = 0;
    
    LoadConfig();
    CountPlayers();
    UpdateServerHostname();
    
    if (g_iAdvertCount > 0)
    {
        CreateTimer(60.0, Timer_ShowAdvert, _, TIMER_REPEAT);
    }
    
    PrintToServer("[CSrating] Плагин загружен! Версия %s", PLUGIN_VERSION);
}

public OnPluginEnd()
{
    ConVar cvHostname = FindConVar("hostname");
    if (cvHostname != null)
    {
        SetConVarString(cvHostname, g_sOriginalHostname);
    }
    ConVar cvAlltalk = FindConVar("sv_alltalk");
    if (cvAlltalk != null)
    {
        SetConVarInt(cvAlltalk, 0);
    }
}

public OnMapStart()
{
    g_iMatchState = STATE_LOBBY;
    g_iCTScore = 0;
    g_iTScore = 0;
    g_iCurrentRound = 0;
    g_iOvertimeCount = 0;
    g_iPlayersReady = 0;
    g_bIsPaused = false;
    g_iTeamSize[0] = 0;
    g_iTeamSize[1] = 0;
    g_iMatchAdmin = 0;
    
    for (new i = 1; i <= MaxClients; i++)
    {
        g_bPlayerReady[i] = false;
        g_iPlayerTeam[i] = 0;
        g_iSubRequests[i] = 0;
    }
    
    CreateTimer(2.0, Timer_CountPlayers);
    CreateTimer(5.0, Timer_RemoveFog);
    
    SetAllTalk(true);
}

public Action:Timer_RemoveFog(Handle:timer)
{
    RemoveFogFromMap();
    return Plugin_Stop;
}

RemoveFogFromMap()
{
    new ent = -1;
    while ((ent = FindEntityByClassname(ent, "env_fog_controller")) != -1)
    {
        if (IsValidEntity(ent))
        {
            AcceptEntityInput(ent, "TurnOff");
        }
    }
    ent = -1;
    while ((ent = FindEntityByClassname(ent, "env_smokestack")) != -1)
    {
        if (IsValidEntity(ent))
        {
            AcceptEntityInput(ent, "TurnOff");
        }
    }
}

public OnClientPostAdminCheck(client)
{
    if (IsFakeClient(client)) return;
    
    if (CheckCommandAccess(client, "sm_start", ADMFLAG_GENERIC, false))
    {
        if (g_iMatchAdmin == 0 || !IsClientInGame(g_iMatchAdmin))
        {
            g_iMatchAdmin = client;
            PrintToChat(client, "\x04[CSrating] \x01Вы управляете матчем! Используйте \x03!menu\x01.");
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01управляет матчем!", client);
        }
    }
    
    if (g_iMatchState == STATE_LOBBY && !g_bPlayerReady[client])
    {
        g_bPlayerReady[client] = true;
        g_iPlayersReady++;
        
        PrintToChatAll("\x04[CSrating] \x03%N \x01готов! (\x02%d/%d\x01)",
                       client, g_iPlayersReady, g_iPlayersPerTeam * 2);
        
        UpdateServerHostname();
        
        if (g_iPlayersReady >= g_iPlayersPerTeam * 2)
        {
            CreateTimer(3.0, Timer_StartCaptainPick);
        }
    }
}

public OnClientDisconnect(client)
{
    if (IsFakeClient(client)) return;
    
    if (client == g_iMatchAdmin)
    {
        g_iMatchAdmin = 0;
        FindNewMatchAdmin();
    }
    
    if (g_bPlayerReady[client])
    {
        g_bPlayerReady[client] = false;
        g_iPlayersReady--;
        if (g_iPlayersReady < 0) g_iPlayersReady = 0;
    }
    
    if (g_iMatchState == STATE_LIVE || g_iMatchState == STATE_OVERTIME)
    {
        if (g_iPlayerTeam[client] > 0)
        {
            new playersInTeams = 0;
            for (new i = 1; i <= MaxClients; i++)
            {
                if (IsClientInGame(i) && !IsFakeClient(i) && g_iPlayerTeam[i] > 0)
                {
                    playersInTeams++;
                }
            }
            
            new totalNeeded = g_iPlayersPerTeam * 2;
            new minPlayers = RoundToCeil(Float:totalNeeded * 0.7);
            
            if (g_iPlayersPerTeam == 1)
            {
                PrintToChatAll("\x04[CSrating] \x01Игрок вышел! Матч отменен!");
                ResetMatch();
                return;
            }
            
            if (playersInTeams < minPlayers)
            {
                PrintToChatAll("\x04[CSrating] \x01Слишком много игроков вышло! Матч отменен!");
                ResetMatch();
                return;
            }
        }
    }
    
    g_iPlayerTeam[client] = 0;
    g_iSubRequests[client] = 0;
    
    UpdateServerHostname();
}

FindNewMatchAdmin()
{
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i))
        {
            if (CheckCommandAccess(i, "sm_start", ADMFLAG_GENERIC, false))
            {
                g_iMatchAdmin = i;
                PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01управляет!", i);
                return;
            }
        }
    }
}

CountPlayers()
{
    g_iPlayersReady = 0;
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i) && IsClientConnected(i))
        {
            g_bPlayerReady[i] = true;
            g_iPlayersReady++;
        }
    }
    UpdateServerHostname();
}

public Action:Timer_CountPlayers(Handle:timer)
{
    CountPlayers();
    return Plugin_Stop;
}

public ConnectToDatabase()
{
    if (SQL_CheckConfig("sourcebans"))
    {
        char error[256];
        g_hDatabase = SQL_Connect("sourcebans", true, error, sizeof(error));
        if (g_hDatabase == INVALID_HANDLE)
        {
            LogError("[CSrating] Ошибка БД: %s", error);
        }
    }
}

LoadAdverts()
{
    g_iAdvertCount = 0;
    
    char configPath[256];
    BuildPath(Path_SM, configPath, sizeof(configPath), "configs/csrating_adverts.cfg");
    
    if (!FileExists(configPath))
    {
        PrintToServer("[CSrating] Конфиг рекламы не найден!");
        return;
    }
    
    new Handle:kv = CreateKeyValues("Adverts");
    FileToKeyValues(kv, configPath);
    
    if (KvGotoFirstSubKey(kv))
    {
        do
        {
            if (g_iAdvertCount >= MAX_ADVERTS) break;
            
            char text[256];
            KvGetString(kv, "text", text, sizeof(text), "");
            
            if (strlen(text) > 0)
            {
                strcopy(g_sAdvertText[g_iAdvertCount], 256, text);
                g_iAdvertCount++;
            }
        }
        while (KvGotoNextKey(kv));
    }
    
    CloseHandle(kv);
    PrintToServer("[CSrating] Загружено %d реклам", g_iAdvertCount);
}

// ИСПРАВЛЕНО: цвета для CS:S
public Action:Timer_ShowAdvert(Handle:timer)
{
    if (g_iAdvertCount == 0) return Plugin_Continue;
    
    if (g_iCurrentAdvert >= g_iAdvertCount)
    {
        g_iCurrentAdvert = 0;
    }
    
    char advert[256];
    strcopy(advert, sizeof(advert), g_sAdvertText[g_iCurrentAdvert]);
    
    // ЦВЕТА CS:SOURCE:
    // \x01 = обычный (серый)
    // \x02 = зеленый
    // \x03 = желтый (ник игрока)
    // \x04 = зеленый (olive)
    // КРАСНОГО ЦВЕТА НЕТ в CS:S через чат!
    
    ReplaceString(advert, sizeof(advert), "{red}", "\x04");
    ReplaceString(advert, sizeof(advert), "{default}", "\x01");
    ReplaceString(advert, sizeof(advert), "{lightgreen}", "\x04");
    ReplaceString(advert, sizeof(advert), "{green}", "\x04");
    ReplaceString(advert, sizeof(advert), "{olive}", "\x04");
    ReplaceString(advert, sizeof(advert), "{teamcolor}", "\x03");
    
    PrintToChatAll("%s", advert);
    
    g_iCurrentAdvert++;
    
    return Plugin_Continue;
}

LoadConfig()
{
    char configPath[256];
    BuildPath(Path_SM, configPath, sizeof(configPath), "configs/csrating_match.cfg");
    
    if (FileExists(configPath))
    {
        new Handle:kv = CreateKeyValues("CSratingMatch");
        FileToKeyValues(kv, configPath);
        
        char configHostname[256];
        KvGetString(kv, "Hostname", configHostname, sizeof(configHostname), "");
        
        g_iMaxRounds = KvGetNum(kv, "MaxRounds", 30);
        g_iRoundsPerHalf = KvGetNum(kv, "RoundsPerHalf", 15);
        g_iOvertimeRounds = KvGetNum(kv, "OvertimeRounds", 6);
        g_iPlayersPerTeam = KvGetNum(kv, "PlayersPerTeam", 5);
        
        CloseHandle(kv);
        
        if (strlen(configHostname) > 0)
        {
            strcopy(g_sOriginalHostname, sizeof(g_sOriginalHostname), configHostname);
        }
    }
    else
    {
        g_iMaxRounds = 30;
        g_iRoundsPerHalf = 15;
        g_iOvertimeRounds = 6;
        g_iPlayersPerTeam = 5;
        strcopy(g_sOriginalHostname, sizeof(g_sOriginalHostname), "CSrating Server");
    }
}

SetAllTalk(bool:enable)
{
    ConVar cvAlltalk = FindConVar("sv_alltalk");
    if (cvAlltalk != null)
    {
        SetConVarInt(cvAlltalk, enable ? 1 : 0);
    }
}

UpdateServerHostname()
{
    char hostname[256];
    
    switch (g_iMatchState)
    {
        case STATE_LOBBY:
        {
            new remaining = (g_iPlayersPerTeam * 2) - g_iPlayersReady;
            if (remaining < 0) remaining = 0;
            Format(hostname, sizeof(hostname), "%s [Ожидание %d]", g_sOriginalHostname, remaining);
        }
        case STATE_CAPTAIN_PICK, STATE_PLAYER_PICK:
        {
            Format(hostname, sizeof(hostname), "%s [Выбор]", g_sOriginalHostname);
        }
        case STATE_LIVE, STATE_HALFTIME:
        {
            Format(hostname, sizeof(hostname), "[CT %d - %d T] %s", g_iCTScore, g_iTScore, g_sOriginalHostname);
        }
        case STATE_OVERTIME:
        {
            Format(hostname, sizeof(hostname), "[OT %d - %d] %s", g_iCTScore, g_iTScore, g_sOriginalHostname);
        }
        case STATE_FINISHED:
        {
            Format(hostname, sizeof(hostname), "[Завершен %d:%d] %s", g_iCTScore, g_iTScore, g_sOriginalHostname);
        }
    }
    
    ConVar cvHostname = FindConVar("hostname");
    if (cvHostname != null)
    {
        SetConVarString(cvHostname, hostname);
    }
}

public Action:Command_Menu(client, args)
{
    if (client == 0) return Plugin_Handled;
    ShowMainMenu(client);
    return Plugin_Handled;
}

public Action:Command_MatchSettings(client, args)
{
    if (client == 0) return Plugin_Handled;
    if (!CheckCommandAccess(client, "sm_start", ADMFLAG_GENERIC, false))
    {
        PrintToChat(client, "\x04[CSrating] \x01Нет доступа!");
        return Plugin_Handled;
    }
    ShowMatchSettingsMenu(client);
    return Plugin_Handled;
}

ShowMainMenu(client)
{
    new Handle:menu = CreateMenu(MenuHandler_MainMenu);
    
    char title[128];
    Format(title, sizeof(title), "CSrating Match\nВерсия: %s", PLUGIN_VERSION);
    SetMenuTitle(menu, title);
    
    if (g_iMatchState == STATE_LOBBY)
    {
        if (g_bPlayerReady[client])
        {
            AddMenuItem(menu, "unready", "Не готов");
        }
        else
        {
            AddMenuItem(menu, "ready", "Готов");
        }
    }
    
    AddMenuItem(menu, "score", "Счет");
    AddMenuItem(menu, "match", "Инфо о матче");
    
    if (g_iMatchState == STATE_LIVE)
    {
        AddMenuItem(menu, "pause", "Пауза");
        AddMenuItem(menu, "unpause", "Снять паузу");
        AddMenuItem(menu, "sub", "Замена");
    }
    
    if (CheckCommandAccess(client, "sm_start", ADMFLAG_GENERIC, false))
    {
        AddMenuItem(menu, "", "----- Админ -----", ITEMDRAW_DISABLED);
        AddMenuItem(menu, "settings", "Настройки матча");
        
        if (g_iMatchState == STATE_LOBBY)
        {
            AddMenuItem(menu, "admin_start", "Принуд. старт");
        }
        AddMenuItem(menu, "admin_restart", "Рестарт");
        AddMenuItem(menu, "admin_cancel", "Отмена");
    }
    
    SetMenuExitButton(menu, true);
    DisplayMenu(menu, client, MENU_TIME_FOREVER);
}

ShowMatchSettingsMenu(client)
{
    new Handle:menu = CreateMenu(MenuHandler_MatchSettings);
    
    char title[128];
    Format(title, sizeof(title), "Настройки матча\nТекущие: MR%d | %dv%d",
           g_iMaxRounds / 2, g_iPlayersPerTeam, g_iPlayersPerTeam);
    SetMenuTitle(menu, title);
    
    AddMenuItem(menu, "rounds_mr15", "Раунды: MR15 (30)");
    AddMenuItem(menu, "rounds_mr12", "Раунды: MR12 (24)");
    AddMenuItem(menu, "rounds_mr9", "Раунды: MR9 (18)");
    AddMenuItem(menu, "players_1v1", "Игроки: 1v1 (2)");
    AddMenuItem(menu, "players_2v2", "Игроки: 2v2 (4)");
    AddMenuItem(menu, "players_3v3", "Игроки: 3v3 (6)");
    AddMenuItem(menu, "players_5v5", "Игроки: 5v5 (10)");
    
    SetMenuExitButton(menu, true);
    DisplayMenu(menu, client, MENU_TIME_FOREVER);
}

public MenuHandler_MainMenu(Handle:menu, MenuAction:action, param1, param2)
{
    if (action == MenuAction_Select)
    {
        char info[32];
        GetMenuItem(menu, param2, info, sizeof(info));
        
        if (StrEqual(info, "ready"))
        {
            FakeClientCommand(param1, "sm_ready");
            CreateTimer(0.5, Timer_ReopenMenu, GetClientUserId(param1));
        }
        else if (StrEqual(info, "unready"))
        {
            FakeClientCommand(param1, "sm_unready");
            CreateTimer(0.5, Timer_ReopenMenu, GetClientUserId(param1));
        }
        else if (StrEqual(info, "score"))
        {
            FakeClientCommand(param1, "sm_score");
            CreateTimer(0.5, Timer_ReopenMenu, GetClientUserId(param1));
        }
        else if (StrEqual(info, "match"))
        {
            FakeClientCommand(param1, "sm_match");
            CreateTimer(0.5, Timer_ReopenMenu, GetClientUserId(param1));
        }
        else if (StrEqual(info, "pause"))
        {
            FakeClientCommand(param1, "sm_pause");
        }
        else if (StrEqual(info, "unpause"))
        {
            FakeClientCommand(param1, "sm_unpause");
        }
        else if (StrEqual(info, "sub"))
        {
            FakeClientCommand(param1, "sm_sub");
        }
        else if (StrEqual(info, "settings"))
        {
            ShowMatchSettingsMenu(param1);
        }
        else if (StrEqual(info, "admin_start"))
        {
            FakeClientCommand(param1, "sm_start");
        }
        else if (StrEqual(info, "admin_restart"))
        {
            FakeClientCommand(param1, "sm_restart");
        }
        else if (StrEqual(info, "admin_cancel"))
        {
            FakeClientCommand(param1, "sm_cancel");
        }
    }
    else if (action == MenuAction_End)
    {
        CloseHandle(menu);
    }
    return 0;
}

public MenuHandler_MatchSettings(Handle:menu, MenuAction:action, param1, param2)
{
    if (action == MenuAction_Select)
    {
        char info[32];
        GetMenuItem(menu, param2, info, sizeof(info));
        
        if (StrEqual(info, "rounds_mr15"))
        {
            g_iMaxRounds = 30;
            g_iRoundsPerHalf = 15;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: MR15", param1);
        }
        else if (StrEqual(info, "rounds_mr12"))
        {
            g_iMaxRounds = 24;
            g_iRoundsPerHalf = 12;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: MR12", param1);
        }
        else if (StrEqual(info, "rounds_mr9"))
        {
            g_iMaxRounds = 18;
            g_iRoundsPerHalf = 9;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: MR9", param1);
        }
        else if (StrEqual(info, "players_1v1"))
        {
            g_iPlayersPerTeam = 1;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: 1v1", param1);
            UpdateServerHostname();
        }
        else if (StrEqual(info, "players_2v2"))
        {
            g_iPlayersPerTeam = 2;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: 2v2", param1);
            UpdateServerHostname();
        }
        else if (StrEqual(info, "players_3v3"))
        {
            g_iPlayersPerTeam = 3;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: 3v3", param1);
            UpdateServerHostname();
        }
        else if (StrEqual(info, "players_5v5"))
        {
            g_iPlayersPerTeam = 5;
            PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01установил: 5v5", param1);
            UpdateServerHostname();
        }
        
        CreateTimer(0.5, Timer_ReopenMenu, GetClientUserId(param1));
    }
    else if (action == MenuAction_End)
    {
        CloseHandle(menu);
    }
    return 0;
}

public Action:Timer_ReopenMenu(Handle:timer, any:userid)
{
    new client = GetClientOfUserId(userid);
    if (client > 0 && IsClientInGame(client))
    {
        ShowMainMenu(client);
    }
    return Plugin_Stop;
}

public Action:Command_Ready(client, args)
{
    if (g_iMatchState != STATE_LOBBY)
    {
        PrintToChat(client, "\x04[CSrating] \x01Матч уже начался!");
        return Plugin_Handled;
    }
    
    if (!g_bPlayerReady[client])
    {
        g_bPlayerReady[client] = true;
        g_iPlayersReady++;
        
        PrintToChatAll("\x04[CSrating] \x03%N \x01готов! (\x02%d/%d\x01)",
                       client, g_iPlayersReady, g_iPlayersPerTeam * 2);
        
        UpdateServerHostname();
        
        if (g_iPlayersReady >= g_iPlayersPerTeam * 2)
        {
            CreateTimer(3.0, Timer_StartCaptainPick);
        }
    }
    else
    {
        PrintToChat(client, "\x04[CSrating] \x01Вы уже готовы!");
    }
    
    return Plugin_Handled;
}

public Action:Command_Unready(client, args)
{
    if (g_iMatchState != STATE_LOBBY)
    {
        PrintToChat(client, "\x04[CSrating] \x01Матч уже начался!");
        return Plugin_Handled;
    }
    
    if (g_bPlayerReady[client])
    {
        g_bPlayerReady[client] = false;
        g_iPlayersReady--;
        if (g_iPlayersReady < 0) g_iPlayersReady = 0;
        
        PrintToChatAll("\x04[CSrating] \x03%N \x01не готов! (\x02%d/%d\x01)",
                       client, g_iPlayersReady, g_iPlayersPerTeam * 2);
        
        UpdateServerHostname();
    }
    else
    {
        PrintToChat(client, "\x04[CSrating] \x01Вы и так не готовы!");
    }
    
    return Plugin_Handled;
}

public Action:Command_Pause(client, args)
{
    if (g_iMatchState != STATE_LIVE)
    {
        PrintToChat(client, "\x04[CSrating] \x01Матч не идет!");
        return Plugin_Handled;
    }
    
    new team = GetClientTeam(client);
    new teamIndex = (team == CS_TEAM_CT) ? 0 : 1;
    
    if (g_iPauseCount[teamIndex] >= 2)
    {
        PrintToChat(client, "\x04[CSrating] \x01Нет пауз!");
        return Plugin_Handled;
    }
    
    if (g_bIsPaused)
    {
        PrintToChat(client, "\x04[CSrating] \x01Уже на паузе!");
        return Plugin_Handled;
    }
    
    g_bIsPaused = true;
    g_iPauseCount[teamIndex]++;
    
    ServerCommand("mp_pause_match");
    PrintToChatAll("\x04[CSrating] \x03%N \x01поставил паузу! (\x02%d/2\x01 осталось)",
                   client, g_iPauseCount[teamIndex]);
    
    return Plugin_Handled;
}

public Action:Command_Unpause(client, args)
{
    if (!g_bIsPaused)
    {
        PrintToChat(client, "\x04[CSrating] \x01Не на паузе!");
        return Plugin_Handled;
    }
    
    g_bIsPaused = false;
    ServerCommand("mp_unpause_match");
    PrintToChatAll("\x04[CSrating] \x03%N \x01снял паузу!", client);
    
    return Plugin_Handled;
}

public Action:Command_Score(client, args)
{
    PrintToChat(client, "\x04[CSrating] \x01Счет: \x03CT %d - %d T\x01 | Раунд: \x02%d/%d",
                   g_iCTScore, g_iTScore, g_iCurrentRound, g_iMaxRounds);
    return Plugin_Handled;
}

public Action:Command_Sub(client, args)
{
    if (g_iMatchState != STATE_LIVE)
    {
        PrintToChat(client, "\x04[CSrating] \x01Только во время матча!");
        return Plugin_Handled;
    }
    
    if (g_iPlayerTeam[client] == 0)
    {
        PrintToChat(client, "\x04[CSrating] \x01Не в команде!");
        return Plugin_Handled;
    }
    
    g_iSubRequests[client] = 1;
    PrintToChatAll("\x04[CSrating] \x03%N \x01запросил замену!", client);
    
    ShowSubMenuToCaptain(client);
    
    return Plugin_Handled;
}

public Action:Command_MatchInfo(client, args)
{
    char stateName[64];
    switch (g_iMatchState)
    {
        case STATE_LOBBY: strcopy(stateName, sizeof(stateName), "Лобби");
        case STATE_CAPTAIN_PICK: strcopy(stateName, sizeof(stateName), "Выбор капитанов");
        case STATE_PLAYER_PICK: strcopy(stateName, sizeof(stateName), "Набор команд");
        case STATE_LIVE: strcopy(stateName, sizeof(stateName), "Матч");
        case STATE_HALFTIME: strcopy(stateName, sizeof(stateName), "Перерыв");
        case STATE_OVERTIME: strcopy(stateName, sizeof(stateName), "Овертайм");
        case STATE_FINISHED: strcopy(stateName, sizeof(stateName), "Завершен");
    }
    
    PrintToChat(client, "\x04[CSrating] \x01Состояние: \x03%s\x01 | Счет: \x02CT %d - %d T | Игроки: %d/%d",
                   stateName, g_iCTScore, g_iTScore, g_iPlayersReady, g_iPlayersPerTeam * 2);
    return Plugin_Handled;
}

public Action:Command_Start(client, args)
{
    if (g_iMatchState != STATE_LOBBY)
    {
        PrintToChat(client, "\x04[CSrating] \x01Матч уже начался!");
        return Plugin_Handled;
    }
    
    CountPlayers();
    
    PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01принудительно начал!", client);
    PrintToChatAll("\x04[CSrating] \x01Игроков: \x02%d", g_iPlayersReady);
    
    CreateTimer(1.0, Timer_StartCaptainPick);
    
    return Plugin_Handled;
}

public Action:Command_Restart(client, args)
{
    PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01перезапустил!", client);
    ResetMatch();
    
    return Plugin_Handled;
}

public Action:Command_SetScore(client, args)
{
    if (args < 2)
    {
        PrintToChat(client, "Использование: sm_setscore <CT> <T>");
        return Plugin_Handled;
    }
    
    char arg1[16], arg2[16];
    GetCmdArg(1, arg1, sizeof(arg1));
    GetCmdArg(2, arg2, sizeof(arg2));
    
    g_iCTScore = StringToInt(arg1);
    g_iTScore = StringToInt(arg2);
    
    PrintToChatAll("\x04[CSrating] \x01Счет установлен: \x03CT %d - %d T", g_iCTScore, g_iTScore);
    UpdateServerHostname();
    
    return Plugin_Handled;
}

public Action:Command_ForcePause(client, args)
{
    if (g_bIsPaused)
    {
        g_bIsPaused = false;
        ServerCommand("mp_unpause_match");
        PrintToChatAll("\x04[CSrating] \x01Админ снял паузу!");
    }
    else
    {
        g_bIsPaused = true;
        ServerCommand("mp_pause_match");
        PrintToChatAll("\x04[CSrating] \x01Админ поставил паузу!");
    }
    
    return Plugin_Handled;
}

public Action:Command_Cancel(client, args)
{
    PrintToChatAll("\x04[CSrating] \x01Админ \x03%N \x01отменил!", client);
    ResetMatch();
    
    return Plugin_Handled;
}

public Action:Timer_StartCaptainPick(Handle:timer)
{
    CountPlayers();
    
    if (g_iPlayersReady < 2)
    {
        PrintToChatAll("\x04[CSrating] \x01Нужно 2 игрока!");
        return Plugin_Stop;
    }
    
    new captainCount = 0;
    
    if (g_iPlayersPerTeam == 1)
    {
        for (new i = 1; i <= MaxClients && captainCount < 2; i++)
        {
            if (IsClientInGame(i) && !IsFakeClient(i) && g_bPlayerReady[i])
            {
                if (captainCount == 0)
                {
                    CS_SwitchTeam(i, CS_TEAM_CT);
                    g_iPlayerTeam[i] = CS_TEAM_CT;
                }
                else
                {
                    CS_SwitchTeam(i, CS_TEAM_T);
                    g_iPlayerTeam[i] = CS_TEAM_T;
                }
                captainCount++;
            }
        }
        
        PrintToChatAll("\x04[CSrating] \x011v1 матч начинается!");
        CreateTimer(2.0, Timer_StartMatch);
        return Plugin_Stop;
    }
    
    g_iMatchState = STATE_CAPTAIN_PICK;
    UpdateServerHostname();
    
    PrintToChatAll("\x04[CSrating] \x01%d игроков готовы! Выбор капитанов...", g_iPlayersReady);
    
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i) && g_bPlayerReady[i])
        {
            CS_SwitchTeam(i, CS_TEAM_SPECTATOR);
        }
    }
    
    captainCount = 0;
    for (new i = 1; i <= MaxClients && captainCount < 2; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i) && g_bPlayerReady[i])
        {
            g_iCaptains[captainCount] = i;
            captainCount++;
        }
    }
    
    if (captainCount < 2)
    {
        PrintToChatAll("\x04[CSrating] \x01Ошибка: нужно 2 капитана!");
        ResetMatch();
        return Plugin_Stop;
    }
    
    PrintToChatAll("\x04[CSrating] \x01Капитаны: \x03%N \x01и \x03%N",
                   g_iCaptains[0], g_iCaptains[1]);
    
    CreateTimer(2.0, Timer_StartPlayerPick);
    
    return Plugin_Stop;
}

public Action:Timer_StartPlayerPick(Handle:timer)
{
    g_iMatchState = STATE_PLAYER_PICK;
    g_iPickOrder = 0;
    g_iCaptainTeam = CS_TEAM_CT;
    
    PrintToChatAll("\x04[CSrating] \x01Капитан \x03%N \x01(CT) выбирает!", g_iCaptains[0]);
    
    ShowCaptainPickMenu(g_iCaptains[0]);
    
    return Plugin_Stop;
}

ShowCaptainPickMenu(captain)
{
    new Handle:menu = CreateMenu(MenuHandler_CaptainPick);
    SetMenuTitle(menu, "Выберите игрока");
    
    for (new i = 1; i <= MaxClients; i++)
    {
        if (i == captain) continue;
        
        if (IsClientInGame(i) && !IsFakeClient(i) && g_bPlayerReady[i] && g_iPlayerTeam[i] == 0)
        {
            char info[16];
            IntToString(i, info, sizeof(info));
            
            char playerName[MAX_NAME_LENGTH];
            GetClientName(i, playerName, sizeof(playerName));
            
            AddMenuItem(menu, info, playerName);
        }
    }
    
    DisplayMenu(menu, captain, MENU_TIME_FOREVER);
}

public MenuHandler_CaptainPick(Handle:menu, MenuAction:action, param1, param2)
{
    if (action == MenuAction_Select)
    {
        char info[16];
        GetMenuItem(menu, param2, info, sizeof(info));
        new selectedPlayer = StringToInt(info);
        
        if (g_iCaptainTeam == CS_TEAM_CT)
        {
            g_iPlayerTeam[selectedPlayer] = CS_TEAM_CT;
            g_iTeamSize[0]++;
            PrintToChatAll("\x04[CSrating] \x03%N \x01выбрал \x03%N \x01в CT!", param1, selectedPlayer);
        }
        else
        {
            g_iPlayerTeam[selectedPlayer] = CS_TEAM_T;
            g_iTeamSize[1]++;
            PrintToChatAll("\x04[CSrating] \x03%N \x01выбрал \x03%N \x01в T!", param1, selectedPlayer);
        }
        
        new totalPlayers = g_iTeamSize[0] + g_iTeamSize[1];
        new playersNeeded = g_iPlayersPerTeam * 2;
        
        if (totalPlayers >= playersNeeded)
        {
            PrintToChatAll("\x04[CSrating] \x01Команды собраны! Старт через 5 сек...");
            CreateTimer(5.0, Timer_StartMatch);
        }
        else
        {
            g_iCaptainTeam = (g_iCaptainTeam == CS_TEAM_CT) ? CS_TEAM_T : CS_TEAM_CT;
            g_iPickOrder = 1 - g_iPickOrder;
            
            new nextCaptain = g_iCaptains[g_iPickOrder];
            char teamName[8];
            strcopy(teamName, sizeof(teamName), (g_iCaptainTeam == CS_TEAM_CT) ? "CT" : "T");
            
            PrintToChatAll("\x04[CSrating] \x01Капитан \x03%N \x01(%s) выбирает!", nextCaptain, teamName);
            
            ShowCaptainPickMenu(nextCaptain);
        }
    }
    else if (action == MenuAction_End)
    {
        CloseHandle(menu);
    }
    return 0;
}

ShowSubMenuToCaptain(leavingPlayer)
{
    new team = g_iPlayerTeam[leavingPlayer];
    new captainIndex = (team == CS_TEAM_CT) ? 0 : 1;
    new captain = g_iCaptains[captainIndex];
    
    if (!IsClientInGame(captain)) return;
    
    new Handle:menu = CreateMenu(MenuHandler_SubPick);
    SetMenuTitle(menu, "Выберите замену");
    
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == CS_TEAM_SPECTATOR)
        {
            char info[16];
            IntToString(i, info, sizeof(info));
            
            char playerName[MAX_NAME_LENGTH];
            GetClientName(i, playerName, sizeof(playerName));
            
            AddMenuItem(menu, info, playerName);
        }
    }
    
    DisplayMenu(menu, captain, MENU_TIME_FOREVER);
}

public MenuHandler_SubPick(Handle:menu, MenuAction:action, param1, param2)
{
    if (action == MenuAction_Select)
    {
        char info[16];
        GetMenuItem(menu, param2, info, sizeof(info));
        new newPlayer = StringToInt(info);
        
        new leavingPlayer = 0;
        for (new i = 1; i <= MaxClients; i++)
        {
            if (g_iSubRequests[i] == 1)
            {
                leavingPlayer = i;
                break;
            }
        }
        
        if (leavingPlayer > 0)
        {
            new team = g_iPlayerTeam[leavingPlayer];
            g_iPlayerTeam[newPlayer] = team;
            g_iPlayerTeam[leavingPlayer] = 0;
            g_iSubRequests[leavingPlayer] = 0;
            
            CS_SwitchTeam(leavingPlayer, CS_TEAM_SPECTATOR);
            if (team == CS_TEAM_CT)
            {
                CS_SwitchTeam(newPlayer, CS_TEAM_CT);
            }
            else
            {
                CS_SwitchTeam(newPlayer, CS_TEAM_T);
            }
            
            PrintToChatAll("\x04[CSrating] \x01Замена: \x03%N \x01вышел, \x03%N \x01зашел!", leavingPlayer, newPlayer);
        }
    }
    else if (action == MenuAction_End)
    {
        CloseHandle(menu);
    }
    return 0;
}

public Action:Timer_StartMatch(Handle:timer)
{
    g_iMatchState = STATE_LIVE;
    g_iCurrentRound = 1;
    g_iCTScore = 0;
    g_iTScore = 0;
    g_iPauseCount[0] = 0;
    g_iPauseCount[1] = 0;
    g_bIsPaused = false;
    
    UpdateServerHostname();
    
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i) && g_iPlayerTeam[i] > 0)
        {
            if (g_iPlayerTeam[i] == CS_TEAM_CT)
            {
                CS_SwitchTeam(i, CS_TEAM_CT);
            }
            else if (g_iPlayerTeam[i] == CS_TEAM_T)
            {
                CS_SwitchTeam(i, CS_TEAM_T);
            }
        }
    }
    
    ServerCommand("mp_maxrounds %d", g_iMaxRounds);
    ServerCommand("mp_startmoney 800");
    ServerCommand("mp_restartgame 1");
    
    SetAllTalk(false);
    
    PrintToChatAll("\x04[CSrating] \x01МАТЧ НАЧАЛСЯ!");
    PrintToChatAll("\x04[CSrating] \x01Формат: MR%d | %dv%d", g_iMaxRounds / 2, g_iPlayersPerTeam, g_iPlayersPerTeam);
    PrintToChatAll("\x04[CSrating] \x01AllTalk выключен!");
    
    return Plugin_Stop;
}

public Event_PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast)
{
}

public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
    if (g_iMatchState == STATE_LIVE || g_iMatchState == STATE_OVERTIME)
    {
        g_iCurrentRound++;
        UpdateServerHostname();
    }
}

public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
    if (g_iMatchState != STATE_LIVE && g_iMatchState != STATE_OVERTIME) return;
    
    new winner = GetEventInt(event, "winner");
    
    if (winner == CS_TEAM_CT)
    {
        g_iCTScore++;
    }
    else if (winner == CS_TEAM_T)
    {
        g_iTScore++;
    }
    
    UpdateServerHostname();
    PrintToChatAll("\x04[CSrating] \x01Счет: \x03CT %d - %d T", g_iCTScore, g_iTScore);
    
    if (g_iCTScore == g_iRoundsPerHalf || g_iTScore == g_iRoundsPerHalf)
    {
        if (g_iOvertimeCount == 0)
        {
            g_iMatchState = STATE_HALFTIME;
            PrintToChatAll("\x04[CSrating] \x01ПЕРЕРЫВ - Смена сторон через 5 сек...");
            
            ServerCommand("mp_switchteams 1");
            ServerCommand("mp_restartgame 1");
            
            CreateTimer(5.0, Timer_ContinueAfterHalftime);
            return;
        }
    }
    
    new maxRounds = g_iMaxRounds + (g_iOvertimeCount * g_iOvertimeRounds * 2);
    new winScore = (maxRounds / 2) + 1;
    
    if (g_iCTScore >= winScore || g_iTScore >= winScore)
    {
        EndMatch();
    }
    else if (g_iCurrentRound >= maxRounds)
    {
        if (g_iCTScore == g_iTScore)
        {
            g_iOvertimeCount++;
            g_iMatchState = STATE_OVERTIME;
            PrintToChatAll("\x04[CSrating] \x01ОВЕРТАЙМ %d!", g_iOvertimeCount);
        }
        else
        {
            EndMatch();
        }
    }
}

public Action:Timer_ContinueAfterHalftime(Handle:timer)
{
    g_iMatchState = STATE_LIVE;
    PrintToChatAll("\x04[CSrating] \x01Матч продолжается!");
    return Plugin_Stop;
}

EndMatch()
{
    g_iMatchState = STATE_FINISHED;
    UpdateServerHostname();
    
    char winner[32];
    if (g_iCTScore > g_iTScore)
    {
        strcopy(winner, sizeof(winner), "CT");
    }
    else if (g_iTScore > g_iCTScore)
    {
        strcopy(winner, sizeof(winner), "T");
    }
    else
    {
        strcopy(winner, sizeof(winner), "Ничья");
    }
    
    PrintToChatAll("\x04[CSrating] \x01МАТЧ ЗАВЕРШЕН!");
    PrintToChatAll("\x04[CSrating] \x01Победитель: \x03%s", winner);
    PrintToChatAll("\x04[CSrating] \x01Итоговый счет: \x03CT %d - %d T", g_iCTScore, g_iTScore);
    
    SetAllTalk(true);
    
    PrintToChatAll("\x04[CSrating] \x01Голосование за карту через 10 сек...");
    CreateTimer(10.0, Timer_StartMapVote);
    
    CreateTimer(30.0, Timer_ResetAfterMatch);
}

public Action:Timer_StartMapVote(Handle:timer)
{
    if (FindPluginByFile("mapchooser.smx") != INVALID_HANDLE)
    {
        PrintToChatAll("\x04[CSrating] \x01Голосование за карту!");
        ServerCommand("sm_mapvote");
    }
    else
    {
        ShowMapVoteMenu();
    }
    
    return Plugin_Stop;
}

ShowMapVoteMenu()
{
    new Handle:menu = CreateMenu(MenuHandler_MapVote);
    SetMenuTitle(menu, "Голосование за карту:");
    
    AddMenuItem(menu, "de_dust2", "de_dust2");
    AddMenuItem(menu, "de_inferno", "de_inferno");
    AddMenuItem(menu, "de_nuke", "de_nuke");
    AddMenuItem(menu, "de_train", "de_train");
    
    SetMenuExitButton(menu, false);
    
    for (new i = 1; i <= MaxClients; i++)
    {
        if (IsClientInGame(i) && !IsFakeClient(i))
        {
            DisplayMenu(menu, i, 20);
        }
    }
}

public MenuHandler_MapVote(Handle:menu, MenuAction:action, param1, param2)
{
    if (action == MenuAction_Select)
    {
        char map[64];
        GetMenuItem(menu, param2, map, sizeof(map));
        
        PrintToChatAll("\x04[CSrating] \x03%N \x01выбрал \x04%s", param1, map);
        CreateTimer(15.0, Timer_ChangeMap);
    }
    else if (action == MenuAction_End)
    {
        CloseHandle(menu);
    }
    return 0;
}

public Action:Timer_ChangeMap(Handle:timer)
{
    PrintToChatAll("\x04[CSrating] \x01Смена карты через 5 сек...");
    CreateTimer(5.0, Timer_DoChangeMap);
    return Plugin_Stop;
}

public Action:Timer_DoChangeMap(Handle:timer)
{
    ServerCommand("changelevel de_dust2");
    return Plugin_Stop;
}

public Action:Timer_ResetAfterMatch(Handle:timer)
{
    ResetMatch();
    return Plugin_Stop;
}

ResetMatch()
{
    g_iMatchState = STATE_LOBBY;
    g_iCTScore = 0;
    g_iTScore = 0;
    g_iCurrentRound = 0;
    g_iOvertimeCount = 0;
    g_iPlayersReady = 0;
    g_bIsPaused = false;
    g_iTeamSize[0] = 0;
    g_iTeamSize[1] = 0;
    g_iPauseCount[0] = 0;
    g_iPauseCount[1] = 0;
    
    for (new i = 1; i <= MaxClients; i++)
    {
        g_bPlayerReady[i] = false;
        g_iPlayerTeam[i] = 0;
        g_iSubRequests[i] = 0;
    }
    
    CountPlayers();
    
    ServerCommand("mp_maxrounds 0");
    
    SetAllTalk(true);
    
    PrintToChatAll("\x04[CSrating] \x01Матч сброшен. Ожидание...");
}
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,836
Реакции
5,273
@Alex777, и ещё один вопрос: а нафига голосование, если при его любом результате карта сменится на 2-й даст? 😏
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,836
Реакции
5,273
И нафига коннектиться к БД sourcebans, если это вообще ни для чего не используется (ну кроме того, чтобы сыпать в лог ошибок сообщение при каждом старте плагина, когда такой БД не существует на сервере)?
 

Alex777

Участник
Сообщения
36
Реакции
1
И нафига коннектиться к БД sourcebans, если это вообще ни для чего не используется (ну кроме того, чтобы сыпать в лог ошибок сообщение при каждом старте плагина, когда такой БД не существует на сервере)?
Была идея давать бан за выход,потом отказался.
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,836
Реакции
5,273
Пока ещё только начал чистить код (а на всё это времени может уйти - мама не горюй) и вот такие результаты пока:
C-подобный:
//// отрефактореный.sp
//
// Code size:         34736 bytes
// Data size:         22756 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   74484 bytes
//
// Compilation Time: 0,16 sec
// ----------------------------------------

//// оригинальный.sp
//
// Code size:         35208 bytes
// Data size:         23776 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   75976 bytes
//
// Compilation Time: 0,19 sec
// ----------------------------------------
Выношу потихоньку создание массивов из циклов наружу и прочие правки непотребного.
Ну и код пока сократился до 1270 строк.
Помимо этого префикс для чата, дефолтное имя сервера и список карт для голосования перемещены в начало исходника для удобства правки.
 

Alex777

Участник
Сообщения
36
Реакции
1
Пока ещё только начал чистить код (а на всё это времени может уйти - мама не горюй) и вот такие результаты пока:
C-подобный:
//// отрефактореный.sp
//
// Code size:         34736 bytes
// Data size:         22756 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   74484 bytes
//
// Compilation Time: 0,16 sec
// ----------------------------------------

//// оригинальный.sp
//
// Code size:         35208 bytes
// Data size:         23776 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   75976 bytes
//
// Compilation Time: 0,19 sec
// ----------------------------------------
Выношу потихоньку создание массивов из циклов наружу и прочие правки непотребного.
Ну и код пока сократился до 1270 строк.
Помимо этого префикс для чата, дефолтное имя сервера и список карт для голосования перемещены в начало исходника для удобства правки.
Искусственный интеллект думает по своему) Если скинешь потом правленый исходник,буду благодарен) Я не силен в создании плагинов,решил через ИИ вот сделать)
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,836
Реакции
5,273
Ещё почистил косяки всякие и перевёл на новый синтаксис:
C-подобный:
//// отрефрактореное.sp
//
// Code size:         33492 bytes
// Data size:         22560 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   73044 bytes
//
// Compilation Time: 0,17 sec
// ----------------------------------------
Теперь исходник имеет 1197 строк.

Но там ещё переписывать есть что (то же полностью нерабочее голосование или рекламные сообщения в статичном строковом массиве).
Сообщения автоматически склеены:

Вообще надо бы добавить поддержку переводов для сообщений в чат и добавить расцветку чата вместо реализованой расцветки чата для CS:Sv34 (т.е. сильно урезаной). И перевести значения переменных из файла конфига в квары. Ну и некоторые константы сделать настраиваемыми (префиксы и дефолтное имя сервера).
Ещё не переработал создание и обработку меню матча, но там сравнительно немного работы.
Сообщения автоматически склеены:

В общем состояние плагина на этот момент
 

Вложения

  • Match System 3.4.0_10.06.2026.sp
    33 КБ · Просмотры: 2
Последнее редактирование:

Alex777

Участник
Сообщения
36
Реакции
1
Ещё почистил косяки всякие и перевёл на новый синтаксис:
C-подобный:
//// отрефрактореное.sp
//
// Code size:         33492 bytes
// Data size:         22560 bytes
// Stack/heap size:      16992 bytes
// Total requirements:   73044 bytes
//
// Compilation Time: 0,17 sec
// ----------------------------------------
Теперь исходник имеет 1197 строк.

Но там ещё переписывать есть что (то же полностью нерабочее голосование или рекламные сообщения в статичном строковом массиве).
Сообщения автоматически склеены:

Вообще надо бы добавить поддержку переводов для сообщений в чат и добавить расцветку чата вместо реализованой расцветки чата для CS:Sv34 (т.е. сильно урезаной). И перевести значения переменных из файла конфига в квары. Ну и некоторые константы сделать настраиваемыми (префиксы и дефолтное имя сервера).
Ещё не переработал создание и обработку меню матча, но там сравнительно немного работы.
Сообщения автоматически склеены:

В общем состояние плагина на этот момент
ИИ делает, человек за ним переделывает все полностью) Красавчик!
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,836
Реакции
5,273
@Alex777, я не всё переделал, что запланировано.
И это я даже логику работы ещё не везде проверял.
Сообщения автоматически склеены:

ИИ делает, человек за ним переделывает все полностью)
 

Вложения

  • IMG_20260612_195114_370.jpg
    IMG_20260612_195114_370.jpg
    93.2 КБ · Просмотры: 8
Сверху Снизу