Основы античита в Pawn: защита сервера

Активный
Статус
Сообщения
516
Лайки
32

8

месяц на сайте

Защита от читов - важная часть любого сервера. Разберем базовые методы защиты.

Проверка скорости
Код:
new Float:PlayerLastPos[MAX_PLAYERS][3];
new PlayerLastUpdate[MAX_PLAYERS];

public OnPlayerUpdate(playerid)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    
    new time = GetTickCount();
    if(PlayerLastUpdate[playerid] > 0)
    {
        new Float:distance = floatsqroot(
            floatpower(x - PlayerLastPos[playerid][0], 2) +
            floatpower(y - PlayerLastPos[playerid][1], 2) +
            floatpower(z - PlayerLastPos[playerid][2], 2)
        );
        
        new interval = time - PlayerLastUpdate[playerid];
        new Float:speed = (distance / float(interval)) * 1000.0;
        
        if(speed > 200.0) // максимальная скорость
        {
            new string[128];
            format(string, sizeof(string), "[Античит] Игрок %s подозревается в использовании читов (скорость: %.2f)", 
                GetPlayerName(playerid), speed);
            SendMessageToAdmins(-1, string);
            
            // Наказание
            SetPlayerHealth(playerid, 0.0);
        }
    }
    
    PlayerLastPos[playerid][0] = x;
    PlayerLastPos[playerid][1] = y;
    PlayerLastPos[playerid][2] = z;
    PlayerLastUpdate[playerid] = time;
    
    return 1;
}

Проверка телепортации
Код:
new Float:PlayerLastPos[MAX_PLAYERS][3];

public OnPlayerSpawn(playerid)
{
    GetPlayerPos(playerid, PlayerLastPos[playerid][0], PlayerLastPos[playerid][1], PlayerLastPos[playerid][2]);
    return 1;
}

public OnPlayerUpdate(playerid)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    
    new Float:distance = floatsqroot(
        floatpower(x - PlayerLastPos[playerid][0], 2) +
        floatpower(y - PlayerLastPos[playerid][1], 2) +
        floatpower(z - PlayerLastPos[playerid][2], 2)
    );
    
    if(distance > 50.0 && !IsPlayerInAnyVehicle(playerid))
    {
        // Возможная телепортация
        new string[128];
        format(string, sizeof(string), "[Античит] Игрок %s подозревается в телепортации", 
            GetPlayerName(playerid));
        SendMessageToAdmins(-1, string);
    }
    
    PlayerLastPos[playerid][0] = x;
    PlayerLastPos[playerid][1] = y;
    PlayerLastPos[playerid][2] = z;
    
    return 1;
}

Проверка оружия
Код:
new PlayerWeapon[MAX_PLAYERS];
new PlayerAmmo[MAX_PLAYERS];

public OnPlayerUpdate(playerid)
{
    new weapon = GetPlayerWeapon(playerid);
    new ammo = GetPlayerAmmo(playerid);
    
    if(weapon != PlayerWeapon[playerid] || ammo != PlayerAmmo[playerid])
    {
        // Проверка на разрешенное оружие
        if(!IsWeaponAllowed(weapon))
        {
            RemovePlayerWeapon(playerid, weapon);
            SendClientMessage(playerid, -1, "Это оружие запрещено");
        }
        
        // Проверка на бесконечные патроны
        if(ammo > PlayerAmmo[playerid] && PlayerAmmo[playerid] > 0)
        {
            new string[128];
            format(string, sizeof(string), "[Античит] Игрок %s подозревается в читах на патроны", 
                GetPlayerName(playerid));
            SendMessageToAdmins(-1, string);
        }
    }
    
    PlayerWeapon[playerid] = weapon;
    PlayerAmmo[playerid] = ammo;
    
    return 1;
}

stock IsWeaponAllowed(weaponid)
{
    new allowed_weapons[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for(new i = 0; i < sizeof(allowed_weapons); i++)
    {
        if(weaponid == allowed_weapons[i])
        {
            return 1;
        }
    }
    return 0;
}

Проверка здоровья
Код:
new Float:PlayerLastHealth[MAX_PLAYERS];

public OnPlayerUpdate(playerid)
{
    new Float:health;
    GetPlayerHealth(playerid, health);
    
    if(health > PlayerLastHealth[playerid] && PlayerLastHealth[playerid] < 100.0)
    {
        // Проверка на автолечение
        if(!IsPlayerAtHospital(playerid))
        {
            new string[128];
            format(string, sizeof(string), "[Античит] Игрок %s подозревается в автолечении", 
                GetPlayerName(playerid));
            SendMessageToAdmins(-1, string);
        }
    }
    
    PlayerLastHealth[playerid] = health;
    return 1;
}

Проверка денег
Код:
new PlayerLastMoney[MAX_PLAYERS];

public OnPlayerUpdate(playerid)
{
    new money = GetPlayerMoney(playerid);
    
    if(money > PlayerLastMoney[playerid])
    {
        new difference = money - PlayerLastMoney[playerid];
        
        // Проверка на подозрительное увеличение денег
        if(difference > 100000 && !IsPlayerEarningMoney(playerid))
        {
            new string[128];
            format(string, sizeof(string), "[Античит] Игрок %s подозревается в читах на деньги (+$%d)", 
                GetPlayerName(playerid), difference);
            SendMessageToAdmins(-1, string);
            
            // Откат денег
            GivePlayerMoney(playerid, -difference);
        }
    }
    
    PlayerLastMoney[playerid] = money;
    return 1;
}

Система предупреждений
Код:
new PlayerWarnings[MAX_PLAYERS];

AddWarning(playerid, reason[])
{
    PlayerWarnings[playerid]++;
    
    new string[128];
    format(string, sizeof(string), "[Античит] Игрок %s получил предупреждение (%d/3): %s", 
        GetPlayerName(playerid), PlayerWarnings[playerid], reason);
    SendMessageToAdmins(-1, string);
    
    if(PlayerWarnings[playerid] >= 3)
    {
        Ban(playerid);
        format(string, sizeof(string), "Игрок %s забанен за читы", GetPlayerName(playerid));
        SendClientMessageToAll(-1, string);
    }
}

public OnPlayerConnect(playerid)
{
    PlayerWarnings[playerid] = 0;
    return 1;
}

Важные моменты:
- Не делайте проверки слишком строгими
- Учитывайте легитимные способы перемещения
- Логируйте все подозрительные действия
- Используйте систему предупреждений
- Регулярно обновляйте защиту

Античит требует постоянного совершенствования!
 

1 человек читают эту тему (Всего: 1, Пользователей: 0, Гостей: 1)

Сверху