#include <amxmodx>
#include <amxmisc>
#include <engine>

#define PLUGIN "ADMIN Gag"
#define VERSION "1.0"
#define AUTHOR "RaZzoR"

#define GAG_FLAG ADMIN_BAN
#define GAG_IMMUNITY ADMIN_IMMUNITY

#define DICTIONARY "admin_gag.txt"

new const gag_file_name[] = "nemitott_jatekos.txt"

enum _:GagData {
	gag_name[32],
	gag_steamid[35],
	gag_length,
	ungag_time[32],
	gag_reason[128],
	admin_name[32]
}

new Trie:g_trie
new Array:g_array
new total_gags, g_ungag_entity
new gag_file[64], Float:get_gag_time[33], tempid[33]

new gag_immunity, gag_ungagcheck

public plugin_init() {
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	register_dictionary(DICTIONARY)	
	
	gag_immunity = register_cvar("gag_immunity", "1")
	gag_ungagcheck = register_cvar("gag_ungagcheck", "1.0")

	register_clcmd("amx_gag", "gag_menu")
	register_clcmd("amx_ungag", "ungag_menu")		

	register_clcmd("GAG_TIME", "clcmd_time")
	register_clcmd("GAG_REASON", "clcmd_reason")

	register_concmd("gag_authid", "concmd_gag_authid", GAG_FLAG, "<nev, #userid, authid> <ido percben> <ok>")
	register_concmd("gag_ip", "concmd_gag_ip", GAG_FLAG, "<nev, #userid, authid> <ido percben> <ok>")
	register_concmd("gag_add", "concmd_gag_add", GAG_FLAG, "<nev> <authid vagy ip> <ido percben> <ok>")
	register_concmd("gag_list", "concmd_gag_list", GAG_FLAG, "[start] -- megmutat minden nemitast")
	register_concmd("ungag", "concmd_ungag", GAG_FLAG, "<authid vagy ip>")

	get_datadir(gag_file, sizeof(gag_file) - 1)
	format(gag_file, sizeof(gag_file) - 1, "%s/%s", gag_file, gag_file_name)

	g_trie = TrieCreate()
	g_array = ArrayCreate(GagData)

	LoadGags()
}

public plugin_cfg() create_ungag_entity()

public client_PostThink(id) {
	static authid[35]
	get_user_authid(id, authid, sizeof(authid) - 1)
	
	static ip[35]
	get_user_ip(id, ip, sizeof(ip) - 1, 1)

	static array_pos	
	if(TrieGetCell(g_trie, authid, array_pos) || TrieGetCell(g_trie, ip, array_pos)) set_speak(id, SPEAK_MUTED)
	else set_speak(id, SPEAK_LISTENALL)
}
	
public create_ungag_entity() {
	static failtimes
	
	g_ungag_entity = create_entity("info_target")
	
	if(!is_valid_ent(g_ungag_entity)) {
		++failtimes
		
		log_amx("[HIBA] Nem sikerült elkészíteni a némító feloldó entity-t (%i/10)", failtimes)
		
		if(failtimes < 10) set_task(1.0, "create_ungag_entity")
		else log_amx("[HIBA] Nem lehet elkészíteni a némító feloldó entity-t!")
		
		return
	}
	
	entity_set_string(g_ungag_entity, EV_SZ_classname, "ungag_entity")
	entity_set_float(g_ungag_entity, EV_FL_nextthink, get_gametime() + 1.0)
	
	register_think("ungag_entity", "UnGag_Check")
}

