• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [SOLVED] RPG - Preventing enemies acting at same time

T

Tofu Heavy Industries

Guest
I have an Rpg im making, with 6 slots in an array for enemies in the battle screen (global.enemy_slot[0-5]). They each take their turn when their alarm is ready (each has an alarm in the obj_control_battle object). I use the below script to try to stagger the enemies actions if multiple ones are ready at one time.

obj_control_battle alarm[x] event
Code:
for(iii=0;iii<6;iii+=1) {   
   if ((instance_exists(global.enemy_slot[iii]) && (iii < 2)) ) {
           if (alarm[iii+1] == global.enemy_slot[iii].en_fightgauge) {
           alarm[3] += 20;
           exit;
             }
       }
}
It checks each enemy in the enemy array lower than themselves, and if one is acting, it adds +20 to its own alarm to create the stagger. Each alarm event for each enemy has the almost the exact same code.(Except alarm #, and iii 'less than' X comparison).

Problem is, after the 1st or second turn, no matter how many enemies there are, it will mess up and some enemies will act at the same time. How do i fix this?
 
As each enemy becomes ready to attack, it should add itself to a master ds_queue.

Then in the step event of your controller, pop off the first enemy in the queue and process that. After he's attacked, reset that enemy's attack timer. You could then have an timer that decides how often you pop an enemy off from the ready queue.
 

TheouAegis

Member
You could, when an enemy is actually performing an attack, or likewise when a player is performing an attack, pause all of the timers. At the beginning of each step, check if a variable set to not countdown the timers is clear, then count down the timer and if it is 0 add the unit to an attack queue. Then after everybody has had a turn to countdown the timers, check if there is anybody in the queue. If there is, SET the variable to not count anybody down, else clear the variable to not count down the timers. And pick a random selection from the queue to have it attack. At the end of the attack, remove that unit from the queue and then check if the size of the queue is 0. If it is, clear the countdown variable.
 
You could, when an enemy is actually performing an attack, or likewise when a player is performing an attack, pause all of the timers. At the beginning of each step, check if a variable set to not countdown the timers is clear, then count down the timer and if it is 0 add the unit to an attack queue. Then after everybody has had a turn to countdown the timers, check if there is anybody in the queue. If there is, SET the variable to not count anybody down, else clear the variable to not count down the timers. And pick a random selection from the queue to have it attack. At the end of the attack, remove that unit from the queue and then check if the size of the queue is 0. If it is, clear the countdown variable.
That's a good idea as it will preserve the state of the count down timers and reduce the chance of their attacks all bunching up.
 
Create a variable that controls when the enemies attack. Put it in the create event.
Code:
attackgo = false;
For each enemy, check to see if attackgo is false before attacking.

Code:
if attackgo == false && alarm[0] == 0{
attackgo = true;
}
Once the attack has ended, set attackgo back to false.

This way, the only way an enemy can attack is if no one else is attacking. As soon as someone attacks, no one else can do anything until the attack ends.
 

TheouAegis

Member
Create a variable that controls when the enemies attack. Put it in the create event.
Code:
attackgo = false;
For each enemy, check to see if attackgo is false before attacking.

Code:
if attackgo == false && alarm[0] == 0{
attackgo = true;
}
Once the attack has ended, set attackgo back to false.

This way, the only way an enemy can attack is if no one else is attacking. As soon as someone attacks, no one else can do anything until the attack ends.
Not bad, except he wanted enemies and players who would attack at the same time to do so in random order. Your suggestion would make the order the same every time.
 
T

Tofu Heavy Industries

Guest
I did figure it out. Im pretty sure. Testing shows it working.. although it does still seem a bit off

obj_control_battle - Create
Code:
//Timing to space out enemy attacks
attack_timing = 0;

//order list for what enemy attacks next
attack_order[0] = 255;
attack_order[1] = 255;
attack_order[2] = 255;
attack_order[3] = 255;
attack_order[4] = 255;
attack_order[5] = 255;
obj_control_battle - each alarm for an enemy
Code:
if (instance_exists(global.enemy_slot[0]) ) {

// check for open attack_order slot then place # into it
for (iii = 0; iii < 6 ; iii+=1){
    if (attack_order[iii] == 255) {
        attack_order[iii] = 0;
        exit;
    }
}

}
obj_control_battle - Step
Code:
attack_timing  +=1;

if (attack_timing == 15) {
    for (iii = 0; iii < 6 ; iii+=1){
        if (attack_order[iii] != 255) {
            global.enemy_slot[attack_order[iii]].act_timer = 20;
            global.enemy_slot[attack_order[iii]].acting = "NULL";
            scr_enemy_turn(attack_order[iii], attack_order[iii]+1);
            attack_order[iii] = 255;
            attack_timing = 0;
            iii = 6;
            break;

        }
    }
  
    for (ii=0; ii<6; ii+=1) {
        if attack_order[ii]==255 {
            break;
        } else {
            attack_order[ii]=attack_order[ii+1]
        }
    }    
} else if ( attack_timing >= 20) {
    attack_timing = 0;
}
 
Top