#include <amxmodx>
#include <kz>

#define BOOSTID 1538

new paused[33];

new bool:boost[33];
new boosttimer;
new kz_enabled;

public plugin_init()
{
	register_plugin("KZ No Block", KZ_VERSION, "teame06");

	register_saycmd("boost", "cmdBoost", -1, "");
	register_saycmd("toggle_boost", "cmdToggleBoost", -1, "");

	boosttimer = get_cvar_pointer("kz_boosttime");
	kz_enabled = get_cvar_pointer("kz_enabled");
}

public kz_Init(_state)
{
	if(!_state)
	{
		pause("a");
		return;
	}

	if(!get_pcvar_num(kz_enabled))
		return;

	register_forward(FM_StartFrame, "fm_startframe");
}

public plugin_natives()
{
	register_library("kz");
	register_native("IsPlayerPause", "native_IsPlayerPause");
	register_native("SetPlayerPause", "native_SetPlayerPause");

	register_native("SetPlayerNotSolid", "native_not_solid");
	register_native("SetPlayerSolid", "native_solid");
}

public native_solid(id, nums)
{
	if(nums != 1)
		return log_error(AMX_ERR_NATIVE, "Bad native parameters");

	_SetPlayerSolid(get_param(1));
	return 0;
}

public native_not_solid(id, nums)
{
	if(nums != 1)
		return log_error(AMX_ERR_NATIVE, "Bad native parameters");

	_SetPlayerNotSolid(get_param(1));
	return 0;
}

_SetPlayerSolid(id)
{
	if(is_user_alive(id))
	{
		_set_rendering(id);
		set_pev(id, pev_solid, SOLID_BBOX);
	}
}

_SetPlayerNotSolid(id)
{
	if(is_user_alive(id))
	{
		_set_rendering(id, kRenderFxDistort, 0, 0, 0, kRenderTransAdd, 127);
		set_pev(id, pev_solid, SOLID_NOT);
	}
}

public native_IsPlayerPause(id, nums)
{
	if(nums != 1)
		return log_error(AMX_ERR_NATIVE, "Bad native parameters");

	return paused[get_param(1)];
}

public native_SetPlayerPause(id, nums)
{
	if(nums != 2)
		return log_error(AMX_ERR_NATIVE, "Bad native parameters");

	new index = get_param(1);

	if(!is_user_alive(id))
		return 0;

	new mode = get_param(2);

	paused[index] = (mode) ? true : false;

	return 1;
}

public client_disconnect(id)
{
	boost[id] = false;
	paused[id] = false;

	remove_task(id + BOOSTID);
}

public cmdBoost(id)
{
	if(get_pcvar_num(kz_enabled))
	{
		new boostid = id + BOOSTID;

		if(!boost[id])
		{
			boost[id] = true;
			set_task(get_pcvar_float(boosttimer), "cmdUNBoost", boostid);
			kz_ShowSyncHudMsg(id, 128, 0, 128, 0.43, 0.89, "Boost is enabled.");
		}
		else
		{
			boost[id] = false;
			remove_task(boostid);
			kz_ShowSyncHudMsg(id, 128, 0, 128, 0.43, 0.89, "Boost is disabled.");
		}
		return PLUGIN_HANDLED;
	}
	return PLUGIN_CONTINUE;
}

public cmdUNBoost(boost_id)
{
	if(kz_enabled)
	{
		new id = boost_id - BOOSTID;

		boost[id] = false;
		kz_ColorChat(id, green, "[kz] Boost is disabled because timer has ran out.");
	}
}

public cmdToggleBoost(id)
{
	if(get_pcvar_num(kz_enabled))
	{
		if(!boost[id])
		{
			boost[id] = true;
			kz_ShowSyncHudMsg(id, 128, 0, 128, 0.30, 0.89, "Boost is enabled. To disable type /boost");
		}
		else
		{
			boost[id] = false;
			kz_ShowSyncHudMsg(id, 128, 0, 128, 0.43, 0.89, "Boost is disabled.");
		}
		return PLUGIN_HANDLED;
	}
	return PLUGIN_CONTINUE;
}

public fm_startframe()
{
	if(get_pcvar_num(kz_enabled))
	{
		static players[32], num, i, j, player, person;
		static Float:player_origin[3], Float:person_origin[3], Float:player_origin2[3], Float:person_origin2[3];
		get_players(players, num, "ach");

		for(i = 0; i < num; i++)
		{
			player = players[i];

			if(paused[player])
				continue;

			_SetPlayerSolid(player);
			pev(player, pev_origin, player_origin);

			player_origin2[2] = player_origin[2];
			player_origin[2] = 0.0;

			for(j = 0; j < num; j++)
			{
				person = players[j];

				if(player == person || paused[person])
					continue;

				if(boost[player] && boost[person] && IsPlayerSolid(player) && IsPlayerSolid(person))
					break;

				pev(person, pev_origin, person_origin);
				person_origin2[2] = person_origin[2];
				person_origin[2] = 0.0;

				if((vector_distance(player_origin, person_origin) < 90 && vector_distance(player_origin2, person_origin2) < 110))
				{
					_SetPlayerNotSolid(player);
					_SetPlayerNotSolid(person);
					break;
				}
			}
		}
	}
	return FMRES_IGNORED;
}

IsPlayerSolid(id)
{
	if(pev(id, pev_solid) == SOLID_BBOX)
		return 1;

	return 0;
}

// Not sure if this function is useful.
stock _check_collision ( entity1, entity2 )
{
	// supplied with invalid entities
	if( !pev_valid(entity1) || !pev_valid(entity2) )
		return 0;

	// retrieve absolutes
	static Float:absmin1[3], Float:absmax1[3], Float:absmin2[3], Float:absmax2[3];

	pev(entity1, pev_absmin, absmin1);
	pev(entity1, pev_absmax, absmax1);
	pev(entity2, pev_absmin, absmin2);
	pev(entity2, pev_absmax, absmax2);

	// not in bounds
	if( absmin1[0] > absmax2[0] ||
	    absmin1[1] > absmax2[1] ||
	    absmin1[2] > absmax2[2] ||
	    absmax1[0] < absmin2[0] ||
	    absmax1[1] < absmin2[1] ||
	    absmax1[2] < absmin2[2] )
	    return 0;

	return 1;
}

// Taken from csdm_protection.sma by BAILOPAN.
stock _set_rendering(index, fx=kRenderFxNone, r=255, g=255, b=255, render=kRenderNormal, amount=16)
{
	set_pev(index, pev_renderfx, fx);
	new Float:RenderColor[3];
	RenderColor[0] = float(r);
	RenderColor[1] = float(g);
	RenderColor[2] = float(b);
	set_pev(index, pev_rendercolor, RenderColor);
	set_pev(index, pev_rendermode, render);
	set_pev(index, pev_renderamt, float(amount));

	return 1;
}