Question

Привет! Решил добавить себе в мод систему инвентаря, взятую с одного из форумов. Всё работает хорошо, но не могу понять как всё это дело сохранять.
Тема: *клик* (Не реклама)

Очень надеюсь на помощь, заранее огромное спасибо!

Share this post


Link to post

21 answers to this question

  • 0

@phizlfs 

Вот код загрузки и сохранения инвентаря через БД с комментариями и разъяснениями:
 

Спойлер

#define DB_TABLE_ACCOUNTS       "Accounts"      // Таблица с данными игроков    // Заменить на свою
#define DB_COLUMN_INVENTORY     "Inventory"     // Столбец с данными инвентаря  // Заменить на свой
#define DB_COLUMN_NICKNAME      "Name"          // Столбец с ником игрока       // Заменить на свой

stock GN(playerid) { // Функция для получения ника игрока
    new funcNN[MAX_PLAYER_NAME]; // Создаём переменную для временого хранения ника
    GetPlayerName(playerid,funcNN,MAX_PLAYER_NAME); // Получаем ник игрока
    return funcNN; // Возвращаем ник игрока
}
stock SaveInventory(playerid) { // Функция для сохранения инвентаря игрока
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1]; // Создаём строку с данными инвентаря
    // 4 - макс. значение ID предмета (если кол-во предметов дойдёт до 1000+)
    // 4 - макс. значение кол-ва предмета (если можно будет стаковать до 1000+)
    // 1 - выделение ячейки на запятую между ID и кол-вом предмета
    // 1 - выделение ячейки на вертикальную черту для разметки ID слотов
    // 1 - выделение ячейки на символ завершения строки - '\0'
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) { // перебираем все слоты игрока
        format(str_inv, sizeof(str_inv), "%s|%d,%d", str_inv, pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
        // Инвентарь будет храниться так: id_предмета,кол-во_предмета|след.слот...
    } strdel(str_inv,0,1); // убираем ненужный первый знак '|'. Как по мне это лучше чем проверка на номер элемента при переборе
    new str_query[sizeof(str_inv) + 100]; // создаём строку для запроса в БД. 100 - примерная доп. длина запроса
    // Форматируем запрос для дальнейшего обращения в БД:
    format(str_query, sizeof(str_query), "UPDATE `%s` SET `%s` = '%s' WHERE `%s` = '%s'", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, str_inv, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_query(1, str_query, false); // отправляем данные в БД без использование кэша
    return 1;
}
stock strsub(text[], sub_char, new_char = ' ') { // Функция для замены символов в строке
    // Если новый символ не указан, то он будет пробелом
    new subed = 0// Создаём переменную для подсчёта заменённых символов
    for(new i = 0; i < strlen(text); i++) { // перебираем все символы текста
        if(text[i] == sub_char) ++subed, text[i] = new_char; // Если символ тот, который надо заменить, заменяем на нужный
    }
    return subed; // Возвращаем кол-во заменённых символов
}
stock LoadInventory(playerid) { // Функция для загрузки инвентаря игрока
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1]; // Создаём строку с данными инвентаря
    // Заодно её можно и использовать для запроса
    // Форматируем запрос для дальнейшего обращения в БД:
    format(str_inv, sizeof(str_inv), "SELECT `%s` FROM `%s` WHERE `%s` = '%s' LIMIT 1", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, DB_COLUMN_NICKNAME, GN(playerid));
    new Cache:inv_cache = mysql_query(1, str_inv, true); // отправляем данные в БД с использованием кэша
    if(!cache_get_row_count(1)) return false// Запрос не дал результата
    cache_get_row(00, str_inv); // Получаем строку с данными инвентаря в str_inv
    cache_delete(inv_cache); // Можем удалять кеш за ненадобностью
    strsub(str_inv, '|'); // Заменяем все вертикальные черточки на пробел (т. к. он стоит по умолчанию)
    new str_inv_slots[INVENTORY_MAX_SLOT][4+4+1+1]; // Создаём переменную для записи каждого слота инвентаря
    // 4 - на максимаольный ID предмета (если дойдёт до 1000+)
    // 4 - на максимаольное кол-во предмета (если будет стакаться до 1000+)
    // 1 - на запятую между кол-вом и ID
    // 1 - на символ окончания строки - '\0'
    new str_for_sscanf[10+2+2+1]; // создание строки для sscanf
    format(str_for_sscanf, sizeof(str_for_sscanf), "a<s[%d]>[%d]"sizeof(str_inv_slots[]), sizeof(str_inv_slots));
    sscanf(str_inv, str_for_sscanf, str_inv_slots); // получаем данные слотов в str_inv_slots
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) { // Переьираем все слоты
        // Получаем данные предметов инвентаря в переменные игрока:
        sscanf(str_inv_slots[i], "p<,>ii", pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
    }
}

 

