#include <shop>

#define PLUGIN_VERSION "1.6.1"

new g_iPlayerPot[MAXPLAYERS + 1], g_iPlayerTeam[MAXPLAYERS + 1], g_iUses[MAXPLAYERS + 1];

new Handle:g_hBettingPeriod = INVALID_HANDLE, g_iBettingPeriod,
	Handle:g_hBettingMinPl = INVALID_HANDLE, g_iBettingMinPl,
	Handle:g_hBettingMultiplier = INVALID_HANDLE, Float:g_fMultiplier,
	Handle:g_hBettingDead = INVALID_HANDLE, bool:g_bBettingDead,
	Handle:g_hMinBet = INVALID_HANDLE, g_iMinBet,
	Handle:g_hMaxBet = INVALID_HANDLE, g_iMaxBet,
	Handle:g_hPerRound = INVALID_HANDLE, g_iPerRound
	Handle:g_hEnableAdvert = INVALID_HANDLE, bool:g_bEnableAdvert, bool:g_bCanBet,
	Handle:g_mTeamMenu, Handle:g_mBetMenu, g_iBettingStart = 0,
	Handle:g_hBettingTeam = INVALID_HANDLE, bool:g_bBettingTeam;

public Plugin:myinfo = 
{
	name = "[Shop] Betting",
	description = "Players can create bet",
	author = "White Wolf (HLModders LLC)",
	version = PLUGIN_VERSION,
	url = "http://hlmod.ru http://tibari.ru"
};

