PDA

Просмотр полной версии : [Вопрос] Как сделать систему стаков для инвентаря?



gw.h
22.10.2019, 17:25
Вообщем просто сломался мозг.

Смотри
Есть 20 ячеек слотов для предметов pInfo[playerid][pItem][20]
Также 20 ячеек в которых хронится кол-во предмета из pInfo[playerid][pItem][20] - pInfo[playerid][pItemChar][20]
Тоесть 1 ячейка pInfo[playerid][pItem][1] записывает кол-во в pInfo[playerid][pItemChar][1]
Так вот, есть переменная которая хранит информацию о предмете
Тут хранится число в которое должен стакатся предмет ItemsInfo[Ид предмета][Stack]
Вопрос такой

Как сделать что бы если мы дабовляем больше чем стакается предмет он раскидывался по ячейкам по стакам
Вот код добавление предмета

stock AddItem(playerid, itemid, amount)
{
if(pInfo[playerid][pItem][0] != itemid && pInfo[playerid][pItem][1] != 0 && pInfo[playerid][pItem][2] != 0 && pInfo[playerid][pItem][3] != 0 && pInfo[playerid][pItem][4] != 0 && pInfo[playerid][pItem][5] != 0 && pInfo[playerid][pItem][6] != 0 && pInfo[playerid][pItem][7] != 0 && pInfo[playerid][pItem][8] != 0 && pInfo[playerid][pItem][9] != 0 && pInfo[playerid][pItem][10] != 0 && pInfo[playerid][pItem][11] != 0
&& pInfo[playerid][pItem][12] != itemid && pInfo[playerid][pItem][13] != 0 && pInfo[playerid][pItem][14] != 0 && pInfo[playerid][pItem][15] != 0 && pInfo[playerid][pItem][16] != 0 && pInfo[playerid][pItem][17] != 0 && pInfo[playerid][pItem][18] != 0 && pInfo[playerid][pItem][19] != 0) return SendClientMessage(playerid, 0xBE5555FF, "[Ошибка] {FFFFFF}У вас не хватает места в инвентаре!");
for(new i = 0; i < 20; i++)
{
if(pInfo[playerid][pItem][i] != itemid) continue;
if(pInfo[playerid][pItemChar][i] > ItemsInfo[itemid][Stack]) continue;
pInfo[playerid][pItemChar][i] += amount;
return 1;
}
for(new i = 0; i < 20; i++)
{
if(amount < 1) continue;
if(pInfo[playerid][pItem][i] != 0) continue;
if(amount > ItemsInfo[itemid][Stack])
{
pInfo[playerid][pItem][i] = itemid;
pInfo[playerid][pItemChar][i] = ItemsInfo[itemid][Stack];
amount -= ItemsInfo[itemid][Stack];
AddItem(playerid, itemid, amount);
continue;
}
pInfo[playerid][pItem][i] = itemid;
pInfo[playerid][pItemChar][i] = amount;
return 1;
}
return 1;
}

Пример:
Придмет под идом 5 стакается по 3 шт
Тоесть мы к примеру добавляем AddItem(playerid, 5, 6)
и он записывает в 2 ячейки по 3 шт

DeimoS
22.10.2019, 17:57
1) При добавлении предметов запускаешь цикл на перебор всех слотов.
2) Если находишь предмет с тем же ID, проверяешь, заполнен ли слот по максимуму.
2.1) Если в слоте есть место - добавляешь в него предметы. При этом, если добавляешь, например, 4 предмета, а места в слоте доступно всего для 2-х - добавляешь только два предмета и продолжаешь проверку других слотов.
2.2) Если в слоте мест нет - пропускаешь его.
3) В конце цикла смотришь, остались ли предметы на добавление. Если остались, начинаешь искать первый свободный слот и добавляешь остаток предметов в него.

gw.h
22.10.2019, 18:03
каким образом 3 пункт реализовать?
вызвав цикл снова?

DeimoS
22.10.2019, 18:19
Ну да.

gw.h
22.10.2019, 18:28
типо вызвать AddItem(playerid, itemid, amount) только уже с остатками
получится цикл пока не закончится amount или слоты

DeimoS
22.10.2019, 18:40
Ну я же всё описал. В первом цикле ты проверяешь наличие свободных мест в уже заполненных предметами слотах. А второй цикл запускаешь если после работы первого цикла остались не добавленные предметы.

