02.09.2018, 19:27
Anti Cheat Tips
[*] Know what you're doingBefore you want to counter a cheat, you need to consider these questions:
What is the cheat?
How will this cheat affect the server?
Can this cheat be countered?
Does this cheat occur in my server daily?
Is there a pattern of how this cheat is used?
How will I counter this cheat?
[*] Here is an example
What is the cheat? Players are increasing their health, AKA using Godmode.
How will this cheat affect the server? Players are complaining that DM is unfair in my server because people are cheating so this might affect my playerbase
Can this cheat be countered? Yes it can, multiple ways.
Does this cheat occur in my server daily? Yes, everyday I atleast spot 2-3 people with this cheat. (Severity = HIGH)
Is there a pattern of how this cheat is used? This cheat is used by people with very high packet-loss and high ping meaning they might be using a VPN, so now I have to consider not banning innocents with bad internet.
How will I counter this cheat? There are multiple ways: Set the server maximum health to 99. Check if player is losing health on each shot.
[*] Trying out ideas
So, we have a owner having a problem with health cheaters, but they have thought of 2 solutions. "Set the server maximum health to 99. Check if player is losing health on each shot.".
Okay, let's try it out!
So, the first idea was the set player health to 99. This mean if player health == 100, then they are not innocent. I would suggest using a timer of every 500-750ms to check for every cheat. This way it would be much cleaner than using multiple timers for each cheat detection. Of course you can use OnPlayerUpdate, but we'll save that for later.
[#] First)
Let's make a command for your administrators to set a player's health and give a player some health.
Requirements: zcmd, sscanf2
PHP Code:
CMD:sethealth(playerid, params[])
{
new Float:health, targetid;
if(sscanf(params, "uf", targetid, health)) return SendClientMessage(playerid, -1, "err: /sethealth [id] [value]");
if(health > 99) SendClientMessage(playerid, -1, "err: You cannot set a player's health more than 99. ");
SetPlayerHealth(playerid, health);
}
[#] Second)
Now, let's detect the cheat by using a timer.
PHP Code:
SetTimerEx("OnAntiCheatDetect", 750, true, "i", playerid);
PHP Code:
forward OnAntiCheatDetect(playerid); public OnAntiCheatDetect(playerid)
{
static Float:playerHP;
GetPlayerHealth(playerid, Float:playerHP);
if(playerHP > 99)
{
Kick(playerid);
}
return 1;
}
[#] Third)
Now, here is the second method that we suggested. Check if player is losing health on each shot.
Requirements: callbacks - by emmet
PHP Code:
new totalShots[MAX_PLAYERS], shotsThatDamaged[MAX_PLAYERS];
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid)
{
if(!IsPlayerPaused(playerid)) shotsThatDamaged[playerid]++;
else {
totalShots[playerid] = 0; shotsThatDamaged[playerid] = 0;
}
return 1;
}
public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
if(hittype == BULLET_HIT_TYPE_PLAYER)
{
if(!IsPlayerPaused(hitid))
{
totalShots[hitid]++;
if(totalShots[hitid] - shotsThatDamaged[hitid] > 1)
{
Kick(hitid);
}
}
}
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
totalShots[playerid] = 0;
shotsThatDamaged[playerid] = 0;
return 1;
}
OnPlayerWeaponShot is always called before OnPlayerTakeDamage.
The logic behind the script is that, on OnPlayerWeaponShot we will count TOTAL_SHOTS_THAT_HIT_SOMEONE, and then on OnPlayerTakeDamage we will count TOTAL_SHOTS_THAT_DAMAGED_SOMEONE. If TOTAL_SHOTS_THAT_HIT_SOMEONE - TOTAL_SHOTS_THAT_DAMAGED_SOMEONE is greater than 1, then there was one shot that hit a player, but did not damage a player, so we will detect them as a cheater.
This is where you need to consider the player's packet loss and ping, because sometimes a player might not get damaged from a shot because of lag.
I would counter this by adding a global variable
PHP Code:
flagGODMODE[MAX_PLAYERS]
PHP Code:
flagGODMODE[playerid]++
PHP Code:
if(flagGODMODE > 3)
PHP Code:
flagGODMODE[playerid] = 0;
Well we all know, to shoot and hit a player, your cross-hair must be on the player. It must be facing at a reasonable place to hit the player.
Well anti-aimbot defies that. Apparently, if you aim metres away from the player, you will still manage to damage that player!
Well, that's easy to think of a solution! Let's use my formula:
What is the cheat? Players are using aim-bot to cheat their aim.
How will this cheat affect the server? Players are complaining that DM is unfair in my server because people are cheating so this might affect my playerbase
Can this cheat be countered? Yes it can.
Does this cheat occur in my server daily? Yes, everyday I atleast spot 2-3 people with this cheat. (Severity = HIGH)
Is there a pattern of how this cheat is used? Players are aiming near the player and not at the player
How will I counter this cheat? I can detect the coordinates when the bullets land and see if they are within a reasonable distance of the player.
Code:
|=|> #bullet |=|> #bullet *hit* O *hit* O ***:::: *** * :: * * * * * * *
We can see there that the bullet doesn't hit the player but still does damage.
This is where https://sampwiki.blast.hk/wiki/GetPlayerLastShotVectors is useful. With the GetPlayerLastShotVectors function we can see where the bullet has landed.
[#] First)
PHP Code:
new aimbotWarning[MAX_PLAYERS];
public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)
{
new Float:hitid_X, Float:hitid_Y, Float:hitid_Z;
GetPlayerPos(playerid, Float:hitid_X, Float:hitid_Y, Float:hitid_Z);
new Float:fOriginX, Float:fOriginY, Float:fOriginZ, Float:fHitPosX, Float:fHitPosY, Float:fHitPosZ;
GetPlayerLastShotVectors(playerid, Float:fOriginX, Float:fOriginY, Float:fOriginZ, Float:fHitPosX, Float:fHitPosY, Float:fHitPosZ);
if(!IsPlayerInRangeOfPoint(hitid, Float:1.5, Float:fHitPosX, Float:fHitPosY, Float:fHitPosZ))
{
aimbotWarning[hitid]++;
if(aimbotWarning[hitid] > 3)
{
Kick(hitid);
aimbotWarning[hitid] = 0;
}
return 1;
}
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
aimbotWarning[playerid] = 0;
}
[*] How about more?
[*] Sorry, but I haven't got any more time today to finish off this tutorial, but I will have tomorrow! I will finish off the anti-aimbot tips and then introduce how to tackle people who c-cbug