SOLVED Inventory system question

FIRST OF ALL: THIS IS JUST A QUERY. I'm not asking for a programming fix or anything here. So if you're here to fix someones bug, this isn't the post for you.

I don't expect this to be taken as a programming error that needs to be fixed or anything, just a bit of a question.
I'm working on a zombie survival game, and I just implemented a system for picking things up and keeping them in an inventory.
First of all, I followed this from these tutorials (
) and noticed a bug. The amount the player is carrying of a certain item isn't actually showing up, its just staying as 1. if anyone has an answer to this, it would be helpful, but that's not the main focus of this.

I wanted to know how I would go about making the player able to select specific items and drop / use them. The inventory has a bunch of static images with a number beside them that corresponds to how much of that item you're carrying and that's pretty cool, but how would I make the player able to seek out specific items and use or drop them in any way?

heres the code I've used.


shouldShowInventory = false

(global.inventory is set elsewhere, it is a ds_map, global.inventoryItems is set elsewhere, it is a ds_list.)

if shouldShowInventory {
draw_sprite(sinventory,0,0,0) //background UI sprite
var len = ds_list_size(global.inventoryItems);
for (var i = 0; i < len; i++) {
var key = ds_list_find_value(global.inventoryItems, i)
var value = ds_map_find_value(global.inventory, key)

var cam = camera_get_active()
var camX = camera_get_view_x(cam)
var camY = camera_get_view_y(cam)

var GRID = 32
draw_sprite_stretched(object_get_sprite(key), 0, camX + 32, (camY + i * GRID) + 64,48,48)
draw_text(camX + 32 + GRID * 2, camY + i * GRID + 64,": "+string(value))
show_debug_message("drew inventory")
}
}

thanks guys

GML:
//code in collision with pickup parent

var key_pickup = keyboard_check_pressed(ord("E"))

if key_pickup {
    if other.object_index != noone {
        var key = other.object_index;
        var value = 1;

        if ds_map_exists(global.inventory,key) {
            value += ds_map_find_value(global.inventory,key);
            
        }
        else {
            ds_map_add(global.inventory,key,value)
            ds_list_add(global.inventoryItems,key)
        }
        
        instance_destroy(other)
    }
}
 
Last edited:

rytan451

Member
As a quick note, I recommend putting your code in code tags, since it makes the code much easier to read. For example:

[code=gml]
show_debug_message("Code is running");
[/code]

Becomes:
GML:
show_debug_message("Code is running");
Looking at the Draw GUI event, you've positioned the inventory items in a grid. Since you are drawing sprites in the grid, you've already calculated the positions of the grid. You can get the mouse position in GUI space using device_mouse_x_to_gui and the corresponding Y position. Then, use point_in_rectangle to check if the mouse position (within the GUI) is within the rectangles of the item.

After that, it's a matter of checking mouse clicks and managing states (keeping track of which item is being held).
 
As a quick note, I recommend putting your code in code tags, since it makes the code much easier to read. For example:

[code=gml]
show_debug_message("Code is running");
[/code]

Becomes:
GML:
show_debug_message("Code is running");
Looking at the Draw GUI event, you've positioned the inventory items in a grid. Since you are drawing sprites in the grid, you've already calculated the positions of the grid. You can get the mouse position in GUI space using device_mouse_x_to_gui and the corresponding Y position. Then, use point_in_rectangle to check if the mouse position (within the GUI) is within the rectangles of the item.

After that, it's a matter of checking mouse clicks and managing states (keeping track of which item is being held).
thanks so much, there are a couple of things in there I didn't know exist (namely point in rectanble). The grid variable used there is a variable that spaces the text and icons apart so they line up corresponding to their order in a list, the items aren't actually drawn in a grid like the Minecraft inventory, but that would be B) cool
 

Nidoking

Member
GML:
//code in collision with pickup parent
var key = other.object_index;
var value = 1;

if ds_map_exists(global.inventory,key) {
value += ds_map_find_value(global.inventory,key);

}
else {
ds_map_add(global.inventory,key,value)
ds_list_add(global.inventoryItems,key)
}

