Simple Inventory using DS_Lists

Locke

Member
Hey Community,

I have a simple inventory using ds_lists. I've implemented picking items up, dropping items and displaying items in an inventory. The only thing left to do is be able to stack the items but I can't quite figure it out. Was hoping someone could help.

I have a sprite that has 7 images of different items you can pick up. Then I have a player object with the following code:

create event:
//List
global.inventory = ds_list_create();
selected_item = 0;
type = -1;
show_inventory = true;

enum e_items
{
pea,
beatroot,
cabbage,
onion,
carrot,
potato,
bean,
tomato
}

Step event:
var item = instance_place(x, y, obj_crops);
var count = 1;

if (item != noone and item.can_be_picked_up == true)
{
show_debug_message("item picked up");

ds_list_add(global.inventory, item.image_index, count);

with (item)
{
instance_destroy();
}
}

Draw GUI Event:
if (show_inventory == false)
{
var margin = 10;
var list_size = ds_list_size(global.inventory);

for (var entry = 0; entry < list_size; entry++)
{
var arr = global.inventory[| entry];
var item = arr[0];
var count = arr[1];

var x_offset = sprite_get_xoffset(spr_crops);
var y_offset = sprite_get_yoffset(spr_crops);

var spr_width = sprite_get_width(spr_crops) + margin;

var draw_x = margin + (x_offset + (entry * spr_width));
var draw_y = (margin * 2) + y_offset;

//Draw the item sprite with the correct image
if (item != undefined)
{
draw_sprite(spr_crops, item, draw_x, draw_y);
draw_text(draw_x+4, draw_y+4, count);
}

//Show which item is selected
if (selected_item == entry)
{
draw_sprite(spr_inventory, 0, draw_x, draw_y);
}

}
}

When I run the game and try to pick up an item it says ... error in draw event of obj_player... trying to index a variable that is not an array... at line (11) var item = arr[0];

Would love if someone could show me what I'm missing. Thanks!
 
You are not adding an array to the list, you're simply adding two items. To add an array you have enclose the two values in square brackets ds_list_add(global.inventory, [item.image_index, count]);
 

Locke

Member
Thank you!! I knew I was missing something I overlooked! ... The only issue now is that when I pick up items they still aren’t stacking. They show the count as I display it for each item but when I pick up the same item they still show up beside each other
 

Nidoking

Member
If you want to find an existing entry for the item and increment the number in the array, you have to write code to do that. As it is, you're just creating a new list entry every time.
 

Locke

Member
Yeah, as I look at the code that’s what I’m realizing too. I can understand how to loop through the inventory.... but we’re I stumble is figuring out how to see if an item already exists in the inventory

var list_size = ds_list_size(global.inventory);

for (var entry = 0; entry < list_size; entry++)
{
var arr = global.inventory[| entry];

if (item does not exists)
{
ds_list_add(global.inventory, item.image_index, count);
}
else
{
Increment item if it does exist
}
}

would someone be able to help me fill in the blanks?
 

TailBit

Member
sure .. here you go
GML:
var list_size = ds_list_size(global.inventory);

// find if existing item exists in inventory, if so, stack it
for (var entry = 0; entry < list_size; entry++)
{
    var arr = global.inventory[| entry];

    if (arr[0] == item.image_index && arr[1]<32)
    {
        arr[1]+=item.amount; // does the item have an amount variable
       
        if arr[1]>32{
            item.amount = arr[1]-32; // put the remaining amount back
            arr[1] = 32; // limit the amount to the max stack
        }else{      
            item.amount = 0;
            instance_destroy(item);
            break; // and end the loop
        }
    }
}

// if there are items left from first search, then there was no or not enough stacks
// then make a slot .. since your inventory doesn't have a max size?
if (item.amount > 0){
ds_list_add(global.inventory, [item.image_index,item.amount] )
32 is the max stack .. you will most likely have a variable for this if they should have different stack size
}
 
Last edited:

Locke

Member
Thanks @TailBit !!
I understand what you’ve written except for item.amount

How would I declare this initially as part of the item variable ?
 

Locke

Member
Nm! - I declared the amount within my item object and it seems to be working!

Only weird thing is now when I pick up an item it’s showing two of that item when it’s displayed in my inventory. Am I doing something wrong in my Draw GUI event?

Draw GUI Event:
if (show_inventory == false)
{
var margin = 10;
var list_size = ds_list_size(global.inventory);

for (var entry = 0; entry < list_size; entry++)
{
var arr = global.inventory[| entry];
var item = arr[0];
var count = arr[1];

var x_offset = sprite_get_xoffset(spr_crops);
var y_offset = sprite_get_yoffset(spr_crops);

var spr_width = sprite_get_width(spr_crops) + margin;

var draw_x = margin + (x_offset + (entry * spr_width));
var draw_y = (margin * 2) + y_offset;

//Draw the item sprite with the correct image
if (item != undefined)
{
draw_sprite(spr_crops, item, draw_x, draw_y);
draw_text(draw_x+4, draw_y+4, count);
}

//Show which item is selected
if (selected_item == entry)
{
draw_sprite(spr_inventory, 0, draw_x, draw_y);
}

}
}
 

TailBit

Member
Ah, sorry, break just ends the loop, the code continues after that and adds the it to an empty slot aswell, so I had the first part set the amount to 0 if it managed to empty all of them, so if there is any amount left then it makes a new slot ..
note that at the end you could make another loop if you for example pick up a huge stack of over 100 so it have to make several new slots and split the amount over them .. but will you need that?

Anyway, my previous code have been updated
 

Locke

Member
Thanks @TailBit !! That solves the duplicating of the item when being picked up. But now when I pick up an item and then pick up the same item again the count is not increasing when I display it in the GUI

Which is weird because I have the same loop that looks through the inventory and I establish The item and amount as arr[0] and arr[1] respectively. Then when I draw my items and text I call amount in my draw text but it’s not updating ... any thoughts?
 

TailBit

Member
var arr = global.inventory[| entry];
Hm, if I'm not misstaken, this doesn't make a reference to the array in global inventory, only copies it?

So after changing arr[1] you will have to write the updated array back into the inventory.

Or change the array in the inventory directly:
global.inventory[| entry][0]+=item.amount
 
Top