////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					     Ultra Hide-N-Seek
//						by Exolent
// =================================================================================================
//	
//	Descripiton:
//		
//		This is mod where the Terrorists must avoid being killed by the Counter-Terrorists.
//		After the hide timer is over, the Terrorist team must run and do whatever is possible
//			to avoid being killed.
//		If the Counter-Terrorist team wins the round, the teams switch.
//		A scrim mod is also included. The types are "Point System" and "Round Wins".
//		
//		Point System:
//			
//			The opposing teams play 5 rounds on each team, 10 total.
//			The winner is based on which team has the most points by the end of the scrim.
//			To receive points, you can:
//				Kill: 1 point + 1 extra point if headshot (points are negative if TK)
//				Suicide: -1 point
//				Round Win: 2 points
//			If both teams have the same points by the end of the scrim, then the teams have
//				have 1 round on each team until a winner is chosen.
//		
//		Round Wins:
//			
//			The Terrorist team must win X rounds in a row to win the scrim.
//				X = cvar number for round wins (hns_scrimwins)
//			If the Counter-Terrorist team wins a round before the Terrorist team reach the
//				minumum amount to win the scrim, the teams switch and the round count resets.
//	
//	
//	Features:
//		
//		2 Different scrim mods
//		Removes footsteps from Terrorists (Changeable by cvar)
//		Anti-boosting (Changeable by cvar)
//		Removes bomb, hostages, rescue points, bomb sites, vents, glass, doors, etc.
//		Uses timer sounds ("two", "one") during the hide countdown.
//		Blocks the use of buying.
//		During scrims, teammates can use alltalk in voicecomm to each other, and not to the other team.
//	
//	
//	Client Say Commands:	
//		
//		/hnshelp -- Displays an motd of what this mod is about.
//		/scrimhelp -- Displays an motd of how scrims work.
//		/scores -- Displays scores during a scrim.
//		/wins -- Same as /scores.
//		/rounds -- Displays the number of rounds left in the scrim.
//		/team -- Displays the current team the player is on in the scrim.
//	
//	
//	Admin Say Commands:
//		
//		/hns -- Toggles the Hide-N-Seek mod.
//		/scrim -- Toggles the scrim mod.
//		/captains -- Displays two random people to be captains of the scrim (for pug scrims)
//	
//	
//	Admin Console Commands:	
//		
//		hns_on <1|0> -- Turns On/Off Hide-N-Seek mod.
//		hns_scrim <1|0> -- Turns On/Off scrim mod.
//		hns_scrimtype <1|2> -- 1 for point system, 2 for round wins
//		hns_scrimvote -- Starts a vote for what scrim type the people want.
//	
//	
//	Cvar Description:
//		
//		hns_pluginon <1|0> -- Determines if the Hide-N-Seek mod is on or off. (Default: 1)
//		hns_gametype <name> -- Gametype for the server (Default: Hide-N-Seek)
//		hns_scrimvoice <1|0> -- Allows alltalk among teammates during scrims. (Default: 1)
//		hns_hudcolor <rrr> <ggg> <bbb> -- RGB color code for the hud message + blind color (Default: 255 75 255)
//		hns_timersounds <1|0> -- Allows the use of countdown sounds when hide timer is below or equal to 10 (Default: 1)
//		hns_scrimwins <N> -- Number of rounds the Terrorist team must win to win the scrim during a "Round Wins" scrim (Default: 3)
//		hns_blockboosting <1|0> -- Allows boosting (a player jumping on a teammate) to be blocked. (players will be punished) (Default: 1)
//		hns_hidetime <N> -- Number of seconds the Terrorist team has until the Counter-Terrorist team can start seeking. (Default: 10)
//		hns_money <N> -- Amount of money each player will always have (Default: 0)
//		hns_helpmsg <1|0> -- Allows the help messages to be shown (Type /hnshelp...) (Default: 1)
//		hns_killpoints <N> -- Points given to a team for a kill during a point system scrim (Default: 1)
//		hns_headshotpoints <N> -- Points given to the kill/suicide score when kill was a headshot (Default: 1)
//		hns_suicidepoints <N> -- Points subtracted from the suicider's team's points during a point system scrim (Default: 1)
//		hns_roundpoints <N> -- Points given to the team that wins the round during a point system scrim (Default: 2)
//		hns_tarmor <N> -- Amount of armor given to the Terrorist team at the start of the round (Default: 75)
//		hns_ctarmor <N> -- Amount of armor given to the CT team at the start of the round (Default: 100)
//		hns_forcewinner <1|0> -- Forces winner in the event of a draw during a point system csrim (allows more rounds) (Default: 1)
//		hns_blindcolors <0|1|2|3> -- Colors on the Counter-Terrorist team during the hide time -- 0 = black; 1 = darker hns_hudcolor; 2 = rainbow colors; 3 = random colors (Default: 1)
//		hns_footsteps <0|1> -- Removes the footsteps from the Terrorist team when 1 (Default: 1)
//		hns_flashbangs <N> -- Number of flashbangs a Terrorist will be given after the hide timer is over (Default: 2)
//		hns_hegrenade <N> -- Number of he grenades a Terrorist will be given after the hide timer is over (Default: 1)
//		hns_smokegrenade <N> -- Number of smoke grenades a Terrorist will be given after the hide timer is over (Default: 1)
//		hns_tknife <1|0> -- Gives Terrorists a knife for the round -- Prevents 240 maxspeed when not holding anything (Default: 1)
//		
//	
//	
//	Changelog:
//		
//		Version 1.0
//		- Initial Release
//		
//		Version 1.1
//		- Added hns_money cvar
//		- Changed hns_gametype cvar to be the actual gametype
//		- Fixed few bugs
//		- Changed the "task_GiveWeapons" task to execute when the hide timer ends
//		- Put the knife giving task into another task so Terrorists will have an item when hiding
//		- Put the scores into separate arrays for later use
//		
//		Version 1.2
//		- Changed all message to emessage_begin, ewrite_byte, etc.
//		- Added hns_helpmsg cvar
//		- Added hns_killpoints cvar
//		- Added hns_headshotpoints cvar
//		- Added hns_suicidepoints cvar
//		- Added hns_roundpoints cvar
//		- Added hns_tarmor cvar
//		- Added hns_ctarmor cvar
//		- Added hns_forcewinner cvar
//		- Added hns_blindcolors cvar
//		- Added hns_footsteps cvar
//		- Added hns_flashbangs cvar
//		- Added hns_hegrenade cvar
//		- Added hns_smokegrenade cvar
//		- Added hns_tknife cvar
//		- Put scores back into single integer
//		- Fixed bug that wouldnt allow a winner in a point system scrim
//		- Fixed buying bug
//		- Fixed check model bug
//		
//		Version 1.3
//		- Fixed small bug about knife giving
//		
//		Version 1.4
//		- Changed the 'TeamInfo' message back to message_begin() style natives
//		- Added hostage outside of the map to remove the slaying of CT team, which forced the round to end
//		- Fixed a few mistakes
//	
//	
//	Credits*:
//	
//		OneEyed
//		-- for the original Hide-N-Seek plugin
//		
//		VEN
//		-- for the No Objectives plugin
//		-- for the No Weapon Drop plugin
//		
//		AMX Mod X Development Team/OLO
//		-- restmenu.sma which provided me fully with buy cmd aliases and other code
//		
//		Cheap_Suit
//		-- for the Anti-Boost plugin
//		
//		hlstriker
//		-- for the code on how to create a hostage outside of the map
//	
//	*If I forgot anyone, please tell me who and what I forgot them for.
//	
// =================================================================================================
////////////////////////////////////////////////////////////////////////////////////////////////////


#include <amxmodx>
#include <amxmisc>
#include <csx>
#include <cstrike>
#include <fakemeta>
#include <fakemeta_util>

#define PLUGINNAME "Ultra Hide-N-Seek"
#define VERSION "1.4"
#define AUTHOR "Exolent"

#pragma semicolon 1

#define MAXMENUPOS 34

