• Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!

GMS 2 SOLVED Problems changing variables in creation code using ds maps

rawket

Member
So I've got an object which runs the create event when I hit "E" near it, and then on a one step alarm, runs a dialogue object using variables in the creation code. I'm now trying to use ds maps to change it's state actively in the creation code and thus use different dialogue options.

Instances creation code--------------------------------------------------------------------------------------------

Code:
key = scr_save_data_get_key();
var _save_data = ds_map_find_value(save_game_data, key);
if (is_undefined(_save_data))
    ds_map_replace(save_game_data, key, "first");
state = ds_map_find_value(save_game_data, key);

if state == "first"
{
    lines = 3;
    scr_resetDialogue();
    i = 0;
    line[i] = "There's a couple books on these shelves.";
    scrpt[i] = [scr_addCoins, 5];
    i++
    line[i] = "One of them has some coins in it!";
    scrpt[i] = [ds_map_replace_intext, save_game_data, key, "looted"];
    i++
    line[i] = "You got 5 coins!";
    scrpt[i] = [scr_change_variable, "state", "looted"];
}
else if state == "looted"
{
    lines = 3;
    scr_resetDialogue();
    i = 0;
    line[i] = "There's a couple books on these shelves.";
    i++
    line[i] = "They appear to be written about the islands history and culture.";
    i++
    line[i] = "Read one?";
}
Objects step event--------------------------------------------------------------------------------------------

Code:
if (!instance_exists(obj_text))
{
    current_line = 0;
}

if (keyboard_check_pressed(ord("E"))) && (distance_to_object(obj_player) <= 4) && (((bbox_left <= obj_player.x) && (obj_player.x <= bbox_right) && (((obj_player.y <= y) && (obj_player.idleDir = 4)) || ((obj_player.y >= y) && (obj_player.idleDir = 2)))) || ((bbox_top <= obj_player.y) && (obj_player.y <= bbox_bottom) && (((obj_player.x <= x) && (obj_player.idleDir = 1)) || ((obj_player.x >= x) && (obj_player.idleDir = 3)))))
{
    event_user(0);
    alarm[0] = 1;
}

if (instance_exists(obj_text)) with obj_player
{
    hsp = 0;
    vsp = 0;
    state = states.handsOff;
}
Objects User Event 0--------------------------------------------------------------------------------------------

Code:
event_perform(ev_create, 0);
So that's the whole thing. If you need any of the custom scripts posted as well I can do that. The issue is that this setup works for pretty much every other thing. I'm trying to get it to change its state after running through the first three lines once so that the next time I interact with it, it runs through the next set of lines. The thing is, it should be working as far as I can tell because, it's successfully changing the variable I need it to change it just doesn't seem to notice UNLESS I leave the room and re-enter, then it goes to the next set of lines. But if I don't leave the room it keeps going through the first set, repeating itself, and allowing me to farm gold unfairly.
 

Nidoking

Member
I've never messed with re-running the Create event. What I do is put the initialization (in this case, everything you've got in the Create event) in User Event 0, then call User Event 0 from the Create event. That way, the initialization is in an event that's meant to be called multiple times. It should function the same way, but it might eliminate the issue here. If it doesn't, there may be a problem elsewhere in the scripting.
 

rawket

Member
I'll try it, but wouldn't that make it so that I have to make a bunch of these types of objects? I put the dialogue stuff in the creation cod for the instance so that I can have one interaction object but plenty of instances with different dialogue
 

Nidoking

Member
Oh, then that explains it! The event_perform is only running the Create event for the OBJECT, not the instance. That's why it doesn't trigger until you leave the room and create the instance again. I can't think of any easier way to do what you want to do than to give every object some kind of list of scripts (the cases in your switch statement) and have something at the object level that knows how to read them, or to create a bunch of objects for every unique interaction. You'd be able to package most of the functionality in a parent object, at least.
 

rawket

Member
The thing is, it IS triggering. I've set it up so that I can watch the state change in real time, and it does change when it's supposed to. The problem is when it triggers the crate event, it reads through the lines again but it thinks the state is still "first" when I can see it being labeled as "looted." It's returning true for state being equal to "first" when I can see, right in front of me, it literally isn't true.
 

Nidoking

Member
It is NOT triggering, I promise you. The state variable is changed in whatever scripting you're doing, but the creation code is not running again to check that variable. Put a breakpoint in the instance creation code and run the debugger if you don't believe me. The breakpoint triggers one time when the room starts, and never again.
 

rawket

Member
It is NOT triggering, I promise you. The state variable is changed in whatever scripting you're doing, but the creation code is not running again to check that variable. Put a breakpoint in the instance creation code and run the debugger if you don't believe me. The breakpoint triggers one time when the room starts, and never again.
Yea sorry I just looked up something about creation code after typing that. It's not like an event, so even though I can see the state changing the creation code is't actually running. Will copying the instance and destroying the current one fix this?
 

Nidoking

Member
Will copying the instance and destroying the current one fix this?
No, because the new instance will not have the same creation code. However, I did think of something you might possibly be able to do. Assuming that all of your instances use similar state variables, you might be able to use a Map to connect values of the state variable to arrays or lists of script triggers, then check the state variable when the event triggers to get the correct list of scripts from the map and execute them. That way, you could put most of the code in the object, where it can be executed using event_perform, and all you'd need to do in the instance creation code is populate the map.
 

rawket

Member
This seems kinda tricky but I have a vague idea how to get it done, so I'll do my best! Sounds like it should work anyway as long as I actually do it right so, for now, thank you!
 

rawket

Member
No, because the new instance will not have the same creation code. However, I did think of something you might possibly be able to do. Assuming that all of your instances use similar state variables, you might be able to use a Map to connect values of the state variable to arrays or lists of script triggers, then check the state variable when the event triggers to get the correct list of scripts from the map and execute them. That way, you could put most of the code in the object, where it can be executed using event_perform, and all you'd need to do in the instance creation code is populate the map.
WOO it does work! It's gonna take a LOT of effort to redo all my text interactions to fit this new structure, but it works so thank you very much!

EDIT: Scratch that. It's actually super easy to incorporate if I'm smart about it
 
Last edited:
Top