SA-MP Forums Archive
Weapon anti-cheat - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+--- Thread: Weapon anti-cheat (/showthread.php?tid=530245)



Weapon anti-cheat - Banditukas - 06.08.2014

Hi,

Код:
#include <a_samp>
#include <foreach>
#include <zcmd>
#include <sscanf2>

#define COLOR_WHITE		 0xFFFFFFFF

#define RELEASED(%0) \
    (((newkeys & (%0)) != (%0)) && ((oldkeys & (%0)) == (%0)))

/*
13 - slot id
1- weapon id, 2 - ammo

Feature things:

*/

new Weapons[MAX_PLAYERS][13][2], bool:Spawned[MAX_PLAYERS], bool:CanCheck[MAX_PLAYERS];

main() { }

public OnGameModeInit()
{
    AddPlayerClass(0, 1958.33, 1343.12, 15.36, 269.15, 0, 0, 0, 0, 0, 0);
    print("Serveris paleistas.");
    return true;
}

public OnPlayerConnect(playerid)
{
    Spawned[playerid] = false;
    CanCheck[playerid] = false;
    AC_ResetPlayerWeapons(playerid, true);
    return true;
}

public OnPlayerSpawn(playerid)
{
    CanCheck[playerid] = false;
    Spawned[playerid] = true;
    return true;
}

public OnPlayerDeath(playerid, killerid, reason)
{
    Spawned[playerid] = false;
    return true;
}

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
    if (RELEASED(KEY_FIRE))
    {
	    new slotid = GetWeaponSlotByWepID(GetPlayerWeapon(playerid));
	    SetTimerEx("AC_UpdatePlayerWeaponAmmo", 100, false, "ii", playerid, slotid);
    }
    return true;
}

public OnPlayerDisconnect(playerid, reason)
{
    return true;
}

public OnPlayerCommandPerformed( playerid, cmdtext[], success )
{
    if( !success )
    {
	    SendClientMessage(playerid, COLOR_WHITE, "Komanda nerasta.");
	    return true;
    }
    else
    {
	    new pName[ MAX_PLAYER_NAME ];
	    GetPlayerName( playerid, pName, MAX_PLAYER_NAME );
	    printf( "[ID:%i] %s has called command: %s.", playerid, pName, cmdtext );
	    return true;
    }
}

/*COMMAND:kill(playerid, params[])
{
    SetPlayerHealth(playerid, 0.0);
    return true;
}

COMMAND:ginklus(playerid, params[])
{
    ResetPlayerWeapons(playerid);
    return true;
}

COMMAND:ginkla(playerid, params[])
{
    new weaponid, ammo;
    if(sscanf(params, "ii", weaponid, ammo)) SendClientMessage(playerid, COLOR_WHITE, "Komandos naudojimas: /ginkla [weapon id] [ammo]");
    else
    {
	    GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return true;
}

COMMAND:iginklus(playerid, params[])
{
    AC_ResetPlayerWeapons(playerid);
    return true;
}

COMMAND:iginkla(playerid, params[])
{
    new weaponid, ammo;
    if(sscanf(params, "ii", weaponid, ammo)) SendClientMessage(playerid, COLOR_WHITE, "Komandos naudojimas: /iginkla [weapon id] [ammo]");
    else
    {
	    AC_GivePlayerWeapon(playerid, weaponid, ammo);
    }
    return true;
}

stock DebugWeapons(playerid)
{
    new tempWeapon[1][2];
    print("[AC] Starting weapons debug...");
    for (new i = 0; i < 13; i++)
    {
	    GetPlayerWeaponData(playerid, i, tempWeapon[0][0], tempWeapon[0][1]);
	    printf("[AC] Weapon slot id: %d, weapon id: %i, weapon ammo: %i", i, tempWeapon[0][0], tempWeapon[0][1]);
    }
    print("[AC] Finished weapons debug.");
}*/

stock AC_ResetPlayerWeapons(playerid, bool:connect = false)
{
    // *** WARNING: Reset weapons when connected ***
    CanCheck[playerid] = false;
    ResetPlayerWeapons(playerid);
    for (new i = 0; i < 13; i++)
    {
	    if(connect) Weapons[playerid][i][0] = 0;
	    Weapons[playerid][i][1] = 0;
    }
}

stock AC_NullPlayerWeapons(playerid)
{
    // *** WARNING: Null weapons before saving ***
    CanCheck[playerid] = false;
    for (new slotid = 0; slotid < 13; slotid++)
    {
	    if(IsWeaponFireable(Weapons[playerid][slotid][0]) && Weapons[playerid][slotid][1] == 0) AC_RemovePlayerWeapon(playerid, slotid);
    }
}

