oxygenium
Компетентный
Предисловие:
Доброго времени суток. Это не готовое решение. Это объяснение принципа работы системы инвентаря, причем не общее, а конкретно моей реализации. На форумах в основном куча криво вырезанных систем с различных копий модов популярных серверов. Я пытался задействовать минимальное количество кода. Так же система не имеет зависимостей, различных самописных дефайнов и прочего. И так, приступим.
Что потребуется?
1) Знание и умение работать с текущей системой хранения вашего сервера (SQLite, MySQL, ini и т.д.). Так как в разных модах применяются разные системы хранения данных, в этом мануале я не буду опираться на какую-то конкретную. Однако вам нужно уметь работать с конкретной системой в вашем моде, чтобы сохранять и читать данные.
2) Плагин и инклуд sscanf. Я думаю, что у многих он есть, однако если это не так - скачайте и установите его
Что такое система инвентаря? Это система, которая позволяет игроку хранить различные предметы, применимо к сампу это могут быть канистры, инструменты для ремонта автомобиля, аптечки, различные аксессуары, такие как очки, шляпы, кепки, часы и прочее. Так же с небольшой доработкой данную систему можно применить не к игроку, а к багажнику автомобиля, если будет фидбек, расскажу как это можно реализовать.
Как работает система инвентаря? Для начала, нам нужно хранить абсолютно все предметы, доступные на сервере в массиве. Это даст нам возможность хранить лишь ID предмета и его количество в базе данных и у игрока, а чтобы получить название предмета, его стоимость, ID модели и т.д. и т.п. нам просто нужно будет обратиться к нужному индексу массива с предметами.
Хранение в базе. Тут я видел достаточно много всяких реализаций. Конечно, можно просто создать ячейку в базе для каждого предмета у каждого игрока. Но что если предметов 100? 200? 1000? Плюс каждый раз нам нужно будет добавлять вручную все эти ячейки при добавлении нового предмета. Поэтому мы поступим проще, и будем хранить одной строкой. Затем, чтобы обработать эту строку, нам понадобится sscanf, все ссылки верху темы.
Перейдем к реализации.
Создание и работа с массивами, удаление и добавление предметов в инвентарь
Так как каждый предмет будет иметь свой ID, который так же будет и индексом массива, нам нужно придумать, как запомнить все ID (не путать с ID объекта) предметов. Проще всего это будет сделать если заменить цифры на буквы. Гораздо проще запомнить что, например, канистра это FUEL_CAN, а не 23, а аптечка это MEDIC_KIT, а не 0. Для реализации этого создадим энуменатор. Он полезен в создании ассоциативных массивов (т.к. в pawn нельзя так просто их создать, как например в js или php), а так же каждый элемент enum автоматически нумеруется от 0 до до бесконечности (до бесконечности это конечно громко сказано, всему есть свои пределы, особенно в pawn).
Создаем enum без названия
Как я уже и говорил выше, это нужно просто для удобства. Enum сам пронумерует все предметы и мы сможем обращаться к индексам по названию.
FUEL_CAN станет равен 0, WORK_HAT станет 1, MEDIC_KIT - 2 и так далее.
Теперь нам нужно создать сам массив с предметами. Если Вы хотите хранить в одном массиве разные типы данных, для этого нам опять потребуется enum
Думаю, многие знают подобную реализацию массивов pInfo, тут принцип тот же. В itemobjectid мы будем хранить ID объекта, не путайте, именно ID самого объекта, а не номер ключа массива. Допустим, для канистры ID объекта будет 1650. Перейдем к объявлению переменной и созданию самого массива.
Что мы только что сделали? Мы создали многомерный массив, с автоматическим подсчетом размера (по факту - количества строк) и с нашими предметами. ITEMS во вторых квадратных скобках - это наш энуменатор. Если сравнивать массив с таблицей, то первые квадратные скобки это строки, а вторые - столбцы. Так же мы не указали количество строк в первых квадратных скобках, компилятор сам посчитает сколько их, и при вызове sizeof invetory выдаст нам их количество. Хотя, запись вида new inventory[5][ITEMS] тоже является правильной, однако если добавить новые элементы в массив и не изменить количество - получим ошибку. Так что используйте вариант без указания количества строк.
После этих манипуляций по факту мы получим следующую конструкцию:
Основа готова. Теперь у нас есть список всех предметов, которые доступны на сервере. Теперь нам нужно реализовать хранение их в инвентаре игрока. Сделаем мы это максимально просто - просто создадим одинарный массив для каждого игрока. Массив этот будет состоять из стольких строк, сколько у нас в глобальном массиве с предметами, в нашем случае - 5.
Если у вас уже есть enum с информацией об игроке, вставьте это туда, однако тут, так как система максимально независимая, мы просто создадим отдельную переменную.
Мы создали массив с 5-ю строками, с индексами от 0 до 4. Сами индексы будут являться ID предмета, а их значение - количеством данного предмета у игрока.
Например, игрок купил канистру. Чтобы добавить канистру к инвентарю, нам не нужно знать индекс, именно для этого мы создавали enum, который автоматически будет задавать индекс, поэтому мы просто сделаем так:
Или, если хотим добавить какое-то определенное количество
Так как до этого никаких манипуляций мы не проводили, а при создании переменных они автоматически равняются 0, то значение FUEL_CAN у нас станет равно одному, при условии что мы использовали инкремент ++, либо станет больше на число n, которое мы указали в конструкции +=4, не забудьте про плюс перед равно, плюс именно прибавляет к текущему значению переменной то число, которое мы указали. Если же использовать конструкцию =4, то независимо от текущего количества переменная станет равна 4. Таким же образом можно либо отнять 1, используя декремент --, либо при помощи конструкции -=n. Думаю тут понятно.
По итогу мы получим то, что массив items у игрока изменится и его индекс, равный 0 (FUEL_CAN как помним так же равна 0) станет равным значению, которое мы присвоили. Как в случае с глобальным массивом предметов, индекс в массиве игрока так же является ID предмета. Для большей наглядности давайте добавим еще один предмет. Дадим игроку 10 аптечек. Опять же, мы помним только простые текстовые названия, нам не нужно запоминать индексы. Соответственно выполняем следующую операцию:
Теперь, чтобы было еще понятней, визуализируем массив
Как видим, индексы 0 и 2 (или же FUEL_CAN и MEDIC_KIT) стали равны нашим значениям. Остальные индексы были равны нулю по умолчанию при создании.
Чтобы получить количество определенного предмета, нам просто нужно обратится по конкретному индексу
Результат будет равен 10, так как до этого мы выдали игроку 10 аптечек.
Немного про удаление. Так как мы можем случайно удалить больше предметов, чем есть у игрока, нам нужно проверить, не будет ли количество меньше нуля при нашем удалении. Простое условие:
Допустим, у игрока 4 канистры, а мы хотим удалить 5. В условии выше, мы просто приравняем количество канистр игрока к 0. Однако, если кому-нибудь понадобится посчитать, сколько канистр мы не удалили и сколько можем удалить - сделать это можно так:
Вывод инвентаря игроку и взаимодействие с предметами
После всех этих манипуляций, когда у нас есть глобальный массив с предметами, массив игрока с его предметами, нам нужно как-нибудь показывать ему эти предметы. Самый простой способ - показать диалог. Диалог у нас будет с заголовками, чтобы было более юзерфренди, если это можно так назвать.
И так, мы имеем массив игрока с его предметами. Но в этом массиве хранятся лишь цифры, однако нам этого более чем достаточно. Теперь нам нужно превратить этот массив в строку для вывода в диалоге. Перед тем как это сделать, я надеюсь вы знаете как работают диалоги. Так вот, дело в том, что мы будем показывать игроку только те предметы, которые у него есть. Соответственно будет разброс в индексах. Если у игрока есть FUEL_CAN и MEDIC_KIT, индексы будут 0 и 2 соответственно. В связи с этим, в OnDialogResponse мы не сможем использовать listitem как индекс.
Как это обойти? Все просто, мы создадим еще один массив. Его отличие от массива items[playerid], что в него мы не будем записывать те предметы, которые у нас есть. И если в items[playerid] как мы уже говорили, к примеру 5 строк, то в новом массиве у нас так же будет 5 строк, однако записывать мы будем начиная с 0 строки, так как у нас есть 2 предмета - аптечка и канистра, то индекс для канистры будет 0, а индексом аптечки - 1, а уже значениями будут индексы аптечки и канистры из enum. Значениями в этом массиве будет не количество, а ID предмета (его индекс). Тем самым индексы и listitem будут совпадать. Создадим этот массив, он так же будет для всех игроков:
В диалоге у нас будет:
В массиве примерно то же самое, но без количества. Это не главное, главное что индексы массива и lisitem у нас будут совпадать. Теперь давайте перейдем к генерации строки для диалога и записи в массив currentitems текущих предметов. Данный массив мы будем заполнять только при вызове команды для открытия диалога, ибо он нам нужен только тут. Вы скажете, почему же сразу в нем не хранить предметы. Во время игры может довольно часто меняться, соответственно нам нужно будет обновлять и этот массив, еще и учитывать чтобы индексы совпадали в дальнейшем с listitem, вообщем это бесполезное занятие.
Как нам сгенерировать строку с имеющимися предметами. Тут я так же предполагаю что вы знаете функцию format и strins. Каким образом мы будем генерировать эту строку? Мы создадим цикл с количеством итераций равному размеру (или же количеству строк, одно и то же) массива inventory, то есть пройдемся по всем предметам, а внутри каждой итерации мы просто будем смотреть, если у игрока конкретный предмет, если есть - запишем его в строку. Так же запишем индексы для нашего массива currentitem.
Получим следующую конструкцию:
Теперь реализация в виде кода, на забудьте поменять dialogid на свой
Теперь мы можем спокойно взаимодействовать с инвентарем в OnDialogResponse. ID (индекс) предмета теперь можно получить так: currentitems[playerid][listitem]
Чтобы присвоить действие для каждого предмета - просто сравниваем itemid с enum
На этом с взаимодействием все.
Сохранение в базе данных
Тут действуем практически по тому же принципу, что и сверху. Единственное записываем немного в другом формате. У меня это будет {предмет},{количество};{предмет},{количество};{предмет},{количество};{предмет},{количество} То есть 0,4;2,10 - 4 канистры (индекс 0) и 10 аптечек (индекс 2)
Принцип тут такой же, как и сверху, поэтому расписывать не буду. Единственное другой формат - не %s\f%d\n, а %d,%d;
На выходе у нас будет строка itemsstr, которая готова для записи в базу данных
Форматируйте ее, чтобы вместо %s была наша строка itemsstr. Так же не забудьте поменять playername.
Чтение из базы
Это самая сложная часть, так как в pawn нет стандартных функций, по типу explode в php, или хотя бы для работы с json. Для этого нам и понадобится инклуд sscanf, помимо проверки параметров команд, он может еще много чего. Одна из функций это разделение строки по символу.
Раскажу как это работает в php, на примере функции explode. Допустим у нас есть строка, и нам нужно разделить ее на части, разделителем будет символ ";". Разделителем может быть что угодно
Функция explode возвращает массив, значениями которого будут соотвественно наши разделенные части
И теперь при обращении к, допустим, $array[0] мы получим "часть1"
Этот разделяющий символ называется делимитер. В sscanf, когда мы проверяем строку, мы пишем s[], когда число - i или d, когда число с плавающей точкой - f. Чтобы указать делимитер в sscanf, мы пишем p<;>, в кавычках мы указываем сам символ делимитера. Так же scanff может записать все в массив. Более подробно читайте в документации.
И так, мы получили из базы данных строку с нашими предметами, пусть это будет
И значением ее будет "0,4;2,10"
Для примера в SQLite, чтобы получить конкретное значение, необходимо выполнить следующую функцию:
Теперь нам нужно создать временный массив, в котором мы будем хранить разделенную строку. Но, сначала она разделится на части вида "0,4" и "2,10".
Во вторых квадратных скобках мы указали длину строки. Для "0,4" она будет 3+1, и т.д. Зависит от максимального количества предметов. 32 думаю хватит за глаза, но пока что нам хватит и 10.
Самое интересное: разделяем строку
Где 5 - размер массива inventory
Теперь массив temp выглядит следующим образом
После этого нам нужно пройтись циклом по массиву и записать значения в массив items[playerid]
После этого весь инвентарь станет доступен в массиве items[]. На этом все.
Доброго времени суток. Это не готовое решение. Это объяснение принципа работы системы инвентаря, причем не общее, а конкретно моей реализации. На форумах в основном куча криво вырезанных систем с различных копий модов популярных серверов. Я пытался задействовать минимальное количество кода. Так же система не имеет зависимостей, различных самописных дефайнов и прочего. И так, приступим.
Что потребуется?
1) Знание и умение работать с текущей системой хранения вашего сервера (SQLite, MySQL, ini и т.д.). Так как в разных модах применяются разные системы хранения данных, в этом мануале я не буду опираться на какую-то конкретную. Однако вам нужно уметь работать с конкретной системой в вашем моде, чтобы сохранять и читать данные.
2) Плагин и инклуд sscanf. Я думаю, что у многих он есть, однако если это не так - скачайте и установите его
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Что такое система инвентаря? Это система, которая позволяет игроку хранить различные предметы, применимо к сампу это могут быть канистры, инструменты для ремонта автомобиля, аптечки, различные аксессуары, такие как очки, шляпы, кепки, часы и прочее. Так же с небольшой доработкой данную систему можно применить не к игроку, а к багажнику автомобиля, если будет фидбек, расскажу как это можно реализовать.
Как работает система инвентаря? Для начала, нам нужно хранить абсолютно все предметы, доступные на сервере в массиве. Это даст нам возможность хранить лишь ID предмета и его количество в базе данных и у игрока, а чтобы получить название предмета, его стоимость, ID модели и т.д. и т.п. нам просто нужно будет обратиться к нужному индексу массива с предметами.
Хранение в базе. Тут я видел достаточно много всяких реализаций. Конечно, можно просто создать ячейку в базе для каждого предмета у каждого игрока. Но что если предметов 100? 200? 1000? Плюс каждый раз нам нужно будет добавлять вручную все эти ячейки при добавлении нового предмета. Поэтому мы поступим проще, и будем хранить одной строкой. Затем, чтобы обработать эту строку, нам понадобится sscanf, все ссылки верху темы.
Перейдем к реализации.
Создание и работа с массивами, удаление и добавление предметов в инвентарь
Так как каждый предмет будет иметь свой ID, который так же будет и индексом массива, нам нужно придумать, как запомнить все ID (не путать с ID объекта) предметов. Проще всего это будет сделать если заменить цифры на буквы. Гораздо проще запомнить что, например, канистра это FUEL_CAN, а не 23, а аптечка это MEDIC_KIT, а не 0. Для реализации этого создадим энуменатор. Он полезен в создании ассоциативных массивов (т.к. в pawn нельзя так просто их создать, как например в js или php), а так же каждый элемент enum автоматически нумеруется от 0 до до бесконечности (до бесконечности это конечно громко сказано, всему есть свои пределы, особенно в pawn).
Создаем enum без названия
C++:
enum
{
FUEL_CAN,
WORK_HAT,
MEDIC_KIT,
CIGAR,
CAR_WHEEL,
}
FUEL_CAN станет равен 0, WORK_HAT станет 1, MEDIC_KIT - 2 и так далее.
Теперь нам нужно создать сам массив с предметами. Если Вы хотите хранить в одном массиве разные типы данных, для этого нам опять потребуется enum
C++:
enum ITEMS
{
itemobjectid,
itemname[16]
}
C++:
new inventory[][ITEMS] = {
{ 1650, "Канистра" },
{ 19160, "Кепка Dude" },
{ 11736, "Аптечка" },
{ 1485, "Сигара" },
{ 1081, "Запасное колесо" }
};
После этих манипуляций по факту мы получим следующую конструкцию:
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Основа готова. Теперь у нас есть список всех предметов, которые доступны на сервере. Теперь нам нужно реализовать хранение их в инвентаре игрока. Сделаем мы это максимально просто - просто создадим одинарный массив для каждого игрока. Массив этот будет состоять из стольких строк, сколько у нас в глобальном массиве с предметами, в нашем случае - 5.
Если у вас уже есть enum с информацией об игроке, вставьте это туда, однако тут, так как система максимально независимая, мы просто создадим отдельную переменную.
C++:
new items[MAX_PLAYERS][sizeof inventory];
Например, игрок купил канистру. Чтобы добавить канистру к инвентарю, нам не нужно знать индекс, именно для этого мы создавали enum, который автоматически будет задавать индекс, поэтому мы просто сделаем так:
C++:
items[playerid][FUEL_CAN]++;
C++:
items[playerid][FUEL_CAN] += 4;
По итогу мы получим то, что массив items у игрока изменится и его индекс, равный 0 (FUEL_CAN как помним так же равна 0) станет равным значению, которое мы присвоили. Как в случае с глобальным массивом предметов, индекс в массиве игрока так же является ID предмета. Для большей наглядности давайте добавим еще один предмет. Дадим игроку 10 аптечек. Опять же, мы помним только простые текстовые названия, нам не нужно запоминать индексы. Соответственно выполняем следующую операцию:
C++:
items[playerid][MEDIC_KIT] += 10;
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Как видим, индексы 0 и 2 (или же FUEL_CAN и MEDIC_KIT) стали равны нашим значениям. Остальные индексы были равны нулю по умолчанию при создании.
Чтобы получить количество определенного предмета, нам просто нужно обратится по конкретному индексу
Код:
items[playerid][MEDIC_KIT]
Немного про удаление. Так как мы можем случайно удалить больше предметов, чем есть у игрока, нам нужно проверить, не будет ли количество меньше нуля при нашем удалении. Простое условие:
C++:
if(items[playerid][FUEL_CAN] - count > 0)
{
// Выполняем удаление
}
else
{
// Ничего не делаем, т.к. уйдем в минус
// Однако можем просто приравнять к 0
items[playerid][FUEL_CAN] = 0;
}
C++:
if(items[playerid][FUEL_CAN] - count > 0)
{
// Выполняем удаление
}
else
{
// Ничего не делаем, т.к. уйдем в минус
// Однако можем посчитать сколько можем удалить
// Представим, что у игрока 2 канистры, а мы хотим удалить 3
new remainder = count - items[playerid][FUEL_CAN]; // Получим 3 - 2 = 1 (лишнее количество предметов)
new subtraction = count - remainder; // Получим 3 - 1 = 2 (Сколько предметов можем удалить)
items[playerid][FUEL_CAN] -= subtraction;
printf("Удалили %i канистр, в остатке осталась %i", subtraction, remainder);
}
После всех этих манипуляций, когда у нас есть глобальный массив с предметами, массив игрока с его предметами, нам нужно как-нибудь показывать ему эти предметы. Самый простой способ - показать диалог. Диалог у нас будет с заголовками, чтобы было более юзерфренди, если это можно так назвать.
И так, мы имеем массив игрока с его предметами. Но в этом массиве хранятся лишь цифры, однако нам этого более чем достаточно. Теперь нам нужно превратить этот массив в строку для вывода в диалоге. Перед тем как это сделать, я надеюсь вы знаете как работают диалоги. Так вот, дело в том, что мы будем показывать игроку только те предметы, которые у него есть. Соответственно будет разброс в индексах. Если у игрока есть FUEL_CAN и MEDIC_KIT, индексы будут 0 и 2 соответственно. В связи с этим, в OnDialogResponse мы не сможем использовать listitem как индекс.
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Как это обойти? Все просто, мы создадим еще один массив. Его отличие от массива items[playerid], что в него мы не будем записывать те предметы, которые у нас есть. И если в items[playerid] как мы уже говорили, к примеру 5 строк, то в новом массиве у нас так же будет 5 строк, однако записывать мы будем начиная с 0 строки, так как у нас есть 2 предмета - аптечка и канистра, то индекс для канистры будет 0, а индексом аптечки - 1, а уже значениями будут индексы аптечки и канистры из enum. Значениями в этом массиве будет не количество, а ID предмета (его индекс). Тем самым индексы и listitem будут совпадать. Создадим этот массив, он так же будет для всех игроков:
Код:
new currentitems[MAX_PLAYERS][sizeof inventory]
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
В диалоге у нас будет:
| Предмет | Количество |
| Канистра | 4 |
| Аптечка | 10 |
В массиве примерно то же самое, но без количества. Это не главное, главное что индексы массива и lisitem у нас будут совпадать. Теперь давайте перейдем к генерации строки для диалога и записи в массив currentitems текущих предметов. Данный массив мы будем заполнять только при вызове команды для открытия диалога, ибо он нам нужен только тут. Вы скажете, почему же сразу в нем не хранить предметы. Во время игры может довольно часто меняться, соответственно нам нужно будет обновлять и этот массив, еще и учитывать чтобы индексы совпадали в дальнейшем с listitem, вообщем это бесполезное занятие.
Как нам сгенерировать строку с имеющимися предметами. Тут я так же предполагаю что вы знаете функцию format и strins. Каким образом мы будем генерировать эту строку? Мы создадим цикл с количеством итераций равному размеру (или же количеству строк, одно и то же) массива inventory, то есть пройдемся по всем предметам, а внутри каждой итерации мы просто будем смотреть, если у игрока конкретный предмет, если есть - запишем его в строку. Так же запишем индексы для нашего массива currentitem.
Получим следующую конструкцию:
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Теперь реализация в виде кода, на забудьте поменять dialogid на свой
C++:
new itemsstr[256]; // Для общей строки, длину рассчитывайте исходя из количества предметов и длины их названия
new arrayindex = 0; // Для индекса массива currentitems[][]
new iterationcount = sizeof(inventory); // Чтобы при каждой итерации не просчитывать размер массива
for (new i = 0; i < iterationcount; i++)
{
if(items[playerid][i] != 0) // Если items[playerid][i] = n, где n не равно 0, т.е. есть какой то предмет под индексом i и количеством n
{
printf("У игрока есть предмет %s в количестве %d", inventory[i][itemname], items[playerid][i]);
format(itemsstr, sizeof itemsstr, "%s\n%s\t%d", itemsstr, inventory[i][itemname], items[playerid][i]);
strins(itemsstr, itemrow, strlen(itemsstr));
currentitems[playerid][arrayindex] = i; // Для примера, как это будет выглядеть - currentitems[playerid][0] = FUEL_CAN;
arrayindex++; // Прибавили arrayindex, в следующий раз это будет выглядеть так currentitems[playerid][1]
}
}
strins(itemsstr, "Предмет\tКоличество", 0); // Добавим в начало заголовок
ShowDialog(playerid, dialogid, DIALOG_STYLE_TABLIST_HEADERS, "Инвентарь", itemsstr, "Использовать", "Выход");
C++:
new itemid = currentitem[playerid][listitem]; // Этот массив мы заполнили, вызывая сам диалог
printf("Игрок выбрал предмет %s (listitem %d)", inventory[itemid][itemname], listitem);
printf("У игрока этот предмет в количестве %d", items[playerid][itemid]);
C++:
switch(itemid)
{
case FUEL_CAN:
{
// Действия с канистрой
SendClientMessage(playerid, -1, "Вы взяли канистру из инвентаря");
}
case WORK_HAT:
{
// Действия с кепкой
}
case MEDIC_KIT:
{
// Действия с аптечкой
}
}
Сохранение в базе данных
Тут действуем практически по тому же принципу, что и сверху. Единственное записываем немного в другом формате. У меня это будет {предмет},{количество};{предмет},{количество};{предмет},{количество};{предмет},{количество} То есть 0,4;2,10 - 4 канистры (индекс 0) и 10 аптечек (индекс 2)
C++:
new itemsstr[256];
new iterationcount = sizeof(inventory);
for (new i = 0; i < iterationcount; i++)
{
if(items[playerid][i] != 0)
{
printf("У игрока есть предмет %s в количестве %d", inventory[i][itemname], items[playerid][i]);
format(itemsstr, sizeof itemsstr, "%s%d,%d;", itemsstr, i, items[playerid][i]);
}
}
strdel(itemsstr, strlen(itemsstr), strlen(itemsstr)); // Удалим последнюю точку с запятой ";"
На выходе у нас будет строка itemsstr, которая готова для записи в базу данных
SQL:
UPDATE `players` SET `items` = '%s' WHERE `playername` = 'Test_Test'
Чтение из базы
Это самая сложная часть, так как в pawn нет стандартных функций, по типу explode в php, или хотя бы для работы с json. Для этого нам и понадобится инклуд sscanf, помимо проверки параметров команд, он может еще много чего. Одна из функций это разделение строки по символу.
Раскажу как это работает в php, на примере функции explode. Допустим у нас есть строка, и нам нужно разделить ее на части, разделителем будет символ ";". Разделителем может быть что угодно
PHP:
$string = "часть1;часть2;часть3"
Код:
$array = explode(";", $string);
PHP:
var_dump($array);
Result:
Array (3) => {0} => "часть 1", {1} => "часть 2", {2} => "часть 3"
И так, мы получили из базы данных строку с нашими предметами, пусть это будет
C++:
new playeritemsstring[128];
Для примера в SQLite, чтобы получить конкретное значение, необходимо выполнить следующую функцию:
C++:
db_get_field_assoc(db_result, "items", playeritemsstring, 128);
C++:
new temp[sizeof inventory][10];
Самое интересное: разделяем строку
C++:
sscanf(playeritemsstring,"p<;>a<s[10]>[5]", temp);
Теперь массив temp выглядит следующим образом
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
После этого нам нужно пройтись циклом по массиву и записать значения в массив items[playerid]
C++:
for (new i = 0; i < sizeof temp; i++) // Количество итераций будет равно количеству строк в массиве temp
{
new itemarr[2][10]; // "буферный" массив для переноса данных
sscanf(temp[i],"p<,>a<s[10]>[5]", itemarr);
/*
После этого получим:
itemarr[0] - ID предмета
itemarr[1] - количество предмета
*/
items[playerid][strval(itemarr[0])] = strval(itemarr[1]);
printf("Загружен инвентарь %s, в количестве %d", inventory[strval(itemarr[0])][itemname], strval(itemarr[1]));
}
