// Anticheat by Valera_Trefilov

#define AC:: AC_
#define MAX_WARNS (2)


forward onCheckUnfreezeTimer(playerid);
forward onAntiCheatUpdate();
forward onCheckAirBrk(playerid);
forward onCheckSpeedHack(playerid);
forward onCheckFlyHack(playerid);
forward onCheckRepairHack(playerid);

new	AC::MaxSpeedCar[212] = {
	87,81,103,-1,73,91,-1,-1,-1,-1,-1,123,93,-1,-1,106,-1,-1,64,82,93,82,82,-1,75,-1,94,-1,-1,112,-1,-1,-1,-1,92,-1,85,-1,-1,93,-1,-1,-1,-1,62,90,-1,-1,-1,-1,-1,107,-1,-1,-1,-1,-1,-1,87,-1,-1,88 ,-1,79 ,-1,-1,
	87,87,79,-1,-1,61,-1,-1,82,96,-1,103,75,77,102,-1,-1,-1,-1,-1,-1,-1,-1,77,-1,82,78,-1,119,97,90,-1,-1,-1,-1,-1,119,119,-1,-1,99,92,-1,-1,-1,-1,
	-1,-1,-1,-1,87,87,91,-1,-1,88,95,-1,-1,-1,-1,87,82,-1,82,-1,-1,-1,90,93,87,96,-1,-1,-1,82,112,91,73,-1,81,82,79,-1,85,80,87,-1,-1,84,87,-1,-1,86,98,94,
	85,98,-1,-1,91,88,96,-1,-1,-1,-1,-1,-1,-1,87,87,-1,-1,87,85,88,-1,-1,-1,87,87,91,-1,90,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,82,-1,93,95,87,73,-1
};


enum ACInfo
{
	Float: AC::Pos_X,
	Float: AC::Pos_Y,
	Float: AC::Pos_Z,
	Float: AC::VehHealth,
	AC::LastUpdate,
	AC::Warns,
	AC::VehTime
}
new AC::Info[MAX_PLAYERS][ACInfo];

public onAntiCheatUpdate()
{
	foreach(Player, i)
	{
	    if(!IsPlayerConnected(i)) continue;
	    onCheckAirBrk(i);
	    onCheckFlyHack(i);
	    if(GetPVarInt(i, "Protect") > 0) SetPVarInt(i, "Protect", GetPVarInt(i, "Protect") - 1);
	    //
	    if(IsPlayerInAnyVehicle(i))
	    {
	        GetVehicleHealth(GetPlayerVehicleID(i),AC::Info[i][AC::VehHealth]);
	    	onCheckSpeedHack(i);
	    	onCheckRepairHack(i);
		}
	}
}

public onCheckRepairHack(playerid)
{
    new Float: AC::VehHealtz[MAX_PLAYERS];
 	GetVehicleHealth(GetPlayerVehicleID(playerid),AC::VehHealtz[playerid]);
   	if(!IsPlayerInAnyVehicle(playerid) && GetPlayerState(playerid) != PLAYER_STATE_DRIVER) return true;
   	if(!AC::NotRepairHack(playerid)) return true;
    if(AC::VehHealtz[playerid] > 1000) AC::Kick(playerid, "8472");
	if(AC::Info[playerid][AC::VehHealth] > AC::VehHealtz[playerid]) AC::Kick(playerid, "8472");
	return true;
}

public onCheckAirBrk(playerid)
{
    	new Float: AC::Pos[3], Float: distance;
    	GetPlayerPos(playerid, AC::Pos[0], AC::Pos[1], AC::Pos[2]);
    	distance = floatround(GetPlayerDistanceFromPoint(playerid, AC::Info[playerid][AC::Pos_X], AC::Info[playerid][AC::Pos_Y], AC::Info[playerid][AC::Pos_Z]));
    	if(GetPVarInt(playerid, "Protect") == 0)
    	{
        	if(GetPlayerState(playerid) == 1)
        	{
            	if(distance > 40) AC::Kick(playerid, "6801");
        	}
        	else
        	{
            	if(distance > 80) AC::Kick(playerid, "6801");
        	}
    	}
	    AC::Info[playerid][AC::Pos_X] = AC::Pos[0];
	    AC::Info[playerid][AC::Pos_Y] = AC::Pos[1];
	    AC::Info[playerid][AC::Pos_Z] = AC::Pos[2];
	    if(GetTickCount() - AC::Info[playerid][AC::LastUpdate] > 2000) SetPVarInt(playerid, "Protect", 500);
	    AC::Info[playerid][AC::LastUpdate] = GetTickCount();
	    return true;
}

