#include <a_bodypart>
#define CONSERVATIVE   //Comment for servers less than 100 players....Use @ your own risk.
#define KEY_AIMFIRE 132

#define PRESSED(%0) \
	(((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))

//----WEAPON RANGES PULLED FROM WEAPONS.DAT--Country Rifle -10.0
new
	Float:ranges[39] =
	{
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		0.0,
		35.0,
		35.0,
		35.0,
		40.0,
		35.0,
		40.0,
		45.0,
		35.0,
		70.0,
		90.0,
		35.0,
		90.0,
		100.0,
		0.0,
		0.0,
		0.0,
		25.0
	};

forward HSTimer(playerid);
public HSTimer(playerid)
{
	new keys, ud, lr;
	GetPlayerKeys(playerid, keys, ud, lr);
	if((keys & KEY_FIRE) == (KEY_FIRE) && NoBadCam(playerid))
	{
		switch(GetPlayerWeapon(playerid))
		{
		    case WEAPON_COLT45, WEAPON_UZI, WEAPON_TEC9, WEAPON_MP5, WEAPON_AK47, WEAPON_M4:{
				if(GetPlayerWeaponState(playerid) != WEAPONSTATE_RELOADING){
                	CheckHeadShot(playerid);
					SetTimerEx("HSTimer", 150, 0, "i", playerid);
				}
			}
			case WEAPON_SHOTGSPA, WEAPON_SAWEDOFF:{
				if(GetPlayerWeaponState(playerid) != WEAPONSTATE_RELOADING){
					CheckHeadShot(playerid);
			    	SetTimerEx("HSTimer", 300, 0, "i", playerid);
				}
			}
			case WEAPON_SILENCED:{
				if(GetPlayerWeaponState(playerid) != WEAPONSTATE_RELOADING){
					CheckHeadShot(playerid);
					SetTimerEx("HSTimer", 500, 0, "i", playerid);
				}
			}
			case WEAPON_DEAGLE:{
			    if(GetPlayerWeaponState(playerid) != WEAPONSTATE_RELOADING){
					CheckHeadShot(playerid);
					SetTimerEx("HSTimer", 800, 0, "i", playerid);
				}
			}
			case WEAPON_SHOTGUN:
			{
				if(GetPlayerWeaponState(playerid) != WEAPONSTATE_NO_BULLETS){
					CheckHeadShot(playerid);
					SetTimerEx("HSTimer", 900, 0, "i", playerid);
				}
			}
			case WEAPON_RIFLE:
			{
				if(GetPlayerWeaponState(playerid) != WEAPONSTATE_RELOADING){
			    	CheckHeadShot(playerid);
			    	SetTimerEx("HSTimer", 1000, 0, "i", playerid);
				}
			}
		}
	}
	return 1;
}

forward CheckHeadShot(playerid);
public CheckHeadShot(playerid)
{
	new Float:x[4], Float:y[4], Float:z[4], Float:dist = 1.0, Float:range = 0.0;
	GetPlayerCameraPos(playerid, x[0], y[0], z[0]);
	GetPlayerCameraFrontVector(playerid, x[1], y[1], z[1]);
	range = ranges[GetPlayerWeapon(playerid)];
	if(range != 0.0)
	{
		switch(GetPlayerWeapon(playerid))
		{
			case WEAPON_RIFLE:
			{
				if(x[1] < 0.0 && y[1] > 0.0 )
				{
					x[1] += 0.0155;
					y[1] += 0.0155;
				}
				else if(x[1] > 0.0 && y[1] > 0.0)
				{
					x[1] += 0.0155;
					y[1] -= 0.0155;
				}
				else if(x[1] < 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0155;
					y[1] += 0.0155;
				}
				else if(x[1] > 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0155;
					y[1] -= 0.0155;
				}
				if(z[1] > 0.1) z[1] += 0.06;
				else z[1] += 0.05;
			}
			case WEAPON_AK47,WEAPON_M4:
			{
				if(x[1] < 0.0 && y[1] > 0.0 )
				{
					x[1] += 0.0225;
					y[1] += 0.0225;
				}
				else if(x[1] > 0.0 && y[1] > 0.0)
				{
					x[1] += 0.0225;
					y[1] -= 0.0225;
				}
				else if(x[1] < 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0225;
					y[1] += 0.0225;
				}
				else if(x[1] > 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0225;
					y[1] -= 0.0225;
				}
				if(z[1] > 0.0) z[1] += 0.08;
				else if(z[1] < -0.0 && z[1] > -0.5) z[1] += 0.06;
				else if(z[1] < -0.5) z[1] -= 0.05;
			}
			case 22..29,32,38:
			{
				if(x[1] < 0.0 && y[1] > 0.0 )
				{
					x[1] += 0.0325;
					y[1] += 0.0325;
				}
				else if(x[1] > 0.0 && y[1] > 0.0)
				{
					x[1] += 0.0325;
					y[1] -= 0.0325;
				}
				else if(x[1] < 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0325;
					y[1] += 0.0325;
				}
				else if(x[1] > 0.0 && y[1] < 0.0)
				{
					x[1] -= 0.0325;
					y[1] -= 0.0325;
				}
				if(z[1] > 0.0) z[1] += 0.125;
				else z[1] += 0.09;
			}
		}
        x[0] += (2.0 * x[1]);
		y[0] += (2.0 * y[1]);
		do
		{
        	x[0] += (x[1] * 1.0);
           	y[0] += (y[1] * 1.0);
           	z[0] += (z[1] * 1.0);
	        {
	            for(new i = 0; i < MAX_PLAYERS; ++i)
				if( i != playerid)
				{
		            GetPlayerPos(i, x[2], y[2], z[2]);
		            if(GetPlayerSpecialAction(i) == SPECIAL_ACTION_DUCK) z[2] -= 0.6;
					else z[2] += 0.8;
					if(PointInRangeOfPoint(0.5, x[0], y[0], z[0], x[2], y[2], z[2]))
					{
						new Float:ph;
						GetPlayerHealth(i, ph);
						SetPlayerHealth(i, ph-45.0);
						return 1;
					}
				}
	        }
            dist += 1.0;
		}
		while( dist < range );
	}
	return 1;
}

stock NoBadCam(playerid)
{

	new Float:x, Float:y, Float:z,Float:ang;
	GetPlayerCameraFrontVector(playerid, x, y, z);
	GetPlayerFacingAngle(playerid,ang);
	if((x < 0.0 && y > 0.0) && (ang > 90.0 && ang < 300.0)) return 0;
	else if((x > 0.0 && y > 0.0) && (ang > 88.16 && ang < 275.0)) return 0;
	else if((x < 0.0 && y < 0.0) && (ang > 257.30 && ang < 360.0)) return 0;
	else if((x > 0.0 && y < 0.0) && (ang < 88.16 && ang < 257.30)) return 0;
	return 1;
}

stock PointInRangeOfPoint(Float:range, Float:x, Float:y, Float:z, Float:X, Float:Y, Float:Z)
{
    X -= x;
    Y -= y;
    Z -= z;
    return ((X * X) + (Y * Y) + (Z * Z)) < (range * range);
}