public UnGag_Check(entity)
{
	if(entity != g_ungag_entity) return
	
	if(total_gags > 0)
	{
		static _hours[5], _minutes[5], _seconds[5], _month[5], _day[5], _year[7]
		format_time(_hours, sizeof(_hours) - 1, "%H")
		format_time(_minutes, sizeof(_minutes) - 1, "%M")
		format_time(_seconds, sizeof(_seconds) - 1, "%S")
		format_time(_month, sizeof(_month) - 1, "%m")
		format_time(_day, sizeof(_day) - 1, "%d")
		format_time(_year, sizeof(_year) - 1, "%Y")
		
		
		new c_hours = str_to_num(_hours)
		new c_minutes = str_to_num(_minutes)
		new c_seconds = str_to_num(_seconds)
		new c_month = str_to_num(_month)
		new c_day = str_to_num(_day)
		new c_year = str_to_num(_year)
		
		static load_ungag_time[32]
		static u_hours, u_minutes, u_seconds, u_month, u_day, u_year
		
		for(new i = 0; i < total_gags; i++) {
			static data[GagData]
			ArrayGetArray(g_array, i, data)
			
			if(data[gag_length] == 0) continue
			
			copy(load_ungag_time, sizeof(load_ungag_time) - 1, data[ungag_time])

			replace_all(load_ungag_time, sizeof(load_ungag_time) - 1, ":", " ")
			replace_all(load_ungag_time, sizeof(load_ungag_time) - 1, "/", " ")
			
			parse(load_ungag_time,\
				_hours, sizeof(_hours) - 1,\
				_minutes, sizeof(_minutes) - 1,\
				_seconds, sizeof(_seconds) - 1,\
				_month, sizeof(_month) - 1,\
				_day, sizeof(_day) - 1,\
				_year, sizeof(_year) - 1
				)
			
			u_hours = str_to_num(_hours)
			u_minutes = str_to_num(_minutes)
			u_seconds = str_to_num(_seconds)
			u_month = str_to_num(_month)
			u_day = str_to_num(_day)
			u_year = str_to_num(_year)
			
			if( u_year < c_year
			|| u_year == c_year && u_month < c_month
			|| u_year == c_year && u_month == c_month && u_day < c_day
			|| u_year == c_year && u_month == c_month && u_day == c_day && u_hours < c_hours
			|| u_year == c_year && u_month == c_month && u_day == c_day && u_hours == c_hours && u_minutes < c_minutes
			|| u_year == c_year && u_month == c_month && u_day == c_day && u_hours == c_hours && u_minutes == c_minutes && u_seconds <= c_seconds ) {
				
					print_color(0, "^3%s ^4némítás ideje letelt^1! [Némítás Oka: ^4%s^1] ", data[gag_name], data[gag_reason])
					RemoveGag(i, data[gag_steamid])
					i--
			}
		}
	}
	
	entity_set_float(g_ungag_entity, EV_FL_nextthink, get_gametime() + get_pcvar_float(gag_ungagcheck))
}

public concmd_gag_authid(id, level, cid) {
	if(!cmd_access(id, level, cid, 4)) return PLUGIN_HANDLED
	
	static arg[128]
	read_argv(1, arg, sizeof(arg) - 1)
	
	new target = cmd_target(id, arg, GetTargetFlags(id))
	if(!target) return PLUGIN_HANDLED
	
	static target_authid[35]
	get_user_authid(target, target_authid, sizeof(target_authid) - 1)

	if(TrieKeyExists(g_trie, target_authid)) {
		console_print(id, "Steam ID [%s] már le van némítva!", target_authid)
		return PLUGIN_HANDLED
	}

	read_argv(2, arg, sizeof(arg) - 1)
	new Float:length = str_to_float(arg)

	static ungag_time2[64], gag_time2[64]

	if(length == 0.0) formatex(ungag_time2, sizeof(ungag_time2) - 1, "Örök némítás")
	else GenerateUnGagTime(length, ungag_time2, sizeof(ungag_time2) - 1)

	read_argv(3, arg, sizeof(arg) - 1)

	static target_name[32]
	get_user_name(target, target_name, sizeof(target_name) - 1)
	
	static admin_authid[35]
	get_user_authid(id, admin_authid, sizeof(admin_authid) - 1)

	GagAdd(target_name, target_authid, arg, floatround(length * 60.0, floatround_floor), ungag_time2)

	GetGagTime(id, length, gag_time2, sizeof(gag_time2) - 1)
	
	print_color(0, "^4ADMIN ^1lenémította ^3%s^1-t. [Oka: ^4%s^1] [Ideje: ^4%s^1] [Lejárata: ^4%s^1]", target_name, arg, gag_time2, ungag_time2)
	
	return PLUGIN_HANDLED
}

