Система выбора скина в Pawn

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

8

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

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

Структура данных скинов

Код:
enum SkinInfo
{
    sID,
    sName[32],
    sCategory,
    sPrice,
    sGender
}

new SkinData[300][SkinInfo];
new TotalSkins = 0;
new SkinCategories[][32] = {
    "Гражданские",
    "Полиция",
    "Медики",
    "Военные",
    "Гангстеры",
    "Спортсмены"
};

Инициализация скинов

Код:
InitializeSkins()
{
    // Гражданские (мужские)
    AddSkin(0, "Carl Johnson", 0, 0, 0);
    AddSkin(1, "Truth", 0, 0, 0);
    AddSkin(2, "Maccer", 0, 0, 0);
    
    // Гражданские (женские)
    AddSkin(9, "Millie Perkins", 0, 0, 1);
    AddSkin(10, "Denise Robinson", 0, 0, 1);
    AddSkin(11, "Helena Wankstein", 0, 0, 1);
    
    // Полиция
    AddSkin(280, "Полицейский LS", 1, 0, 0);
    AddSkin(281, "Полицейский SF", 1, 0, 0);
    AddSkin(282, "Полицейский LV", 1, 0, 0);
    AddSkin(283, "Полицейский SWAT", 1, 5000, 0);
    
    // Медики
    AddSkin(274, "Медик", 2, 0, 0);
    AddSkin(275, "Медик", 2, 0, 1);
    
    // Военные
    AddSkin(287, "Солдат", 3, 10000, 0);
    AddSkin(285, "Офицер", 3, 15000, 0);
    
    return 1;
}

AddSkin(skinid, name[], category, price, gender)
{
    if(TotalSkins >= sizeof(SkinData))
    {
        return -1;
    }
    
    SkinData[TotalSkins][sID] = skinid;
    strcpy(SkinData[TotalSkins][sName], name, 32);
    SkinData[TotalSkins][sCategory] = category;
    SkinData[TotalSkins][sPrice] = price;
    SkinData[TotalSkins][sGender] = gender;
    
    TotalSkins++;
    return TotalSkins - 1;
}

Меню выбора скина

Код:
ShowSkinMenu(playerid)
{
    new string[512] = "Выберите категорию скинов:\n\n";
    
    for(new i = 0; i < sizeof(SkinCategories); i++)
    {
        format(string, sizeof(string), "%s%d. %s\n", string, i+1, SkinCategories[i]);
    }
    
    ShowPlayerDialog(playerid, DIALOG_SKIN_CATEGORY, DIALOG_STYLE_LIST, "Выбор скина", string, "Выбрать", "Отмена");
    return 1;
}

ShowSkinList(playerid, category)
{
    new string[512], count = 0, list[100];
    
    for(new i = 0; i < TotalSkins; i++)
    {
        if(SkinData[i][sCategory] == category)
        {
            format(list, sizeof(list), "%d. %s", SkinData[i][sID], SkinData[i][sName]);
            if(SkinData[i][sPrice] > 0)
            {
                format(list, sizeof(list), "%s ($%d)\n", list, SkinData[i][sPrice]);
            }
            else
            {
                strcat(list, "\n");
            }
            strcat(string, list);
            count++;
        }
    }
    
    if(count == 0)
    {
        SendClientMessage(playerid, -1, "В этой категории нет скинов");
        return 1;
    }
    
    SetPVarInt(playerid, "SkinCategory", category);
    ShowPlayerDialog(playerid, DIALOG_SKIN_LIST, DIALOG_STYLE_LIST, "Список скинов", string, "Выбрать", "Назад");
    return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if(dialogid == DIALOG_SKIN_CATEGORY)
    {
        if(response)
        {
            ShowSkinList(playerid, listitem);
        }
        return 1;
    }
    
    if(dialogid == DIALOG_SKIN_LIST)
    {
        if(response)
        {
            new category = GetPVarInt(playerid, "SkinCategory");
            new skinIndex = -1, currentIndex = 0;
            
            for(new i = 0; i < TotalSkins; i++)
            {
                if(SkinData[i][sCategory] == category)
                {
                    if(currentIndex == listitem)
                    {
                        skinIndex = i;
                        break;
                    }
                    currentIndex++;
                }
            }
            
            if(skinIndex != -1)
            {
                if(SkinData[skinIndex][sPrice] > 0)
                {
                    if(GetPlayerMoney(playerid) < SkinData[skinIndex][sPrice])
                    {
                        new string[128];
                        format(string, sizeof(string), "Недостаточно денег. Нужно: $%d", SkinData[skinIndex][sPrice]);
                        SendClientMessage(playerid, -1, string);
                        return 1;
                    }
                    
                    GivePlayerMoney(playerid, -SkinData[skinIndex][sPrice]);
                }
                
                SetPlayerSkin(playerid, SkinData[skinIndex][sID]);
                
                new string[128];
                format(string, sizeof(string), "Вы выбрали скин: %s", SkinData[skinIndex][sName]);
                SendClientMessage(playerid, -1, string);
                
                PlayerInfo[playerid][pSkin] = SkinData[skinIndex][sID];
            }
        }
        else
        {
            ShowSkinMenu(playerid);
        }
        return 1;
    }
    return 0;
}

