[Include] OnPlayerFakeKill.inc
#1

OnPlayerFakeKill
When I searched the SA-MP forums for an anti fake kill I was horrified to see most scripts checking to see how many times the player died / was killed in x amount of time. This is very bad for many reasons, one being it doesn't even actually say if used fakekill, rapidfire or if they just had a minigun(they also could've simply used the SetPlayerHealth function! This isn't even accounted for at all). So simply this method detects if the killer has given(or if the player has taken) damage from the killing player. If they have taken damage, they have been killed legitly. If they haven't; they are either fake killing or the server is sending the data(you shouldn't call the OnPlayerDeath callback while using this script for that reason).

It has two callbacks and hooks three as found below:

Usable Callbacks:
pawn Code:
forward OnPlayerDie(playerid, killerid, reason);
forward OnPlayerFakeKill(playerid, killerid, reason);
Hooked callbacks:
pawn Code:
OnPlayerConnect
OnPlayerTakeDamage
OnPlayerDeath
I haven't extensively tested it; I tested it on a localhost server with 2 players so if there are any issues let me know. It is suggested to use the OnPlayerDie callback for the death response, this is only called when the player has legitly died / been legitly killed.

Download: http://pastebin.com/CC7chyn9

Example script:
pawn Code:
#include <a_samp>
#include <fakekill>

public OnPlayerFakeKill(playerid, killerid, reason)
{
    SendClientMessage(playerid, 0xFF0000FF, "fuck off faggot");
        SetTimerEx("_Ban", 1000, false, "d", playerid);
    return 1;
}

forward _Ban(playerid);
public _Ban(playerid)
{
      Ban(playerid);
      return 1;
}

public OnPlayerDie(playerid, killerid, reason)
{
    return 1;
}
Callback explanations:
pawn Code:
OnPlayerDie
- This is simply called when the player is actually killed. This is not called in the event of a fakekill.

pawn Code:
OnPlayerFakeKill(playerid, killerid, reason)
- This is called when a player uses fake kill. The "playerid" is the player faking the kill.

It should be noted that the OnPlayerDeath callback is as of this version(I will most likely make it not call when the player uses fake kill in future versions) still gets called in the event of a fake kill. You should use OnPlayerDie for your death response, and not OnPlayerDeath.
Reply
#2

Very useful, +1.
Reply
#3

An issue:
pawn Code:
SetTimerEx("_Ban", "d", playerid);
pawn Code:
SetTimerEx("_Ban", 100, false, "i", playerid);
Suggestion:
  • Use a boolean instead of a whole integer number as it only requires to handle the values 0 and 1.
Even though this is most likely using common sense and a pinch of basic knowledge on how some callbacks work/do, it's vastly better than probably every other similar system released on this forum. Good job, bud!
Reply
#4

Quote:
Originally Posted by SickAttack
View Post
An issue:
pawn Code:
SetTimerEx("_Ban", "d", playerid);
pawn Code:
SetTimerEx("_Ban", 100, false, "i", playerid);
My bad, it's like 12:26AM, I have fixed the example. I also appreciate your boolean suggestion, I will take it into account when I update the include again.
Reply
#5

Better Hook Names that won't conflict with other includes
Code:
#if defined _ALS_OnPlayerConnect
  #undef OnPlayerConnect
#else
#define _ALS_OnPlayerConnect
#endif
 
#define OnPlayerConnect OnPlayerConnectEx
You must use better hook names for example, "OnPlayerConnect_OPFK" so that it won't conflict with other libraries. Good practice! There are many who still use CallbackNameEx.

Static Variables & Char Variables

Code:
new givenDamage[MAX_PLAYERS][MAX_PLAYERS];
Keep it static so that it won't conflict with any other script.

You can also make it into a char array since you just need to store true/false.

Code:
static givenDamage[MAX_PLAYERS][MAX_PLAYERS char];
Memset is WAY faster than manually setting array elements to zero
Use memset for these loops, its WAY faster than your PAWN loop.
Code:
for(new i; i < MAX_PLAYERS; i++)
{
     givenDamage[playerid][i] = 0;
}
Check New Code Optimizations Tip #5 for more information

CallLocalFunction is horribly slow
CallLocalFunction is very slow and you are going to call it every time a player takes damage which makes it more worse!

Why
Code:
 CallLocalFunction("OnPlayerTakeDamage", "ddfdd", playerid, issuerid, amount, weaponid, bodypart);
when you can simply
Code:
#if defined OnPlayerTakeDamage
OnPlayerTakeDamage(playerid, issuerid, amount, weaponid, bodypart);
#endif
The same TIP applies to these
Code:
CallLocalFunction("OnPlayerDeathEx", "ddd", playerid, killerid, reason);
CallLocalFunction("OnPlayerDie", "ddd", playerid, killerid, reason);
CallLocalFunction("OnPlayerFakeKill", "ddd", playerid, killerid, reason);
Check New Code Optimizations Tip #2 for more information

Include won't work -> Infinite Loop
You just made an infinite loop!

Code:
public OnPlayerTakeDamage(playerid, issuerid, Float: amount, weaponid, bodypart)
{
        if(issuerid == INVALID_PLAYER_ID || playerid == issuerid) return 1;
        givenDamage[playerid][issuerid] = 1;
       
        CallLocalFunction("OnPlayerTakeDamage", "ddfdd", playerid, issuerid, amount, weaponid, bodypart);
       
        return 1;
}
OnPlayerTakeDamage gets called and you call it again when calls again...

It think it should have been OnPlayerTakeDamageEx :/

Suggestion:
Instead of having people use a new callback "OnPlayerDie" why not let them use OnPlayerDeath? You are hooking OnPlayerDeath, that means you can control OnPlayerDeath calls. Call OnPlayerDeath when the player made a legit kill and don't call when player made an illegal kill.

I do see more potential issue with the include, especially when you kill a player who is AFK (If a player is AFK and you shoot him, when he returns he dies and OnPlayerDeath is called).
Reply
#6

Also this will fail hard, really hard. Sometimes (and due to unknown reasons) OnPlayerDeath gets called while OnPlayerTake/GiveDamage never get called. For example, heli blading or car ramming on < 2 HP. So basically all you can do at this point is, when the killer haven't gave damage, is to ignore the kill.
Reply
#7

I have a question , why are you calling this ? :

CallLocalFunction("OnPlayerDeathEx", "ddd", playerid, killerid, reason);
Reply
#8

There are some fakekills which call OnPlayerGive/Take damage.
Reply
#9

Fake kills are also able to fake "OnPlayerTakeDamage" which could fool the detection used in your include. Fake kills are mostly spams and can be detected using time. It's better to have a server sided health system so you can manage the death callback efficiently and securely.
Reply
#10

Quote:
Originally Posted by Yashas
View Post
Better Hook Names that won't conflict with other includes
...
Thanks for the feedback, I have fixed most of the important issues. Also, regarding calling OnPlayerDeath only when it's a legit kill, I noted somewhere in the thread it may appear in future versions.

Quote:
Originally Posted by Ralfie
View Post
Also this will fail hard, really hard. Sometimes (and due to unknown reasons) OnPlayerDeath gets called while OnPlayerTake/GiveDamage never get called. For example, heli blading or car ramming on < 2 HP. So basically all you can do at this point is, when the killer haven't gave damage, is to ignore the kill.
You can customize OnPlayerFakeKill to your liking and omit certain reasons, you can also check if they were tabbed within the last minute or whatever.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)