[Tutorial] Anti Cheat Tips
#1

Anti Cheat Tips
[*] Know what you're doing

Before 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(playeridparams[])
{
    new 
Float:healthtargetid;
    if(
sscanf(params"uf"targetidhealth)) return SendClientMessage(playerid, -1"err: /sethealth [id] [value]");
    if(
health 99SendClientMessage(playerid, -1"err: You cannot set a player's health more than 99. ");
    
SetPlayerHealth(playeridhealth);

As you can notice, we didn't just make the command. We made the command WITH checks. This is to make sure the administrator doesn't accidentally set anyones health over the limit that will ban a player. When you're trying to implement a counter for a cheat, make sure it cannot be accidentally produced manually by someone.

[#] Second)

Now, let's detect the cheat by using a timer.
PHP Code:
SetTimerEx("OnAntiCheatDetect"750true"i"playerid); 
Here we are making a timer with the callback "OnAntiCheatDetect". Make sure you make the timer's name very readable and clear for what purpose you're going to use it. In my case, this timer will handle all the anti cheat detections. On the second parameter, I have set the timer at 750ms on loop, with the third parameter true.

PHP Code:
forward OnAntiCheatDetect(playerid); public OnAntiCheatDetect(playerid)
{
    static 
Float:playerHP;
    
GetPlayerHealth(playeridFloat:playerHP);
    if(
playerHP 99)
    {
        
Kick(playerid);
    }
    return 
1;

Here in the call back we have collected the player's health on "playerHP" as a float. There was then a condition to check if player's health is greater than 99. Then inside the scope is where the code will be executed, in my case, I wrote Kick(playerid);, however, realistically I would store the value of how much times the player has been detected of cheating and then notify the admins, then kick.


[#] 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(playeridissueridFloat:amountweaponid)
{
    if(!
IsPlayerPaused(playerid)) shotsThatDamaged[playerid]++;
    else { 
            
totalShots[playerid] = 0shotsThatDamaged[playerid] = 0;
         }
    return 
1;
}
public 
OnPlayerWeaponShot(playeridweaponidhittypehitidFloat:fXFloat:fYFloat:fZ)
{
    if(
hittype == BULLET_HIT_TYPE_PLAYER)
    {
        if(!
IsPlayerPaused(hitid))
        {
            
totalShots[hitid]++;
            if(
totalShots[hitid] - shotsThatDamaged[hitid] > 1)
            {
                
Kick(hitid);
            }
        }
    }
    return 
1;
}
public 
OnPlayerDisconnect(playeridreason)
{
    
totalShots[playerid] = 0;
    
shotsThatDamaged[playerid] = 0;
    return 
1;

In here, we are checking for players TOTAL_SHOTS_THAT_HIT_SOMEONE and players TOTAL_SHOTS_THAT_DAMAGED_SOMEONE.
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
, then each time a player gets detected as a cheater I would increase the variable
PHP Code:
flagGODMODE[playerid]++ 
. Then if the variable is greater than 3,
PHP Code:
if(flagGODMODE 3
I would then kick the player and reset the variable for that id on OnPlayerDisconnect,
PHP Code:
flagGODMODE[playerid] = 0
[*] How about anti-aimbot?

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               											  
***::::                                    ***         
 * ::                                       *
 *                                          *
* *                                        * *
That above is a visual representation of aimbot.
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(playeridweaponidhittypehitidFloat:fXFloat:fYFloat:fZ)
{
        new 
Float:hitid_XFloat:hitid_YFloat:hitid_Z;
        
GetPlayerPos(playeridFloat:hitid_XFloat:hitid_YFloat:hitid_Z);
 
        new 
Float:fOriginXFloat:fOriginYFloat:fOriginZFloat:fHitPosXFloat:fHitPosYFloat:fHitPosZ;
        
GetPlayerLastShotVectors(playeridFloat:fOriginXFloat:fOriginYFloat:fOriginZFloat:fHitPosXFloat:fHitPosYFloat:fHitPosZ);
   
 
        if(!
IsPlayerInRangeOfPoint(hitidFloat:1.5Float:fHitPosXFloat:fHitPosYFloat:fHitPosZ))
        {
            
aimbotWarning[hitid]++;
            if(
aimbotWarning[hitid] > 3)
            {
                
Kick(hitid);
                
aimbotWarning[hitid] = 0;
            }
            return 
1;
        }
        return 
1;
}
public 
OnPlayerDisconnect(playeridreason)
{
    
aimbotWarning[playerid] = 0;

From the code above, you can see that we are grabbing the player id's last shot vectors as coordinates so we can compare this to the hit id's coordinates and see if the bullet if within 1.5m of the player, if not, then kick them after a few warnings!


[*] 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
Reply
#2

RESERVED
Reply
#3

Very very nice cant wait to see it finished keep it up
Reply
#4

Quote:
Originally Posted by RogueDrifter
View Post
Very very nice cant wait to see it finished keep it up
Thanks, yeah I'll try to finish it.
Reply
#5

The tutorial is fully understandable and clean The content also, keep it up, I'll be watching the topic.
Reply
#6

"OnPlayerWeaponShot" does not work (bug) on ​​lag shot servers, or am I wrong?
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)