instance_destroy(other)
}
}
Let's examine your code more closely and see if you can find the problem. First, you set the variable value to 1. Then, you do ONE of the following:
  1. If the key exists in the map, you update the value variable and then throw the result away.
  2. If the key doesn't exist in the map, you add the key with the value of value (which is always 1) to the map.
In other words, there is no possible condition where you set a value to anything that is not 1. Having incremented the value of the value variable, you need to put that value into the map, presumably associated with the key key.
 
Let's examine your code more closely and see if you can find the problem. First, you set the variable value to 1. Then, you do ONE of the following:
  1. If the key exists in the map, you update the value variable and then throw the result away.
  2. If the key doesn't exist in the map, you add the key with the value of value (which is always 1) to the map.
In other words, there is no possible condition where you set a value to anything that is not 1. Having incremented the value of the value variable, you need to put that value into the map, presumably associated with the key key.
the value += ds_map_find_value should change the value variable though, did I do that wrong??
 
the value += ds_map_find_value should change the value variable though, did I do that wrong??
So you update "value"? "value" has no bearing on what is stored inside the ds_map, it's just a temp variable. As your code is structured now, you only change the number stored in the ds_map if the key did not exist (ds_map_add(global.inventory,key,value)). There's no equivalent code for when the key does exist. All you do in that case is alter the temp variable "value" and never touch what is actually stored in the ds_map.
 
So you update "value"? "value" has no bearing on what is stored inside the ds_map, it's just a temp variable. As your code is structured now, you only change the number stored in the ds_map if the key did not exist (ds_map_add(global.inventory,key,value)). There's no equivalent code for when the key does exist. All you do in that case is alter the temp variable "value" and never touch what is actually stored in the ds_map.
what should I write to make it work?
 
Just so you know, the reason we haven't provided code already is that giving you code to copy+paste shortcircuits the learning process and means that you learn less about what is going on than if you were to solve it yourself with our guidance, but anyway:

Personally, I would change it to this:
Code:
if key_pickup {
    if other.object_index != noone {
        var key = other.object_index;
        var value = 1;

       if ds_map_exists(global.inventory,key) {
            value += ds_map_find_value(global.inventory,key); // Here we add the already existing number stored in the global.inventory[? key] to value
        }
        else {
            ds_list_add(global.inventoryItems,key)
        }
        ds_map_set(global.inventory,key,value); // Here we set the key in global.inventory to hold the updated value number
        instance_destroy(other)
    }
}
What is happening above? Well, to begin with value is holding the number 1. If the key already exists, we know we are already holding a certain number of the item, so we add that number to value. If the key doesn't exist, we add it to the global.inventoryItems list. Now we're at the point where value either holds 1 or 1+X. We then use ds_map_set to update the value held in key in the global.inventory ds_map. Why ds_map_set? Because that doesn't care if the key exists or not, it will either update or create the key.
 
Just so you know, the reason we haven't provided code already is that giving you code to copy+paste shortcircuits the learning process and means that you learn less about what is going on than if you were to solve it yourself with our guidance, but anyway:

Personally, I would change it to this:
Code:
if key_pickup {
    if other.object_index != noone {
        var key = other.object_index;
        var value = 1;

       if ds_map_exists(global.inventory,key) {
            value += ds_map_find_value(global.inventory,key); // Here we add the already existing number stored in the global.inventory[? key] to value
        }
        else {
            ds_list_add(global.inventoryItems,key)
        }
        ds_map_set(global.inventory,key,value); // Here we set the key in global.inventory to hold the updated value number
        instance_destroy(other)
    }
}
What is happening above? Well, to begin with value is holding the number 1. If the key already exists, we know we are already holding a certain number of the item, so we add that number to value. If the key doesn't exist, we add it to the global.inventoryItems list. Now we're at the point where value either holds 1 or 1+X. We then use ds_map_set to update the value held in key in the global.inventory ds_map. Why ds_map_set? Because that doesn't care if the key exists or not, it will either update or create the key.
thanks for the help :)
 
Top