GMS 2.3+ data structure keys keep changing between games (having more problems)

Hi there

so i fixed my inventory system so that is now features usable items, and it works... sometimes.

I noticed the keys of objects is changing every now and then, which is making the items unusable. Of course, i don't want my items to be unusable.

the previous key of the first aid kit was 49, but now its 50. whyyyyyyyyy

heres my code:

GML:
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_list_add(global.inventoryItems,key)
        }
        ds_map_set(global.inventory,key,value);
        instance_destroy(other)
    }
}

GML:
function inventory_use_items(){
    item = argument0
    if item = 52 {
        nutrition += 50
        audio_play_sound(soeat,0,0)
        audio_play_sound(souse,0,0)
    }  
    if item = 73 {
        water += 45
        audio_play_sound(sodrink,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 90 {
        water += 30
        audio_play_sound(sodrink,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 146 {
        water += 15
        audio_play_sound(sodrink,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 35 {
        nutrition += 25
        audio_play_sound(soeat,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 84 {
        nutrition += 10
        audio_play_sound(soeat,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 44 {
        global.hp += 15
        audio_play_sound(sopainkiller,0,0)
        audio_play_sound(souse,0,0)
    }
    if item = 49 {
        global.hp += 60
        audio_play_sound(somedkit,0,0)
        audio_play_sound(souse,0,0)
    }

GML:
if shouldShowInventory {
    draw_sprite(sinventory,0,0,0)
    var len = ds_list_size(global.inventoryItems);
    for (var i = 0; i < len; i++) {
        draw_set_colour(c_white)
        clickleft = mouse_check_button_pressed(mb_left);
        clickright = mouse_check_button_pressed(mb_right);
       
        var key = ds_list_find_value(global.inventoryItems, i)
        var value = ds_map_find_value(global.inventory, key)
       
        if value = undefined {
            value = 0
        }
       
        xMouse = device_mouse_x_to_gui(0)
        yMouse = device_mouse_y_to_gui(0)
       
        mouseinbox = false
       
        var GRID = 32
       
        draw_sprite_stretched(object_get_sprite(key), 0, 0 + 32, (0 + i * GRID) + 64,48,48)
        draw_text(0 + 32 + GRID * 2, 0 + i * GRID + 64,": "+string(value))
       
        if point_in_rectangle(xMouse,yMouse,0,(0 + i * GRID) + 72,0*GRID+32,(0 + i * GRID) + 102) {
            draw_set_colour(c_green)
            fireav = false
            mouseinbox = true
           
            if clickleft = true and value > 0 {
                inventory_use_items(key)
                ds_map_set(global.inventory,key,value - 1)
                show_debug_message("CLICKED. KEY IS: "+string(key))
            }
        }
        draw_rectangle(0,(0 + i * GRID) + 72,0*GRID+32,(0 + i * GRID) + 102,true)
    }
}


this was solved, but i've started getting errors. The key in the draw gui event isn't able to draw the sprite because the key has changed. Heres the error im getting:


___________________________________________
############################################################################################
ERROR in
action number 1
of Draw Event
for object player:

object_get_sprite argument 1 incorrect type (string) expecting a Number (YYGI32)
at gml_Object_player_Draw_64 (line 46) - draw_sprite_stretched(object_get_sprite(key), 0, 0 + 32, (0 + i * GRID) + 64,48,48)
############################################################################################
gml_Object_player_Draw_64 (line 46)

thanks for helping people who answered before by the way!! :)
 
Last edited:
Instead of using other.object_index as the key, you should instead use object_get_name(other.object_index);. That's guaranteed to be the same each time GMS runs. If you need to get the object_index back from that key (the key will end up being a string of something like "obj_whatever", which isn't able to be used when actually referring to the object), you can then use asset_get_index(key) which will return the actual object_index in reference to the string the key holds.
 

TheouAegis

Member
Out of curiosity....

Are you adding objects or other assets between runs?
Are you modifying any objects or assets between runs?
Does it happen on an actual compiled executable (not the test runner)?

Either way, due to GMS2.3's lame asset-handling code, you can't really rely on any asset indexing at all now. There may be a few exceptions, but in general, don't risk it. And regardless of which version of GM you're using, you need to be aware that relying on asset indexing in any version of GM requires you to never modify the current assets, nor the ordering of said assets, ever again. EVER. You could save object_index 0 in an early build, then in a later build if you moved object 0 down the asset list, your code from that early build is automatically broken. With Refresher's suggestion, you wouldn't be allowed to change the names of the assets, but you could make any other changes you want.
 
Out of curiosity....

Are you adding objects or other assets between runs?
Are you modifying any objects or assets between runs?
Does it happen on an actual compiled executable (not the test runner)?

Either way, due to GMS2.3's lame asset-handling code, you can't really rely on any asset indexing at all now. There may be a few exceptions, but in general, don't risk it. And regardless of which version of GM you're using, you need to be aware that relying on asset indexing in any version of GM requires you to never modify the current assets, nor the ordering of said assets, ever again. EVER. You could save object_index 0 in an early build, then in a later build if you moved object 0 down the asset list, your code from that early build is automatically broken. With Refresher's suggestion, you wouldn't be allowed to change the names of the assets, but you could make any other changes you want.
[/QUOTE]
some objects and assets are being added, yes. I added a new shotgun type when the bug showed up this specific time. when the program runs, everything works, except the items don't use.
 
Out of curiosity....

Are you adding objects or other assets between runs?
Are you modifying any objects or assets between runs?
Does it happen on an actual compiled executable (not the test runner)?

Either way, due to GMS2.3's lame asset-handling code, you can't really rely on any asset indexing at all now. There may be a few exceptions, but in general, don't risk it. And regardless of which version of GM you're using, you need to be aware that relying on asset indexing in any version of GM requires you to never modify the current assets, nor the ordering of said assets, ever again. EVER. You could save object_index 0 in an early build, then in a later build if you moved object 0 down the asset list, your code from that early build is automatically broken. With Refresher's suggestion, you wouldn't be allowed to change the names of the assets, but you could make any other changes you want.
Sometimes I add new objects and assets, and that is normally when the bug shows up. the last two times I used the debug_message to get the keys and rewrite the numbers in the inventory_use_items script.
 

TheouAegis

Member
Well there's your problem. Apparently. You added an object. You've modified the asset list. And GMS 2.3, any and every change to the asset list as a strong probability of changing indexes.
 
What is 52? Where do you define 52 to be the value of whatever item this is supposed to be? If it's an object index, then use the name of that object (as defined in the Resource tree) to refer to it. These "magic numbers" are pretty much always bad.
yeah... 52 is just the number that showed up for one of the items, so I added it to the code.
 
Instead of using other.object_index as the key, you should instead use object_get_name(other.object_index);. That's guaranteed to be the same each time GMS runs. If you need to get the object_index back from that key (the key will end up being a string of something like "obj_whatever", which isn't able to be used when actually referring to the object), you can then use asset_get_index(key) which will return the actual object_index in reference to the string the key holds.
aha! got it working now, thank you so much
 

Nidoking

Member
Don't use object_get_name. There's no reason to do that. Just use the object index. Not the number that the object index corresponds to. The index variable that you type into the Name field when you create the object.
 

gnysek

Member
Not the number that the object index corresponds to. The index variable that you type into the Name field when you create the object.
If you're saying, that instead of using (for example) 15 you should use object15, then it's not better idea, as this constant is being replaced on compile time to 15... Of course it changes when there's any movement in resource tree. Using name is better, you can also use tags, which will allow you to rename objects without problems (tags are added in 2.3+).
 

Nidoking

Member
If you're saying, that instead of using (for example) 15 you should use object15, then it's not better idea, as this constant is being replaced on compile time to 15...
If that's your belief, then why are you using Game Maker at all? All of those instructions are being replaced at compile time with ones and zeroes. You should be writing in binary.

Of course it changes when there's any movement in resource tree.
This is why you use the name instead of the number. The name only changes if you change the name. If that name is object15, then sure, the number isn't likely to be 15. But why do you have an object named object15? Do the objects in your game have so little meaning to you that you only identify them by number? What is an object15? Is it, perhaps, a sword? Then call it obj_sword. obj_sword is pretty clearly a sword, and what number it is is irrelevant, because the number is obj_sword.

you can also use tags, which will allow you to rename objects without problems (tags are added in 2.3+).
I've found tags to be infinitely more painful than just doing a search and replace on the very rare occasion that I feel the need to rename an object. The interface for creating them is annoying, and you have to use functions to read them or find objects that use them. If I name my object obj_sword, then I can find instances of it using obj_sword, or access instances of it using obj_sword.
 

gnysek

Member
This is why you use the name instead of the number. The name only changes if you change the name
Ok, I was already also thinking about saving it into file. Then, using a object name variable would change if you reorder objects, that's what I meant. Of course if it's not saved into file, then that solution is good.
 

TheouAegis

Member
Oh yeah, OP wasn't talking about saving. You'd need object_get_name() if saving. I dunno where I got the idea that he was saving. But in general use, yeah, quit using numbers. lol
 
Top