public OnPluginStart()
{
	// Plugin version
	CreateConVar("sm_shop_bet_version", PLUGIN_VERSION, _, FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY);
	
	g_hBettingPeriod = CreateConVar("sm_shop_bet_period", "15", "How many seconds betting should be enabled after round start", FCVAR_PLUGIN, true, 0.0);
	g_iBettingPeriod = GetConVarInt(g_hBettingPeriod);
	HookConVarChange(g_hBettingPeriod, OnCvarChange);
	g_hBettingMinPl = CreateConVar("sm_shop_bet_minpl", "8", "Minimal count of players needed to run betting", FCVAR_PLUGIN, true, 0.0);
	g_iBettingMinPl = GetConVarInt(g_hBettingMinPl);
	HookConVarChange(g_hBettingMinPl, OnCvarChange);
	g_hBettingMultiplier = CreateConVar("sm_shop_bet_multiplier", "1.6", "Multiplier for winner (if 1.0 then player will give him bet credits back)", FCVAR_PLUGIN, true, 1.0);
	g_fMultiplier = GetConVarFloat(g_hBettingMultiplier);
	HookConVarChange(g_hBettingMultiplier, OnCvarChange);
	g_hBettingDead = CreateConVar("sm_shop_bet_dead", "0", "Only dead players can use bet?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
	g_bBettingDead = GetConVarBool(g_hBettingDead);
	HookConVarChange(g_hBettingDead, OnCvarChange);
	g_hMinBet = CreateConVar("sm_shop_bet_minbet", "100", "Minimal required bet", FCVAR_PLUGIN, true, 0.0);
	g_iMinBet = GetConVarInt(g_hMinBet);
	HookConVarChange(g_hMinBet, OnCvarChange);
	g_hMaxBet = CreateConVar("sm_shop_bet_maxbet", "300", "Maxmimum allowed bet", FCVAR_PLUGIN, true, 0.0);
	g_iMaxBet = GetConVarInt(g_hMaxBet);
	HookConVarChange(g_hMaxBet, OnCvarChange);
	g_hPerRound = CreateConVar("sm_shop_bet_per_round", "1", "Allowed bet per round. 0 - unlim", FCVAR_PLUGIN, true, 0.0);
	g_iPerRound = GetConVarInt(g_hPerRound);
	HookConVarChange(g_hPerRound, OnCvarChange);
	g_hEnableAdvert = CreateConVar("sm_shop_bet_advert", "1", "Show advert of plugin use on round start?", FCVAR_PLUGIN, true, 0.0, true, 1.0);
	g_bEnableAdvert = GetConVarBool(g_hEnableAdvert);
	HookConVarChange(g_hEnableAdvert, OnCvarChange);
	g_hBettingTeam = CreateConVar("sm_shop_bet_team", "1", "Запретить делать ставки на свою команду? [1 - да; 0 - нет]", FCVAR_PLUGIN, true, 0.0, true, 1.0); 
	g_bBettingTeam = GetConVarBool(g_hBettingTeam);
	HookConVarChange(g_hBettingTeam, OnCvarChange);
	
	RegConsoleCmd("sm_sbet", Command_Bet, "Take a bet for a team");
	RegAdminCmd("sm_cbet", Command_CBet, ADMFLAG_RCON, "Change multiplier for bet");
	
	HookEvent("round_start", Event_OnRoundStart, EventHookMode_PostNoCopy);
	HookEvent("round_end", Event_OnRoundEnd, EventHookMode_PostNoCopy);
	
	AutoExecConfig(true, "shop_betting", "shop");
	
	if (Shop_IsStarted()) Shop_Started();
	
	MenuInitializator();
}

public OnCvarChange(Handle:cvar, const String:sOldValue[], const String:sNewValue[])
{
	if (cvar == g_hBettingPeriod) g_iBettingPeriod = StringToInt(sNewValue);
	else if (cvar == g_hBettingMinPl) g_iBettingMinPl = StringToInt(sNewValue);
	else if (cvar == g_hBettingMultiplier) g_fMultiplier = StringToFloat(sNewValue);
	else if (cvar == g_hBettingDead) g_bBettingDead = bool:(StringToInt(sNewValue));
	else if (cvar == g_hMinBet) g_iMinBet = StringToInt(sNewValue);
	else if (cvar == g_hMaxBet) g_iMaxBet = StringToInt(sNewValue);
	else if (cvar == g_hPerRound) g_iPerRound = StringToInt(sNewValue);
	else if (cvar == g_hEnableAdvert) g_bEnableAdvert = bool:(StringToInt(sNewValue));
	else if (cvar == g_hBettingTeam) g_bBettingTeam = bool:(StringToInt(sNewValue));
}

public OnClientDisconnect(client)
{
	if (g_iPlayerPot[client])
	{
		Shop_GiveClientCredits(client, g_iPlayerPot[client]);
		g_iPlayerPot[g_iPlayerTeam[g_iUses[client]]] = 0;
		// PrintToChatAll("\x01[\x03Shop|Bet\x01] %N Покинул сервер и отменил свою ставку", client);
	}
}

public Shop_Started()
{
	Shop_AddToFunctionsMenu(FuncDisplay, FuncSelect);
}

public FuncDisplay(client, String:buffer[], maxlen)
{
	strcopy(buffer, maxlen, "Сделать ставку");
}

public bool:FuncSelect(client)
{
	if (!g_bCanBet)
	{
		PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете сделать ставку");
		Shop_ShowFunctionsMenu(client); // Вернем игрока в главное меню ф-ций.
	}
	else if (GetClientCount() < g_iBettingMinPl)
	{
		PrintToChat(client, "\x01[\x03Shop|Bet\x01] Недостаточно игроков, нужно %d", g_iBettingMinPl);
		Shop_ShowFunctionsMenu(client); // Вернем игрока в главное меню ф-ций.
	}
	else if (g_iBettingPeriod && g_iBettingStart+g_iBettingPeriod < GetTime())
	{
		PrintToChat(client, "\x01[\x03Shop|Bet\x01] Период ставок истёк");
		Shop_ShowFunctionsMenu(client); // Вернем игрока в главное меню ф-ций.
	}
	else if (g_iPerRound && g_iUses[client] >= g_iPerRound)
	{
		PrintToChat(client, "\x01[\x03Shop|Bet\x01] Превышено максимальное кол-во ставок на раунд (%d)", g_iPerRound);
		Shop_ShowFunctionsMenu(client); // Вернем игрока в главное меню ф-ций.
	}
	else if (g_bBettingDead)
	{
		if (IsPlayerAlive(client))
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы должны быть мертвы чтобы делать ставки.");
			Shop_ShowFunctionsMenu(client); // Вернем игрока в главное меню ф-ций.
		} else DisplayMenu(g_mTeamMenu, client, 20);
	} else DisplayMenu(g_mTeamMenu, client, 20);
	
	return true;
}

