Система фракций в Pawn: создание и управление

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

8

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

Фракции позволяют создавать группы игроков с общими целями. Разберем создание системы.

Структура данных фракции
Код:
enum FactionInfo
{
    fName[64],
    fType,
    fColor,
    fSpawnX,
    fSpawnY,
    fSpawnZ,
    fInterior,
    fSkin[10],
    fRanks[15][32],
    fVehicles[20]
}

enum PlayerFactionInfo
{
    pFaction,
    pRank,
    pLeader
}

new FactionData[10][FactionInfo];
new PlayerFaction[MAX_PLAYERS][PlayerFactionInfo];
new TotalFactions = 0;

Создание фракции
Код:
CreateFaction(name[], type, color, Float:x, Float:y, Float:z, interior)
{
    if(TotalFactions >= sizeof(FactionData))
    {
        return -1;
    }
    
    strcpy(FactionData[TotalFactions][fName], name, 64);
    FactionData[TotalFactions][fType] = type;
    FactionData[TotalFactions][fColor] = color;
    FactionData[TotalFactions][fSpawnX] = x;
    FactionData[TotalFactions][fSpawnY] = y;
    FactionData[TotalFactions][fSpawnZ] = z;
    FactionData[TotalFactions][fInterior] = interior;
    
    // Установка рангов по умолчанию
    strcpy(FactionData[TotalFactions][fRanks][0], "Рекрут", 32);
    strcpy(FactionData[TotalFactions][fRanks][1], "Солдат", 32);
    strcpy(FactionData[TotalFactions][fRanks][2], "Сержант", 32);
    strcpy(FactionData[TotalFactions][fRanks][3], "Лейтенант", 32);
    strcpy(FactionData[TotalFactions][fRanks][4], "Капитан", 32);
    strcpy(FactionData[TotalFactions][fRanks][5], "Командир", 32);
    
    TotalFactions++;
    return TotalFactions - 1;
}

Вступление в фракцию
Код:
JoinFaction(playerid, factionid)
{
    if(factionid >= TotalFactions)
    {
        SendClientMessage(playerid, -1, "Неверный ID фракции");
        return 0;
    }
    
    if(PlayerFaction[playerid][pFaction] != -1)
    {
        SendClientMessage(playerid, -1, "Вы уже состоите во фракции");
        return 0;
    }
    
    PlayerFaction[playerid][pFaction] = factionid;
    PlayerFaction[playerid][pRank] = 0;
    PlayerFaction[playerid][pLeader] = 0;
    
    new string[128];
    format(string, sizeof(string), "Вы вступили во фракцию: %s", FactionData[factionid][fName]);
    SendClientMessage(playerid, -1, string);
    
    // Уведомление членов фракции
    SendFactionMessage(factionid, -1, "Новый член фракции!");
    
    return 1;
}

LeaveFaction(playerid)
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите во фракции");
        return 0;
    }
    
    new factionid = PlayerFaction[playerid][pFaction];
    new string[128];
    format(string, sizeof(string), "%s покинул фракцию", GetPlayerName(playerid));
    SendFactionMessage(factionid, -1, string);
    
    PlayerFaction[playerid][pFaction] = -1;
    PlayerFaction[playerid][pRank] = 0;
    PlayerFaction[playerid][pLeader] = 0;
    
    SendClientMessage(playerid, -1, "Вы покинули фракцию");
    return 1;
}

Система рангов
Код:
SetPlayerRank(playerid, rank)
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        return 0;
    }
    
    if(rank < 0 || rank >= 15)
    {
        return 0;
    }
    
    PlayerFaction[playerid][pRank] = rank;
    
    new string[128];
    format(string, sizeof(string), "Ваш ранг изменен на: %s", 
        FactionData[PlayerFaction[playerid][pFaction]][fRanks][rank]);
    SendClientMessage(playerid, -1, string);
    
    return 1;
}

GetPlayerRankName(playerid)
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        return "Нет";
    }
    
    return FactionData[PlayerFaction[playerid][pFaction]][fRanks][PlayerFaction[playerid][pRank]];
}

PromotePlayer(playerid, targetid)
{
    if(PlayerFaction[playerid][pFaction] == -1 || PlayerFaction[targetid][pFaction] == -1)
    {
        return 0;
    }
    
    if(PlayerFaction[playerid][pFaction] != PlayerFaction[targetid][pFaction])
    {
        SendClientMessage(playerid, -1, "Игрок не в вашей фракции");
        return 0;
    }
    
    if(PlayerFaction[playerid][pRank] <= PlayerFaction[targetid][pRank])
    {
        SendClientMessage(playerid, -1, "У вас недостаточно прав");
        return 0;
    }
    
    if(PlayerFaction[targetid][pRank] >= 14)
    {
        SendClientMessage(playerid, -1, "Игрок уже имеет максимальный ранг");
        return 0;
    }
    
    PlayerFaction[targetid][pRank]++;
    
    new string[128];
    format(string, sizeof(string), "%s повысил %s до ранга: %s", 
        GetPlayerName(playerid), 
        GetPlayerName(targetid),
        GetPlayerRankName(targetid));
    SendFactionMessage(PlayerFaction[playerid][pFaction], -1, string);
    
    return 1;
}