gw.h
22.10.2019, 18:41
Чувак можешь написать эту систему? а то у меня уже сил просто нет это сделать, у меня мозг стопорится на 2 пункте

DeimoS
22.10.2019, 19:55
stock AddItem(playerid, itemid, amount)
{
new temp;
for(...)
{
if(id_предмета_в_слоте != itemid)
continue;
if(количество_предмета_в_слоте >= максимальное_количество_предмета_в_одном_слоте)
continue;

temp = максимальное_количество_предмета_в_одном_слоте-количество_предмета_в_слоте;
if(temp > amount)
{
количество_предмета_в_слоте = максимальное_количество_предмета_в_одном_слоте;
amount -= temp;
if(amount <= 0)
return 1;
}
else
{
количество_предмета_в_слоте += amount;
return 1;
}
}
for(...)
{
if(id_предмета_в_слоте != свободный_слот)
continue;
id_предмета_в_слоте = itemid;
количество_предмета_в_слоте = amount;
break;
}
return 1;
}

Приблизительно, так. Дальше уж сам. Или в стол заказов пиши.

UPD: Ну ниже скинули, собственно, доведённый до ума алгоритм, который я описал в этом сообщении.

Daniel_Cortez
22.10.2019, 20:38
Поделюсь своим понтокодом:

enum EItem // enum с кодами всех видов предметов
{
ITEM_NONE, // Для обозначения пустого места в слоте
ITEM_DEAGLE,

// Объявим константу __MAX_ITEM так, чтобы она была равна
// ID последнего объявленного ID предмета (т.е. ITEM_DEAGLE).
// Это пригодится для проверки правильности кодов предметов.
__DUMMY_ENUM_ITEM,
__MAX_ITEM = __DUMMY_ENUM_ITEM - 2
};

#define MAX_ITEM_SLOTS 15 // Допустим, игрок может таскать до 15 разных предметов.
#define MAX_ITEM_AMOUNT 10 // До 10 предметов на слот (при желании можно сделать массив
// и в нём отдельно установить максимум для каждого предмета).

enum EPlayerInfo
{
pAccID,
pLevel,
pMoney,
// ...
EItem:pItems[MAX_ITEM_SLOTS], // Слоты для предметов
pNumItems[MAX_ITEM_SLOTS] // Кол-во предмета в каждом слоте
};
new player_info[MAX_PLAYERS][EPlayerInfo];

Inventory_AddItem(playerid, EItem:item, amount)
{
// Для отлова ошибок с помощью crashdetect
assert(item > ITEM_NONE);
assert(item <= __MAX_ITEM);
assert(amount > 0);

// 1-й цикл: проверяем, есть ли такой предмет в инвентаре
for (new i = 0; i < MAX_ITEM_SLOTS; ++i)
{
// Если уже есть - переходим к накоплению в одном слоте
if (player_info[playerid][pItems][i] == item)
{
// Если добавляемое количество не выходит за лимит слота
// просто сохраним всё в в этом слоте и выйдем из функции.
// "return 0" означает, что мы сохранили всё без остатка.
if (player_info[playerid][pNumItems][i] + amount <= MAX_ITEM_SLOTS)
{
player_info[playerid][pNumItems][i] += amount;
return 0;
}
// Если же количество слишком большое для одного слота,
// добавляем в слот лишь столько, сколько вместится,
// оставшееся потом попытаемся добавить в другой слот.
amount -= (MAX_ITEM_SLOTS - player_info[playerid][pNumItems][i]);
player_info[playerid][pNumItems][i] = MAX_ITEM_SLOTS;
}
}

// 2-й цикл: пробуем добавить в пустые слоты.
for (new i = 0; i < MAX_ITEM_SLOTS; ++i)
{
if (player_info[playerid][pItems][i] == ITEM_NONE)
{
player_info[playerid][pItems][i] = item;
if (amount <= MAX_ITEM_SLOTS)
{
player_info[playerid][pNumItems][i] = amount;
return 0;
}
amount -= MAX_ITEM_SLOTS;
player_info[playerid][pNumItems][i] = MAX_ITEM_SLOTS;
}
}

// Если не нашлось достаточно слотов, чтобы сохранить предмет,
// вернём оставшееся количество, для которого не нашлось места.
// Так если мы попытаемся сохранить предмет в большем количестве,
// чем может вместить инвентарь, то сможем узнать, сколько не вместилось.
return amount;
}

Предупреждаю сразу, работоспособность не проверял.