MenuInitializator()
{
	g_mTeamMenu = CreateMenu(g_mTeamMenuHandler);
	SetMenuTitle(g_mTeamMenu, "Выберите команду:\n\n");
	AddMenuItem(g_mTeamMenu, "t", "Террористы");
	AddMenuItem(g_mTeamMenu, "ct", "Контр-Террористы");
	AddMenuItem(g_mTeamMenu, "", "", ITEMDRAW_SPACER);
	AddMenuItem(g_mTeamMenu, "curbet", "Текущая ставка");
	AddMenuItem(g_mTeamMenu, "cancel", "Отменить ставку");
	SetMenuExitBackButton(g_mTeamMenu, false);
	
	g_mBetMenu = CreateMenu(g_mBetMenuHandler);
	SetMenuTitle(g_mBetMenu, "Сколько поставить:\n\n");
	AddMenuItem(g_mBetMenu, "100", "100");
	AddMenuItem(g_mBetMenu, "200", "200");
	AddMenuItem(g_mBetMenu, "300", "300");
	AddMenuItem(g_mBetMenu, "500", "500");
	AddMenuItem(g_mBetMenu, "1000", "1000");
	SetMenuExitBackButton(g_mBetMenu, false);
}

public g_mTeamMenuHandler(Handle:menu, MenuAction:action, client, slot)
{
	switch (action)
	{
		case MenuAction_Select:
		{
			if (!slot)
			{
				g_iPlayerTeam[client] = 2;
				
				if (GetClientTeam(client) == 2 && g_iPlayerTeam[client] == 2) {
					PrintToChat(client, "\x01[\x03Shop|Bet\x01] Нельзя делать ставку на свою команду.");
					Shop_ShowFunctionsMenu(client);
					return;
				} else DisplayMenu(g_mBetMenu, client, 20);
			}
			switch (slot)
			{
				case 1:
				{
					g_iPlayerTeam[client] = 3;
					
					if (GetClientTeam(client) == 3 && g_iPlayerTeam[client] == 3) {
						PrintToChat(client, "\x01[\x03Shop|Bet\x01] Нельзя делать ставку на свою команду.");
						Shop_ShowFunctionsMenu(client);
						return;
					} else DisplayMenu(g_mBetMenu, client, 20);
				}
				
				case 3:
				{
					if (g_iPlayerPot[client])
					{
						switch (g_iPlayerTeam[client])
						{
							case 2: PrintToChat(client, "\x01[\x03Shop|Bet\x01] Команда за которую вы отдали ставку: Террористы");
							case 3: PrintToChat(client, "\x01[\x03Shop|Bet\x01] Команда за которую вы отдали ставку: Контр-Террористы");
						}
					} else PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не делали ставку.");
					Shop_ShowFunctionsMenu(client); // Вернем игрока в меню ф-ций
				}
				
				case 4:
				{
					if (g_iPlayerPot[client])
					{
						Shop_GiveClientCredits(client, g_iPlayerPot[client]);
						g_iPlayerPot[g_iPlayerTeam[client]] = 0;
						PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы отменили свою ставку");
					} else PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете отменить ставку которой нет");
					Shop_ShowFunctionsMenu(client); // Вернем игрока в меню ф-ций
				}
			}
		}
	}
}

public g_mBetMenuHandler(Handle:menu, MenuAction:action, client, slot)
{
	switch (action)
	{
		case MenuAction_Cancel:
		{
			if (!g_iPlayerPot[client]) g_iPlayerTeam[client] = 0;
		}
		case MenuAction_Select:
		{
			decl String:infoBuf[8], String:sTeam[16];
			GetMenuItem(menu, slot, infoBuf, sizeof(infoBuf));
			new bet = StringToInt(infoBuf);
			new hascredits = Shop_GetClientCredits(client);
			if (bet < g_iMinBet)
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить меньше чем %d кр, ваша ставка: %d. Ставка не засчитана.", g_iMinBet, bet);
				Shop_ShowFunctionsMenu(client);
			}
			else if (bet > g_iMaxBet || g_iPlayerPot[client] > g_iMaxBet)
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить больше чем %d кр, ваша ставка: %d. Ставка не засчитана (ограничение сервера).", g_iMaxBet, bet);
				Shop_ShowFunctionsMenu(client);
			}
			else if (bet < hascredits)
			{
				g_iPlayerPot[client] += bet;
				
				switch (g_iPlayerTeam[client])
				{
					case 3: strcopy(sTeam, sizeof(sTeam), "Контров");
					case 2: strcopy(sTeam, sizeof(sTeam), "Терров");
				}
				
				PrintToChatAll("\x01[\x03Shop|Bet\x01] \x04%N \x01 поставил \x04%d кр. \x01на команду \x04%s", client, bet, sTeam);
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Ваша ставка составляет %d кр.", g_iPlayerPot[client]);
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы сделали ставку на команду \x04%s", sTeam);
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] В случае успеха ваш выигрыш составит \x03%d \x01кр.", RoundToCeil(g_iPlayerPot[client] * g_fMultiplier));
				Shop_TakeClientCredits(client, bet);
				g_iUses[client]++;
				
				Shop_ShowFunctionsMenu(client);
			}
			else
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] У вас недостаточно кредитов (%d)", hascredits);
				
				if (!g_iPlayerPot[client]) g_iPlayerTeam[client] = 0;
				Shop_ShowFunctionsMenu(client);
			}
		}
	}
}

