
/* AMX Mod script.
*
* (c) Copyright 2002, OLO
* This file is provided as is (no warranties).
*
*/

#include <amxmod> /* read this file to learn the functions */

/* cvars:
*  sets how many slots we want keep for admins
*  amx_reserved_slots < value >
*
*  sets kicking rules to keep reservered slots free
*  amx_reservation < value >
*  0 - don't kick anyone
*  1 - kick by shortest playing time
*  2 - kick by worst ping
*/

new maxplayers
new reserved
new kickmethod

check_slots(id,num)
{
	if (reserved > 0) {
		new players = get_playersnum() + num /* on connection we must add you */
		if (players > maxplayers - reserved)
			return  (get_user_flags(id) & ADMIN_RESERVATION) ? 2 : 1
	}
	return 0
}

public delayed_kick(user[])
{
	server_cmd("kick #%d",user[0])
}

kick_lag(skip)
{
	new players[32], inum
	get_players(players,inum)
	new who = 0, ping, loss, worst
	for(new a = 0; a < inum; ++a) {
		if ((get_user_flags(players[a]) & ADMIN_RESERVATION) || (skip == players[a]) )
			continue
		get_user_ping(players[a],ping,loss)
		if ((who == 0) || (ping > worst)) {
			worst = ping
			who = players[a]
		}
	}
	if (who) {
		client_cmd(who,"echo [AMX] Dropped due to slot reservation")
		new userid[1] /* not using disconnect because we want kick also bots */
		userid[0] = get_user_userid(who)
		set_task(1.0,"delayed_kick",0,userid,1) /* allow client to recive his drop reason msg */
	}
}

kick_fresh(skip)
{
	new players[32], inum
	get_players(players,inum)
	new who = 0, time, shortest
	for(new a = 0; a < inum; ++a) {
		if ( (get_user_flags(players[a]) & ADMIN_RESERVATION) || (skip == players[a]) )
			continue
		time = get_user_time(players[a])
		if ((who == 0) || (shortest > time)){
			shortest = time 
			who = players[a]
		}
	
	}
	if (who) {
		client_cmd(who,"echo [AMX] Dropped due to slot reservation")
		new userid[1]
		userid[0] = get_user_userid(who)
		set_task(1.0,"delayed_kick",0,userid,1)
	}
}

public client_disconnect(id)
{
	reserved = get_cvar_num("amx_reserved_slots")
	kickmethod = get_cvar_num("amx_reservation")
	maxplayers = get_maxplayers()

	if (check_slots(id,-1)) {
		switch(kickmethod){
		case 1: kick_fresh(id)
		case 2: kick_lag(id)
		}
	}

	return PLUGIN_CONTINUE
}

public client_putinserver(id)
{
	if (check_slots(id,0)) {
		switch(kickmethod){
		case 1: kick_fresh(0)
		case 2: kick_lag(0)
		}
	}

	return PLUGIN_CONTINUE
}

public client_connect(id)
{
	reserved = get_cvar_num("amx_reserved_slots")
	kickmethod = get_cvar_num("amx_reservation")
	maxplayers = get_maxplayers()

	switch(check_slots(id,1)){
	case 2:	client_cmd(id,"echo [AMX] You are using reserved slot")
	case 1:	
		{
		client_cmd(id,"echo [AMX] No free slots")
		new userid[1]
		userid[0] = get_user_userid(id)
		set_task(1.0,"delayed_kick",0,userid,1)
		}
	}

	return PLUGIN_CONTINUE
}

public plugin_init()
{
	register_plugin("Slots Reservation","0.5","default")
	register_cvar("amx_reserved_slots","2")
	register_cvar("amx_reservation","1")

	return PLUGIN_CONTINUE
}


