[RMVX ACE] SO I FOUND AN INTERESTING BUG.
Posts
Pages:
1
I've been working on the latest edition of Slip into Ruby (finally!) and am currently delving deep in the innards of Game_Interpreter. While I was looking through the code for the Shake Screen command, I noticed something a bit odd, namely this line:
Now in this context,
is the speed of the shake (1-9) and
is the duration in frames. So basically, as written, what this line is doing is waiting for 1-9 frames if the shake has a duration.
You see the problem here? It basically means that the "wait for completion" box on Shake Screen doesn't really do anything, because even 9 frames is a barely-noticeable duration. The line SHOULD be
which will correctly wait for *duration* frames if the wait for completion box was checked.
Just an interesting tidbit I thought I'd share before I publish the new SIR.
wait(@params[1]) if @params[2]
Now in this context,
@params[1]
@params[2]
You see the problem here? It basically means that the "wait for completion" box on Shake Screen doesn't really do anything, because even 9 frames is a barely-noticeable duration. The line SHOULD be
wait(@params[2]) if @params[3]
which will correctly wait for *duration* frames if the wait for completion box was checked.
Just an interesting tidbit I thought I'd share before I publish the new SIR.
Protip: Look at the Break Loop command
That was a fun discovery trying to find out why my game would softlock under certain circumstances!
That was a fun discovery trying to find out why my game would softlock under certain circumstances!
Wait, what's wrong with Break Loop?
Starts an infinite loop, each iteration increments index by 1, returns if index is greater than or equal to the size of the commands list less 1, returns if the code of the new command is 413 (Repeat Above) and the indent of the new command is less than the current indent.
Am I missing a circumstance under which neither of those return conditions is met?
def command_113 loop do @index += 1 return if @index >= @list.size - 1 return if @list[@index].code == 413 && @list[@index].indent < @indent end end
Starts an infinite loop, each iteration increments index by 1, returns if index is greater than or equal to the size of the commands list less 1, returns if the code of the new command is 413 (Repeat Above) and the indent of the new command is less than the current indent.
Am I missing a circumstance under which neither of those return conditions is met?
author=psy_wombats
Has there /ever/ been a version of RM where Break Loop worked right?
When I found the issue I was curious and tried it in a few other RMs, iirc it does exist in 2k, 2k3, VX, Ace, and MV! XP is a pain to get working so I couldn't test it.
author=Trihan
Am I missing a circumstance under which neither of those return conditions is met?
The snippet isn't where the softlock occurs, the snippet is the cause of the softlock because the break loop doesn't place the next interpreter command index in the correct position. Consider:
author=Trihan
... the indent of the new command is less than the current indent.
The answer:
Tons of fun was had here
e: To be clear, the break command in the conditional branch looks for the next "Repeat Above" command with a smaller indentation of the "Break Loop" command. The first one it sees is part of an inner loop so it places the next event command pointer after it, where it hits the main loop's "Repeat Above" command causing it to go back to the top of the loop where it spews out the loop iteration message command and repeats infinitely resulting in a softlock.
I think the issue was in the original RM2k and they just looked at the source code and copied it verbatim to the current language because the other RMs I tested on have the exact same behavior with nested loops.
e: Expanded what was in the hidden block because it's still kinda vague until the problem clicks
I stumbled upon that Break Loop oversight in my RPG Maker 2003 project. You have to solve it by making only the very last Break Loop be the one that exits the main loop. You can also avoid it if you put the nested loop away in another event/common event.
The best way seems to be this: If you have a free variable, you can set up a bunch of exit conditions to turn that variable to, say, 1, and then set up the code so that the Break Loop will only activate when that variable is 1.
The best way seems to be this: If you have a free variable, you can set up a bunch of exit conditions to turn that variable to, say, 1, and then set up the code so that the Break Loop will only activate when that variable is 1.
I like rewriting the break loop command to fix it myself, plus I can release by writing call kinds of vulgar comments while I do so! (if I was using 2k/3 I'd replace Break Loops with jump to labels. I'd keep the original loops though since those work afaik plus the indentation is handy for structure when reading event code)
My quick hack fix for VX is just
Vulgar comments removed though (although I'm not cleaning up the structure, it's an angry edit of the VX code). It basically tracks nested loops as depth: Each inner loops has a repeat above command so each time we hit a Loop Begins command we will skip over one additional Repeat Above command. Once we hit #ofLoopBegins + 1 Repeat Above commands we break and resume. It worked in the game where the bug was relevant but I haven't tested it beyond that. I wouldn't be surprised if there's some dumb oversight of my own, I spent more time than I should've at work trying to fix shit because I got mixed up when some data was zero-indexed and when it wasn't.
My quick hack fix for VX is just
def command_113 depth = 0 loop do @index += 1 if @index >= @list.size-1 return true end # INC depth on 'Begin Loop' depth += 1 if @list[@index].code == 112 # DEC depth or exit on 'Loop Above' if @list[@index].code == 413 if depth > 0 depth -= 1 else return true end end end end
Vulgar comments removed though (although I'm not cleaning up the structure, it's an angry edit of the VX code). It basically tracks nested loops as depth: Each inner loops has a repeat above command so each time we hit a Loop Begins command we will skip over one additional Repeat Above command. Once we hit #ofLoopBegins + 1 Repeat Above commands we break and resume. It worked in the game where the bug was relevant but I haven't tested it beyond that. I wouldn't be surprised if there's some dumb oversight of my own, I spent more time than I should've at work trying to fix shit because I got mixed up when some data was zero-indexed and when it wasn't.
Edit: Never mind, I see the problem now.
author=Zachary_Braun
I stumbled upon that Break Loop oversight in my RPG Maker 2003 project. You have to solve it by making only the very last Break Loop be the one that exits the main loop. You can also avoid it if you put the nested loop away in another event/common event.
The best way seems to be this: If you have a free variable, you can set up a bunch of exit conditions to turn that variable to, say, 1, and then set up the code so that the Break Loop will only activate when that variable is 1.
Or just use Go To Label like a real man.
author=psy_wombats
Or just use Go To Label like a real man.
You mean "Loop backwards in the event commands until you find a label called X"? :P
author=BlackWolf1992Same here. Once you figure out how Labels work, there's no reason to keep using Loops at all. Especially since they don't work that well anyway.
I never used Break Loop event. I just use labels. xD
Pages:
1

















