#pragma semicolon 1

#include <sourcemod>
#include <sdktools>
#include <zombiereloaded>
#include <cstrike>
#include <multicolors>

int g_iHighRatio;
int g_iMediumRatio;
int g_iLowRatio;

int g_iHighStreak;
int g_iMediumStreak;
int g_iLowStreak;

int g_iHumanScore;
int g_iZombieScore;
int g_iOldZombieScore;

float g_fKnockbackLowBoost;
float g_fKnockbackMediumBoost;
float g_fKnockbackHighBoost;

float g_fNapalmLowReduction;
float g_fNapalmMediumReduction;
float g_fNapalmHighReduction;

int g_iZombieStreak;

bool g_bLowPopulation;
int g_iMaxPopulation;
float g_fKnockbackPopulationBoost;
float g_fNapalmPopulationReduction;

bool g_bAntiNoob;
char g_cAntiNoobHelp[64];
char g_cAntiNoobPopulation[32];

public Plugin myinfo =
{
	name = "AntiNoob",
	author = "Dogan",
	description = "Provide help when the server is doing bad on a map",
	version = "3.0.0",
	url = ""
}

public void OnPluginStart()
{
	HookEvent("round_start", OnRoundStart);

	ConVar cvar;
	HookConVarChange((cvar = CreateConVar("sm_an_help", "1", "1 = AntiNoob performs help, 0 = AntiNoob is disabled", FCVAR_NONE, true, 0.0, true, 1.0)), g_cvAntiNoob);
	g_bAntiNoob = cvar.BoolValue;
	HookConVarChange((cvar = CreateConVar("sm_an_maxplayers", "40", "max active players until the kb should be increased")), g_cvMaxPopulation);
	g_iMaxPopulation = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_kb_population", "5.0", "knockback boost during low population in procent (stacks with the helps)")), g_cvKnockbackPopulationBoost);
	g_fKnockbackPopulationBoost = cvar.FloatValue / 100.0;
	HookConVarChange((cvar = CreateConVar("sm_an_napalm_population", "2.0", "napalm damage reduction needed during low population for full burn from nades (stacks with the helps)")), g_cvNapalmPopulationReduction);
	g_fNapalmPopulationReduction = cvar.FloatValue;
	HookConVarChange((cvar = CreateConVar("sm_an_lowratio", "3", "human:zombie ratio to perform low help")), g_cvLowRatio);
	g_iLowRatio = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_mediumratio", "5", "human:zombie ratio to perform medium help")), g_cvMediumRatio);
	g_iMediumRatio = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_highratio", "7", "human:zombie ratio to perform high help")), g_cvHighRatio);
	g_iHighRatio = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_lowstreak", "2", "zombie win streaks to perfom low help")), g_cvLowStreak);
	g_iLowStreak = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_mediumstreak", "4", "zombie win streaks to perfom medium help")), g_cvMediumStreak);
	g_iMediumStreak = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_highstreak", "6", "zombie win streaks to perfom high help")), g_cvHighStreak);
	g_iHighStreak = cvar.IntValue;
	HookConVarChange((cvar = CreateConVar("sm_an_kb_lowhelp", "5.0", "knockback boost in procent when low help is performed (stacks with low population boost)")), g_cvKnockbackLowBoost);
	g_fKnockbackLowBoost = cvar.FloatValue / 100.0;
	HookConVarChange((cvar = CreateConVar("sm_an_kb_mediumhelp", "10.0", "knockback boost in procent when medium help is performed (stacks with low population boost)")), g_cvKnockbackMediumBoost);
	g_fKnockbackMediumBoost = cvar.FloatValue / 100.0;
	HookConVarChange((cvar = CreateConVar("sm_an_kb_highhelp", "15.0", "knockback boost in procent when high help is performed (stacks with low population boost)")), g_cvKnockbackHighBoost);
	g_fKnockbackHighBoost = cvar.FloatValue / 100.0;
	HookConVarChange((cvar = CreateConVar("sm_an_napalm_lowhelp", "2.0", "napalm damage reduction needed when low help is perfomed for full burn from nades (stacks with low population reduction)")), g_cvNapalmLowReduction);
	g_fNapalmLowReduction = cvar.FloatValue;
	HookConVarChange((cvar = CreateConVar("sm_an_napalm_mediumhelp", "4.0", "napalm damage reduction needed when medium help is performed for full burn from nades (stacks with low population reduction)")), g_cvNapalmMediumReduction);
	g_fNapalmMediumReduction = cvar.FloatValue;
	HookConVarChange((cvar = CreateConVar("sm_an_napalm_highhelp", "6.0", "napalm damage reduction needed when high help is perfomed for full burn from nades (stacks with low population reduction)")), g_cvNapalmHighReduction);
	g_fNapalmHighReduction = cvar.FloatValue;
	delete cvar;

	g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Plugin still loading";
	g_cAntiNoobPopulation = "{white}.";

	RegAdminCmd("sm_antinoob", Command_AntiNoob, ADMFLAG_RCON, "returns the current helps or boosts for this round");

	AutoExecConfig(true, "plugin.AntiNoob");
}

public void g_cvAntiNoob(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_bAntiNoob = convar.BoolValue;
}

public void g_cvMaxPopulation(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iMaxPopulation = convar.IntValue;
}

public void g_cvKnockbackPopulationBoost(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fKnockbackPopulationBoost = convar.FloatValue / 100.0;
}

