/ D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(189) : error 001: expected token: ";", but found "#"
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(189) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(191) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(193) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(195) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(199) : error 001: expected token: ";", but found "."
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(199) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(202) : error 122: expected type expression
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(202) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(203) : error 054: unmatched closing brace ("}")
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(204) : error 010: invalid function or declaration
// D:\0000\archive-2024-05-26T150426+0500\scripting\roul2.sp(213) : error 029: invalid expression, assumed zero

Код:
#include <sourcemod>
#include <shop>
#include <timers>

enum BetType
{
    Bet_None,
    Bet_Color,
    Bet_Dozen,
    Bet_Number,
    Bet_Column,
    Bet_Row
};

int g_PlayerBet[MAXPLAYERS + 1];       // How much player has bet
BetType g_PlayerBetType[MAXPLAYERS + 1];   // What kind of bet player has made
int g_PlayerBetValue[MAXPLAYERS + 1];  // The value player has bet on
bool g_PlayerHasBet[MAXPLAYERS + 1];   // Whether player has bet or not
bool g_PlayerBetSelected[MAXPLAYERS + 1];  // Whether player has selected a bet type

public Plugin myinfo =
{
    name = "Roulette Plugin",
    author = "anon",
    description = "A simple roulette plugin for CS:Source",
    version = "1.0",
    url = "https://www.example.com"
};

public void OnPluginStart()
{
    RegConsoleCmd("sm_roul", Command_Roul);
    RegConsoleCmd("sm_bet", Command_Bet);
    CreateTimer(30.0, Timer_RouletteEnd, TIMER_REPEAT);
}

public Action Command_Roul(int client, int args)
{
    if (!IsClientInGame(client))
    {
        return Plugin_Handled;
    }

    ShowRouletteMenu(client);
    return Plugin_Handled;
}

public void ShowRouletteMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_Roulette);

    menu.SetTitle("Выберите ставку");
    menu.AddItem("color", "На цвет");
    menu.AddItem("dozen", "На дюжину");
    menu.AddItem("number", "На число");
    menu.AddItem("column", "На колонну");
    menu.AddItem("row", "На столбец");

    menu.Display(client, 0);
}

public void SelectColorMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_SelectColor);
    menu.SetTitle("Выберите цвет");
    menu.AddItem("red", "Красный");
    menu.AddItem("black", "Черный");
    menu.Display(client, 0);
}

public void SelectDozenMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_SelectDozen);
    menu.SetTitle("Выберите дюжину");
    menu.AddItem("dozen1", "1-12");
    menu.AddItem("dozen2", "13-24");
    menu.AddItem("dozen3", "25-36");
    menu.Display(client, 0);
}

public void SelectNumberMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_SelectNumber);
    menu.SetTitle("Выберите число");
    for (int i = 0; i <= 36; i++)
    {
        char num[4];
        IntToString(i, num, sizeof(num));
        menu.AddItem(num, num);
    }
    menu.Display(client, 0);
}

public void SelectColumnMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_SelectColumn);
    menu.SetTitle("Выберите колонну");
    menu.AddItem("col1", "Колонна 1");
    menu.AddItem("col2", "Колонна 2");
    menu.AddItem("col3", "Колонна 3");
    menu.Display(client, 0);
}

public void SelectRowMenu(int client)
{
    Menu menu = CreateMenu(MenuHandler_SelectRow);
    menu.SetTitle("Выберите строку");
    for (int i = 1; i <= 12; i++)
    {
        char num[4];
        IntToString(i, num, sizeof(num));
        menu.AddItem(num, num);
    }
    menu.Display(client, 0);
}

public int MenuHandler_Roulette(Menu menu, MenuAction action, int client, int param)
{
    if (action == MenuAction_End)
    {
        menu.Close();
    }
    else if (action == MenuAction_Select)
    {
        char selection[32];
        menu.GetItem(param, selection, sizeof(selection));

        if (StrEqual(selection, "color"))
        {
            SelectColorMenu(client);
        }
        else if (StrEqual(selection, "dozen"))
        {
            SelectDozenMenu(client);
        }
        else if (StrEqual(selection, "number"))
        {
            SelectNumberMenu(client);
        }
        else if (StrEqual(selection, "column"))
        {
            SelectColumnMenu(client);
        }
        else if (StrEqual(selection, "row"))
        {
            SelectRowMenu(client);
        }
    }
    return 0;
}

public Action Command_Bet(int client, int args)
{
    if (!IsClientInGame(client) || args < 1)
    {
        return Plugin_Handled;
    }

    if (!g_PlayerBetSelected[client])
    {
        PrintToChat(client, "Вы должны сначала выбрать категорию ставки. Введите /roul для выбора.");
        return Plugin_Handled;
    }

    char arg[32];
    GetCmdArg(1, arg, sizeof(arg));

    int bet = StringToInt(arg);
    int credits = Shop_GetClientCredits(client);

    if (bet <= 0 || bet > credits)
    {
        PrintToChat(client, "Некорректная ставка.");
        return Plugin_Handled;
    }

    g_PlayerBet[client] = bet;
    g_PlayerHasBet[client] = true;
    Shop_SetClientCredits(client, credits - bet);

    PrintToChatAll("Игрок %N поставил %d кредитов.", client, bet);

    return Plugin_Handled;
}


