Система банд в Pawn

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

8

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

Руководство по созданию системы банд с территориями, войнами и иерархией участников.

Структура данных банды

Код:
enum GangInfo
{
    gName[32],
    gTag[8],
    gColor,
    gLeader[MAX_PLAYER_NAME],
    gMembers,
    gTerritories,
    gWins,
    gLosses,
    Float:gSpawnX,
    Float:gSpawnY,
    Float:gSpawnZ,
    gInterior
}

new GangData[20][GangInfo];
new TotalGangs = 0;
new PlayerGang[MAX_PLAYERS] = {-1, ...};
new PlayerGangRank[MAX_PLAYERS];

Создание банды

Код:
CreateGang(name[], tag[], color, Float:x, Float:y, Float:z, interior)
{
    if(TotalGangs >= sizeof(GangData))
    {
        return -1;
    }
    
    strcpy(GangData[TotalGangs][gName], name, 32);
    strcpy(GangData[TotalGangs][gTag], tag, 8);
    GangData[TotalGangs][gColor] = color;
    GangData[TotalGangs][gSpawnX] = x;
    GangData[TotalGangs][gSpawnY] = y;
    GangData[TotalGangs][gSpawnZ] = z;
    GangData[TotalGangs][gInterior] = interior;
    GangData[TotalGangs][gMembers] = 0;
    GangData[TotalGangs][gTerritories] = 0;
    GangData[TotalGangs][gWins] = 0;
    GangData[TotalGangs][gLosses] = 0;
    
    TotalGangs++;
    return TotalGangs - 1;
}

Вступление в банду

Код:
JoinGang(playerid, gangid)
{
    if(gangid < 0 || gangid >= TotalGangs)
    {
        return 0;
    }
    
    if(PlayerGang[playerid] != -1)
    {
        SendClientMessage(playerid, -1, "Вы уже состоите в банде");
        return 0;
    }
    
    PlayerGang[playerid] = gangid;
    PlayerGangRank[playerid] = 0;
    GangData[gangid][gMembers]++;
    
    new string[128];
    format(string, sizeof(string), "Вы вступили в банду: %s [%s]", GangData[gangid][gName], GangData[gangid][gTag]);
    SendClientMessage(playerid, GangData[gangid][gColor], string);
    
    SetPlayerColor(playerid, GangData[gangid][gColor]);
    
    return 1;
}

Выход из банды

Код:
LeaveGang(playerid)
{
    if(PlayerGang[playerid] == -1)
    {
        return 0;
    }
    
    new gangid = PlayerGang[playerid];
    new name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));
    
    // Проверка на лидера
    if(strcmp(GangData[gangid][gLeader], name) == 0)
    {
        SendClientMessage(playerid, -1, "Лидер не может покинуть банду. Используйте /disband");
        return 0;
    }
    
    GangData[gangid][gMembers]--;
    PlayerGang[playerid] = -1;
    PlayerGangRank[playerid] = 0;
    SetPlayerColor(playerid, 0xFFFFFFFF);
    
    new string[128];
    format(string, sizeof(string), "Вы покинули банду: %s", GangData[gangid][gName]);
    SendClientMessage(playerid, -1, string);
    
    return 1;
}

Система территорий

Код:
enum TerritoryInfo
{
    Float:tMinX,
    Float:tMinY,
    Float:tMaxX,
    Float:tMaxY,
    tOwner,
    tCaptureProgress,
    tCapturingGang
}

new TerritoryData[50][TerritoryInfo];
new TotalTerritories = 0;
new PlayerInTerritory[MAX_PLAYERS] = {-1, ...};