DemotePlayer(playerid, targetid)
{
    if(PlayerFaction[playerid][pFaction] == -1 || PlayerFaction[targetid][pFaction] == -1)
    {
        return 0;
    }
    
    if(PlayerFaction[playerid][pFaction] != PlayerFaction[targetid][pFaction])
    {
        SendClientMessage(playerid, -1, "Игрок не в вашей фракции");
        return 0;
    }
    
    if(PlayerFaction[playerid][pRank] <= PlayerFaction[targetid][pRank])
    {
        SendClientMessage(playerid, -1, "У вас недостаточно прав");
        return 0;
    }
    
    if(PlayerFaction[targetid][pRank] <= 0)
    {
        SendClientMessage(playerid, -1, "Игрок уже имеет минимальный ранг");
        return 0;
    }
    
    PlayerFaction[targetid][pRank]--;
    
    new string[128];
    format(string, sizeof(string), "%s понизил %s до ранга: %s", 
        GetPlayerName(playerid), 
        GetPlayerName(targetid),
        GetPlayerRankName(targetid));
    SendFactionMessage(PlayerFaction[playerid][pFaction], -1, string);
    
    return 1;
}

Спавн фракции
Код:
public OnPlayerSpawn(playerid)
{
    if(PlayerFaction[playerid][pFaction] != -1)
    {
        new factionid = PlayerFaction[playerid][pFaction];
        SetPlayerPos(playerid, FactionData[factionid][fSpawnX], 
            FactionData[factionid][fSpawnY], 
            FactionData[factionid][fSpawnZ]);
        SetPlayerInterior(playerid, FactionData[factionid][fInterior]);
        
        // Установка скина фракции
        new skin = FactionData[factionid][fSkin][PlayerFaction[playerid][pRank]];
        if(skin > 0)
        {
            SetPlayerSkin(playerid, skin);
        }
        
        // Выдача оружия в зависимости от ранга
        GiveFactionWeapons(playerid, factionid, PlayerFaction[playerid][pRank]);
    }
    return 1;
}

GiveFactionWeapons(playerid, factionid, rank)
{
    switch(FactionData[factionid][fType])
    {
        case 1: // Полиция
        {
            GivePlayerWeapon(playerid, 24, 100); // Пистолет
            if(rank >= 2)
            {
                GivePlayerWeapon(playerid, 25, 50); // Дробовик
            }
            if(rank >= 4)
            {
                GivePlayerWeapon(playerid, 31, 200); // M4
            }
        }
        case 2: // Медики
        {
            // Медики не получают оружие
        }
        case 3: // Армия
        {
            GivePlayerWeapon(playerid, 24, 100);
            GivePlayerWeapon(playerid, 30, 200); // AK-47
            if(rank >= 3)
            {
                GivePlayerWeapon(playerid, 31, 200); // M4
            }
        }
    }
}

Чат фракции
Код:
CMD:f(playerid, params[])
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите во фракции");
        return 1;
    }
    
    if(isnull(params))
    {
        SendClientMessage(playerid, -1, "Использование: /f [текст]");
        return 1;
    }
    
    new string[256];
    format(string, sizeof(string), "[%s] %s (%s): %s", 
        FactionData[PlayerFaction[playerid][pFaction]][fName],
        GetPlayerName(playerid),
        GetPlayerRankName(playerid),
        params);
    
    SendFactionMessage(PlayerFaction[playerid][pFaction], FactionData[PlayerFaction[playerid][pFaction]][fColor], string);
    return 1;
}

SendFactionMessage(factionid, color, message[])
{
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(IsPlayerConnected(i) && PlayerFaction[i][pFaction] == factionid)
        {
            SendClientMessage(i, color, message);
        }
    }
}

Команды
Код:
CMD:finvite(playerid, params[])
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите во фракции");
        return 1;
    }
    
    if(PlayerFaction[playerid][pRank] < 3)
    {
        SendClientMessage(playerid, -1, "У вас недостаточно прав");
        return 1;
    }
    
    new targetid;
    if(sscanf(params, "u", targetid))
    {
        SendClientMessage(playerid, -1, "Использование: /finvite [id]");
        return 1;
    }
    
    if(PlayerFaction[targetid][pFaction] != -1)
    {
        SendClientMessage(playerid, -1, "Игрок уже состоит во фракции");
        return 1;
    }
    
    JoinFaction(targetid, PlayerFaction[playerid][pFaction]);
    
    new string[128];
    format(string, sizeof(string), "%s пригласил %s во фракцию", 
        GetPlayerName(playerid), GetPlayerName(targetid));
    SendFactionMessage(PlayerFaction[playerid][pFaction], -1, string);
    
    return 1;
}

CMD:fmembers(playerid, params[])
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите во фракции");
        return 1;
    }
    
    new count = 0;
    SendClientMessage(playerid, -1, "Члены фракции:");
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(IsPlayerConnected(i) && PlayerFaction[i][pFaction] == PlayerFaction[playerid][pFaction])
        {
            count++;
            new string[128];
            format(string, sizeof(string), "%s - %s", 
                GetPlayerName(i), GetPlayerRankName(i));
            SendClientMessage(playerid, -1, string);
        }
    }
    
    if(count == 0)
    {
        SendClientMessage(playerid, -1, "В фракции нет других членов");
    }
    return 1;
}

CMD:fleave(playerid, params[])
{
    LeaveFaction(playerid);
    return 1;
}

Важные моменты:
- Сохраняйте данные фракций в базе данных
- Реализуйте систему прав доступа
- Предоставляйте удобные команды управления
- Учитывайте баланс между фракциями

Фракции создают социальную структуру на сервере!
 

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

Сверху