#define DEFINE_MENU_HANDLER(NAME, TYPE, VALUEFN)

public int MenuHandler_##NAME(Menu menu, MenuAction action, int client, int param)
{
	if (action == MenuAction_End)
	{
		menu.Close();
	}
	else if (action == MenuAction_Select)
	{
		g_PlayerBetType[client] = TYPE;
		char selection[32];
		menu.GetItem(param, selection, sizeof(selection));
		VALUEFN;
		g_PlayerBetSelected[client] = true;
		PrintToChat(client, "Введите свою ставку через !bet <сумма>");
	}
	return 0;
}

DEFINE_MENU_HANDLER(SelectColor, Bet_Color, g_PlayerBetValue[client] = StrEqual(selection, "red") ? 1 : 2)
DEFINE_MENU_HANDLER(SelectDozen, Bet_Dozen, g_PlayerBetValue[client] = param + 1)
DEFINE_MENU_HANDLER(SelectNumber, Bet_Number, g_PlayerBetValue[client] = StringToInt(selection))
DEFINE_MENU_HANDLER(SelectColumn, Bet_Column, g_PlayerBetValue[client] = param + 1)
DEFINE_MENU_HANDLER(SelectRow, Bet_Row, g_PlayerBetValue[client] = param + 1)

public Action Timer_RouletteEnd(Handle timer, any data)
{
    int result = GetRandomInt(0, 36);

    PrintToChatAll("Рулетка прокрутилась! Выпало число: %d", result);

    for (int i = 1; i <= MaxClients; i++)
    {
        if (g_PlayerHasBet[i])
        {
            bool won = false;
            int payout = 0;

            switch (g_PlayerBetType[i])
            {
                case Bet_Color:
                {
                    if ((g_PlayerBetValue[i] == 1 && IsRed(result)) ||
                        (g_PlayerBetValue[i] == 2 && !IsRed(result)))
                    {
                        won = true;
                        payout = 2 * g_PlayerBet[i];
                    }
                    break;
                }

                case Bet_Dozen:
                {
                    if (ResultMatchesDozen(result, g_PlayerBetValue[i]))
                    {
                        won = true;
                        payout = 3 * g_PlayerBet[i];
                    }
                    break;
                }

                case Bet_Number:
                {
                    if (result == g_PlayerBetValue[i])
                    {
                        won = true;
                        payout = 36 * g_PlayerBet[i];
                    }
                    break;
                }

                case Bet_Column:
                {
                    if (ResultMatchesColumn(result, g_PlayerBetValue[i]))
                    {
                        won = true;
                        payout = 3 * g_PlayerBet[i];
                    }
                    break;
                }

                case Bet_Row:
                {
                    if (ResultMatchesRow(result, g_PlayerBetValue[i]))
                    {
                        won = true;
                        payout = 3 * g_PlayerBet[i];
                    }
                    break;
                }
            }

            if (won)
            {
                PrintToChat(i, "Вы выиграли! Ваш выигрыш: %d кредитов.", payout);
                Shop_SetClientCredits(i, Shop_GetClientCredits(i) + payout);
            }
            else
            {
                PrintToChat(i, "Вы проиграли.");
            }

            g_PlayerHasBet[i] = false;
            g_PlayerBetSelected[i] = false;
            g_PlayerBet[i] = 0;
            g_PlayerBetType[i] = Bet_None;
            g_PlayerBetValue[i] = 0;
        }
    }

    return Plugin_Continue;
}

const int RED_NUMBERS_COUNT = 18;
int redNumbers[RED_NUMBERS_COUNT] =
    {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36};

bool IsRed(int number)
{
    for (int i = 0; i < RED_NUMBERS_COUNT; i++)
    {
        if (redNumbers[i] == number)
        {
            return true;
        }
    }
    return false;
}

bool ResultMatchesDozen(int result, int dozen)
{
    switch (dozen)
    {
        case 1:
            return result >= 1 && result <= 12;
        case 2:
            return result >= 13 && result <= 24;
        case 3:
            return result >= 25 && result <= 36;
        default:
            return false;
    }
}

bool ResultMatchesColumn(int result, int column)
{
    switch (column)
    {
        case 1:
            return (result % 3 == 1);
        case 2:
            return (result % 3 == 2);
        case 3:
            return (result % 3 == 0);
        default:
            return false;
    }
}

bool ResultMatchesRow(int result, int row)
{
    return ((result - 1) / 3) + 1 == row;
}