CreateTerritory(Float:minX, Float:minY, Float:maxX, Float:maxY)
{
    if(TotalTerritories >= sizeof(TerritoryData))
    {
        return -1;
    }
    
    TerritoryData[TotalTerritories][tMinX] = minX;
    TerritoryData[TotalTerritories][tMinY] = minY;
    TerritoryData[TotalTerritories][tMaxX] = maxX;
    TerritoryData[TotalTerritories][tMaxY] = maxY;
    TerritoryData[TotalTerritories][tOwner] = -1;
    TerritoryData[TotalTerritories][tCaptureProgress] = 0;
    TerritoryData[TotalTerritories][tCapturingGang] = -1;
    
    TotalTerritories++;
    return TotalTerritories - 1;
}

IsPlayerInTerritory(playerid, territoryid)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    
    if(x >= TerritoryData[territoryid][tMinX] && x <= TerritoryData[territoryid][tMaxX] &&
       y >= TerritoryData[territoryid][tMinY] && y <= TerritoryData[territoryid][tMaxY])
    {
        return 1;
    }
    return 0;
}

Захват территории

Код:
ProcessTerritoryCapture(playerid)
{
    if(PlayerGang[playerid] == -1)
    {
        return 0;
    }
    
    new gangid = PlayerGang[playerid];
    new territoryid = -1;
    
    // Поиск территории
    for(new i = 0; i < TotalTerritories; i++)
    {
        if(IsPlayerInTerritory(playerid, i))
        {
            territoryid = i;
            break;
        }
    }
    
    if(territoryid == -1)
    {
        PlayerInTerritory[playerid] = -1;
        return 0;
    }
    
    PlayerInTerritory[playerid] = territoryid;
    
    // Если территория уже принадлежит банде игрока
    if(TerritoryData[territoryid][tOwner] == gangid)
    {
        return 0;
    }
    
    // Если никто не захватывает
    if(TerritoryData[territoryid][tCapturingGang] == -1)
    {
        TerritoryData[territoryid][tCapturingGang] = gangid;
        TerritoryData[territoryid][tCaptureProgress] = 0;
    }
    
    // Если захватывает другая банда
    if(TerritoryData[territoryid][tCapturingGang] != gangid)
    {
        TerritoryData[territoryid][tCaptureProgress] = 0;
        TerritoryData[territoryid][tCapturingGang] = gangid;
    }
    
    // Подсчет участников банды в территории
    new gangMembers = 0;
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(IsPlayerConnected(i) && PlayerGang[i] == gangid && IsPlayerInTerritory(i, territoryid))
        {
            gangMembers++;
        }
    }
    
    // Прогресс захвата
    TerritoryData[territoryid][tCaptureProgress] += gangMembers;
    
    if(TerritoryData[territoryid][tCaptureProgress] >= 100)
    {
        CaptureTerritory(territoryid, gangid);
    }
    
    new string[128];
    format(string, sizeof(string), "~w~Захват территории: ~r~%d%%", TerritoryData[territoryid][tCaptureProgress]);
    GameTextForPlayer(playerid, string, 1000, 3);
    
    return 1;
}

CaptureTerritory(territoryid, gangid)
{
    new oldOwner = TerritoryData[territoryid][tOwner];
    
    if(oldOwner != -1)
    {
        GangData[oldOwner][gTerritories]--;
        GangData[oldOwner][gLosses]++;
    }
    
    TerritoryData[territoryid][tOwner] = gangid;
    TerritoryData[territoryid][tCaptureProgress] = 0;
    TerritoryData[territoryid][tCapturingGang] = -1;
    GangData[gangid][gTerritories]++;
    GangData[gangid][gWins]++;
    
    new string[256];
    format(string, sizeof(string), "~g~Территория захвачена бандой %s [%s]!", GangData[gangid][gName], GangData[gangid][gTag]);
    SendClientMessageToAll(GangData[gangid][gColor], string);
    
    return 1;
}

Ганг-чат