stock AC_GivePlayerWeapon(playerid, weaponid, ammo)
{
    CanCheck[playerid] = false;
    new slotid = GetWeaponSlotByWepID(weaponid), finalAmmo = ammo;
    if(IsWeaponsInSameSlot(AC_GetPlayerWeaponIDFromSlot(playerid, slotid), weaponid)) finalAmmo += AC_GetPlayerWeaponAmmoFromSlot(playerid, slotid);
    if(IsWeaponFireable(weaponid) && finalAmmo == 0) Weapons[playerid][slotid][1] = 0;
    else
    {
	    Weapons[playerid][slotid][0] = weaponid;
	    Weapons[playerid][slotid][1] = finalAmmo;
    }
    GivePlayerWeapon(playerid, weaponid, ammo);
}

stock AC_RegivePlayerWeapons(playerid)
{
    CanCheck[playerid] = false;
    for (new slotid = 0; slotid < 13; slotid++)
    {
	    GivePlayerWeapon(playerid, Weapons[playerid][slotid][0], Weapons[playerid][slotid][1]);
    }
}

forward AC_UpdatePlayerWeaponAmmo(playerid, slotid);
public AC_UpdatePlayerWeaponAmmo(playerid, slotid)
{
    new weaponid, ammo;
    GetPlayerWeaponData(playerid, slotid, weaponid, ammo);
    if(IsWeaponFireable(weaponid) && Weapons[playerid][slotid][0] == weaponid) Weapons[playerid][slotid][1] = ammo;
}

stock AC_RemovePlayerWeapon(playerid, slotid)
{
    Weapons[playerid][slotid][0] = 0;
    Weapons[playerid][slotid][1] = 0;
}

public OnPlayerUpdate(playerid)
{
    foreach(Player, i)
    {
	    if(Spawned[i])
	    {
		    if(!CanCheck[i]) CanCheck[i] = true;
		    else
		    {
			    if(GetPlayerWeapon(i) == 0)
			    {
				    for (new slotid = 0; slotid < 13; slotid++)
				    {
					    AC_CheckPlayerWeapon(i, slotid);
				    }
			    }
			    else AC_CheckPlayerWeapon(i);
		    }
	    }
    }
    return true;
}

stock AC_CheckPlayerWeapon(playerid, slotid = -1)
{
    new tempWeapon[1][2];
    if(slotid == -1) slotid = GetWeaponSlotByWepID(GetPlayerWeapon(playerid));
    GetPlayerWeaponData(playerid, slotid, tempWeapon[0][0], tempWeapon[0][1]);
    if(tempWeapon[0][0] != 0)
    {
	    if(tempWeapon[0][0] != AC_GetPlayerWeaponIDFromSlot(playerid, slotid) || (IsWeaponFireable(tempWeapon[0][0]) && tempWeapon[0][1] > AC_GetPlayerWeaponAmmoFromSlot(playerid, slotid)))
	    {
		    // kick
		    printf("[ID:%i] is kicked for gun cheats", playerid);
		    SendClientMessage(playerid, COLOR_WHITE, "KICKED");
		    printf("[ID:%i] is kicked for gun cheats. Wep id %i, ammo %i, ac wep id %i, ammo %i", playerid, tempWeapon[0][0], tempWeapon[0][1], Weapons[playerid][slotid][0], Weapons[playerid][slotid][1]);
	    }
	    else if(IsWeaponFireable(tempWeapon[0][0]) && AC_GetPlayerWeaponAmmoFromSlot(playerid, slotid) > tempWeapon[0][1]) Weapons[playerid][slotid][1] = tempWeapon[0][1];
    }
}

stock GetWeaponSlotByWepID(weaponid)
{
    switch (weaponid)
    {
	    case 0, 1	  : return 0;
	    case 2..9	  : return 1;
	    case 22..24    : return 2;
	    case 25..27    : return 3;
	    case 28, 29, 32: return 4;
	    case 30, 31    : return 5;
	    case 33, 34    : return 6;
	    case 35..38    : return 7;
	    case 16..19, 39: return 8;
	    case 41..43    : return 9;
	    case 10..15    : return 10;
	    case 44..46    : return 11;
	    case 40	    : return 12;
    }
    return -1;
}

stock IsWeaponFireable(weaponid)
{
    switch (weaponid)
    {
	    case 0..15, 40, 44..46: return false;
    }
    return true;
}

stock IsWeaponsInSameSlot(oldweaponid, newweaponid)
{
    if(GetWeaponSlotByWepID(oldweaponid) == GetWeaponSlotByWepID(newweaponid)) return true;
    return false;
}

stock AC_GetPlayerWeaponIDFromSlot(playerid, slotid) return Weapons[playerid][slotid][0];

stock AC_GetPlayerWeaponAmmoFromSlot(playerid, slotid) return Weapons[playerid][slotid][1];
Why in this anti-cheat when player release key_fire, then server update ammo? if player in that time will make ammo with ******s?