public onCheckSpeedHack(playerid)
{
    if(!AC::NotAntiCheatHack(playerid)) return true;
    if(AC::MaxSpeedCar[GetVehicleModel(GetPlayerVehicleID(playerid)-400)] == -1) return true;
   	new Float: AC::Pos[3], Float:distance;
   	GetPlayerPos(playerid, AC::Pos[0], AC::Pos[1], AC::Pos[2]);
   	distance = floatround(GetPlayerDistanceFromPoint(playerid, AC::Pos[0], AC::Pos[1], AC::Pos[2]));
    if(AC::SpeedCar(playerid) > AC::MaxSpeedCar[GetVehicleModel(GetPlayerVehicleID(playerid)-400)]+30) AC::Kick(playerid, "1801");
    else if(distance > 40) AC::Kick(playerid, "1801");
    return true;
}

public onCheckFlyHack(playerid)
{
	if(IsPlayerInAnyVehicle(playerid)) return true;
	new Float:X, Float:Y, Float:Z;
	new var = GetPlayerAnimationIndex(playerid);
	GetPlayerPos(playerid, X, Y, Z);
	if(Z >= 2 && (var == 1543 || var == 1538 || var == 1539 || var == 1544))
	{
	    if(!AC::NotAntiCheatHack(playerid)) return true;
		if(IsPlayerInRangeOfPoint(playerid, 300.0, -1084.94,2649.50,40.04) && Z < 45) return true;
		else if(IsPlayerInRangeOfPoint(playerid, 50.0, 2108.07,1907.37,10.0) && Z < 10) return true;
		else if(IsPlayerInRangeOfPoint(playerid, 50.0, 1962.66,-1190.69,17.45) && Z < 20) return true;
		else if(IsPlayerInRangeOfPoint(playerid, 200, -758.4480,-1986.5779,5.3543) && Z <= 7.0) return true;
		else if(IsPlayerInRangeOfPoint(playerid, 180, -568.3068,2197.2542,40.0401) && Z <= 41.0) return true;
		if(AC::Info[playerid][AC::Warns] < MAX_WARNS) return AC::Freeze(playerid, 2000),AC::Info[playerid][AC::Warns]++;
		else AC::Kick(playerid, "3478");
	}
	return true;
}

AC::NotAntiCheatHack(playerid)
{
	if(IsPlayerInRangeOfPoint(playerid, 28, 1095.2384,-672.5684,111.4500)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 28, 1277.8842,-805.4534,86.1230)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 56, 2532.0527,1571.6040,8.4171)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 54, 2159.9509,1283.8008,7.3372)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 54, 1240.1476,-2383.6343,8.3145)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 75, 1947.6244,1613.9171,8.0484)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 45, -2718.9143,-447.1990,3.3696)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 100.0, 1962.16,1599.64,10.0)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 50.0, 2147.28,1131.29,10.0)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 1237.01,-2378.30,10.0)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 300.0, -1168.11,2151.00,40.0)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 300.0, -958.11,2401.0,40.0)) return true;
	else return false;
}

AC::NotRepairHack(playerid)
{
	if(IsPlayerInRangeOfPoint(playerid, 30.0, 2064.2842,-1831.4736,13.5469)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 487.6401,-1739.9479, 11.1385)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 1024.8651,-1024.0870,32.1016)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 617.5467, -2.0437, 1000.5823)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 615.2847,-124.2390, 997.6888)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, -1904.7019,284.5968, 41.0469)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, -2425.7822,1022.1392,50.3977)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, -1420.5195,2584.2305,55.8433)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, -99.9417, 1117.9048, 19.7417)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 1975.2384,2162.5088, 11.0703)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 720.0854, -457.8807, 16.3359)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 615.9690, -75.0127, 997.9922)) return true;
	else if(IsPlayerInRangeOfPoint(playerid, 30.0, 617.5361, -1.9889, 1000.6007)) return true;
	else return false;
}

AC::SpeedCar(playerid)
{
    if(!IsPlayerInAnyVehicle(playerid)) return true;
    new Float:ST[4];
    GetVehicleVelocity(GetPlayerVehicleID(playerid),ST[0],ST[1],ST[2]);
    ST[3] = floatsqroot(floatpower(floatabs(ST[0]), 2.0) + floatpower(floatabs(ST[1]), 2.0) + floatpower(floatabs(ST[2]), 2.0)) * 100.3;
    return floatround(ST[3]);
}

stock AC::Freeze(playerid,time)
{
    TogglePlayerControllable(playerid, false);
    return SetTimerEx("onCheckUnfreezeTimer", time, 0, "i", playerid);
}

public onCheckUnfreezeTimer(playerid)
{
    return TogglePlayerControllable(playerid, true);
}