public void g_cvNapalmPopulationReduction(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fNapalmPopulationReduction = convar.FloatValue;
}

public void g_cvLowRatio(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iLowRatio = convar.IntValue;
}

public void g_cvMediumRatio(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iMediumRatio = convar.IntValue;
}

public void g_cvHighRatio(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iHighRatio = convar.IntValue;
}

public void g_cvLowStreak(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iLowStreak = convar.IntValue;
}

public void g_cvMediumStreak(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iMediumStreak = convar.IntValue;
}

public void g_cvHighStreak(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_iHighStreak = convar.IntValue;
}

public void g_cvKnockbackLowBoost(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fKnockbackLowBoost = convar.FloatValue / 100.0;
}

public void g_cvKnockbackMediumBoost(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fKnockbackMediumBoost = convar.FloatValue / 100.0;
}

public void g_cvKnockbackHighBoost(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fKnockbackHighBoost = convar.FloatValue / 100.0;
}

public void g_cvNapalmLowReduction(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fNapalmLowReduction = convar.FloatValue;
}

public void g_cvNapalmMediumReduction(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fNapalmMediumReduction = convar.FloatValue;
}

public void g_cvNapalmHighReduction(ConVar convar, const char[] oldValue, const char[] newValue)
{
	g_fNapalmHighReduction = convar.FloatValue;
}

public void OnMapStart()
{
	g_iHumanScore = 1;
	g_iZombieScore = 0;
	g_iOldZombieScore = 0;
	g_iZombieStreak = 0;
}

public Action Command_AntiNoob(int client, int args)
{
	CPrintToChat(client, "%s%s", g_cAntiNoobHelp, g_cAntiNoobPopulation);

	return Plugin_Handled;
}

public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
{
	g_iHumanScore = GetTeamScore(CS_TEAM_CT);
	g_iZombieScore = GetTeamScore(CS_TEAM_T);

	if(g_iHumanScore == 0)
	{
		g_iHumanScore = 1;
	}

	if(g_iZombieScore != g_iOldZombieScore)
	{
		g_iZombieStreak++;
		g_iOldZombieScore++;
	}
	else
	{
		g_iZombieStreak = 0;
	}

	int ActivePlayers;

	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) >= CS_TEAM_T)
		{
			ActivePlayers++;
		}
	}

	if(!g_bAntiNoob)
	{
		g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Currently disabled";
		g_cAntiNoobPopulation = "{white}.";
		PerformReset();
		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsRootAdmin(i))
				CPrintToChat(i,"%s%s", g_cAntiNoobHelp, g_cAntiNoobPopulation);
		}

		return;
	}

	if(ActivePlayers <= g_iMaxPopulation)
	{
		g_bLowPopulation = true;
		g_cAntiNoobPopulation = "{white} + Low Population Boost.";
	}
	else
	{
		g_bLowPopulation = false;
		g_cAntiNoobPopulation = "{white}.";
	}

	if(g_iZombieScore / g_iHumanScore >= g_iHighRatio || g_iZombieStreak >= g_iHighStreak)
	{
		g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Currently perfoming High Help";
		PerformHighHelp();
	}
	else if(g_iZombieScore / g_iHumanScore >= g_iMediumRatio || g_iZombieStreak >= g_iMediumStreak)
	{
		g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Currently perfoming Medium Help";
		PerformMediumHelp();
	}
	else if(g_iZombieScore / g_iHumanScore >= g_iLowRatio || g_iZombieStreak >= g_iLowStreak)
	{
		g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Currently perfoming Low Help";
		PerformLowHelp();
	}
	else
	{
		g_cAntiNoobHelp = "{cyan}[AntiNoob]{white} Currently perfoming No Help";
		PerformReset();
	}

	for(int i = 1; i <= MaxClients; i++)
	{
		if(IsRootAdmin(i))
			CPrintToChat(i,"%s%s", g_cAntiNoobHelp, g_cAntiNoobPopulation);
	}
}

public void PerformHighHelp()
{
	if(g_bLowPopulation)
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackHighBoost + g_fKnockbackPopulationBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmHighReduction - g_fNapalmPopulationReduction);
	}
	else
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackHighBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmHighReduction);
	}
}

public void PerformMediumHelp()
{
	if(g_bLowPopulation)
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackMediumBoost + g_fKnockbackPopulationBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmMediumReduction - g_fNapalmPopulationReduction);
	}
	else
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackMediumBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmMediumReduction);
	}
}

public void PerformLowHelp()
{
	if(g_bLowPopulation)
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackLowBoost + g_fKnockbackPopulationBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmLowReduction - g_fNapalmPopulationReduction);
	}
	else
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackLowBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmLowReduction);
	}
}

public void PerformReset()
{
	if(g_bLowPopulation && g_bAntiNoob)
	{
		ServerCommand("zr_class_set_multiplier zombies knockback %f", 1.0 + g_fKnockbackPopulationBoost);
		ServerCommand("zr_napalm_time_scale %f", 50.0 - g_fNapalmPopulationReduction);
	}
	else
	{
		ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
		ServerCommand("zr_napalm_time_scale 50.0");
	}
}

static stock bool IsRootAdmin(int client)
{
	if (client > 0 && client <= MaxClients && IsClientInGame(client) && CheckCommandAccess(client, "", ADMFLAG_RCON))
		return true;
	else
		return false;
}