public OnPluginEnd()
{
	Shop_RemoveFromFunctionsMenu(FuncDisplay, FuncSelect);
	Shop_UnregisterMe();
}

public Action:Command_CBet(client, args)
{
	if (client && IsClientInGame(client))
	{
		if (Flood(client)) return Plugin_Handled;
		else if (args != 1)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] sm_cbet <count|1.0 - def>");
			return Plugin_Handled;
		}
		
		decl String:sAmount[4];
		GetCmdArg(1, sAmount, sizeof(sAmount));
		new Float:multiplier = StringToFloat(sAmount);
		
		if (multiplier > 0.0)
		{
			g_fMultiplier = multiplier;
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Новый коэфициент для ставок установлен. (%.1f)", multiplier);
		}
		
		return Plugin_Handled;
	}
	
	return Plugin_Handled;
}

public Action:Command_Bet(client, args)
{
	if (client && IsClientInGame(client))
	{
		if (!g_bCanBet) return Plugin_Handled;
		else if (g_bBettingDead)
		{
			if (IsPlayerAlive(client))
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы должны быть мертвы чтобы делать ставки.");
				return Plugin_Handled;
			}
		}
		if (GetClientCount() < g_iBettingMinPl)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Недостаточно игроков, нужно %d", g_iBettingMinPl);
			return Plugin_Handled;
		}
		else if (g_iBettingPeriod && g_iBettingStart+g_iBettingPeriod < GetTime())
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Период ставок истёк");
			return Plugin_Handled;
		}
		else if (g_iPerRound && g_iUses[client] >= g_iPerRound)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Превышено максимальное кол-во ставок на раунд (%d)", g_iPerRound);
			return Plugin_Handled;
		}
		else if (Flood(client)) return Plugin_Handled;
		else if (args != 2)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] sm_sbet <t/ct> <bet/all/cancel>");
			return Plugin_Handled;
		}
		
		decl String:sTeam[16], String:sAmount[8];
		GetCmdArg(1, sTeam, sizeof(sTeam));
		GetCmdArg(2, sAmount, sizeof(sAmount));
		
		if (strcmp(sTeam, "t", true) || strcmp(sTeam, "т", true))
		{
			g_iPlayerTeam[client] = 2;
			
			if (GetClientTeam(client) == 2 && g_iPlayerTeam[client] == 2) {
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Нельзя делать ставку на свою команду.");
				return Plugin_Handled;
			} else strcopy(sTeam, sizeof(sTeam), "Терров");
		}
		else if (strcmp(sTeam, "ct", true) || strcmp(sTeam, "кт", true))
		{
			g_iPlayerTeam[client] = 3;
			
			if (GetClientTeam(client) == 3 && g_iPlayerTeam[client] == 3) {
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Нельзя делать ставку на свою команду.");
				return Plugin_Handled;
			} else strcopy(sTeam, sizeof(sTeam), "Контров");
		}
		else
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Неверная команда");
			return Plugin_Handled;
		}
		
		new hascredits = Shop_GetClientCredits(client);
		new credits = StringToInt(sAmount);
		if (strcmp(sAmount, "all", true))
		{
			if (hascredits < g_iMinBet)
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить меньше чем %d кр, ваша ставка: %d. Ставка не засчитана.", g_iMinBet, hascredits);
				Shop_ShowFunctionsMenu(client);
				return Plugin_Handled;
			}
			else if (hascredits > g_iMaxBet || g_iPlayerPot[client] > g_iMaxBet)
			{
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить больше чем %d кр, ваша ставка: %d. Ставка не засчитана (ограничение сервера).", g_iMaxBet, hascredits);
				Shop_ShowFunctionsMenu(client);
				return Plugin_Handled;
			}
			g_iPlayerPot[client] = hascredits;
			PrintToChatAll("\x01[\x03Shop|Bet\x01] \x04%N \x01поставил все свои кредиты (%d кр) на команду \x04%s", client, hascredits, sTeam);
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Ваша ставка составляет %d кр.", g_iPlayerPot[client]);
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] В случае успеха ваш выигрыш составит \x03%d \x01кр.", RoundToCeil(g_iPlayerPot[client] * g_fMultiplier));
			Shop_SetClientCredits(client, 0);
			g_iUses[client]++;
		}
		else if (strcmp(sAmount, "cancel", true))
		{
			if (g_iPlayerPot[client])
			{
				Shop_GiveClientCredits(client, g_iPlayerPot[client]);
				g_iPlayerPot[g_iPlayerTeam[client]] = 0;
				PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы отменили свою ставку");
			}
			else PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете отменить ставку которой нет");
		}
		else if (credits < 1) PrintToChat(client, "\x01[\x03Shop|Bet\x01] Неверное количество кредитов.");
		else if (credits < g_iMinBet)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить меньше чем \x04%d\x01 кр,\nваша ставка: \x04%d\x01 кр. Ставка не засчитана.", g_iMinBet, credits);
			Shop_ShowFunctionsMenu(client);
		}
		else if (credits > g_iMaxBet || g_iPlayerPot[client] > g_iMaxBet)
		{
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Вы не можете поставить больше чем %d кр, ваша ставка: %d. Ставка не засчитана (ограничение сервера).", g_iMaxBet, credits);
			Shop_ShowFunctionsMenu(client);
		}
		else if (credits < hascredits)
		{
			g_iPlayerPot[client] += credits;
			PrintToChatAll("\x01[\x03Shop|Bet\x01] \x04%N \x01 поставил \x04%d кр. \x01на команду \x04%s", client, credits, sTeam);
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] Ваша ставка составляет %d кр.", g_iPlayerPot[client]);
			PrintToChat(client, "\x01[\x03Shop|Bet\x01] В случае успеха ваш выигрыш составит \x03%d \x01кр.", RoundToCeil(g_iPlayerPot[client] * g_fMultiplier));
			Shop_TakeClientCredits(client, credits);
			g_iUses[client]++;
		}
		else PrintToChat(client, "\x01[\x03Shop|Bet\x01] У вас недостаточно кредитов")
		
		return Plugin_Handled;
	}
	return Plugin_Handled;
}