Код:
CMD:g(playerid, params[])
{
    if(PlayerGang[playerid] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите в банде");
        return 1;
    }
    
    new message[128];
    if(sscanf(params, "s[128]", message))
    {
        SendClientMessage(playerid, -1, "Использование: /g [сообщение]");
        return 1;
    }
    
    new gangid = PlayerGang[playerid];
    new name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));
    
    new string[256];
    format(string, sizeof(string), "[%s] %s: %s", GangData[gangid][gTag], name, message);
    
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(IsPlayerConnected(i) && PlayerGang[i] == gangid)
        {
            SendClientMessage(i, GangData[gangid][gColor], string);
        }
    }
    
    return 1;
}

Команды управления бандой

Код:
CMD:creategang(playerid, params[])
{
    if(PlayerInfo[playerid][pAdmin] < 5)
    {
        SendClientMessage(playerid, -1, "У вас нет доступа");
        return 1;
    }
    
    new name[32], tag[8], color;
    if(sscanf(params, "s[32]s[8]d", name, tag, color))
    {
        SendClientMessage(playerid, -1, "Использование: /creategang [название] [тег] [цвет]");
        return 1;
    }
    
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    
    new gangid = CreateGang(name, tag, color, x, y, z, GetPlayerInterior(playerid));
    
    if(gangid != -1)
    {
        new string[128];
        format(string, sizeof(string), "Банда '%s' создана (ID: %d)", name, gangid);
        SendClientMessage(playerid, -1, string);
    }
    
    return 1;
}

CMD:joingang(playerid, params[])
{
    new gangid;
    if(sscanf(params, "d", gangid))
    {
        SendClientMessage(playerid, -1, "Использование: /joingang [id банды]");
        return 1;
    }
    
    JoinGang(playerid, gangid);
    return 1;
}

CMD:leavegang(playerid, params[])
{
    LeaveGang(playerid);
    return 1;
}

CMD:ganginfo(playerid, params[])
{
    if(PlayerGang[playerid] == -1)
    {
        SendClientMessage(playerid, -1, "Вы не состоите в банде");
        return 1;
    }
    
    new gangid = PlayerGang[playerid];
    new string[512];
    format(string, sizeof(string),
        "Информация о банде: %s [%s]\n\n\
        Лидер: %s\n\
        Участников: %d\n\
        Территорий: %d\n\
        Побед: %d\n\
        Поражений: %d",
        GangData[gangid][gName],
        GangData[gangid][gTag],
        GangData[gangid][gLeader],
        GangData[gangid][gMembers],
        GangData[gangid][gTerritories],
        GangData[gangid][gWins],
        GangData[gangid][gLosses]
    );
    
    ShowPlayerDialog(playerid, DIALOG_GANG_INFO, DIALOG_STYLE_MSGBOX, "Информация о банде", string, "Закрыть", "");
    return 1;
}

Обновление территорий

Код:
public OnPlayerUpdate(playerid)
{
    if(PlayerGang[playerid] != -1)
    {
        ProcessTerritoryCapture(playerid);
    }
    return 1;
}

Сохранение данных банды

Код:
SaveGangData(gangid)
{
    new query[512];
    format(query, sizeof(query),
        "UPDATE gangs SET name = '%e', tag = '%e', color = %d, leader = '%e', members = %d, territories = %d, wins = %d, losses = %d, spawnx = %.2f, spawny = %.2f, spawnz = %.2f, interior = %d WHERE id = %d",
        GangData[gangid][gName],
        GangData[gangid][gTag],
        GangData[gangid][gColor],
        GangData[gangid][gLeader],
        GangData[gangid][gMembers],
        GangData[gangid][gTerritories],
        GangData[gangid][gWins],
        GangData[gangid][gLosses],
        GangData[gangid][gSpawnX],
        GangData[gangid][gSpawnY],
        GangData[gangid][gSpawnZ],
        GangData[gangid][gInterior],
        gangid
    );
    mysql_query(g_SQL, query);
    return 1;
}

Система банд добавляет глубину игровому процессу с территориальными войнами и командной игрой.
 

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

Сверху