public concmd_gag_ip(id, level, cid) {
	if(!cmd_access(id, level, cid, 4)) return PLUGIN_HANDLED
	
	static arg[128]
	read_argv(1, arg, sizeof(arg) - 1)
	
	new target = cmd_target(id, arg, GetTargetFlags(id))
	if(!target) return PLUGIN_HANDLED
	
	static target_ip[35]
	get_user_ip(target, target_ip, sizeof(target_ip) - 1, 1)

	if(TrieKeyExists(g_trie, target_ip)) {
		console_print(id, "IP [%s] már le van némítva!", target_ip)
		return PLUGIN_HANDLED
	}

	read_argv(2, arg, sizeof(arg) - 1)
	new Float:length = str_to_float(arg)

	static ungag_time2[64], gag_time2[64]

	if(length == 0.0) formatex(ungag_time2, sizeof(ungag_time2) - 1, "Örök némítás")
	else GenerateUnGagTime(length, ungag_time2, sizeof(ungag_time2) - 1)

	read_argv(3, arg, sizeof(arg) - 1)

	static target_name[32]
	get_user_name(target, target_name, sizeof(target_name) - 1)
	
	static admin_authid[35]
	get_user_authid(id, admin_authid, sizeof(admin_authid) - 1)

	GagAdd(target_name, target_ip, arg, floatround(length * 60.0, floatround_floor), ungag_time2)

	GetGagTime(id, length, gag_time2, sizeof(gag_time2) - 1)
	print_color(0,"^4ADMIN ^1lenémította ^3%s^1-t. [Oka: ^4%s^1] [Ideje: ^4%s^1] [Lejárata: ^4%s^1]", target_name, arg, gag_time2, ungag_time2)
	
	return PLUGIN_HANDLED
}

public concmd_gag_add(id, level, cid) {
	if(!cmd_access(id, level, cid, 5)) return PLUGIN_HANDLED

	static target_name[128], target_authid[128], gagtime[128], reason[128]
	read_argv(1, target_name, sizeof(target_name) - 1)
	read_argv(2, target_authid, sizeof(target_authid) - 1)
	read_argv(3, gagtime, sizeof(gagtime) - 1)
	read_argv(4, reason, sizeof(reason) - 1)
	
	new bool:is_ip = bool:(containi(target_authid, ".") != -1)

	if(TrieKeyExists(g_trie, target_authid)) {
		console_print(id, "%L", id, is_ip ? "ALREADY_GAGGED_IP" : "ALREADY_GAGGED_STEAMID", target_authid)
		return PLUGIN_HANDLED
	}

	new Float:length = str_to_float(gagtime) 
	static ungag_time2[64], gag_time2[64]

	if(length == 0.0) formatex(ungag_time2, sizeof(ungag_time2) - 1, "Örök némítás")
	else GenerateUnGagTime(length, ungag_time2, sizeof(ungag_time2) - 1)

	GagAdd(target_name, target_authid, reason, floatround(length * 60.0, floatround_floor), ungag_time2)

	GetGagTime(id, length, gag_time2, sizeof(gag_time2) - 1)
	
	print_color(0,"^4ADMIN ^1lenémította ^3%s^1-t. [Oka: ^4%s^1] [Ideje: ^4%s^1] [Lejárata: ^4%s^1]", target_name, reason, gag_time2, ungag_time2)	

	return PLUGIN_HANDLED
}	

public concmd_ungag(id, level, cid) {
	if(!cmd_access(id, level, cid, 2)) return PLUGIN_HANDLED
	
	static arg[35]
	read_argv(1, arg, sizeof(arg) - 1)

	if(TrieKeyExists(g_trie, arg)) {
		static array_pos;
		TrieGetCell(g_trie, arg, array_pos);
		
		static data[GagData]
		ArrayGetArray(g_array, array_pos, data)
		
				
		static authid[35]
		get_user_authid(id, authid, sizeof(authid) - 1)
		
		print_color(0, "^4ADMIN ^1feloldotta a némítását neki: ^3%s ^1. [Némítás Oka: ^4%s^1]", data[gag_name], data[gag_reason])
		
		RemoveGag(array_pos, data[gag_steamid])
		
		return PLUGIN_HANDLED
	}

	console_print(id, "Nem található némítás!", arg)

	return PLUGIN_HANDLED
}