public Event_OnRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
	g_bCanBet = true;
	g_iBettingStart = GetTime();
	for (new i = 1; i <= MaxClients; i++) g_iPlayerPot[g_iPlayerTeam[g_iUses[i]]] = 0;
	
	if (g_bEnableAdvert && GetClientCount() < g_iBettingMinPl)
	{
		PrintToChatAll("\x01[\x03Shop|Bet\x01] На сервере работают \x03ставки на кредиты\x01.");
		PrintToChatAll("\x01[\x03Shop|Bet\x01] Сделать ставку: \x04!sbet \x01или \x04/sbet \x01в чате.");
	}
}

public Event_OnRoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
	g_bCanBet = false;
	new iWinnerTeam = GetEventInt(event, "winner");
	for (new i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i) && g_iPlayerPot[i])
		{
			if (iWinnerTeam < 2)
			{
				Shop_GiveClientCredits(i, g_iPlayerPot[i]);
				g_iPlayerPot[g_iPlayerTeam[g_iUses[i]]] = 0;
			}
			else
			{
				if (g_iPlayerTeam[i] != iWinnerTeam) PrintToChat(i, "\x01[\x03Shop|Bet\x01] Вы проиграли \x03%d кр. \x01в ставках", g_iPlayerPot[i]);
				else
				{
					g_iPlayerPot[i] = RoundToCeil(g_iPlayerPot[i] * g_fMultiplier);
					Shop_GiveClientCredits(i, g_iPlayerPot[i]);
					PrintToChat(i, "\x01[\x03Shop|Bet\x01] Вы выйграли \x03%d кр. \x01за победившую команду", g_iPlayerPot[i]);
				}
			}
		}
	}
}

//ANTI-FLOOD
bool:Flood(client)
{
	static last_time[MAXPLAYERS + 1], curr_time, time;
	curr_time = GetTime();
	time = curr_time - last_time[client];
	if (time < 3)
	{
		PrintToChat(client, "\x01[\x03Shop|Bet\x01] Не флуди командой! Подожди %d с.", 3 - time);
		return true;
	}
	last_time[client] = curr_time;
	return false;
}