Just use a anticheat system.
Код:
#define FILTERSCRIPT
#include <a_samp>
new Float:previousHealthValue[MAX_PLAYERS],
hits[MAX_PLAYERS],
noDamageCount[MAX_PLAYERS], //count how many times the player didn't lose health after being hit
bool:delayer[MAX_PLAYERS], // delayer is neccessary because damage is not updated quickly enough and gives false detections
bool:afterSpawnCover[MAX_PLAYERS], //to avoid false detections straight after spawn which happened to me while testing it (it's set to 3 seconds right now)
bool:isDead[MAX_PLAYERS]; // hp check to see if the player is dead didn't work(the value of hp stayed the same as before last shot)
////////////////////////////////
//SETTINGS
#define DELAY_TIME 500 // 500ms delay works well on my syrver with 2 players online, I'm not sure what's it's going to be like on a server with over 100 players online
#define AFTER_SPAWN_COVER_TIME 3000
#define NO_DAMAGE_COUNT_LIMIT 0 // number of times the script detected someone taking no damage after shot needed to: send info to admins/kick/ban
//SETTINGS
////////////////////////////////
public OnFilterScriptInit()
{
print("\n--------------------------------------");
print("Health-hack detector by monday");
print("--------------------------------------\n");
return 1;
}
public OnPlayerConnect(playerid)
{
previousHealthValue[playerid] = 0.0;
hits[playerid] = 0;
noDamageCount[playerid] = 0;
delayer[playerid] = false;
return 1;
}
public OnPlayerDeath(playerid, killerid, reason)
{
isDead[playerid] = true;
return 1;
}
public OnPlayerSpawn(playerid)
{
previousHealthValue[playerid] = 0.0;
hits[playerid] = 0;
delayer[playerid] = false;
afterSpawnCover[playerid] = true;
SetTimerEx("RemoveSpawnCover", AFTER_SPAWN_COVER_TIME, false, "i", playerid);
isDead[playerid] = false;
return 1;
}
forward SwitchDelay(playerid);
public SwitchDelay(playerid)
{
delayer[playerid] = true;
return 1;
}
forward RemoveSpawnCover(playerid);
public RemoveSpawnCover(playerid)
{
afterSpawnCover[playerid] = false;
return 1;
}
public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
if(hittype == BULLET_HIT_TYPE_PLAYER)
{
new Float:h, Float:a, Float:newHealthValue, message[128], cheaterName[MAX_PLAYER_NAME];
if(hits[hitid] == 0)
{
GetPlayerHealth(hitid, h);
GetPlayerArmour(hitid, a);
previousHealthValue[hitid] = h + a;
if(isDead[hitid] == true || afterSpawnCover[hitid] == true) // + here must be a check for AFK to avoid false detections
{
hits[hitid] = 0;
}
else
{
SetTimerEx("SwitchDelay", DELAY_TIME, false, "i", hitid);
}
}
else if(delayer[hitid] == true)
{
delayer[hitid] = false;
GetPlayerHealth(hitid, h);
GetPlayerArmour(hitid, a);
newHealthValue = h + a;
if(newHealthValue == previousHealthValue[hitid] && isDead[hitid] != true && afterSpawnCover[hitid] != true)
{
noDamageCount[hitid]++;
if(noDamageCount[hitid] > NO_DAMAGE_COUNT_LIMIT)
{
//send message to admins, kick, ban
GetPlayerName(hitid, cheaterName, sizeof(cheaterName));
format(message,sizeof(message),"%s didn't lose health %d times after being shot since his last login.",cheaterName, noDamageCount[hitid]);
SendClientMessageToAll(0xED6755AA,message);
}
}
else
{
previousHealthValue[hitid] = newHealthValue; //update health value if it decreased like it should
}
SetTimerEx("SwitchDelay", DELAY_TIME, false, "i", hitid); // new delay before next check
}
hits[hitid]++;
}
return 1;
}