enum
{
	SCRIM_NONE = 0,
	SCRIM_POINTS,
	SCRIM_WINS
};
enum
{
	TEAM_0 = -1,
	TEAM_1,
	TEAM_2
};
enum
{
	TIMER_MINUTES = 0,
	TIMER_SECONDS
};
const TASK_SCRIMVOTE = 40000;
const TASK_TIMER = 41000;
const TASK_CHECKMODEL = 42000;
const TASK_GIVEWEAPONS = 43000;
const TASK_STRIPWEAPONS = 44000;
const TASK_GIVEKNIFE = 45000;
new const g_ClientTaskids[] =
{
	TASK_CHECKMODEL,
	TASK_GIVEWEAPONS,
	TASK_STRIPWEAPONS,
	TASK_GIVEKNIFE
};
new const g_BasePrefix[] = "[HnS]";
new const g_ScrimPrefix[] = "[HnS-Scrim]";
const bool:base = true;
const bool:scrim = false;
new g_HelpMsg = -1;
const g_MaxHelpMsgs = 5;
new const g_HelpMsgs[g_MaxHelpMsgs][] =
{
	"Type^x03 /hnshelp^x01 to understand what happens here.",
	"Type^x03 /scrimhelp^x01 to understand how^x03 HnS scrims^x01 work.",
	"Type^x03 /scores^x01 to view the current^x03 scrim score.",
	"Type^x03 /rounds^x01 to view the rounds left in the^x03 scrim.",
	"Type^x03 /team^x01 to see what^x03 team^x01 you are on."
};
new const bool:g_HelpMsgTypes[g_MaxHelpMsgs] =
{
	base,
	scrim,
	scrim,
	scrim,
	scrim
};
new const CsInternalModel:g_PlayerModels[][] =
{
	{CS_DONTCHANGE, CS_DONTCHANGE, CS_DONTCHANGE, CS_DONTCHANGE},
	{CS_T_TERROR, CS_T_LEET, CS_T_ARCTIC, CS_T_GUERILLA},
	{CS_CT_URBAN, CS_CT_GSG9, CS_CT_SAS, CS_CT_GIGN},
	{CS_DONTCHANGE, CS_DONTCHANGE, CS_DONTCHANGE, CS_DONTCHANGE}
};
new const g_DefaultPlayerModels[][][] =
{
	{"sas", "sas", "sas", "sas"},
	{"terror", "leet", "arctic", "guerilla"},
	{"urban", "gsg9", "sas", "gign"},
	{"sas", "sas", "sas", "sas"}
};
new const g_RemovedEntities[][] =
{
	"func_bomb_target",
	"info_bomb_target",
	"hostage_entity",
	"monster_scientist",
	"func_hostage_rescue",
	"info_hostage_rescue",
	"info_vip_start",
	"func_vip_safetyzone",
	"func_escapezone",
	"func_door",
	"func_door_rotating",
	"func_breakable"
};
new const bool:g_PrimaryEntity[] =
{
	true,
	true,
	true,
	false,
	false,
	false,
	false,
	true,
	true,
	false,
	false,
	false
};
new const g_HideTimerSounds[][] =
{
	"zero", "one", "two", "three", "four", "five",
	"six", "seven", "eight", "nine", "ten"
};
new g_BuyAliases[MAXMENUPOS][] =
{
	"usp",		//Pistols
	"glock", 
	"deagle", 
	"p228", 
	"elites", 
	"fn57", 

	"m3",		//Shotguns
	"xm1014", 

	"mp5",		//SMG
	"tmp", 
	"p90", 
	"mac10", 
	"ump45", 

	"ak47",		//Rifles
	"galil", 
	"famas", 
	"sg552", 
	"m4a1", 
	"aug", 
	"scout", 
	"awp", 
	"g3sg1", 
	"sg550", 

	"m249",		//Machine Gun

	"vest",		//Equipment
	"vesthelm", 
	"flash", 
	"hegren", 
	"sgren", 
	"defuser", 
	"nvgs", 
	"shield", 

	"primammo", //Ammo
	"secammo"
};
new g_BuyAliases2[MAXMENUPOS][] =
{
	"km45",		//Pistols
	"9x19mm", 
	"nighthawk", 
	"228compact", 
	"elites", 
	"fiveseven", 

	"12gauge",	//Shotguns
	"autoshotgun", 

	"smg",		//SMG
	"mp", 
	"c90", 
	"mac10", 
	"ump45", 

	"cv47",		//Rifles
	"defender", 
	"clarion", 
	"krieg552", 
	"m4a1", 
	"bullpup", 
	"scout", 
	"magnum", 
	"d3au1", 
	"krieg550", 

	"m249",		//Machine Gun

	"vest",		//Equipment
	"vesthelm", 
	"flash", 
	"hegren", 
	"sgren", 
	"defuser", 
	"nvgs", 
	"shield", 
	"primammo", //Ammo
	"secammo"
};
const g_MaxColors = 7;
const g_LastColor = g_MaxColors-1;
new const g_BlindColors_red[g_MaxColors] =
{
	120, 120, 0, 0, 0, 80, 120
};
new const g_BlindColors_grn[g_MaxColors] =
{
	0, 60, 120, 107, 60, 0, 0
};
new const g_BlindColors_blu[g_MaxColors] =
{
	0, 0, 0, 119, 120, 120, 120
};

const Float:g_HudTextX = -1.0;
const Float:g_HudTextYHide = 0.60;
new const Float:g_HudTextYTime[2] = {0.84, 0.97};
const g_HudEffects = 0;
const Float:g_HudFxTime = 1.1;
const Float:g_HudHoldTime = 1.1;
const Float:g_HudFadeInTime = 0.0;
const Float:g_HudFadeOutTime = 0.0;
const g_HudChannel = 1;

new g_Hostage;
new g_HideTimer;
new g_HudSyncObj;
new g_RoundTimer[2];
new g_FreezeTimer;

new bool:g_RestartRound;
new bool:g_ObjectiveMap;
new bool:g_RestartAttempt[32];
new bool:g_WaitForRoundStart;

new Float:g_MsgDelay[32];
new Float:g_BoostDelay[32];
new Float:g_BoostMsgDelay[32];

new MaxPlayers;
new MaxEntities;
new SayText;
new TeamInfo;
new ScreenFade;
new HideWeapon;

new amx_vote_answers;
new hns_pluginon;
new hns_gametype;
new hns_scrimvoice;
new hns_hudcolor;
new hns_timersounds;
new hns_scrimwins;
new hns_blockboosting;
new hns_hidetime;
new hns_money;
new hns_helpmsg;
new hns_killpoints;
new hns_headshotpoints;
new hns_suicidepoints;
new hns_roundpoints;
new hns_tarmor;
new hns_ctarmor;
new hns_forcewinner;
new hns_blindcolors;
new hns_footsteps;
new hns_flashbangs;
new hns_hegrenade;
new hns_smokegrenade;
new hns_tknife;
new mp_freezetime;
new mp_roundtime;

new g_ScrimType;
new g_KillPoints;
new g_ScrimVotes[3];
new g_ScrimTeams[2];
new g_ScrimWinner;
new g_ScrimRounds;
new g_RoundPoints;
new g_ScrimVoteMenu;
new g_SuicidePoints;
new g_ScrimScores[4];
new g_MaxScrimRounds;
new g_HeadshotPoints;

new bool:g_ScrimOn;
new bool:g_ScrimIsDraw;
new bool:g_ScrimHasWinner;
new bool:g_ScrimIsStarting;

new g_BasicHelp[200];
new g_ScrimHelp[200];
new g_NormalCfg[200];
new g_ScrimCfg[200];

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Plugin Info
// =================================================================================================
public plugin_precache()
{
	register_forward(FM_Spawn, "fwd_Spawn");
	g_Hostage = fm_create_entity("hostage_entity");
	engfunc(EngFunc_SetOrigin, g_Hostage, Float:{0.0, 0.0, -55000.0});
	engfunc(EngFunc_SetSize, g_Hostage, Float:{-1.0, -1.0, -1.0}, Float:{1.0, 1.0, 1.0});
	dllfunc(DLLFunc_Spawn, g_Hostage);
}

