Вопросы

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

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

Поделиться сообщением


Ссылка на сообщение

21 ответ на этот вопрос

  • 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;

 

Поделиться сообщением


Ссылка на сообщение
  • 0

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

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

Поделиться сообщением


Ссылка на сообщение
  • 0

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

Поделиться сообщением


Ссылка на сообщение
  • 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);

Поделиться сообщением


Ссылка на сообщение
  • 0

Скиньте по 5 строк выше и ниже строки 29004@phizlfs 

Поделиться сообщением


Ссылка на сообщение
  • 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

Отредактировано пользователем phizlfs

Поделиться сообщением


Ссылка на сообщение
  • 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]);
}

 

 

Поделиться сообщением


Ссылка на сообщение
  • 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

Отредактировано пользователем phizlfs

Поделиться сообщением


Ссылка на сообщение
  • 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;

 

Поделиться сообщением


Ссылка на сообщение
  • 0

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

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

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

Поделиться сообщением


Ссылка на сообщение
  • 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);
}

 

Поделиться сообщением


Ссылка на сообщение
  • 0

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

Поделиться сообщением


Ссылка на сообщение
  • 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);
        }
    } 

 

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

Отредактировано пользователем phizlfs

Поделиться сообщением


Ссылка на сообщение
  • 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 БД
Это позволит проверять и надевать на игроков акс-ы при входе, а так же при надевании, допустим чёрно гитары, проверить надет ли на игроки другой акс. на спину (к примеру та же чёрная гитара)

Отредактировано пользователем Sleash

Поделиться сообщением


Ссылка на сообщение
  • 0
enum {
    ITEM_TYPE_ACS = 0,     // гитара

    __DUMMY_ELEMENT_,
    ITEM_TYPE_COUNT = __DUMMY_ELEMENT_
}

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

@Sleash

Отредактировано пользователем phizlfs

Поделиться сообщением


Ссылка на сообщение
  • 0

@phizlfs 
 

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

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

    __DUMMY_ELEMENT_,
    ITEM_TYPE_COUNT = __DUMMY_ELEMENT_
}

 

Поделиться сообщением


Ссылка на сообщение
  • 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: после добавления гитары всё работало отлично, гитара надевалась и появлялась

Поделиться сообщением


Ссылка на сообщение
  • 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],

Поделиться сообщением


Ссылка на сообщение
  • 0

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

Поделиться сообщением


Ссылка на сообщение
  • 0

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


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

Отредактировано пользователем phizlfs

Поделиться сообщением


Ссылка на сообщение
  • 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, """");
}

 

 

Поделиться сообщением


Ссылка на сообщение
Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Похожий контент

    • Sten Developer
      От Sten Developer
      Объясню всю ситуацию, пишу систему смерти игрока но она не работает. Решил по приколу написать туда обычный вывод текста SCM(playerid, COLOR_RED, "Вы умерли");
      Но однако после смерти текст не выводиться. Не работает абсолютно все. Кто знает как решить эту проблему?