25.04.2012, 02:36
You don't need to reset those variables.
Also a bit suprised you mentioned that script and didn't mention the other tip I gave you.
Note down all weapon damages
for example:
{ 30, 9.900000, },//ak-47
{ 31, 9.900000, },//m4
Then frequently get the players health (using OPU would be ideal) and when they die check if their health was greater than the reason for their death.
So if they had 40hp and they suddenly die from a 9mm pistol which deals a damage of 8.25 then it's suspicious and you should alert the admins, however if it's a faster firing weapon you might get incorrect warnings due to OPU not getting called fast enough which is why you could note down the firing speed of each weapon and set a safe zone of a few bullets so you get less false positives.
This is how I got the weapon firing speeds, I found that it works best if you walk while you're firing, and fire up into the air so the game doesn't generate dust or sparks which could interfere with the testing results.
Now you're probably thinking what if there are multiple people firing at one person and they die from all of them?
Well you can use OnPlayerTakeDamage and count how many different other players the player has taken damage from and use that number in figuring out if its a fake kill or not.
Here's the check following no scripting rules whatsoever
But this also raises the question about what if the other players attacking aren't using the same weapon which could be likely.
One more thing that came into mind when writing this and it's if the player is on low health and a group of players all shoot at the same time and that doesn't give OPTD to note everything before OPD is called, this could be a problem and a possible solution is to use OPGD as well, as that should be called before OPTD, I understand lag shooting where you have to aim in front however you'll find a lot of players that lag shoot will often hit their skin unintentionally.
There is one more thing I have experienced and that's vehicle explosions that causes the closest player to become killerid with their equipped weapon, and for this I will just paste things from the Anti-Carjack bug thread which can be found here https://sampforum.blast.hk/showthread.php?tid=305601
I seem to remember that GetPlayerVehicleID also works under OPD (needs confirming)
So lastly to recap on all the things mentioned here I'll quickly write up and example (most likely non working) pawn script which you'll be able to modify and hopefully reduce the cheaters and false positives
This was only meant to be a short post but I got a little carried away, the script probably won't compile but as long as you understand what I meant then that's all that matters, also there's loop holes in the script that could be exploited but you can patch them up when you discover them.
Also a bit suprised you mentioned that script and didn't mention the other tip I gave you.
Note down all weapon damages
for example:
{ 30, 9.900000, },//ak-47
{ 31, 9.900000, },//m4
Then frequently get the players health (using OPU would be ideal) and when they die check if their health was greater than the reason for their death.
So if they had 40hp and they suddenly die from a 9mm pistol which deals a damage of 8.25 then it's suspicious and you should alert the admins, however if it's a faster firing weapon you might get incorrect warnings due to OPU not getting called fast enough which is why you could note down the firing speed of each weapon and set a safe zone of a few bullets so you get less false positives.
This is how I got the weapon firing speeds, I found that it works best if you walk while you're firing, and fire up into the air so the game doesn't generate dust or sparks which could interfere with the testing results.
pawn Code:
public OnPlayerKeyStateChange(playerid,newkeys,oldkeys)
{
if(HOLDING(KEY_FIRE))
{
SetPVarInt(playerid,"firing",1);
}
else
{
DeletePVar(playerid,"firing");
}
return 1;
}
new lastShotTime;
new lastAmmo;
new lastWeapon;
public OnPlayerUpdate(playerid)
{
if(GetPVarInt(playerid,"firing"))
{
if(lastWeapon == GetPlayerWeapon(playerid) && GetPlayerAmmo(playerid) < lastAmmo)
{
printf("%d %d %d",lastWeapon,lastAmmo - GetPlayerAmmo(playerid),GetTickCount() - lastShotTime);
lastShotTime = GetTickCount();
}
lastAmmo = GetPlayerAmmo(playerid);
lastWeapon = GetPlayerWeapon(playerid);
}
return 1;
}
Well you can use OnPlayerTakeDamage and count how many different other players the player has taken damage from and use that number in figuring out if its a fake kill or not.
Here's the check following no scripting rules whatsoever
Code:
If Last_Health > MaxDamage[reason] * Leniency[reason] * PlayersAttacking[playerid]
Code:
variable HealthLimit
Loop Through Players
{
if itteration shot player and time shot is less than X (I'd say about 2 seconds)
{
increase HealthLimit to MaxDamage weapon used to damage * Leniency of weapon used
}
}
if Last_Health > HealthLimit something seems a little suspicious
There is one more thing I have experienced and that's vehicle explosions that causes the closest player to become killerid with their equipped weapon, and for this I will just paste things from the Anti-Carjack bug thread which can be found here https://sampforum.blast.hk/showthread.php?tid=305601
pawn Code:
GetVehicleHealth(GetPVarInt(playerid,"vehicleid"),Health);
if(Health > 250.0)
{
//possible car jack bug
}
So lastly to recap on all the things mentioned here I'll quickly write up and example (most likely non working) pawn script which you'll be able to modify and hopefully reduce the cheaters and false positives
pawn Code:
new PlayerDamagedPlayer[MAX_PLAYERS][MAX_PLAYERS] = { 255, ... };//sets default Value to 255 (unknown) this variable will store the weaponid used to attack
new PlayerDamagedPlayerTime[MAX_PLAYERS][MAX_PLAYERS];//this will store the time in seconds when the player was attacked
new Float:LastPlayerHealthUpdate[MAX_PLAYERS];
//PlayerDamagedPlayer will be in the format of [damagerid][victimid]
public OnPlayerSpawn(playerid)
{
for(new i=0;i<MAX_PLAYERS;i++)
{
//reset the variables when they respawn or after the checks in OPD
PlayerDamagedPlayer[playerid][i] = 255;
PlayerDamagedPlayer[i][playerid] = 255;
}
}
stock Float:GetMaxWeaponDamage(weaponid)
{
switch(weaponid)
{
case 22: return 8.25;//9mm
case 23: return 13.20;//silencer
case 24: return 46.20;//deagle
}
return 255.0;//just because it safely exceeds 200 (100 health + 100 armour)
}
//returns ticks inbetween each shot fired
stock GetWeaponFiringRate(weaponid)
{
switch(weaponid)
{
case 22: return 100;//9mm
case 23: return 250;//silencer
case 24: return 600;//deagle
}
}
public OnPlayerTakeDamage(playerid, issuerid, Float:amount, weaponid)
{
PlayerDamagedPlayer[issuerid][playerid] = weaponid;
PlayerDamagedPlayerTime[issuerid][playerid] = gettime();
}
public OnPlayerGiveDamage(playerid, damagedid, Float:amount, weaponid)
{
PlayerDamagedPlayer[playerid][damagedid] = weaponid;
PlayerDamagedPlayerTime[playerid][damagedid] = gettime();
}
public OnPlayerUpdate(playerid)
{
new Float:health;
GetPlayerHealth(playerid,health);
LastPlayerHealthUpdate[playerid] = health;
}
public OnPlayerDeath(playerid,killerid,reason)
{
new Float:TotalMaxDamage = 0.0;
new CurrentTime = gettime();
if(killerid != INVALID_PLAYERID)//killed by another player
{
for(new i=0;i<MAX_PLAYERS;i++)
{
if(PlayerDamagePlayer[i][playerid] != 255 && PlayerDamagePlayerTime[i][playerid] + 2 > CurrentTime)
{
new Float:MaxDamageFromPlayer = 0.0;
MaxDamageFromplayer = GetMaxWeaponDamage(PlayerDamagePlayer[i][playerid]);
switch(GetWeaponFiringRate(PlayerDamagePlayer[i][playerid]))
{
case 0 .. 100:
{
MaxDamageFromPlayer *= 4;
}
case 101 .. 200:
{
MaxDamageFromPlayer *= 2;
}
}
TotalMaxDamage += MaxDamageFromPlayer;
}
}
if(LastPlayerHealthUpdate[playerid] > TotalMaxDamage)
{
new Float:VehicleHealth;
GetVehicleHealth(GetPlayerVehicleID(vehicleid),VehicleHealth);
if(!IsPlayerInAnyVehicle(playerid) || VehicleHealth > 250.0)
{
//posible fake kill
}
}
}
}

