GameMaker SOLVED Alarm resetting before taking effect.

A

AtomicBlade

Guest
I’m somewhat familiar with alarms, but this issue has stumped me. For every alarm I use, I always make sure that it only resets if it has run it’s code, using

if (alarm[x] < 1) alarm[x]= y

but for some reason, this specific alarm resets once it hits 0 without running the code.

here’s the code. Alarm4 itself simply causes tracking to be false. I’d appreciate any help you can give, but I won’t be able to reply immediately. Thanks a lot and have a good day.

GML:
if(y <= -30){
    if(move = 2){
    grv = 0;
    hsp = 0;
    vsp = 0;
    megarising = false;
    tracking = true;
    if(!megarising){
          if (alarm[4] < 1) alarm[4] = 60;
              if(tracking) {
                   if(instance_exists(oPlayer)){
                        if(playerdisplacement > 5) hsp = -4;
                        else if (playerdisplacement < -5) hsp = 4;
                        else hsp = 0;
}
}
}
    }
}
 

Slyddar

Member
Probably should just use debugging. Place a breakpoint on the alarm line and run with F6, then step through (F11) and see what the values are. F5 will loop it around to the next breakpoint. Either hover over the values or add them as watches to monitor.
Also sometimes you don't need alarms. If you set tracking to be 60, then you can use a check like this:
Code:
if tracking-- <= 60 {
Last note, your code here will never not run, considering you are setting it to false, and then checking it straight away.
Code:
    megarising = false;
    tracking = true;
    if(!megarising){
 
A

AtomicBlade

Guest
I always forget to debug. I was using a draw text to see what value the alarm was at. It always resets as it should take effect. How does debugging work exactly? I’m still pretty new.
 
A

AtomicBlade

Guest
Thanks for your help. Hopefully it works. I guess I’ll find out in the morning.
 

Yal

🐧 *penguin noises*
GMC Elder
There's at least two problems with this piece of code:
1595402150160.png
  • The last line is indented as if it was in a code block controlled by the if(alarm[4] < 1) check, but it isn't... it will always happen. The indentation might mislead you when reading the code.
  • You always set tracking to true, so if the alarm changes it, it still has no effect because you reset it the next step.
 

Roleybob

Member
Looks like this is already solved but out of interest, when does the value of an alarm decrease and when does an alarm activate in GM2's internal code?

Is it basically:

GML:
if (--alarm[0] == 0)
{
    //execute alarm[0] code//;
}
Which would make sense to me, but if GM does something weird like decreases the value of alarms, then runs other code / events, then checks whether alarms == 0 then it could be resetting before the alarm == 0 check.

I doubt this is what GM does but if it is then it could be fixed with if (alarm[0] < 0) instead, as alarms ''idle state" value is -1
 
A

AtomicBlade

Guest
Thank you everyone for your help. Thanks to Yal, I realised that the alarm was triggering, but it’s only effect was being undone immediately by
If(move = 2) tracking = true;
Now the only issue is preventing this from happening. Any suggestions?
 
A

AtomicBlade

Guest
Looks like this is already solved but out of interest, when does the value of an alarm decrease and when does an alarm activate in GM2's internal code?

Is it basically:

GML:
if (--alarm[0] == 0)
{
    //execute alarm[0] code//;
}
Which would make sense to me, but if GM does something weird like decreases the value of alarms, then runs other code / events, then checks whether alarms == 0 then it could be resetting before the alarm == 0 check.

I doubt this is what GM does but if it is then it could be fixed with if (alarm[0] < 0) instead, as alarms ''idle state" value is -1
to my knowledge, the alarms value is decreased by one every frame. Once it hits 0, the code is executed and, as you said, when not in use, the value is -1. As there is only one frame difference between alarm = 0 and = -1, I think the reason that code usually uses if (alarm < 1) is because it has the same effect, but is one frame faster meaning that using alarm < 0 would actually cause a timer that should take 60 frames every loop, will actually take 61. Idk if that’s how it actually works, but from experience, that’s what I assume.
 

Roleybob

Member
AtomicBlade

to my knowledge, the alarms value is decreased by one every frame. Once it hits 0, the code is executed and, as you said, when not in use, the value is -1. As there is only one frame difference between alarm = 0 and = -1, I think the reason that code usually uses if (alarm < 1) is because it has the same effect, but is one frame faster meaning that using alarm < 0 would actually cause a timer that should take 60 frames every loop, will actually take 61. Idk if that’s how it actually works, but from experience, that’s what I assume.

What I meant was, I assume that GM evaluates alarms in a sensible way like this:

  • Decrease all alarms with a count greater than -1 by 1
  • Execute code in alarms with a count equal to 0
  • Begin Step
  • etc...
So that no other code is run in between the alarm counting down and the alarm evaluating whether to execute its code. I can't imagine why it would not work like this, but if GM does something really odd with its timing like this:

  • Decrease all alarms with a count greater than -1 by 1
  • Begin Step event
  • Execute code in alarms with a count equal to 0
  • Step
  • Etc...

Then if there were code in the Begin Step event which changed the count in the alarm then it could stop the alarm from executing.

It's well known that GMS2 doesn't have a specific order of events but as long as the alarm executes immediately after counting down (if it reaches 0) then there's no problem. Was just an idle thought.

Yes - alarms with a count >= 0 count down by 1 per frame.
No - most code will not use an alarm check and then manually trigger an alarm as this is done internally, that's the point of alarms. If you are going to check manually and then tell the alarm to trigger then you may as well use your own variable and code block / script / whatever. In my limited experience anyway.
 
A

AtomicBlade

Guest
Oh, ok. I found the solution. I changed move to 3 in that alarm, which stopped tracking from becoming true again, I also had to change how move changed to 2 as it also overrode the alarms change of move to 3. Thanks for all the help. I’m slowly getting better at the problem solving side of coding.
 

TheouAegis

Member
It's either
What I meant was, I assume that GM evaluates alarms in a sensible way like this:

  • Decrease all alarms with a count greater than -1 by 1
  • Execute code in alarms with a count equal to 0
  • Begin Step
  • etc...
So that no other code is run in between the alarm counting down and the alarm evaluating whether to execute its code. I can't imagine why it would not work like this, but if GM does something really odd with its timing like this:

  • Decrease all alarms with a count greater than -1 by 1
  • Begin Step event
  • Execute code in alarms with a count equal to 0
  • Step
  • Etc...

Then if there were code in the Begin Step event which changed the count in the alarm then it could stop the alarm from executing.

It's well known that GMS2 doesn't have a specific order of events but as long as the alarm executes immediately after counting down (if it reaches 0) then there's no problem. Was just an idle thought.

Yes - alarms with a count >= 0 count down by 1 per frame.
No - most code will not use an alarm check and then manually trigger an alarm as this is done internally, that's the point of alarms. If you are going to check manually and then tell the alarm to trigger then you may as well use your own variable and code block / script / whatever. In my limited experience anyway.
Your first one is closer. Note this is GMS1 and GMS2.2 although GMS2.3 may have tweaked the mechanics here.
Code:
event_perform(ev_step,ev_step_begin)
for(i=0; i<12; i++) {
    if alarm[i] not negative {
        alarm[i]--;
        if alarm[i] is zero {
            event_perform(ev_alarm,i)
        }
    }
}
event_peform(ev_step,ev_step_normal)
Obviously I'm leaving out a bunch of stuff in between. Begin Step event runs before anything. All the automated tasks then run and their corresponding events run. The point is the alarm does indeed remain at 0 for one full step.

Personally I just use !alarm[0] and take advantage of GM's type mishandling, but yes a check of <0 or ==-1 will cause one full frame to pass between the alarm firing and the alarm getting reset. And while there are a few cases where you would want a looping alarm check outside the alarm event itself, for an optimal performance, the alarm event should be handling all the looping. Why check if an alarm is less than 1 when the alarm event already does that?
 

Roleybob

Member
Ok, so Begin Step event happens before the built in tasks instead of after (which could be useful to know in itself thanks).

My point was whether there is any gap at all between alarm[j] counting down to 0 and it triggering, i.e. does it trigger immediately without the possibility of any other code interfering.

From what you wrote it sounds like it is immediate (I can't imagine why it would not work like that) so thanks

EDIT: I can't use alarm[/i] in the example because it makes the text become italicised!
 

Yal

🐧 *penguin noises*
GMC Elder
EDIT: I can't use alarm[/i] in the example because it makes the text become italicised!
You could use the [code=gml] tag? (CODE gives you monospaced text, CODE=GML gives you GML syntax highlighting, and ICODE makes code inline instead of in a separate block of text, like the tag example I just posted)
 
Top