public plugin_init()
{
	register_plugin(PLUGINNAME, VERSION, AUTHOR);
	
	register_clcmd("say", "clcmd_Say");
	register_clcmd("say_team", "clcmd_Say");
	register_clcmd("autobuy", "clcmd_Buy");
	register_clcmd("rebuy", "clcmd_Buy");
	register_clcmd("buy", "clcmd_Buy");
	register_clcmd("buyequip", "clcmd_Buy");
	register_clcmd("buyammo1", "clcmd_Buy");
	register_clcmd("buyammo2", "clcmd_Buy");
	register_clcmd("cl_setautobuy", "clcmd_Buy");
	register_clcmd("cl_autobuy", "clcmd_Buy");
	register_clcmd("fullupdate", "clcmd_Fullupdate");
	
	register_concmd("hns_on", "cmd_HnsOn", ADMIN_KICK, "<1|0> -- Turns On/Off Hide-N-Seek");
	register_concmd("hns_scrim", "cmd_HnsScrim", ADMIN_KICK, "<1|0> -- Turns On/Off Hide-N-Seek Scrim mode");
	register_concmd("hns_scrimtype", "cmd_HnsScrimType", ADMIN_KICK, "<1|2> -- 1 or Point System, 2 for Round Wins");
	register_concmd("hns_scrimvote", "cmd_HnsScrimVote", ADMIN_KICK, "-- Starts a vote for Scrim Type");
	
	register_logevent("logevent_Round_Start", 2, "1=Round_Start");
	register_logevent("logevent_Round_End", 2, "1=Round_End");
	
	register_event("TextMsg", "event_TextMsg", "a", "2&#Game_w");
	register_event("ResetHUD", "event_ResetHUD", "be");
	register_event("CurWeapon", "event_CurWeapon", "be");
	register_event("HLTV", "event_HLTV", "a", "1=0", "2=0");
	register_event("DeathMsg", "event_DeathMsg", "a");
	
	register_message(get_user_msgid("Money"), "message_Money");
	
	register_forward(FM_Touch, "fwd_Touch");
	register_forward(FM_SetModel, "fwd_SetModel");
	register_forward(FM_ClientKill, "fwd_ClientKill");
	register_forward(FM_ClientCommand, "fwd_ClientCommand");
	register_forward(FM_PlayerPreThink, "fwd_PlayerPreThink");
	register_forward(FM_GetGameDescription, "fwd_GetGameDescription");
	register_forward(FM_Voice_SetClientListening, "fwd_Voice_SetClientListening");
	
	amx_vote_answers = get_cvar_pointer("amx_vote_answers");
	hns_pluginon = register_cvar("hns_pluginon", "1");
	hns_gametype = register_cvar("hns_gametype", "Hide-N-Seek");
	hns_scrimvoice = register_cvar("hns_scrimvoice", "1");
	hns_hudcolor = register_cvar("hns_hudcolor", "255 75 255");
	hns_timersounds = register_cvar("hns_timersounds", "1");
	hns_scrimwins = register_cvar("hns_scrimwins", "3");
	hns_blockboosting = register_cvar("hns_blockboosting", "1");
	hns_hidetime = register_cvar("hns_hidetime", "10");
	hns_money = register_cvar("hns_money", "0");
	hns_helpmsg = register_cvar("hns_helpmsg", "1");
	hns_killpoints = register_cvar("hns_killpoints", "1");
	hns_headshotpoints = register_cvar("hns_headshotpoints", "1");
	hns_suicidepoints = register_cvar("hns_suicidepoints", "1");
	hns_roundpoints = register_cvar("hns_roundpoints", "2");
	hns_tarmor = register_cvar("hns_tarmor", "75");
	hns_ctarmor = register_cvar("hns_ctarmor", "100");
	hns_forcewinner = register_cvar("hns_forcewinner", "1");
	hns_blindcolors = register_cvar("hns_blindcolors", "1");
	hns_footsteps = register_cvar("hns_footsteps", "1");
	hns_flashbangs = register_cvar("hns_flashbangs", "2");
	hns_hegrenade = register_cvar("hns_hegrenade", "1");
	hns_smokegrenade = register_cvar("hns_smokegrenade", "1");
	hns_tknife = register_cvar("hns_tknife", "1");
	mp_freezetime = get_cvar_pointer("mp_freezetime");
	mp_roundtime = get_cvar_pointer("mp_roundtime");
}