вот же код без комментариев, который сразу можно внедрять в мод:
 

Спойлер

#define DB_TABLE_ACCOUNTS       "Accounts"
#define DB_COLUMN_INVENTORY     "Inventory"
#define DB_COLUMN_NICKNAME      "Name"
stock GN(playerid){new funcNN[MAX_PLAYER_NAME];GetPlayerName(playerid,funcNN,MAX_PLAYER_NAME);return funcNN;}
stock SaveInventory(playerid) { 
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1];
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) format(str_inv, sizeof(str_inv), "%s|%d,%d", str_inv, pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
    strdel(str_inv,0,1); new str_query[sizeof(str_inv) + 100];
    format(str_query, sizeof(str_query), "UPDATE `%s` SET `%s` = '%s' WHERE `%s` = '%s'", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, str_inv, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_query(1, str_query, false);
    return 1;
}
stock strsub(text[], sub_char, new_char = ' ') {
    new subed = 0;
    for(new i = 0; i < strlen(text); i++){if(text[i]==sub_char){++subed,text[i]=new_char;}}
    return subed;
}
stock LoadInventory(playerid) { 
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1];
    format(str_inv, sizeof(str_inv), "SELECT `%s` FROM `%s` WHERE `%s` = '%s' LIMIT 1", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, DB_COLUMN_NICKNAME, GN(playerid));
    new Cache:inv_cache = mysql_query(1, str_inv, true);
    if(!cache_get_row_count(1)) return false;
    cache_get_row(00, str_inv),cache_delete(inv_cache),strsub(str_inv, '|');
    new str_inv_slots[INVENTORY_MAX_SLOT][4+4+1+1], str_for_sscanf[10+2+2+1]; 
    format(str_for_sscanf, sizeof(str_for_sscanf), "a<s[%d]>[%d]"sizeof(str_inv_slots[]), sizeof(str_inv_slots));
    sscanf(str_inv, str_for_sscanf, str_inv_slots); 
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) sscanf(str_inv_slots[i], "p<,>ii", pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
}

 

Не забудьте изменить название ячеек базы данных на своё, а так же создать слобец для хранения информации инвентаря
Если что его можно сделать таким запросом в базе данных:

ALTER TABLE `Таблица с акк-ами` ADD `Столбец с данными инвентаря` TEXT NOT NULL;
-- Пример:
ALTER TABLE `Accounts` ADD `Inventory` TEXT NOT NULL;

 

Share this post


Link to post
  • 0

Огромное Вам спасибо!

 ADD `Inventory` TEXT NOT NULL; создавать любое имя, или такое, какое прописано в теме на другом форуме? (если это там есть, может я что-то не понял)

Share this post


Link to post
  • 0

@phizlfs Создавать с таким же названием, коке у вас в DB_COLUMN_INVENTORY

Share this post


Link to post
  • 0

Добавил всё в точности как написали вы, сохранение не работало. Попробовал добавить в /additem сток SaveInventory(playerid). Начало выдавать эти огибки:
 

C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : error 012: invalid function call, not a valid address
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : warning 215: expression has no effect
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : warning 215: expression has no effect
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : warning 215: expression has no effect
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : error 001: expected token: ";", but found ")"
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : error 029: invalid expression, assumed zero
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(29004) : fatal error 107: too many error messages on one line

 

Жалуется на паблик SaveInventory(playerid). 
 

строка 29004: mysql_query(1, str_query, false);

Share this post


Link to post
  • 0