Предпросмотр скина

Код:
PreviewSkin(playerid, skinid)
{
    if(skinid < 0 || skinid > 299)
    {
        return 0;
    }
    
    SetPlayerSkin(playerid, skinid);
    
    new Float:x, Float:y, Float:z, Float:angle;
    GetPlayerPos(playerid, x, y, z);
    GetPlayerFacingAngle(playerid, angle);
    
    // Поворот для лучшего обзора
    SetPlayerFacingAngle(playerid, angle + 180.0);
    
    new string[128];
    format(string, sizeof(string), "Предпросмотр скина ID: %d\nИспользуйте /buyskin чтобы купить", skinid);
    SendClientMessage(playerid, -1, string);
    
    SetPVarInt(playerid, "PreviewSkin", skinid);
    return 1;
}

CMD:previewskin(playerid, params[])
{
    new skinid;
    if(sscanf(params, "d", skinid))
    {
        SendClientMessage(playerid, -1, "Использование: /previewskin [id скина]");
        return 1;
    }
    
    PreviewSkin(playerid, skinid);
    return 1;
}

CMD:buyskin(playerid, params[])
{
    if(!GetPVarType(playerid, "PreviewSkin"))
    {
        SendClientMessage(playerid, -1, "Сначала используйте /previewskin для предпросмотра");
        return 1;
    }
    
    new skinid = GetPVarInt(playerid, "PreviewSkin");
    new skinIndex = -1;
    
    for(new i = 0; i < TotalSkins; i++)
    {
        if(SkinData[i][sID] == skinid)
        {
            skinIndex = i;
            break;
        }
    }
    
    if(skinIndex == -1)
    {
        SendClientMessage(playerid, -1, "Скин не найден в базе");
        return 1;
    }
    
    if(SkinData[skinIndex][sPrice] > 0)
    {
        if(GetPlayerMoney(playerid) < SkinData[skinIndex][sPrice])
        {
            new string[128];
            format(string, sizeof(string), "Недостаточно денег. Нужно: $%d", SkinData[skinIndex][sPrice]);
            SendClientMessage(playerid, -1, string);
            return 1;
        }
        
        GivePlayerMoney(playerid, -SkinData[skinIndex][sPrice]);
    }
    
    SetPlayerSkin(playerid, skinid);
    PlayerInfo[playerid][pSkin] = skinid;
    DeletePVar(playerid, "PreviewSkin");
    
    new string[128];
    format(string, sizeof(string), "Вы купили скин: %s", SkinData[skinIndex][sName]);
    SendClientMessage(playerid, -1, string);
    
    return 1;
}

Сохранение скина игрока

Код:
SavePlayerSkin(playerid)
{
    new query[256], name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));
    
    format(query, sizeof(query), "UPDATE players SET skin = %d WHERE name = '%e'", PlayerInfo[playerid][pSkin], name);
    mysql_query(g_SQL, query);
    return 1;
}

