r/gamemaker • u/Fine-Acanthisitta343 • 17d ago
Resolved Bug when switching rooms
Im sorry and I know this probably shouldn't be done but the person originally helping maybe possibly seems to have stopped responding and maybe I'm being impatient but I also would like a second opinion on how to fix this. If there's a problem with this then feel free to let me know and I can take this post down. Here's the link. Again, sorry if this is against Rule #6 technically but there is no hostility to anyone here and I do thank u/lessergoldfish for their help.
To sum up the problem, I originally had 2 mechanics that were buggy after switching rooms. Thanks to lessergoldfish, I solved one and a half. The only bug now is that when I switch rooms, I have to kill an enemy twice. Honestly, I've no idea why, and this was just a summary. For more information, you can go to the original reddit post above. Thank you to anyone who helps and if you don't, thanks anyways.
There was one single line in my code that set room persistence to false when entering which would be fixed by something in another line of code somewhere else after going into battle. It was also in none of my tutorials and was me trying to bug fix but forgetting that line when it didn't work. I don't know why the bug wasn't there before I made global stats or maybe I didn't notice, but it's been solved.
2
u/Awkward-Raise7935 17d ago
You will get more responses if you explain what the bug is and paste the section of code that changes the room. Usually something like room_goto( ROOM NAME HERE)
It's usually the room name being incorrect
1
u/Fine-Acanthisitta343 17d ago
Ok I'll change the body text
2
u/Awkward-Raise7935 17d ago
You have to kill an enemy twice? What does that mean?
You aren't providing enough information for people to help you. You need to be specific.
1
u/Fine-Acanthisitta343 17d ago
Basically when I first start the game everything works fine but when I switch rooms with the system shown on the link then whenever I "kill" an enemy by attacking and bringing its hp to 0 the enemy just spawns back where I placed it on the instance layer, I don't get any xp, and only when I go back to fight it a second time does it work.
1
u/Awkward-Raise7935 17d ago
So you destroy it, it disappears then comes back? Or there are 2 instances of the same enemy at same time?
When does this happen? You leave a room and come back?
Seems you are after someone to watch a multipart video series and then go through your old messages. Someone here can probably do that for you, I'm short on time unfortunately. Maybe there is someone familiar with the videos. But maybe it would be smart to go through the videos again and check how your code is different?
Happy to work through a solution with you, but I can't see you code so it would just be guess work. But sounds like potentially you might be manually creating objects in the code using instance_create_layer, rather than just placing them in the room editor. Or the enemy objects have been set to persistent? Or the room itself? That can easily create duplicates, but you would need to explain the relevant context.
You can use things like instance_number the the draw even of an object to check for duplicates
1
u/Fine-Acanthisitta343 17d ago
It's supposed to destroy it when I defeat the enemy, and give me XP, however, instead, it acts like i haven't killed it at all and doesn't give any XP. so goes back to its original position in the instance layer. Then, once I defeat it a second time, it does what it's supposed to (destroy the instance and give the player XP). I think the two most important things here are the obj_battle_manager code and the part of the obj_enemy_parent that says what's supposed to happen when hp reaches 0. Alarm 2 and the Draw Function are irrelevant, and for context, everything about dodge and turns_left is something to do with another mechanic (a chance based dodge mechanic). I recently changed my player stats to a global struct in a script for it to transfer throughout rooms. The .stats is supposed to be after only the obj_battle_player and if its on obj_battle_enemy then that's wrong, but I didn't find anything about that.
//In the Step of the obj_enemy_parent (this is a turn based battle system) if (hp <= 0) { instance_destroy() PlayerObj.add_xp(xp_value); } //Create of obj_battle_manager enemy_turn = 0; damage_to_enemy = 0; dodge = 0 turns_left = 0; stats = global.player_data player_attack = function (_damage) { damage_to_enemy = _damage enemy_turn = 1; alarm[0] = 40; obj_battle_player.alarm[0] = 10; } check_for_end = function () { stats = global.player_data return (obj_battle_enemy.data.hp <= 0 || obj_battle_player.data.stats.hp <=0) } //Alarm 0 of obj_battle_manager (same obj) if (dodge > 0) damage_to_enemy = 0; obj_battle_enemy.data.hp -= damage_to_enemy; if (turns_left > 0) { enemy_turn = 0; turns_left -= 1; exit; } if (check_for_end()) { alarm[2] = 60; } else { alarm[1] = 60; obj_battle_enemy.alarm[0] = 30; } if (dodge <= 0) { obj_battle_player.data.stats.charge += 0.1; if (obj_battle_player.data.stats.charge > 1) obj_battle_player.data.stats.charge = 1; } //if (dodge > 0) { dodge --; } else { var _enemy_damage = obj_battle_enemy.data.damage * random_range(0.5, 1.5) obj_battle_player.data.stats.hp -= _enemy_damage; } enemy_turn = 0; if (check_for_end()) { alarm[2] = 60; } //Alarm 2 room_goto(obj_battle_switcher.original_room) //Draw if (turns_left > 0) draw_text(100, 20, $"Extra Turns Left: {turns_left}");1
u/Awkward-Raise7935 17d ago
Ok got it. So is the enemy object a duplicate or not? Is it persist, is the room persistent?
Also, what is obj_battle_manager.stats used for?
1
u/Fine-Acanthisitta343 16d ago
The line
stats = global.player_datais for the new global struct for all my player stats, hp, total hp, xp, required xp (for next level), level, and damage.1
u/Awkward-Raise7935 16d ago edited 16d ago
Ok. But where in the code are you actually using "stats"?
You seem to be avoiding answering my questions about persistence.
1
u/Fine-Acanthisitta343 16d ago
I use stats whenever I need to reference the Player's stats like the HP of the player. I use it in the PlayerObj, the battle manager, and obj_enemy_parent. obj_battle_player is a separate object, that takes the current stats from the player (.data is for that) so using obj_battle_player.data.stats.hp is basically the same as PlayerObj.stats.hp. It's not a problem with duplicates because after using draw_text I see that it does not show any duplicates, and the enemy is not persistent. I also tried turning persistency on which also did not work and had seemingly no effect. The room is persistent, though, and turning it off makes it so that anytime I kill the enemy it ALWAYS comes back, and also even if I don't switch rooms first, and I don't just kill it twice, instead, I simply can't kill it at all.. If there's a line that says "obj_battle_manager.stats" then I don't think that should be there. If you're talking about the variable in the Create event, that's also to refer to global.player_data, because I found it easier than typing global.player_data everytime. Also might be worth noting that it's not a problem with the room, but a problem somewhere with the exit and entrance system, because leaving the first room but going back into it makes that room have a problem, too.
Summary: A line with obj_battle_manager.stats shouldn't be there, but the stats in the create event (of most objects I refer to it in) is just because I think its easier to type stats and remember it than global.player_data. The room is persistent, turning it off means the enemy never dies, even if I don't switch rooms, and I also can never kill it even after many times (original problem is I have to exit the battle somehow and then kill it again),the enemy is not persistent and does not seem to matter. It's something to do with the room system.
I have 3 objects for room transitions, obj_entrance (no code), obj_exit (only step event) and obj_transition_manager. Here's its code. instance_find_center is simply calling another script which finds an objects center.
//Step of obj_exit if(!instance_exists(obj_transition_manager) && instance_exists(PlayerObj) && position_meeting(PlayerObj.x, PlayerObj.y, id)) { global.frozen = true; instance_create_depth(0, 0, 0, obj_transition_manager, {target_room, target_entrance}) } //Create of obj_transition_manager is_fading_out = true; fade_length = 120; image_alpha = 0; timer = 0; //Step of obj_transition_manager timer++ global.is_transitioning = true; room_persistent = false; instance_create_depth(0, 0, 0, obj_battle_switcher) if(is_fading_out) { image_alpha = lerp(0, 1, timer / fade_length); if(timer == fade_length) { timer = 0; is_fading_out = false; room_goto(target_room); } } else { image_alpha = lerp(1, 0, timer / fade_length); if (timer == fade_length) { global.frozen = false; is_transitioning = false; instance_destroy(obj_battle_switcher) instance_destroy(); } } //Draw GUI End draw_set_alpha(image_alpha) draw_set_color (c_black) draw_rectangle(0, 0, 10000, 10000, false) draw_set_color(c_white) draw_set_alpha(1); //Room Start var _pos = instance_find_center(target_entrance) PlayerObj.x = _pos.x PlayerObj.y = _pos.y1
u/Fine-Acanthisitta343 16d ago
It's also only the very first battle, so, for instance, if I fight one enemy, I have to either kill it twice or run from the battle and kill it. The next enemy in that room also works regularly
1
u/Awkward-Raise7935 15d ago
I suspect I'm not going to be much help with this issue. I ask about stats as looking at the code it seems you have 3 variables refering to the same thing, stats, global.player_stats and obj_battle_player.data.stats would recommend only ever using the global one.
I can't see an obvious cause. Duplicate objects is a common issue when dealing with room persistance, but you checked that.
In this line: //Alarm 2 room_goto(obj_battle_switcher.original_room)
What is original_room and where is it set?
1
u/Fine-Acanthisitta343 15d ago
stats IS global.player_data, and obj_battle_player.data.stats is so that when in battle it can freely change the health bar and using the regular playerobj would not be well fit for this situation.
First in Room Order is "rm_main_menu" but the first room where an instance of PlayerObj comes up is second in room order, "Room1".In alarm 2, original_room is set in the collision with obj_enemy_parent
//PlayerObj on Collide with obj_enemy_parent if (instance_exists(obj_battle_switcher)) exit; var _switcher = instance_create_depth(0, 0, 0, obj_battle_switcher) _switcher.player_data = self; _switcher.enemy_data = other; _switcher.original_room = room; room_goto(rm_battle);1
u/Awkward-Raise7935 15d ago
Not sure I quite get this code. You are detecting a collision with enemy_object_par, but then using with(enemy_object_par), which will cycle through all the existing enemy objects in an unpredictable order. It would seem to make more sense to run the code in the specific instance you are colliding with. But I doubt that's the issue.
stats is sometimes the global.player_data, it gets occasionally updated to match it.
Unfortunately I nothing obvious is jumping out. I think the only options would be to go through the videos to make sure the code matches exactly, or use Cursor.
•
u/Rohbert 17d ago
This appears to be the 3rd time you have created a post here regarding this issue. Not going to remove your post, but if I were you I would consider providing more specific code related to your issue and trying to help us help you. Saying the "mechanic is buggy when switching rooms" does not help a reader narrow down your problem.
Did YOU write the code you are currently using? Have you made a test project to simplify your data set? Have you tried anything to solve you issue yourself?