public concmd_gag_list(id, level, cid) {
	if(!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED
	
	if(!total_gags) {
		console_print(id, "Nem található némítás!")
		return PLUGIN_HANDLED;
	}
	
	static start
	if(read_argc() > 1) {
		static arg[5]
		read_argv(1, arg, sizeof(arg) - 1)
		
		start = min(str_to_num(arg), total_gags) - 1
	}
	
	else start = 0
	
	new last = min(start + 10, total_gags)
	
	if(id == 0) server_cmd("echo ^"%L^"", id, "GAG_LIST_NUM", start + 1, last)
	else console_print(id, "%L", id, "GAG_LIST_NUM", start + 1, last)
	
	for(new i = start; i < last; i++) {
		static data[GagData]
		ArrayGetArray(g_array, i, data)
		
		PrintGagInfosToConsole(id, data[gag_name], data[gag_steamid], data[gag_length], data[gag_reason], data[ungag_time])
	}
	
	if(++last < total_gags) {
		if(id == 0) server_cmd("echo ^"%L^"", id, "GAG_LIST_NEXT", last)
		else console_print(id, "%L", id, "GAG_LIST_NEXT", last)
	}
	
	return PLUGIN_HANDLED
}	

public gag_menu(id) {
	if(!(get_user_flags(id) & GAG_FLAG))
		return PLUGIN_HANDLED
	
	new menu_line[99], menu_newline[99], id_data[64]
	format(menu_line, charsmax(menu_line), "\r[uT-team] \yTíltó Menü^n\r[\yKit szeretnél letiltani?\r]")
	
	new menu = menu_create(menu_line, "gag_menu_handler")
	
	new players[32], name[32], num
	get_players(players, num, "c")
	
	for(new i = 0; i <num; i++) {
		new pid = players[i]
		get_user_name(pid, name, 31)
		num_to_str(pid, id_data, sizeof(id_data))
		
		format(menu_newline, charsmax(menu_newline), "%s", name)
		menu_additem(menu, menu_newline, id_data, 0)
	}
	
	menu_display(id, menu, 0)
	return PLUGIN_CONTINUE
}

public ungag_menu(id) {
	if(!(get_user_flags(id) & GAG_FLAG))
		return PLUGIN_HANDLED

	if(!total_gags) {
		
		print_color(id, "^4Nem található feloldható némítás!")
		
		return PLUGIN_HANDLED
	}
	
	new menu_line[99], menu_newline[200]
	format(menu_line, charsmax(menu_line), "\r[uT-team] \yFeloldó Menü^n\r[\yKit szeretnél feloldani?\r]")
	
	new menu = menu_create(menu_line, "ungag_menu_handler")
	
	for(new i = 0; i < total_gags; i++) {
		static data[GagData]
		ArrayGetArray(g_array, i, data)
		
		format(menu_newline, charsmax(menu_newline), "\r[\y%s\r]\w||\r[\y%s\r]\w||\r[\dok:\y%s\r]", data[gag_name] , data[gag_steamid], data[gag_reason])
		menu_additem(menu, menu_newline, data[gag_steamid], 0)
	}
	
	menu_display(id, menu, 0)
	return PLUGIN_CONTINUE
}

public gag_menu_handler(id, menu, item) {
	if(item == MENU_EXIT) {
		menu_destroy(menu)
		return PLUGIN_HANDLED
	}
	
	new data[64], szName[64]
	new access, callback
	menu_item_getinfo(menu, item, access, data,charsmax(data), szName,charsmax(szName), callback)
	
	tempid[id] = str_to_num(data)
	
	static authid[35]
	get_user_authid(tempid[id], authid, sizeof(authid) - 1)
	
	static ip[35]
	get_user_ip(tempid[id], ip, sizeof(ip) - 1, 1)
	static array_pos	
	
	if(get_user_flags(tempid[id]) & GAG_IMMUNITY) {
		
			print_color(id, "^1Ez a játésok ^4ADMIN^1, őt nem tudod lenémítani! Válassz máskit!")
			
			gag_menu(id)
			return PLUGIN_HANDLED
	}
	else if(TrieGetCell(g_trie, authid, array_pos) || TrieGetCell(g_trie, ip, array_pos)) {
		static data[GagData]
		ArrayGetArray(g_array, array_pos, data)

		static gag_length2[64]
		new Float:gag_len = float(data[gag_length]) / 60.0
		GetGagTime(id, gag_len, gag_length2, sizeof(gag_length2) - 1)
		
		print_color(id, "^4Ez a játékos már le van némítva! ^1[Oka: ^4%s^1] [Ideje: ^4%s^1] [Lejárata: ^4%s^1]", data[gag_reason], gag_length2, data[ungag_time])
		
		return PLUGIN_HANDLED
	}
	
	else { 
	
			print_color(id, "^4Írd be az időt!   ^1(percben)^4!")
			
			client_cmd(id, "messagemode GAG_TIME")
	}
	
	return PLUGIN_CONTINUE
}

public ungag_menu_handler(id, menu, item) {
	if(item == MENU_EXIT) {
		menu_destroy(menu)
		return PLUGIN_HANDLED
	}
	
	new data[64], szName[64]
	new access, callback
	menu_item_getinfo(menu, item, access, data, charsmax(data), szName, charsmax(szName), callback)

	client_cmd(id, "ungag ^"%s^"", data)

	return PLUGIN_CONTINUE
}

public clcmd_time(id) {
	if(!(get_user_flags(id) & GAG_FLAG))
		return PLUGIN_HANDLED

	new gag_times[33][100]
	read_args(gag_times[id], 99)
	remove_quotes(gag_times[id])

	get_gag_time[id] = str_to_float(gag_times[id])
	
	print_color(id, "^4Írd be az okot!")
	
	client_cmd(id, "messagemode GAG_REASON")
	
	return PLUGIN_HANDLED
}

public clcmd_reason(id) {
	if(!(get_user_flags(id) & GAG_FLAG))
		return PLUGIN_HANDLED

	new get_gag_reason[33][100]
	read_args(get_gag_reason[id], 99)
	remove_quotes(get_gag_reason[id])
	
	static target_authid[32]
	get_user_authid(tempid[id], target_authid, sizeof(target_authid) - 1)

	client_cmd(id, "gag_authid ^"%s^" ^"%f^" ^"%s^"", target_authid, get_gag_time[id], get_gag_reason[id])
	
	return PLUGIN_HANDLED
}

public gag_say(id) {
	static authid[35]
	get_user_authid(id, authid, sizeof(authid) - 1)
	
	static ip[35]
	get_user_ip(id, ip, sizeof(ip) - 1, 1)

	static array_pos	
	if(TrieGetCell(g_trie, authid, array_pos) || TrieGetCell(g_trie, ip, array_pos)) {
		static data[GagData]
		ArrayGetArray(g_array, array_pos, data)

		static gag_length2[64]
		new Float:gag_len = float(data[gag_length]) / 60.0
		GetGagTime(id, gag_len, gag_length2, sizeof(gag_length2) - 1)
		
		print_color(id, "^4Le vagy némítva! ^1[Oka: ^4%s^1] [Ideje: ^4%s^1] [Lejárata: ^4%s^1]", data[gag_reason], gag_length2, data[ungag_time])
		
		return PLUGIN_HANDLED
	}
	
	return PLUGIN_CONTINUE
}

public PrintGagInfosToConsole(index, const target_name[], const target_steamid[], const target_length, const target_reason[], const target_ungag_time[]) {
	static gag_length2[64]
	new bool:is_ip = bool:(containi(target_steamid, ".") != -1)
	
	if(index == 0) {
		server_print("************************************************")
		server_print("Nemitas Informacio")
		server_print("Nev: %s", target_name)
		server_print("%L: %s", index, !is_ip ? "GAG_STEAMID" : "GAG_IP", target_steamid)
		server_print("Ok: %s", target_reason)
		if(target_length > 0) {
			new Float:gag_len = float(target_length) / 60.0
			GetGagTime(index, gag_len, gag_length2, sizeof(gag_length2) - 1)

			server_print("Nemitas ideje: %s", gag_length2)
		}
		server_print("Nemitas feloldasa: %s", target_ungag_time)
		server_print("************************************************")
	}
	
	else {
		console_print(index, "************************************************")
		console_print(index, "Nemitas Informacio")
		console_print(index, "Nev: %s", target_name)
		console_print(index, "%L: %s", index, !is_ip ? "GAG_STEAMID" : "GAG_IP", target_steamid)
		console_print(index, "Ok: %s", target_reason)
		if(target_length > 0) {
			new Float:gag_len = float(target_length) / 60.0
			GetGagTime(index, gag_len, gag_length2, sizeof(gag_length2) - 1)

			console_print(index, "Nemitss ideje: %s", gag_length2)
		}
		console_print(index, "Nemitas feloldasa: %s", target_ungag_time)
		console_print(index, "************************************************")
	}
}

public LoadGags() {
	if(total_gags) {
		TrieClear(g_trie)
		ArrayClear(g_array)
		total_gags = 0
	}
	
	if(file_exists(gag_file)) {
		new f = fopen(gag_file, "rt")
		static filedata[512], length[10]
		
		static data[GagData]
		while(!feof(f)){
			fgets(f, filedata, sizeof(filedata) - 1)
			
			if(!filedata[0]) continue
			
			parse(filedata,\
				data[gag_steamid], sizeof(data[gag_steamid]) - 1,\
				data[gag_name], sizeof(data[gag_name]) - 1,\
				length, sizeof(length) - 1,\
				data[ungag_time], sizeof(data[ungag_time]) - 1,\
				data[gag_reason], sizeof(data[gag_reason]) - 1
				)
			
			data[gag_length] = str_to_num(length)
			
			ArrayPushArray(g_array, data)
			TrieSetCell(g_trie, data[gag_steamid], total_gags)
					
			total_gags++
		}
		
		fclose(f)
	}
}

public RemoveGag(pos, const authid[]) {
	TrieDeleteKey(g_trie, authid)
	ArrayDeleteItem(g_array, pos)
	
	total_gags--
	
	new f = fopen(gag_file, "wt")
	new data[GagData]

	for(new i = 0; i < total_gags; i++ ) {
		ArrayGetArray(g_array, i, data)
		TrieSetCell(g_trie, data[gag_steamid], i)
		
		fprintf(f, "^"%s^" ^"%s^" ido: %iperc ^"%s^" ^"%s^"^n",\
			data[gag_steamid],\
			data[gag_name],\
			data[gag_length],\
			data[ungag_time],\
			data[gag_reason]
			)
	}
	
	fclose(f)
}

public GagAdd(const target_name[], const target_steamid[], const reason[], const length, const ungag_time3[]) {
	new f = fopen(gag_file, "a+")
	
	fprintf(f, "^"%s^" ^"%s^" ido: %iperc ^"%s^" ^"%s^"^n",\
		target_steamid,\
		target_name,\
		length,\
		ungag_time3,\
		reason
		)
	
	fclose(f)

	static data[GagData]
	copy(data[gag_name], sizeof(data[gag_name]) - 1, target_name)
	copy(data[gag_steamid], sizeof(data[gag_steamid]) - 1, target_steamid)
	data[gag_length] = length
	copy(data[ungag_time], sizeof(data[ungag_time]) - 1, ungag_time3)
	copy(data[gag_reason], sizeof(data[gag_reason]) - 1, reason)
	
	TrieSetCell(g_trie, target_steamid, total_gags)
	ArrayPushArray(g_array, data)
	
	total_gags++
}

GetGagTime(index, Float:gagtime, length[], len) {
	new minutes = floatround(gagtime, floatround_floor)
	new seconds = floatround(floatfract(gagtime) * 60, floatround_floor)
	new hours = 0
	new days = 0
	
	while(minutes >= 60) {
		minutes -= 60
		hours++
	}
	
	while(hours >= 24) {
		hours -= 24
		days++
	}
	
	new bool:add_before
	if(seconds) {
		formatex(length, len, "%i Másodperc", seconds)	
		add_before = true
	}

	if(minutes) {
		if(add_before) format(length, len, "%i Perc, %s", minutes, length)

		else{
			formatex(length, len, "%i Perc", minutes)			
			add_before = true
		}
	}

	if(hours) {
		if(add_before) format(length, len, "%i Óra, %s", hours, length)

		else{
			formatex(length, len, "%i Óra", hours, index, "GAG_HOURS")			
			add_before = true
		}
	}

	if(days) {
		if(add_before) format(length, len, "%i %L, %s", days, index, "GAG_DAYS", length)

		else {
			formatex(length, len, "%i Nap", days, index, "GAG_DAYS")			
			add_before = true
		}
	}

	if(!add_before) formatex(length, len, "Nap")
}

GetTargetFlags(index) {
	static const flags_no_immunity = (CMDTARGET_ALLOW_SELF|CMDTARGET_NO_BOTS)
	static const flags_immunity = (CMDTARGET_ALLOW_SELF|CMDTARGET_NO_BOTS|CMDTARGET_OBEY_IMMUNITY)
	
	switch(get_pcvar_num(gag_immunity)) {
		case 1: return flags_immunity
		case 2: return access(index, GAG_IMMUNITY) ? flags_no_immunity : flags_immunity
	}
	
	return flags_no_immunity
}
	
GenerateUnGagTime(const Float:input, output[], const len) {
	static _hours[5], _minutes[5], _seconds[5], _month[5], _day[5], _year[7]
	format_time(_hours, sizeof(_hours) - 1, "%H")
	format_time(_minutes, sizeof(_minutes) - 1, "%M")
	format_time(_seconds, sizeof(_seconds) - 1, "%S")
	format_time(_month, sizeof(_month) - 1, "%m")
	format_time(_day, sizeof(_day) - 1, "%d")
	format_time(_year, sizeof(_year) - 1, "%Y")
 
	new hours = str_to_num(_hours)
	new month = str_to_num(_month)
	new day = str_to_num(_day)
	new year = str_to_num(_year)

	new minutes = floatround(input, floatround_floor) + str_to_num(_minutes)
	new seconds = floatround(floatfract(input) * 60, floatround_floor)

	while(minutes >= 60) {
		minutes -= 60
		hours++
	}
 
	while(hours >= 24) {
		hours -= 24
		day++
	}

	new max_days = GetDaysInMonth(month, year)
	while(day > max_days) {
		day -= max_days
		month++
	}
 
	while(month > 12) {
		month -= 12
		year++
	}

	seconds += str_to_num(_seconds)
	if(seconds > 59) {
		seconds -= 60
		if(minutes < 59) minutes++

		else {
			minutes = 0
			if(hours < 23) hours++

			else {
				hours = 0
				if(day < max_days) day++

				else {
					day = 1
					if(month < 12) month++

					else {
						month = 1
						year++
					}
				}
			}
		}
	}	

	formatex(output, len, "%i:%02i:%02i %i/%i/%i", hours, minutes, seconds, month, day, year)
}

GetDaysInMonth(month, year=0) {
	switch(month) {
		case 1:	return 31 // January
		case 2:	return ((year % 4) == 0) ? 29 : 28 // February
		case 3:	return 31; // March
		case 4:	return 30; // April
		case 5:	return 31; // May
		case 6:	return 30; // June
		case 7:	return 31; // July
		case 8:	return 31; // August
		case 9:	return 30; // September
		case 10: return 31; // October
		case 11: return 30; // November
		case 12: return 31; // December
	}
	 
	return 30
}

stock print_color(const id, const input[], any:...)
{
        new count = 1, players[32]
        static msg[191]
        vformat(msg, 190, input, 3)
 
        replace_all(msg, 190, "!g", "^4")
        replace_all(msg, 190, "!y", "^1")
        replace_all(msg, 190, "!t", "^3")
 
        if (id) players[0] = id; else get_players(players, count, "ch")
        {
                for (new i = 0; i < count; i++)
                {
                        if (is_user_connected(players[i]))
                        {
                                message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), _, players[i])
                                write_byte(players[i])
                                write_string(msg)
                                message_end()
                        }
                }
        }
        return PLUGIN_HANDLED
}
