Timers in state scripts?

G

gurglovt

Guest
I'm trying to make a boss enemy with 2 or 3 attacks that trigger randomly after however much downtime from the boss itself. I found this:

GML:
if (start_timer == true) {timer = room_speed * 30;}

if (timer > 0) {timer--;}

if (timer == 0)
{
 do alarm stuff
 timer = -1; // This is important, or the timer will trigger every step once it runs out
}
on another thread, but it didn't work at all, any ideas?

Thanks
 

SubWolf

Member
I think you have to change the variable "start_timer" to false right after you set "timer = room_speed * 30;" or every step it will enter the "if (start_timmer == true)" and set the timer to 30 seconds.

Hint: if you're checking a boolean variable you don't need to write "start_timer == true", if you do like below it works:

if (start_timer) { timer = room_speed * 30; start_timer = false; }

If you want to check if the variable is false you just code like this:

if (!start_timer) //whatever

PS: don't forget to set "start_timer" to true again when you want to initiate the boss attack. Maybe on the alarm event?
 
G

gurglovt

Guest
would this work any differently if im relying on scripts separate from the boss object itself?
 

TheouAegis

Member
the premise of have any timers inside of states is one state would actually set the timer, the other state will count down the timer and transition to a different state when the timer reaches zero, typically.
 
G

gurglovt

Guest
Still doesn't seem to be working, I added a draw event to check if the timer is even going down and it seems to be stuck at 179, here's my code:

GML:
///Create Event
spd = 1;
state = bState.bIdle;
timer = 0;

enum bState
{
    bIdle,
    attack1,
    attack2,
    death
}

///Step Event
move_towards_point(oPlayer.x, oPlayer.y, spd);
timer = room_speed * 3;

switch (state)
{
    case bState.bIdle: scr_bIdle(); break;
    case bState.attack1: scr_attack1(); break;
    case bState.attack2: scr_attack2(); break;
    case bState.death: scr_death(); break;
}

///Draw Event
draw_sprite(sChefMother,0,x,y);
image_speed = 1;
draw_text(x,y+100,string(timer));

///scr_bIdle
sprite_index = sChefMother;
image_speed = 1;
move_towards_point(oPlayer.x,oPlayer.y,spd);

if (timer > 0) {timer--;}

if (timer == 0)
{
 state = bState.attack1;
 timer = -1;
}

///scr_attack1
sprite_index = sChefMother_a1;
image_speed = 1;
vspeed = 0;
hspeed = 0;

instance_create_depth(x+211, y+35, 1, oPeaBoss); //these just spawn projectiles
instance_create_depth(x+155, y+35, 1, oPeaBoss);
 

Pixel-Team

Master of Pixel-Fu
This is how I would work it. In the create event, set up a wait time. You can also randomize this value, but I put 3 for 3 seconds.

GML:
///Create Event
spd = 1;
state = bState.bIdle;
timer = 0;
wait_time = 3; //number of seconds to wait

enum bState
{
    bIdle,
    attack1,
    attack2,
    death
}
In the Idle script, which I presume would be run on each frame, we increment the timer. We measure the timer against the total wait time, which if we want it to be in seconds, we multiply it by the room speed. If the timer exceeds it, we change the state.

GML:
///scr_bIdle
sprite_index = sChefMother;
image_speed = 1;
move_towards_point(oPlayer.x,oPlayer.y,spd);

timer++;

var max_time = wait_time * room_speed;

if (timer >= max_time) {
    state = bState.attack1;
     timer = 0;
}
 
G

gurglovt

Guest
see if wait_time = 3 the game launches with the boss in state.attack1, whereas any integer above 3 means that the boss never enters state.attack1
 
Top