LoadPlayerSkin(playerid)
{
    new query[256], name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));
    
    format(query, sizeof(query), "SELECT skin FROM players WHERE name = '%e'", name);
    mysql_query(g_SQL, query);
    mysql_store_result();
    
    if(mysql_num_rows() > 0)
    {
        PlayerInfo[playerid][pSkin] = mysql_fetch_int("skin");
        SetPlayerSkin(playerid, PlayerInfo[playerid][pSkin]);
    }
    else
    {
        // Скин по умолчанию
        PlayerInfo[playerid][pSkin] = 0;
        SetPlayerSkin(playerid, 0);
    }
    
    mysql_free_result();
    return 1;
}

Команда смены скина

Код:
CMD:skin(playerid, params[])
{
    ShowSkinMenu(playerid);
    return 1;
}

CMD:myskin(playerid, params[])
{
    new string[128];
    format(string, sizeof(string), "Ваш текущий скин: ID %d", PlayerInfo[playerid][pSkin]);
    SendClientMessage(playerid, -1, string);
    return 1;
}

Ограничение скинов по фракциям

Код:
CanPlayerUseSkin(playerid, skinid)
{
    if(PlayerFaction[playerid][pFaction] == -1)
    {
        // Гражданские могут использовать только гражданские скины
        for(new i = 0; i < TotalSkins; i++)
        {
            if(SkinData[i][sID] == skinid)
            {
                if(SkinData[i][sCategory] == 0)
                {
                    return 1;
                }
                return 0;
            }
        }
        return 0;
    }
    
    // Проверка скинов фракции
    new factionid = PlayerFaction[playerid][pFaction];
    for(new i = 0; i < TotalSkins; i++)
    {
        if(SkinData[i][sID] == skinid)
        {
            if(SkinData[i][sCategory] == FactionData[factionid][fSkinCategory])
            {
                return 1;
            }
            return 0;
        }
    }
    return 0;
}

SetPlayerSkinSafe(playerid, skinid)
{
    if(!CanPlayerUseSkin(playerid, skinid))
    {
        SendClientMessage(playerid, -1, "Вы не можете использовать этот скин");
        return 0;
    }
    
    SetPlayerSkin(playerid, skinid);
    PlayerInfo[playerid][pSkin] = skinid;
    return 1;
}

Случайный скин

Код:
CMD:randomskin(playerid, params[])
{
    new category = 0;
    if(!isnull(params))
    {
        category = strval(params);
    }
    
    new availableSkins[300], count = 0;
    
    for(new i = 0; i < TotalSkins; i++)
    {
        if(SkinData[i][sCategory] == category)
        {
            if(CanPlayerUseSkin(playerid, SkinData[i][sID]))
            {
                availableSkins[count] = SkinData[i][sID];
                count++;
            }
        }
    }
    
    if(count == 0)
    {
        SendClientMessage(playerid, -1, "Нет доступных скинов в этой категории");
        return 1;
    }
    
    new randomSkin = availableSkins[random(count)];
    SetPlayerSkinSafe(playerid, randomSkin);
    
    new string[128];
    format(string, sizeof(string), "Выбран случайный скин: ID %d", randomSkin);
    SendClientMessage(playerid, -1, string);
    
    return 1;
}

Список всех скинов

Код:
CMD:skinlist(playerid, params[])
{
    new string[512] = "Доступные скины:\n\n";
    new count = 0;
    
    for(new i = 0; i < TotalSkins && count < 20; i++)
    {
        if(CanPlayerUseSkin(playerid, SkinData[i][sID]))
        {
            format(string, sizeof(string), "%sID %d: %s\n",
                string, SkinData[i][sID], SkinData[i][sName]);
            count++;
        }
    }
    
    if(count == 0)
    {
        strcat(string, "Нет доступных скинов");
    }
    
    ShowPlayerDialog(playerid, DIALOG_SKIN_LIST_ALL, DIALOG_STYLE_MSGBOX, "Список скинов", string, "Закрыть", "");
    return 1;
}

Система выбора скина - важная часть игрового процесса. Эти примеры показывают полный функционал работы со скинами с категориями, предпросмотром и ограничениями.
 

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

Сверху