public plugin_cfg()
{
	MaxPlayers = global_get(glb_maxClients);
	MaxEntities = global_get(glb_maxEntities);
	SayText = get_user_msgid("SayText");
	TeamInfo = get_user_msgid("TeamInfo");
	ScreenFade = get_user_msgid("ScreenFade");
	
	g_ScrimVoteMenu = menu_create("Scrim Type Vote", "menu_ScrimVote");
	menu_additem(g_ScrimVoteMenu, "Point System", "1");
	menu_additem(g_ScrimVoteMenu, "Round Wins", "2");
	menu_setprop(g_ScrimVoteMenu, MPROP_PERPAGE, 0);
	menu_setprop(g_ScrimVoteMenu, MPROP_EXIT, MEXIT_NEVER);
	
	g_HudSyncObj = CreateHudSyncObj();
	
	g_ObjectiveMap = is_objective_map();
	if(!g_ObjectiveMap)
	{
		HideWeapon = get_user_msgid("HideWeapon");
		register_message(HideWeapon, "message_HideWeapon");
		set_msg_block(get_user_msgid("RoundTime"), BLOCK_SET);
	}
	
	new ConfigsDir[200];
	get_configsdir(ConfigsDir, 199);
	
	formatex(g_NormalCfg, 199, "%s/hns-normal.cfg", ConfigsDir);
	formatex(g_ScrimCfg, 199, "%s/hns-scrim.cfg", ConfigsDir);
	formatex(g_BasicHelp, 199, "%s/hns-basic.txt", ConfigsDir);
	formatex(g_ScrimHelp, 199, "%s/hns-scrim.txt", ConfigsDir);
	
	set_task(45.0, "task_ShowHelpMsgs", _, _, _, "b");
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Client -> Server
// =================================================================================================
public client_putinserver(id)
{
	g_RestartAttempt[id-1] = false;
	return PLUGIN_CONTINUE;
}

public client_disconnect(id)
{
	remove_client_tasks(id);
	return PLUGIN_CONTINUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Client Commands
// =================================================================================================
public clcmd_Say(id)
{
	new message[192];
	read_args(message, 191);
	remove_quotes(message);
	if(equali(message, "/hnshelp"))
	{
		if(file_exists(g_BasicHelp))
			show_motd(id, g_BasicHelp, "HnS Basic Help");
		else
			ShowMsg_HnsMsg(id, "The current hns help file does not exist.", base);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/scrimhelp"))
	{
		if(file_exists(g_ScrimHelp))
			show_motd(id, g_ScrimHelp, "HnS Scrim Help");
		else
			ShowMsg_HnsMsg(id, "The current scrim help file does not exist.", scrim);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/wins") || equali(message, "/scores"))
	{
		if(g_ScrimOn)
		{
			if(g_ScrimType == SCRIM_POINTS)
			{
				show_scrim_scores(id);
				return PLUGIN_HANDLED;
			}
			formatex(message, 191, "Terrorists have won^x03 %d / %d^x01 rounds.", g_ScrimRounds, g_MaxScrimRounds);
			id = 0;
		}
		else
			formatex(message, 191, "There is on scrim taking place.");
		
		ShowMsg_HnsMsg(id, message, scrim);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/rounds"))
	{
		if(g_ScrimOn)
		{
			id = 0;
			new rounds;
			if(g_ScrimType == SCRIM_POINTS)
			{
				if(g_ScrimRounds <= 4)
				{
					rounds = (g_MaxScrimRounds/2) - g_ScrimRounds;
					formatex(message, 191, "There %s^x03 %d round%s^x01 left in the^x03 half.", (rounds != 1) ? "are" : "is", rounds, (rounds != 1) ? "s" : "");
					ShowMsg_HnsMsg(id, message, scrim);
				}
				rounds = g_MaxScrimRounds - g_ScrimRounds;
				formatex(message, 191, "There %s^03 %d round%s^x01 total left in the^x03 scrim.", (rounds != 1) ? "are" : "is", rounds, (rounds != 1) ? "s" : "");
			}
			else
			{
				rounds = g_MaxScrimRounds - g_ScrimRounds;
				formatex(message, 191, "Terrorists need^x03 %d round%s^x01 to win the^x03 scrim.", rounds, (rounds != 1) ? "s" : "");
			}
		}
		else
			formatex(message, 191, "There is no scrim taking place.");
		
		ShowMsg_HnsMsg(id, message, scrim);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/team"))
	{
		if(g_ScrimOn)
		{
			new team[4];
			if(g_ScrimType == SCRIM_POINTS)
				num_to_str((g_ScrimTeams[TEAM_1] == get_user_team(id)) ? 1 : 2, team, 3);
			else
				formatex(team, 3, "%sT", (get_user_team(id) == 1) ? "" : "C");
			
			formatex(message, 191, "Your team is^x03 Team %s.", team);
		}
		else
			formatex(message, 191, "There is no scrim taking place.");
		
		ShowMsg_HnsMsg(id, message, scrim);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/hns"))
	{
		set_hns_status(id);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/scrim"))
	{
		set_hns_scrim(id);
		return PLUGIN_HANDLED;
	}
	if(equali(message, "/captains"))
	{
		if(get_user_flags(id) & ADMIN_LEVEL_H) 
		{
			new players[32], pnum;
			get_players(players, pnum, "ch");
			
			new i = random(pnum);
			new captain1 = players[i];
			for(; i < pnum; i++)
			{
				if(i+1 < pnum)
					players[i] = players[i+1];
			}
			new captain2 = players[random(--pnum)];
			
			new name[32];
			get_user_name(captain1, name, 31);
			formatex(message, 191, "Captains will be:^x03 %s", name);
			get_user_name(captain2, name, 31);
			format(message, 191, "%s^x01 and^x03 %s", message, name);
			ShowMsg_HnsMsg(0, message, scrim);
		}
		return PLUGIN_HANDLED;
	}
	return PLUGIN_CONTINUE;
}

public clcmd_Buy(id)
{
	if(get_pcvar_num(hns_pluginon) && cs_get_user_buyzone(id) == 1)
	{
		new Float:gametime = get_gametime();
		if(gametime >= g_MsgDelay[id-1])
		{
			ShowMsg_HnsMsg(id, "You^x03 cannot buy^x01 during Hide-N-Seek!", base);
			g_MsgDelay[id-1] = gametime + 2.0;
		}
		return PLUGIN_HANDLED;
	}
	return PLUGIN_CONTINUE;
}

public clcmd_Fullupdate(id)
{
	return PLUGIN_HANDLED_MAIN;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Admin Commands
// =================================================================================================
public cmd_HnsOn(id, level, cid)
{
	if(!cmd_access(id, level, cid, 2))
		return PLUGIN_HANDLED;
	
	new arg[4];
	read_argv(1, arg, 3);
	if(str_to_num(arg) > 0)
		set_hns_status(id, 1, 1);
	else
		set_hns_status(id, 0, 1);
	
	return PLUGIN_HANDLED;
}

public cmd_HnsScrim(id, level, cid)
{
	if(!cmd_access(id, level, cid, 2))
		return PLUGIN_HANDLED;
	
	new arg[4];
	read_argv(1, arg, 3);
	if(str_to_num(arg) > 0)
		set_hns_scrim(id, 1, 1);
	else
		set_hns_scrim(id, 0, 1);
	
	return PLUGIN_HANDLED;
}

public cmd_HnsScrimType(id, level, cid)
{
	if(!cmd_access(id, level, cid, 2))
		return PLUGIN_HANDLED;
	
	new arg[4];
	read_argv(1, arg, 3);
	new num = str_to_num(arg);
	if(num == 1 || num == 2)
		g_ScrimType = num;
	else
	{
		console_print(id, "%s Paramter #1 should be ^"1^" or ^"2^"", g_ScrimPrefix);
		return PLUGIN_HANDLED;
	}
	if(g_ScrimOn)
	{
		console_print(id, "%s You cannot change the scrim type during a scrim.");
		return PLUGIN_HANDLED;
	}
	new message[192];
	get_user_name(id, message, 31);
	format(message, 191, "^x04%s^x03 ADMIN %s:^x01 set the scrim type to %s", g_ScrimPrefix, message, (g_ScrimType == SCRIM_POINTS) ? "Point System" : "Round Wins");
	for(new player=1; player <= MaxPlayers; player++)
	{
		if(is_user_connected(player))
			ShowMsg_SayText(id, player, message);
	}
	return PLUGIN_HANDLED;
}

public cmd_HnsScrimVote(id, level, cid)
{
	if(!cmd_access(id, level, cid, 1))
		return PLUGIN_HANDLED;
	
	if(task_exists(TASK_SCRIMVOTE))
	{
		console_print(id, "%s A vote for the scrim type is already taking place.", g_ScrimPrefix);
		return PLUGIN_HANDLED;
	}
	if(g_ScrimOn)
	{
		console_print(id, "%s You cannot vote for a scrim type during a scrim.");
		return PLUGIN_HANDLED;
	}
	g_ScrimType = SCRIM_NONE;
	g_ScrimVotes[SCRIM_POINTS] = 0;
	g_ScrimVotes[SCRIM_WINS] = 0;
	for(new pid=1; pid <= MaxPlayers; pid++)
		if(is_user_connected(pid))
			menu_display(pid, g_ScrimVoteMenu);
	
	ShowMsg_HnsMsg(0, "What^x03 scrim type^x01 would you like to play?", scrim);
	set_task(30.0, "task_DecideScrimVote", TASK_SCRIMVOTE);
	return PLUGIN_HANDLED;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Log Events
// =================================================================================================
public logevent_Round_Start()
{
	if(get_pcvar_num(hns_pluginon))
	{
		if(task_exists(TASK_TIMER))
			remove_task(TASK_TIMER);
		
		g_WaitForRoundStart = false;
		new id;
		if(g_ScrimOn)
		{
			if(g_ScrimType == SCRIM_POINTS)
			{
				new message[192];
				if(g_ScrimHasWinner && (g_ScrimWinner == TEAM_1 || g_ScrimWinner == TEAM_2))
				{
					formatex(message, 191, "^x03 Team %d^x03 has won!", g_ScrimWinner + 1);
					ShowMsg_HnsMsg(0, message, scrim, false);
					show_scrim_scores(0);
					set_hns_scrim(0, 0);
					return PLUGIN_CONTINUE;
				}
				else if(g_ScrimIsDraw)
				{
					ShowMsg_HnsMsg(0, "Score is a^x03 draw!", scrim);
					if(get_pcvar_num(hns_forcewinner))
					{
						ShowMsg_HnsMsg(0, "Allowing 1 round per team to determine winner!", scrim);
						g_MaxScrimRounds = 2;
						g_ScrimRounds = 0;
						cs_switch_teams();
					}
					else
						ShowMsg_HnsMsg(0, "Scrim Mode turning off...", scrim);
					
					g_ScrimIsDraw = false;
					server_cmd("sv_restart 1");
					return PLUGIN_CONTINUE;
				}
				else if(g_ScrimIsStarting)
				{
					for(id=1; id <= MaxPlayers; id++)
					{
						if(!is_user_connected(id))
							continue;
						
						if(!is_playing(id))
							continue;
						
						formatex(message, 191, "Your team is^x03 Team %d.", get_user_team(id));
						ShowMsg_HnsMsg(id, message, scrim);
					}
					g_ScrimIsStarting = false;
					g_ScrimTeams[TEAM_1] = 1;
					g_ScrimTeams[TEAM_2] = 2;
				}
			}
			else if(g_ScrimHasWinner)
			{
				ShowMsg_HnsMsg(0, "Terrorist Team has won!", scrim);
				ShowMsg_HnsMsg(0, "Scrim Mode turning off...", scrim);
				set_hns_scrim(0, 0);
				return PLUGIN_CONTINUE;
			}
			else if(g_RestartRound)
			{
				g_RestartRound = false;
				server_cmd("sv_restart 1");
				return PLUGIN_CONTINUE;
			}
		}
		set_task(0.0, "task_Timers", TASK_TIMER);
	}
	return PLUGIN_CONTINUE;
}

public logevent_Round_End()
{
	if(!get_pcvar_num(hns_pluginon))
		return PLUGIN_CONTINUE;
	
	if(task_exists(TASK_TIMER))
		remove_task(TASK_TIMER);
	
	new HudMsg[192];
	new bool:TerroristsWin = false;
	new bool:draw = true;
	new RoundWinner = 0;
	g_WaitForRoundStart = true;
	
	new id, connect[32], alive[32], CsTeams:team[32];
	for(id=1; id <= MaxPlayers; id++)
	{
		connect[id-1] = is_user_connected(id);
		if(!connect[id-1])
			continue;
		
		team[id-1] = cs_get_user_team(id);
		alive[id-1] = is_user_alive(id);
		if(team[id-1] == CS_TEAM_T && !TerroristsWin)
		{
			draw = false;
			if(alive[id-1])
				TerroristsWin = true;
		}
	}
	
	if(TerroristsWin)
	{
		formatex(HudMsg, 191, "Terrorists Won Round");
		if(g_ScrimOn)
		{
			if(g_ScrimType == SCRIM_POINTS)
				RoundWinner = 1;
			else if(g_ScrimType == SCRIM_WINS)
			{
				if(++g_ScrimRounds < g_MaxScrimRounds)
				{
					new message[192];
					formatex(message, 191, "Terrorists have won^x03 %d / %d^x01 rounds.", g_ScrimRounds, g_MaxScrimRounds);
					ShowMsg_HnsMsg(0, message, scrim);
				}
				else
					g_ScrimHasWinner = true;
			}
		}
		else
			add(HudMsg, 191, "^nNo Team Change");
	}
	else if(draw)
		formatex(HudMsg, 191, "Round Draw^nNo Team Change");
	else
	{
		formatex(HudMsg, 191, "Counter-Terrorist Won Round");
		if(!g_ScrimOn)
		{
			add(HudMsg, 191, "^nSwitching Teams");
			cs_switch_teams();
		}
		else if(g_ScrimType == SCRIM_POINTS)
			RoundWinner = 2;
		
		else if(g_ScrimType == SCRIM_WINS)
		{
			ShowMsg_HnsMsg(0, "Counter-Terrorists won the round.", scrim);
			ShowMsg_HnsMsg(0, "Restarting scores...", scrim);
			g_RestartRound = true;
			cs_switch_teams();
		}
	}
	
	new red, green, blue;
	get_hud_colors(red, green, blue);
	SetSyncHudMsg(red, green, blue);
	ShowSyncHudMsg(0, g_HudSyncObj, HudMsg);
	
	if(g_ScrimOn && g_ScrimType == SCRIM_POINTS)
	{
		if(RoundWinner > 0)
		{
			new points = g_RoundPoints;
			g_ScrimScores[RoundWinner] += points;
			
			new message[192];
			formatex(message, 191, "^x04%s^x01 The^x03 %sT team^x01 gained^x03 %d point%s^x01 for winning the round!", g_ScrimPrefix, (RoundWinner == 2) ? "C" : "", points, (points != 1) ? "s" : "");
			
			new team[16], pTeam[16];
			copy(team, 15, (RoundWinner == 2) ? "CT" : "TERRORIST");
			for(id=1; id <= MaxPlayers; id++)
			{
				if(!is_user_connected(id))
					continue;
				
				if(get_user_team(id, pTeam, 15) != RoundWinner)
				{
					ShowMsg_TeamInfo(id, team);
					ShowMsg_SayText(id, id, message);
					ShowMsg_TeamInfo(id, pTeam);
				}
				else
					ShowMsg_SayText(id, id, message);
			}
		}
		if(float(++g_ScrimRounds) == (float(g_MaxScrimRounds) / 2))
			cs_switch_teams();
		else if(g_ScrimRounds == g_MaxScrimRounds)
		{
			g_ScrimHasWinner = calculate_winner();
			g_ScrimIsDraw = !g_ScrimHasWinner;
		}
	}
	return PLUGIN_CONTINUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Events
// =================================================================================================
public event_TextMsg()
{
	if(get_pcvar_num(hns_pluginon))
	{
		g_ScrimHasWinner = false;
		if(task_exists(TASK_TIMER))
			remove_task(TASK_TIMER);
	}
	
	for(new id=1; id <= MaxPlayers; id++)
	{
		if(!is_user_connected(id))	
			continue;
		
		remove_client_tasks(id);
		
		if(is_user_alive(id))
			g_RestartAttempt[id-1] = true;
	}
	return PLUGIN_CONTINUE;
}

public event_ResetHUD(id)
{
	if(!is_user_connected(id))
		return PLUGIN_CONTINUE;
	
	if(g_RestartAttempt[id-1])
		g_RestartAttempt[id-1] = false;
	else
	{
		new bool:playing = is_playing(id);
		if(!playing || get_pcvar_num(hns_pluginon))
		{
			if(is_user_alive(id))
			{
				remove_client_tasks(id);
				
				set_task(0.3, "task_RemoveWeapons", id + TASK_STRIPWEAPONS);
				set_task(0.6, "task_GiveKnife", id + TASK_GIVEKNIFE);
				set_task(0.9, "task_CheckModel", id + TASK_CHECKMODEL);
				
				new Float:time = 0.6;
				if(playing)
				{
					if(g_HideTimer > 0)
						time += float(g_HideTimer);
					if(g_FreezeTimer > 0)
						time += float(g_FreezeTimer);
				}
				set_task(time, "task_GiveWeapons", id + TASK_GIVEWEAPONS);
			}
			if(!g_ObjectiveMap)
			{
				emessage_begin(MSG_ONE, HideWeapon, _, id);
				ewrite_byte((1<<4));
				emessage_end();
			}
		}
	}
	return PLUGIN_CONTINUE;
}

public event_CurWeapon(id)
{
	if(!get_pcvar_num(hns_pluginon))
		return PLUGIN_CONTINUE;
	
	if(g_HideTimer > 0 && cs_get_user_team(id) == CS_TEAM_CT)
		set_pev(id, pev_maxspeed, -1.0);
	
	return PLUGIN_CONTINUE;
}

public event_HLTV()
{
	g_RoundTimer[TIMER_SECONDS] = floatround((get_pcvar_float(mp_roundtime) * 60.0), floatround_floor);
	g_RoundTimer[TIMER_MINUTES] = 0;
	while(g_RoundTimer[TIMER_SECONDS] >= 60)
	{
		g_RoundTimer[TIMER_SECONDS] -= 60;
		g_RoundTimer[TIMER_MINUTES]++;
	}
	g_HideTimer = get_pcvar_num(hns_hidetime);
	g_FreezeTimer = get_pcvar_num(mp_freezetime);
	set_task(0.0, "task_FreezeTimer", TASK_TIMER);
	return PLUGIN_CONTINUE;
}

public event_DeathMsg()
{
	if(!get_pcvar_num(hns_pluginon))
		return PLUGIN_CONTINUE;
	
	new killer = read_data(1);
	new victim = read_data(2);
	if((0 < killer <= MaxPlayers) && killer != victim)
		return PLUGIN_CONTINUE;
	
	if(!g_WaitForRoundStart && g_ScrimOn && g_ScrimType == SCRIM_POINTS && is_playing(victim))
	{
		new name[32], message[192];
		get_user_name(victim, name, 31);
		new points = g_SuicidePoints;
		formatex(message, 191, "^x04%s^x03 %s^x01 lost^x03 %d point%s^x01 from thier team's score!", g_ScrimPrefix, name, points, (points != 1) ? "s" :" ");
		for(new id=1; id <= MaxPlayers; id++)
		{
			if(is_user_connected(id))
				ShowMsg_SayText(victim, id, message);
		}
		g_ScrimScores[get_user_team(victim)] -= points;
	}
	return PLUGIN_CONTINUE;
}

public client_death(killer, victim, weapon, hitbox, TK)
{
	if(!g_ScrimOn || g_ScrimType != SCRIM_POINTS)
		return PLUGIN_CONTINUE;
	
	if(!is_playing(killer) || !is_playing(victim) || killer == victim)
		return PLUGIN_CONTINUE;
	
	new points = 0;
	if(hitbox == HIT_HEAD)
		points += g_HeadshotPoints;
	
	new message[192], name[32];
	get_user_name(killer, name, 31);
	new team = get_user_team(killer);
	if(get_user_team(victim) == team)
	{
		points += g_SuicidePoints;
		points *= -1;
		formatex(message, 191, "^x04%s^x03 %s^x01 lost^x03 %d point%s^x01 from their team's score!", g_ScrimPrefix, name, points, (points != 1) ? "s" : "");
	}
	else
	{
		points += g_KillPoints;
		formatex(message, 191, "^x04%s^x03 %s^x01 gained^x03 %d point%s^x01 for their team's score!", g_ScrimPrefix, name, points, (points != 1) ? "s" : "");
	}
	
	g_ScrimScores[team] += points;
	
	for(new id=1; id <= MaxPlayers; id++)
	{
		if(is_user_connected(id))
			ShowMsg_SayText(killer, id, message);
	}
	return PLUGIN_CONTINUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Messages
// =================================================================================================
public message_Money(msgid, dest, id)
{
	new money = get_pcvar_num(hns_money);
	if(get_pcvar_num(hns_pluginon) && get_msg_arg_int(1) != money)
		set_msg_arg_int(1, ARG_LONG, money);
	
	return PLUGIN_CONTINUE;
}

public message_HideWeapon(msgid, dest, id)
{
	set_msg_arg_int(1, ARG_BYTE, (get_msg_arg_int(1)|(1<<4)));
	return PLUGIN_CONTINUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Forwards
// =================================================================================================
public fwd_Spawn(ent)
{
	if(!pev_valid(ent) || ent == g_Hostage)
		return FMRES_IGNORED;
	
	static ClassName[32], i, size;
	pev(ent, pev_classname, ClassName, 31);
	size = sizeof(g_RemovedEntities);
	for(i=0; i < size; i++)
	{
		if(equali(ClassName, g_RemovedEntities[i]))
		{
			engfunc(EngFunc_RemoveEntity, ent);
			return FMRES_SUPERCEDE;
		}
	}
	return FMRES_IGNORED;
}

public fwd_Touch(ptr, ptd)
{
	if(!get_pcvar_num(hns_blockboosting))
		return FMRES_IGNORED;
	
	if(!pev_valid(ptr) || !pev_valid(ptd))
		return FMRES_IGNORED;
	
	if(!is_playing(ptr) || !is_playing(ptd))
		return FMRES_IGNORED;
	
	if(!is_user_alive(ptr) || !is_user_alive(ptd))
		return FMRES_IGNORED;
	
	if(get_user_team(ptr) != get_user_team(ptd))
		return FMRES_IGNORED;
	
	static Float:PtrOrigin[3], Float:PtdOrigin[3];
	pev(ptr, pev_origin, PtrOrigin);
	pev(ptd, pev_origin, PtdOrigin);
	
	if(!(49.0 < (PtdOrigin[2] - PtrOrigin[2]) < 73.0))
		return FMRES_IGNORED;
	
	new Float:gametime = get_gametime();
	if(gametime >= g_BoostDelay[ptr-1])
	{
		cs_user_slap(ptr);
		g_BoostDelay[ptr-1] = gametime + 0.5;
	}
	if(gametime >= g_BoostDelay[ptd-1])
	{
		cs_user_slap(ptd);
		g_BoostDelay[ptd-1] = gametime + 0.5;
	}
	if(gametime >= g_BoostMsgDelay[ptr-1])
	{
		ShowMsg_HnsMsg(ptr, "No boosting allowed!", scrim);
		g_BoostMsgDelay[ptr-1] = gametime + 1.0;
	}
	if(gametime >= g_BoostMsgDelay[ptd-1])
	{
		ShowMsg_HnsMsg(ptd, "No boosting allowed!", scrim);
		g_BoostMsgDelay[ptd-1] = gametime + 1.0;
	}
	return FMRES_IGNORED;
}

public fwd_SetModel(ent, const model[])
{
	if(!get_pcvar_num(hns_pluginon)
	|| !pev_valid(ent)
	|| !equali(model, "models/w_", 9)
	|| equali(model, "models/w_weaponbox.mdl"))
		return FMRES_IGNORED;
	
	static owner;
	owner = pev(ent, pev_owner);
	if(!(0 < owner <= MaxPlayers) || !is_user_connected(owner))
		return FMRES_IGNORED;
	
	static ClassName[32];
	pev(ent, pev_classname, ClassName, 31);
	if(equal(ClassName, "weapon_shield"))
	{
		set_pev(ent, pev_effects, EF_NODRAW);
		set_task(0.1, "task_RemoveShield", ent);
		return FMRES_IGNORED;
	}
	if(!equal(ClassName, "weaponbox"))
		return FMRES_IGNORED;
	
	static i;
	for(i = MaxPlayers+1; i < MaxEntities; i++)
	{
		if(!pev_valid(i) || ent != pev(i, pev_owner))
			continue;
		
		dllfunc(DLLFunc_Think, ent);
		break;
	}
	return FMRES_IGNORED;
}

public fwd_ClientKill(id)
{
	if(get_pcvar_num(hns_pluginon))
	{
		new Float:gametime = get_gametime();
		if(gametime >= g_MsgDelay[id-1])
		{
			ShowMsg_HnsMsg(id, "You cannot kill yourself during Hide-N-Seek!", base);
			g_MsgDelay[id-1] = gametime + 2.0;
		}
		return FMRES_SUPERCEDE;
	}
	return FMRES_IGNORED;
}

public fwd_ClientCommand(id)
{
	if(get_pcvar_num(hns_pluginon))
	{
		static cmd[16];
		if(read_argv(0, cmd, 15) > 11)
			return FMRES_IGNORED;
		
		if(equali(cmd, "chooseteam") && is_playing(id))
		{
			ShowMsg_HnsMsg(id, "You cannot change teams during Hide-N-Seek!", base);
			return FMRES_SUPERCEDE;
		}
		if(is_buy_command(id, cmd))
			return FMRES_SUPERCEDE;
	}
	return FMRES_IGNORED;
}

public fwd_PlayerPreThink(id)
{
	if(!get_pcvar_num(hns_pluginon) || !is_user_alive(id))
		return FMRES_IGNORED;
	
	static team;
	team = get_user_team(id);
	if(g_HideTimer > 0 && team == 2)
		set_pev(id, pev_maxspeed, -1.0);
	
	if(team == 1 && get_pcvar_num(hns_footsteps))
		set_pev(id, pev_flTimeStepSound, 999);
	
	static temp;
	if((0 < team < 3) && get_user_weapon(id, temp, temp) == CSW_KNIFE)
	{
		static button, oldbutton;
		oldbutton = pev(id, pev_button);
		button = oldbutton;
		if(button & IN_ATTACK)
		{
			button &= ~IN_ATTACK;
			if(team == 2)
				button |= IN_ATTACK2;
		}
		if((button & IN_ATTACK2) && team == 1)
			button &= ~IN_ATTACK2;
		
		if(oldbutton != button)
			set_pev(id, pev_button, button);
	}
	return FMRES_IGNORED;
}

public fwd_GetGameDescription()
{
	new gametype[32];
	get_pcvar_string(hns_gametype, gametype, 31);
	forward_return(FMV_STRING, (strlen(gametype) > 0) ? gametype : "Hide-N-Seek");
	return FMRES_SUPERCEDE;
}

public fwd_Voice_SetClientListening(receiver, sender, listen)
{
	if(!get_pcvar_num(hns_scrimvoice) || sender == receiver || !is_user_connected(sender) || !is_user_connected(receiver) || !g_ScrimOn)
		return FMRES_IGNORED;
	
	if(cs_get_user_team(sender) != cs_get_user_team(receiver))
	{
		engfunc(EngFunc_SetClientListening, receiver, sender, 0);
		return FMRES_SUPERCEDE;
	}
	if(is_user_alive(sender) == is_user_alive(receiver))
		return FMRES_IGNORED;
	
	engfunc(EngFunc_SetClientListening, receiver, sender, 1);
	return FMRES_SUPERCEDE;
}

public CS_InternalCommand(id, const cmd[])
{
	return (is_buy_command(id, cmd)) ? PLUGIN_HANDLED : PLUGIN_CONTINUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Menu
// =================================================================================================
public menu_ScrimVote(id, menu, item)
{
	if(item < 0)
		return PLUGIN_CONTINUE;
	
	if(!task_exists(TASK_SCRIMVOTE))
		return PLUGIN_HANDLED;
	
	new num[3], access, callback;
	menu_item_getinfo(menu, item, access, num, 2, _, _, callback);
	
	new vote = str_to_num(num);
	g_ScrimVotes[vote]++;
	
	if(get_pcvar_num(amx_vote_answers))
	{
		new message[192];
		get_user_name(id, message, 31);
		format(message, 191, "^x03 %s^x01 voted for^x03 %s", message, (vote == SCRIM_POINTS) ? "Point System" : "Round Wins");
		ShowMsg_HnsMsg(0, message, scrim, false);
	}
	if((g_ScrimVotes[SCRIM_POINTS] + g_ScrimVotes[SCRIM_WINS]) == get_playersnum())
	{
		remove_task(TASK_SCRIMVOTE);
		task_DecideScrimVote();
	}
	return PLUGIN_HANDLED;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Tasks
// =================================================================================================
public task_RemoveWeapons(id)
{
	fm_strip_user_weapons(id - TASK_STRIPWEAPONS);
}

public task_CheckModel(id)
{
	if(get_pcvar_num(hns_pluginon))
	{
		id -= TASK_CHECKMODEL;
		new CsTeams:team = cs_get_user_team(id);
		if(team != CS_TEAM_T && team != CS_TEAM_CT)
			return;
		
		new model[16];
		cs_get_user_model(id, model, 15);
		team = (team == CS_TEAM_T) ? CS_TEAM_CT : CS_TEAM_T;
		for(new i=0; i < 4; i++)
		{
			if(equali(model, g_DefaultPlayerModels[_:team][i]))
			{
				team = (team == CS_TEAM_T) ? CS_TEAM_CT : CS_TEAM_T;
				cs_set_user_model(id, g_DefaultPlayerModels[_:team][random(4)]);
				break;
			}
		}
	}
}

public task_GiveKnife(id)
{
	id -= TASK_GIVEKNIFE;
	if(cs_get_user_team(id) == CS_TEAM_T && !get_pcvar_num(hns_tknife))
		return;
	
	fm_give_item(id, "weapon_knife");
}

public task_GiveWeapons(id)
{
	id -= TASK_GIVEWEAPONS;
	if(get_pcvar_num(hns_pluginon) || !is_playing(id))
	{
		switch(cs_get_user_team(id))
		{
			case CS_TEAM_T:
			{
				new hecount = get_pcvar_num(hns_hegrenade);
				if(hecount > 0)
				{
					fm_give_item(id, "weapon_hegrenade");
					cs_set_user_bpammo(id, CSW_HEGRENADE, hecount);
				}
				
				new flashcount = get_pcvar_num(hns_flashbangs);
				if(flashcount > 0)
				{
					fm_give_item(id, "weapon_flashbang");
					cs_set_user_bpammo(id, CSW_FLASHBANG, flashcount);
				}
				
				new smokecount = get_pcvar_num(hns_smokegrenade);
				if(smokecount > 0)
				{
					fm_give_item(id, "weapon_smokegrenade");
					cs_set_user_bpammo(id, CSW_SMOKEGRENADE, smokecount);
				}
				
				new armor = get_pcvar_num(hns_tarmor);
				if(!(0 <= armor <= 100))
					armor = 50;
				
				cs_set_user_armor(id, armor, CS_ARMOR_KEVLAR);
			}
			case CS_TEAM_CT: 
			{
				new armor = get_pcvar_num(hns_ctarmor);
				if(!(0 <= armor <= 100))
					armor = 50;
				
				cs_set_user_armor(id, armor, CS_ARMOR_KEVLAR);
			}
			default:
			{
				fm_give_item(id, "weapon_usp");
				set_pev(id, pev_takedamage, 0.0);
			}
		}
	}
}

public task_RemoveShield(ent)
{
	dllfunc(DLLFunc_Think, ent);
}

public task_FreezeTimer()
{
	if(task_exists(TASK_TIMER))
		remove_task(TASK_TIMER);
	
	if(g_FreezeTimer-- > 0)
	{
		new seconds[10];
		formatex(seconds, 9, "%s%d", (g_FreezeTimer < 10) ? "0" : "", g_FreezeTimer);
		
		new red, green, blue;
		get_hud_colors(red, green, blue);
		for(new id=1; id <= MaxPlayers; id++)
		{
			if(!is_user_connected(id))
				continue;
			
			SetSyncHudMsg(red, green, blue, is_user_alive(id));
			ShowSyncHudMsg(id, g_HudSyncObj, "0:%s^nFreeze Timer", seconds);
		}
		if(g_FreezeTimer > 0)
			set_task(1.0, "task_FreezeTimer", TASK_TIMER);
	}
}

public task_Timers()
{
	if(task_exists(TASK_TIMER))
		remove_task(TASK_TIMER);
	
	if(!get_pcvar_num(hns_pluginon))
		return;
	
	new red, grn, blu;
	get_hud_colors(red, grn, blu);
	
	new id, HudMsg[192], seconds[10];
	if(g_HideTimer >= 0)
	{
		new BlindColors[3];
		get_blind_colors(BlindColors[0], BlindColors[1], BlindColors[2]);
		
		new CsTeams:team, connect[32], alive[32];
		new sounds = get_pcvar_num(hns_timersounds);
		new size = sizeof(g_HideTimerSounds);
		formatex(seconds, 9, "%s%d", (g_HideTimer < 10) ? "0" : "", g_HideTimer);
		formatex(HudMsg, 191, "0:%s^nHide Timer", seconds);
		for(id=1; id <= MaxPlayers; id++)
		{
			connect[id-1] = is_user_connected(id);
			if(!connect[id-1])
				continue;
			
			team = cs_get_user_team(id);
			alive[id-1] = is_user_alive(id);
			SetSyncHudMsg(red, grn, blu, alive[id-1]);
			ShowSyncHudMsg(id, g_HudSyncObj, HudMsg);
			if(team != CS_TEAM_T && team != CS_TEAM_CT)
				continue;
			
			if(g_HideTimer > 0)
			{
				if(g_HideTimer < size && sounds)
					client_cmd(id, "spk vox/%s.wav", g_HideTimerSounds[g_HideTimer]);
				
				if(team == CS_TEAM_CT && alive[id-1])
					blind_player(id, (1<<15), (1<<15), (1<<12), BlindColors[0], BlindColors[1], BlindColors[2], 255);
			}
			else if(team == CS_TEAM_CT && alive[id-1])
			{
				blind_player(id, (1<<0), (1<<0), (1<<12), BlindColors[0], BlindColors[1], BlindColors[2], 255);
				set_pev(id, pev_maxspeed, 250.0);
			}
		}
		g_HideTimer--;
		set_task(1.0, "task_Timers", TASK_TIMER);
	}
	else if(g_RoundTimer[TIMER_MINUTES] > 0 || g_RoundTimer[TIMER_SECONDS] > 0)
	{
		if(g_RoundTimer[TIMER_SECONDS] == 0)
		{
			g_RoundTimer[TIMER_MINUTES]--;
			g_RoundTimer[TIMER_SECONDS] = 59;
		}
		else
			g_RoundTimer[TIMER_SECONDS]--;
		
		formatex(seconds, 9, "%s%d", (g_RoundTimer[TIMER_SECONDS] < 10) ? "0" : "", g_RoundTimer[TIMER_SECONDS]);
		formatex(HudMsg, 191, "%d:%s^nRound Timer", g_RoundTimer[TIMER_MINUTES], seconds);
		for(id=1; id <= MaxPlayers; id++)
		{
			if(!is_user_connected(id))
				continue;
			
			SetSyncHudMsg(red, grn, blu, is_user_alive(id));
			ShowSyncHudMsg(id, g_HudSyncObj, HudMsg);
		}
		
		if(g_RoundTimer[TIMER_MINUTES] > 0 || g_RoundTimer[TIMER_SECONDS] > 0)
			set_task(1.0, "task_Timers", TASK_TIMER);
		else
			set_task(1.0, "logevent_Round_End", TASK_TIMER);
	}
}

public task_DecideScrimVote()
{
	if(g_ScrimVotes[SCRIM_POINTS] > g_ScrimVotes[SCRIM_WINS])
		g_ScrimType = SCRIM_POINTS;
	else if(g_ScrimVotes[SCRIM_WINS] > g_ScrimVotes[SCRIM_POINTS])
		g_ScrimType = SCRIM_WINS;
	else
		g_ScrimType = random_num(SCRIM_POINTS, SCRIM_WINS);
	
	ShowMsg_HnsMsg(0, "Voting over.", scrim);
	
	new message[192];
	formatex(message, 191, "Scrim Type will be^x03 %s!", (g_ScrimType == SCRIM_POINTS) ? "Point System" : "Round Wins");
	ShowMsg_HnsMsg(0, message, scrim);
}

public task_ShowHelpMsgs()
{
	if(!get_pcvar_num(hns_helpmsg))
		return;
	
	if(++g_HelpMsg >= g_MaxHelpMsgs)
		g_HelpMsg = 0;
	
	if(g_ScrimOn)
	{
		if(g_HelpMsgTypes[g_HelpMsg] == scrim)
			ShowMsg_HnsMsg(0, g_HelpMsgs[g_HelpMsg], scrim);
		else
			task_ShowHelpMsgs();
	}
	else if(g_HelpMsgTypes[g_HelpMsg] == base)
		ShowMsg_HnsMsg(0, g_HelpMsgs[g_HelpMsg], base);
	else
		task_ShowHelpMsgs();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// =================================================================================================
//					Functions
// =================================================================================================
bool:is_objective_map()
{
	new size = sizeof(g_RemovedEntities);
	for(new i=0; i < size; i++)
	{
		if(g_PrimaryEntity[i] && engfunc(EngFunc_FindEntityByString, FM_NULLENT, "classname", g_RemovedEntities[i]))
			return true;
	}
	return false;
}

bool:is_playing(id)
{
	return ((0 < id <= MaxPlayers) && is_user_connected(id) && (0 < get_user_team(id) < 3));
}

bool:calculate_winner()
{
	if(g_ScrimOn && g_ScrimType == SCRIM_POINTS)
	{
		new score1, score2;
		get_scrim_scores(score1, score2);
		if(score1 > score2)
			g_ScrimWinner = TEAM_1;
		else if(score1 < score2)
			g_ScrimWinner = TEAM_2;
		else
		{
			g_ScrimWinner = TEAM_0;
			return false;
		}
		return true;
	}
	return false;
}

bool:is_buy_command(id, const cmd[])
{
	static i;
	for(i=0; i < MAXMENUPOS; i++)
	{
		if(equal(cmd, g_BuyAliases[i]) || equali(cmd, g_BuyAliases2[i]))
		{
			clcmd_Buy(id);
			return true;
		}
	}
	return false;
}

CsInternalModel:cs_get_model_by_team(CsTeams:team)
{
	return g_PlayerModels[_:team][random(4)];
}

show_scrim_scores(id)
{
	new score1, score2;
	get_scrim_scores(score1, score2);
	
	new message[192];
	formatex(message, 191, "^x03 Team 1:^x01 %d points  ^x03  Team 2:^x01 %d points", score1, score2);
	ShowMsg_HnsMsg(id, message, scrim, false);
}

get_scrim_scores(&score1, &score2)
{
	score1 = g_ScrimScores[g_ScrimTeams[TEAM_1]];
	score2 = g_ScrimScores[g_ScrimTeams[TEAM_2]];
}

get_hud_colors(&red, &grn, &blu)
{
	new color[16], r[4], g[4], b[4];
	get_pcvar_string(hns_hudcolor, color, 15);
	parse(color, r, 3, g, 3, b, 3);
	red = str_to_num(r);
	grn = str_to_num(g);
	blu = str_to_num(b);
}

get_blind_colors(&red, &grn, &blu)
{
	switch(get_pcvar_num(hns_blindcolors))
	{
		case 0:
		{
			red = 0;
			grn = 0;
			blu = 0;
		}
		case 1:
		{
			new r, g, b;
			get_hud_colors(r, g, b);
			red = calculate_darker_color(r);
			grn = calculate_darker_color(g);
			blu = calculate_darker_color(b);
		}
		case 2:
		{
			new color = random_num(0, g_LastColor);
			red = g_BlindColors_red[color];
			grn = g_BlindColors_grn[color];
			blu = g_BlindColors_blu[color];
		}
		case 3:
		{
			red = random(181);
			grn = random(181);
			blu = random(181);
		}
	}
}

calculate_darker_color(color)
{
	return floatround((((float(color)*2.0) - (float(color)/2.0)) / 3.0), floatround_floor);
}

remove_client_tasks(id)
{
	new taskid, size = sizeof(g_ClientTaskids);
	for(new i=0; i < size; i++)
	{
		taskid = g_ClientTaskids[i] + id;
		if(task_exists(taskid))
			remove_task(taskid);
	}
}

set_hns_status(id, num = -1, console = 0)
{
	if((0 < id <= MaxPlayers) && !(get_user_flags(id) & ADMIN_KICK))
	{
		if(console)
			console_print(id, "You have no access to that command!");
		else
		{
			new Float:gametime = get_gametime();
			if(gametime >= g_MsgDelay[id-1])
			{
				ShowMsg_HnsMsg(id, "", base);
				g_MsgDelay[id-1] = gametime + 2.0;
			}
		}
	}
	else
	{
		new name[64];
		get_user_name(id, name, 63);
		
		new pluginon = get_pcvar_num(hns_pluginon);
		if(pluginon && num < 1)
			pluginon = 0;
		else if(!pluginon && num != 0)
			pluginon = 1;
		
		set_pcvar_num(hns_pluginon, pluginon);
		server_cmd("sv_restart 1");
		
		new message[192];
		formatex(message, 191, "^x03 ADMIN %s:^x01 st%sed Hide-N-Seek!", name, pluginon ? "art" : "opp");
		ShowMsg_HnsMsg(0, message, base, false);
	}
}

set_hns_scrim(id, num = -1, console = 0)
{
	if((0 < id <= MaxPlayers) && !(get_user_flags(id) & ADMIN_KICK))
	{
		if(console)
			console_print(id, "You have no access to that command!");
		else
		{
			new Float:gametime = get_gametime();
			if(gametime >= g_MsgDelay[id-1])
			{
				ShowMsg_HnsMsg(id, "", base);
				g_MsgDelay[id-1] = gametime + 2.0;
			}
		}
	}
	else
	{
		if(g_ScrimOn && num < 1)
		{
			g_ScrimOn = false;
			if(file_exists(g_NormalCfg))
				server_cmd("exec %s", g_NormalCfg);
			
			server_cmd("sv_restart 1");
			
			new message[192], name[64];
			get_user_name(id, name, 63);
			formatex(message, 191, "^x03 ADMIN %s:^x01 stopped the HnS scrim!", name);
			ShowMsg_HnsMsg(0, message, scrim, false);
		}
		else if(!g_ScrimOn && num != 0)
		{
			if(g_ScrimType == SCRIM_NONE)
				g_ScrimType = random_num(1, 2);
			
			g_ScrimOn = true;
			g_ScrimRounds = 0;
			g_ScrimWinner = 0;
			g_ScrimHasWinner = false;
			g_ScrimIsStarting = true;
			if(g_ScrimType == SCRIM_POINTS)
			{
				g_MaxScrimRounds = 10;
				g_SuicidePoints = get_pcvar_num(hns_suicidepoints);
				g_KillPoints = get_pcvar_num(hns_killpoints);
				g_HeadshotPoints = get_pcvar_num(hns_headshotpoints);
				g_RoundPoints = get_pcvar_num(hns_roundpoints);
				clear_scrim_scores();
			}
			else
			{
				new wins = get_pcvar_num(hns_scrimwins);
				if(wins <= 0)
					wins = 3;
				
				g_MaxScrimRounds = wins;
			}
			if(file_exists(g_ScrimCfg))
				server_cmd("exec %s", g_ScrimCfg);
			
			server_cmd("sv_restart 1");
			
			new message[192], name[64];
			get_user_name(id, name, 63);
			formatex(message, 191, "^x03 ADMIN %s:^x01 started the HnS scrim!", name);
			ShowMsg_HnsMsg(0, message, scrim, false);
		}
	}
}

clear_scrim_scores()
{
	g_ScrimScores[1] = 0;
	g_ScrimScores[2] = 0;
}

cs_switch_teams()
{
	for(new id=1; id <= MaxPlayers; id++)
	{
		if(is_playing(id))
			cs_switch_user_team(id, cs_get_user_team(id));
	}
	if(g_ScrimOn)
	{
		if(g_ScrimType == SCRIM_POINTS)
		{
			new temp = g_ScrimScores[1];
			g_ScrimScores[1] = g_ScrimScores[2];
			g_ScrimScores[2] = temp;
			temp = g_ScrimTeams[TEAM_1];
			g_ScrimTeams[TEAM_1] = g_ScrimTeams[TEAM_2];
			g_ScrimTeams[TEAM_2] = temp;
		}
		else
			g_ScrimRounds = 0;
	}
}

cs_switch_user_team(id, CsTeams:team)
{
	switch(team)
	{
		case CS_TEAM_T: team = CS_TEAM_CT;
		case CS_TEAM_CT: team = CS_TEAM_T;
		default: team = CS_TEAM_SPECTATOR;
	}
	cs_set_user_team(id, team, cs_get_model_by_team(team));
}

blind_player(id, duration, holdtime, flags, red, green, blue, alpha)
{
	emessage_begin(MSG_ONE, ScreenFade, _, id);
	ewrite_short(duration);
	ewrite_short(holdtime);
	ewrite_short(flags);
	ewrite_byte(red);
	ewrite_byte(green);
	ewrite_byte(blue);
	ewrite_byte(alpha);
	emessage_end();
}

SetSyncHudMsg(red, green, blue, alive = -1)
{
	set_hudmessage(\
		red,\
		green,\
		blue,\
		g_HudTextX,\
		(alive >= 0) ? g_HudTextYTime[alive] : g_HudTextYHide,\
		g_HudEffects,\
		g_HudFxTime,\
		g_HudHoldTime,\
		g_HudFadeInTime,\
		g_HudFadeOutTime,\
		g_HudChannel);
}

cs_user_slap(id)
{
	new Float:health;
	pev(id, pev_health, health);
	health -= 25.0;
	if(health <= 0)
	{
		user_kill(id, 1);
		cs_set_user_deaths(id, cs_get_user_deaths(id)+1);
	}
	else
		set_pev(id, pev_health, health);
	
	new Float:velocity[3], Float:angle[3];
	pev(id, pev_velocity, velocity);
	pev(id, pev_angles, angle);
	
	for(new i=0; i < 3; i++)
	{
		velocity[i] += (random_num(0, 1) == 1) ? 400.0 : -400.0;
		if(i < 2)
			angle[i] += (random_num(0, 1) == 1) ? 50.0 : -50.0;
	}
	
	set_pev(id, pev_velocity, velocity);
	set_pev(id, pev_angles, angle);
}

ShowMsg_HnsMsg(id, message[], bool:BaseMsg, bool:space = true)
{
	new FinalMsg[192];
	formatex(FinalMsg, 191, "^x04%s^x01%s%s", BaseMsg ? g_BasePrefix : g_ScrimPrefix, space ? " " : "", message);
	if((0 < id <= MaxPlayers))
		ShowMsg_SayText(id, id, FinalMsg);
	else if(id == 0)
	{
		for(id=1; id <= MaxPlayers; id++)
			if(is_user_connected(id))
				ShowMsg_SayText(id, id, FinalMsg);
	}
}

ShowMsg_SayText(sender, receiver, message[])
{
	do_message(receiver, sender, message, SayText);
}

ShowMsg_TeamInfo(id, team[])
{
	do_message(id, id, team, TeamInfo);
}

do_message(id1, id2, message[], msgid)
{
	emessage_begin(MSG_ONE_UNRELIABLE, msgid, _, id1);
	ewrite_byte(id2);
	ewrite_string(message);
	emessage_end();
}