stock SaveInventory(playerid)
{
    new mysql_query[128];
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1];
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) format(str_inv, sizeof(str_inv), "%s|%d,%d", str_inv, pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
    strdel(str_inv,0,1); new str_query[sizeof(str_inv) + 100];
    format(str_query, sizeof(str_query), "UPDATE `%s` SET `%s` = '%s' WHERE `%s` = '%s'", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, str_inv, DB_COLUMN_NICKNAME, GN(playerid));

 

ниже:

return 1;
}
stock strsub(text[], sub_char, new_char = ' ')
{
    new subed = 0;

@Sleash

Edited by phizlfs

Share this post


Link to post
  • 0

@phizlfs Значит у вас не новая версия MySQL, попробуйте так:
 

Спойлер

#define DB_TABLE_ACCOUNTS       "Accounts"
#define DB_COLUMN_INVENTORY     "Inventory"
#define DB_COLUMN_NICKNAME      "Name"
stock GN(playerid){new funcNN[MAX_PLAYER_NAME];GetPlayerName(playerid,funcNN,MAX_PLAYER_NAME);return funcNN;}
stock SaveInventory(playerid) { 
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1];
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) format(str_inv, sizeof(str_inv), "%s|%d,%d", str_inv, pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
    strdel(str_inv,0,1); new str_query[sizeof(str_inv) + 100];
    format(str_query, sizeof(str_query), "UPDATE `%s` SET `%s` = '%s' WHERE `%s` = '%s'", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, str_inv, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_tquery(1, str_query, """");
    return 1;
}
stock strsub(text[], sub_char, new_char = ' ') {
    new subed = 0;
    for(new i = 0; i < strlen(text); i++){if(text[i]==sub_char){++subed,text[i]=new_char;}}
    return subed;
}
stock LoadInventory(playerid) { 
    new sql_str[64];
    format(sql_str, sizeof(sql_str), "SELECT `%s` FROM `%s` WHERE `%s` = '%s' LIMIT 1", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_tquery(1, sql_str, "SQLLoadInv""i", playerid);
}
forward SQLLoadInv(playerid);
public SQLLoadInv(playerid) {
    new str_inv[INVENTORY_MAX_SLOT*(4+4+1+1)+1];
    cache_get_row(00, str_inv),strsub(str_inv, '|');
    new str_inv_slots[INVENTORY_MAX_SLOT][4+4+1+1], str_for_sscanf[10+2+2+1]; 
    format(str_for_sscanf, sizeof(str_for_sscanf), "a<s[%d]>[%d]"sizeof(str_inv_slots[]), sizeof(str_inv_slots));
    sscanf(str_inv, str_for_sscanf, str_inv_slots); 
    for(new i = 0; i < INVENTORY_MAX_SLOT; i++) sscanf(str_inv_slots[i], "p<,>ii", pInventoryData[playerid][idItem][i], pInventoryData[playerid][idAmount][i]);
}

 

 

Share this post


Link to post
  • 0

Код скомпилировался. В логах выдаёт этот текст:
1064, You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''Christopher_' at line 1, SQLLoadInv, SELECT `Accounts` FROM `Inventory` WHERE `Name` = 'Christopher_, 1

в базе 'inventory' начало появляться: 2,3|3,3|4,3|1,3|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0|0,0

 

Но при коннекте этих вещей в инвентаре нет

@Sleash

 И еще при коннекте это появляется в логах: 1146, Table 'gs219520.Inventory' doesn't exist, SQLLoadInv, SELECT `Accounts` FROM `Inventory` WHERE `Name` = 'Christopher_Bryte' LIMIT 1, 1

Edited by phizlfs

Share this post


Link to post
  • 0

@phizlfs 
1) Я чуть просчитался с размером строки для запроса, попробуйте так:

stock LoadInventory(playerid) { 
    new sql_str[128];
    format(sql_str, sizeof(sql_str), "SELECT `%s` FROM `%s` WHERE `%s` = '%s' LIMIT 1", DB_TABLE_ACCOUNTS, DB_COLUMN_INVENTORY, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_tquery(1, sql_str, "SQLLoadInv""i", playerid);
}

2) Table 'gs219520.Inventory' doesn't exis
Тут всё и так понятно, столбца `Inventory` не существует
Если вы не добавляли его, добавьте по примеру из первого сообщения
Если вы помните, что добавляли его, то проверьте его название
P.S. Учитывая данные из логов ваш запрос в базу должен выглядеть так:

ALTER TABLE `Accounts` ADD `Inventory` TEXT NOT NULL;

 

Share this post


Link to post
  • 0

По прежнему не загружает инвентарь. При коннекте выдаёт это:

1146, Table 'gs219520.Inventory' doesn't exist, SQLLoadInv, SELECT `Accounts` FROM `Inventory` WHERE `Name` = 'Christopher_Bryte' LIMIT 1, 1

p.s: в коннекте у меня и прописана загрузка инвентаря, а так же при спавне (пробовал вписывать всё это по отдельности, все равно не работает)
@Sleash

Share this post


Link to post
  • 0

@phizlfs 
Ошибка была моя, так как я переметал местами таблицу и столбец, код ниже должен работать

stock LoadInventory(playerid) { 
    new sql_str[128];
    format(sql_str, sizeof(sql_str), "SELECT `%s` FROM `%s` WHERE `%s` = '%s' LIMIT 1", DB_COLUMN_INVENTORY, DB_TABLE_ACCOUNTS, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_tquery(1, sql_str, "SQLLoadInv""i", playerid);
}

 

Share this post


Link to post
  • 0

Вроде как всё работает, щас подетальнее потестирую, спасибо большое!

Share this post


Link to post
  • 0

Чтоб добавить в инвентарь другие предметы, к примеру аксы. Нужно так сделать? @Sleash

stock UseInventoryItem(playerid, slot, itemid, type) 
{
    switch(type) 
    {
        case ITEM_TYPE_SKIN: // единственная функция, которая была в теме по стандарту.
        { 
            if(GetPlayerSkin(playerid) == itemid)
                return 1;

            SetPlayerSkin(playerid, itemid);
        } 
        case ITEM_TYPE_ACS: // То, что я хотел бы добавить
        { 
            if(IsPlayerAttachedObjectSlotUsed(playerid, 5)) RemovePlayerAttachedObject(playerid, 5); // ГИТАРА КРАСНАЯ
            SetPlayerAttachedObject(playerid, 51931710.114000,-0.122000,-0.0529994.199994,119.299995,-4.7000010.688000,1.000000,0.696000);
        }
    } 

 

А то я в подобных системах плохо понимаю

Edited by phizlfs

Share this post


Link to post
  • 0

@phizlfs 
В gInventoryItem у вас должна быть такая запись:

{19317"НАДЕТЬ""Красная гитара",    "Описание", ITEM_TYPE_ACS, 0.00.00.01.0}

А проверку лучше сделать такой:
 

stock UseInventoryItem(playerid, slot, itemid, type) 
{
    switch(type) 
    {
        case ITEM_TYPE_SKIN: // единственная функция, которая была в теме по стандарту.
        { 
            if(GetPlayerSkin(playerid) == itemid)
                return 1;

            SetPlayerSkin(playerid, itemid);
        } 
        case ITEM_TYPE_ACS: // То, что я хотел бы добавить
        { 
            switch(itemid) {
                case 19317: {
                    if(IsPlayerAttachedObjectSlotUsed(playerid, 5)) RemovePlayerAttachedObject(playerid, 5); // ГИТАРА КРАСНАЯ
                    SetPlayerAttachedObject(playerid, 51931710.114000,-0.122000,-0.0529994.199994,119.299995,-4.7000010.688000,1.000000,0.696000);
                }
            }
        }
    }

Ну или вместо switch использовать if, решать уже вам

Ещё лучше создать массив, который будет запоминать какие акс-ы на игроке надеты
И желательно это тоже с save + load БД
Это позволит проверять и надевать на игроков акс-ы при входе, а так же при надевании, допустим чёрно гитары, проверить надет ли на игроки другой акс. на спину (к примеру та же чёрная гитара)

Edited by Sleash

Share this post


Link to post
  • 0
enum {
    ITEM_TYPE_ACS = 0,     // гитара

    __DUMMY_ELEMENT_,
    ITEM_TYPE_COUNT = __DUMMY_ELEMENT_
}

Тут создать такой же enum? или же как-то приписать это к enum со скином?

@Sleash

Edited by phizlfs

Share this post


Link to post
  • 0

@phizlfs 
 

enum {
    ITEM_TYPE_SKIN = 0,     // скины

    ITEM_TYPE_ACS = 1,     // аксессуары

    __DUMMY_ELEMENT_,
    ITEM_TYPE_COUNT = __DUMMY_ELEMENT_
}

 

Share this post


Link to post
  • 0

Добавил гитару и RC игрушку, начало почему-то выбивать это:
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(423) : warning 228: length of initialler exceeds size of the enum field
C:\Users\phuzl\Desktop\INV\gamemodes\edit.pwn(423) : error 018: initialization data exceeds declared size

new gInventoryItem[][e_InventoryItems] = {
    {0" "" "" ", __DUMMY_ELEMENT_, 0.00.00.01.0},
    {1"НАДЕТЬ""Одежда Truth №1",     "Можно приобрести в магазине одежды", ITEM_TYPE_SKIN, 0.00.00.01.0},
    {2"НАДЕТЬ""Одежда Maccer №2",    "Можно приобрести в магазине одежды", ITEM_TYPE_SKIN, 0.00.00.01.0},
    {3"НАДЕТЬ""Одежда Andre №3",     "Можно приобрести в магазине одежды", ITEM_TYPE_SKIN, 0.00.00.01.0},
    {4"НАДЕТЬ""Одежда Bbthin №4",    "Можно приобрести в магазине одежды", ITEM_TYPE_SKIN, 0.00.00.01.0},
    {19317"НАДЕТЬ""Красная гитара",  "Купить можно в /mm - 9", ITEM_TYPE_ACS, 0.00.00.01.0},
    {564"ИСПОЛЬЗОВАТЬ""RC",          "Купить можно в /mm - 9", ITEM_TYPE_RC, 0.00.00.01.0}
};

как раз на последний пункт ругается 
@Sleash

p.s: после добавления гитары всё работало отлично, гитара надевалась и появлялась

Share this post


Link to post
  • 0

@phizlfs Взглянем на enum с данными предметов:

enum e_InventoryItems {
    /*
        Enum, содержащий информацию о предметах Инвентаря
    */
    iItemID,
    iUse[10], // Вот тут длина слова не может быть более 10 символов
    iName[30],
    iDesc[110],
    iType,

    Float: iItemPosX,
    Float: iItemPosY,
    Float: iItemPosZ,
    Float: iItemPosC
};

А у вас стоит слово "Использовать" - это 12 символов, надо просто увеличить размер с 10 до, к примеру, 15-и символов:
iUse[10], -> iUse[15],

Share this post


Link to post
  • 0

Аа.. Не обратил внимание, благодарю!

Share this post


Link to post
  • 0

Все отлично работает, спасибо вам)


Я тут столкнулся с небольшой проблемой, а именно загрузкой последний надетых аксессуаров на персонаже при спавне/смерти.
У меня есть предположение как это сделать, но всё накладывается друг на друга или удаляется в занятом слоте до тех пор, пока не дойдёт до последнего пункта в коде. Как это можно реализовать? @Sleash
 

Edited by phizlfs

Share this post


Link to post
  • 0

@phizlfs 
1) Я написал +- примитивный код, постарайтесь изучить его, что бы понять как это работает
2) Если появятся ещё вопросы - прошу создавать новую тему на форуме.
3) Код на работоспособность не проверял, но он компилируется:
 

Спойлер

// Для начала надо бы раставить index`ы на прикрепления объектов к игроку,
// что бы в дальнейшем было проще, к примеру:
enum {
    ATTACH_IDX_NONE = -1// Несуществующий индекс
    ATTACH_IDX_HEAD = 0// index для акс-ов на голову
    ATTACH_IDX_BACK = 1// index для акс-ов на спину
    ATTACH_IDX_RARM = 2// index для акс-ов на правую руку
    ATTACH_IDX_LARM = 3 // index для акс-ов на левую руку
    // И так далее, но, если я не ошибасю у них есть ограничение от 0 до 9-и
    // Точно не помню действует ли оно в SA:MP 0.3.7
};
#define MAX_ATTACHS 3 // Тут пишем последне число, котороые было в enum выше
#define DB_TABLE_ACCOUNTS       "Accounts"
#define DB_COLUMN_USEDACS       "UsedAcs"
#define DB_COLUMN_NICKNAME      "Name"
// Дальше неплохо было бы докинуть к переменным надетые акс-ы игрока:
new pUsedAcs[MAX_PLAYERS][MAX_ATTACHS+1];

public OnPlayerSpawn(playerid) {
    new str_sql[128];
    format(str_sql, 128"SELECT `%s` FROM `%s` WHERE `%s` = '%s'", DB_COLUMN_USEDACS, DB_TABLE_ACCOUNTS, DB_COLUMN_NICKNAME, GN(playerid));
    SetPVarInt(playerid, "SpawnLoadUsedAcs"1);
    mysql_tquery(1, str_sql, "LoadUsedAcs""i", playerid);
    // ...
}

// Теперь создадим функцию дял получения типа индекса:
stock GetAttachIDX(itemID) {
    switch(itemID) {
        case 19317return ATTACH_IDX_BACK; // Если это гитара, то возвращает спину
        defaultreturn ATTACH_IDX_NONE; // Если акс-а нет в перечни case, то возвращаем несуществующий id
    }
    return ATTACH_IDX_NONE;
}
// Далее рассмотрим надевание акс-са
stock UseInventoryItem(playerid, slot, itemid, type) 
{
    switch(type) 
    {
        case ITEM_TYPE_ACS: return UseAcs(plaeyrid, itemid); // перенаправляем на нашу функцию
        //...
    }
    //...
}
// Теперь распишем полную функцию использования акс-а:
stock UseAcs(playerid, itemid, onspawn = 0) {
    new index = GetAttachIDX(itemid); // Получаем индекс акс-а
    if(index == ATTACH_IDX_NONE && onspawn) return false// Если индекс неверный при спавне
    if(index == ATTACH_IDX_NONE && !onspawn) return SendClientMessage(playerid, -1"Неизвестный аксессуар"); // Если индекс неверный при попытке надеть
    if(pUsedAcs[playerid][index]) RemovePlayerAttachedObject(playerid, index); // если на этот индекс уже надет акс. - снимаем
    pUsedAcs[playerid][index] = itemid; // Обновляем переменную по нашему индексу на новый акс.
    // Плюсом для удобства я бы добавил себе define
    #define AcsAttach(%0) SetPlayerAttachedObject(playerid,index,itemid,%0)
    // Далее перебор акс-ов
    switch(itemid) {
        // Нам остаётся ввести просто кость и координаты:
        case 19317: AcsAttach(10.114000,-0.122000,-0.0529994.199994,119.299995,-4.7000010.688000,1.000000,0.696000);
    }
    return 1// Можно на этом и заканчивать цепочку действий надевания акс-а
}
// Созданение функций загрузки и разгрузки использованных акс-ов:
// Сначала загрузка акс-ов:
forward LoadUsedAcs(playerid);
public LoadUsedAcs(playerid) {
    new sql_usedacs[(MAX_ATTACHS+1)*(5+1)]; // создаём массив для получения данных
    if(GetPVarInt(playerid, "SpawnLoadUsedAcs")) { //Если сток вызван по случаю входа игрока
        cache_get_row(00, sql_usedacs); // получаем данные
        new f_sscanf[15]; // создаём массив для форматирование строки для sscanf
        format(f_sscanf, 15"p<,>a<d>[%d]", MAX_ATTACHS+1);
        // Мы удаляя из строки запятые получаем числа в кол-ве MAX_ATTACHS+1
        sscanf(sql_usedacs, f_sscanf, pUsedAcs[playerid]); // Получил числа отдельно в массив pUsedAcs
        DeletePVar(playerid, "SpawnLoadUsedAcs");
    } // Дальше простая загрузка
    // GetPVarInt(playerid, "SpawnLoadUsedAcs") был добавлен, что бы мы не получали пустую строку, если хотим обновить акс-ы игркоа в середине игры без запроса
    // Это сожно будет делать просто вызываю функцию: LoadUsedAcs(playerid);
    // Как раз для тех моментов, когада надо обновить акс-ы игрока при, допустим, смерти (как вы и указывали на форуме)
    for(new i = 0; i <= MAX_ATTACHS+1; i++) UseAcs(playerid, pUsedAcs[playerid][i], true); // пытаемся надеть все акс-ы
}
// Теперь сохранение акс-ов:
stock SaveUsedAcs(playerid) {
    new sql_usedacs[(MAX_ATTACHS+1)*(5+1)+1]; // создаём массив для сохранения данных данных
    for(new i = 0; i <= MAX_ATTACHS+1; i++)
        format(sql_usedacs, sizeof(sql_usedacs), "%s,%d",sql_usedacs, pUsedAcs[playerid][i]); // перебираем все акс-ы
    strdel(sql_usedacs,0,1); // Убираем лишнюю запятую в начале
    new str_sql[128+sizeof(sql_usedacs)]; // Переменная для запроса
    //UPDATE `Qelksekm` SET `OldIP` = '%s',`onl_status`='1001',`Lastlogin` = CURDATE() WHERE `ID` = '%i'
    format(str_sql, 128"UPDATE `%s` SET `%s` = '%s' WHERE `%s` = '%s'", DB_TABLE_ACCOUNTS, DB_COLUMN_USEDACS, sql_usedacs, DB_COLUMN_NICKNAME, GN(playerid));
    mysql_tquery(1, str_sql, """");
}

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • Topowich
      By Topowich
      Недавно начал создавать свой комп сервер,начал потихоньку заменять модели тс и столкнулся с такой проблемой,что не могу понять как менять настройку авто. Подскажите пожалуйста,как это сделать?Мне не принципиально  чтобы настройки были в коде сервера,можно и на файлах если будет хорошо работать