• 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] Simple problem with RTS game.

J

Jonatherin

Guest
I'm creating a RTS Sci-fi game and I've run into a little problem.

I've been working on the enemy AI and I need a variable that is set to 1(true) when the enemies enemy(the player) has a fighter ship in the range of one of the enemy ships, and its set to 0(false) when there are no playerfighterships in the range of any(all) of the enemyships. Here's the code I made but simplified, ENEMY_SHIP-STEP_EVENT if (player_fighter_ship in range) {player_attacking=1;} else {player_attacking=0;} Obviously this causes a problem cause even if one enemyship is in the range of a playerfightership, another enemyship could not be in the range of a playerfightership and both enemyships will conctradict each other and the player_attack variable wont work right.

Sorry if this is confusing. I'm not that good at making forums or explaining things.
 
C

chico_haze

Guest
I might run the check in some external object, not the enemy ships themselves. Have one external object like obj_level_control run the check every step and cycle through all the enemy ships to see if any have a player in range. Something like this might work:

Code:
global.player_attacking= false;
with(obj_enemy_ship){
  if(distance_to_object(obj_player_ship) < range){
    global.player_attacking = true;
  }
}
 
D

DKR_87

Guest
Ok, so it seems you need to change player_attacking variable to TRUE for the specific enemy instance. It sounds like when one enemy is in range, you're changing the variable player_attacking = 1 for ALL enemies...instead of just that specific one.

Maybe someone else will correct me, or have a more elegant way of doing this.

You could use distance_to_object in each STEP event of your enemies I believe. Replace my example object names with the appropriate names from your project.

Code:
if distance_to_object(obj_player) <= 200 
{ player_attacking = 1}
else
{ player_attacking = 0 }
However, the distance_to_object is useful, I think, if you have only one instance of the player objects. If you're creating an RTS, I assume you're going to have lots of player units. So, instead use point_distance. But you'll need to get the distance away to the nearest player unit, so a couple variables are required.

Code:
var unit_x, unit_y;
unit_x = instance_nearest(x, y, obj_player).x;
unit_y = instance_nearest(x, y, obj_player).y;

if point_distance(x, y, unit_x, unit_y) < 200
{ player_attacking = 1 }
else
{ player_attacking = 0 }
 
J

Jonatherin

Guest
Actually that's almost exactly what I already have. Sorry I probably didn't explain myself well enough.

What I need is a global variable(global.player_attacking) and its set to TRUE when any of the playerattackships are in range of an enemies ship, AND its set to FALSE when there are no(nada, zero,not one) enemyships in range of a playerattackship.

So its actually a variable for the whole team and not for individual enemy ships.
For example I could use global.player_attacking to set all the enemy ships to an UNDER_ATTACK state and all the enemy ship would react to being under attack.
 
D

DKR_87

Guest
Unless I misunderstand, the code above does just that. But if you want it for ALL enemy ships, the whole team, then you can simply create an enemy parent object and change player_attacking = 1 for the parent object. This will apply to all enemy ships that are children of it.

And when the player is out of range of ANY enemy ships, it will be set to 0 (false)

Again, the code above will change your desired variable, but it simply sounds like you need that variable to be within a create event of an enemy parent object.

But if I still don't understand your intended goal, don't get frustrated. Please elaborate on what you're trying to accomplish. I've played many RTS games!
 
A

anomalous

Guest
Do you use this to determine the AI of the enemy ship state?
ENEMY_SHIP-STEP_EVENT if (player_fighter_ship in range) {player_attacking=1;} else {player_attacking=0;}

That's fine, continue to use that if you like. Make sure "player_attacking" is an instance variable (not a var, not a global).

What you need is a separate global variable to know if ANY of those enemy ships have "player_attacking" set to true. Then the global variable takes on the true value.
You do this from a controller or the player object, in ONE place. I suggest you use a different variable name that indicates the state.

From some controller, run this whenever you want, it could be every step or it could be every second, etc.

global.player_under_attack = 0; // set to false as default
with obj_enemy_ship{
if player_attacking == 1{
global.player_under_attack = 1; // someone is attacking player
break; // stop the loop because all you need is to know if any are in combat
}
}
 
J

Jonatherin

Guest
Let me try to explain exactly what I'm doing here.

So I'm making the ENEMIES AI and in RTS games there are lots of states(for ex: work, attack, idle). Well for me to make some of these states I need a global variable(global.player_attacking) that keeps track if the enemy as a whole is under attack or not. Well to get that variable to work I need an individual variable(under_attack) for every individual enemy ship which keeps track if that individual ship is being attacked or not.

The code that you guys suggest to me works except for one thing. Which is setting global.player_attacking to 0 when all of the enemy ships have under_attack set to 0

Here's the code I'm using in obj_controller Step_Event:

if (instance_exists(obj_enemy_ship))
{
with (obj_enemy_ship)
{
if (under_attack == 1)
{
global.player_attacking = 1;
break;
}

if (under_attack == 0)
{
global.player_attacking = 0;
break;
}
}
}

So let me explain exactly what I want this to do.

If any enemyships have under_attack = 1 then global.player_attacking = 1, but if no enemyships have under_attack = 1(all have under_attack = 0) then global.player_attacking = 0.

And then here's the code for obj_enemy_ship Step_Event:

if (distance_to_point(obj_player_fighter.x, obj_player_fighter.y) <= 256 && global.player_attacking = 0)
{
under_attack = 1;
}
else if (distance_to_point(obj_player_fighter.x, obj_player_fighter.y) > 256)
{
under_attack = 0;
}


BTW I'm not getting frustrated. I'm actually very grateful you all are helping! :)
 
A

anomalous

Guest
The code that you guys suggest to me works except for one thing. Which is setting global.player_attacking to 0 when all of the enemy ships have under_attack set to 0
The code outline I provided does that, did you see the default?

global.player_under_attack = 0; // << here, it's zero when all enemies are set to 0, this remains 0
with obj_enemy_ship{
if player_attacking == 1{ //
global.player_under_attack = 1; // << here it is only set if at least one is under attack
break; // stop the loop because all you need is to know if any are in combat
}
}
 
J

Jonatherin

Guest
That doesn't set global.player_attacking back to 0 when all of under_attack's are 0.
That just sets it to 1 then it stays that way forever.
 
Not if you put his code:
if (player_fighter_ship in range) {player_attacking=1;} else {player_attacking=0;}
in the step event of the enemy object.
In the create event of the enemy object, set player_attacking to 0.
 
J

Jonatherin

Guest
It seems like that would work but the only problem is setting global.player_attacking back to 0.
I need like an "all" command that checks if all of enemyship's under_attack variables are 0.
And no I'm not talking about the all command they already have.
 
A

anomalous

Guest
That doesn't set global.player_attacking back to 0 when all of under_attack's are 0.
That just sets it to 1 then it stays that way forever.
It certainly looks like it does:
Again, in some controller object that runs this once per (whatever you want, step or more than 1 step):

global.player_under_attack = 0;
^^^ This sets it back to 0 ALWAYS. ALWAYS it is set to 0, that includes when all under attacks are 0. You say it doesn't, but clearly it does set it to 0 in every case.

The below, ALWAYS checks every ship, and if any of them are under attack = 1, it sets the global attack = 1.
with obj_enemy_ship{
if player_attacking == 1{ //
global.player_under_attack = 1; // << here it is only set if at least one is under attack
break; // stop the loop because all you need is to know if any are in combat

}
}

So the only time your global under attack is set to 1, is if a ship attacking is set to 1. else, it remains 0.
 
J

Jonatherin

Guest
Oh duhhh I'm dumb. Sorry I didn't notice the global.player_attacking = 0; in the STEP_EVENT part.
Works! Thanks so much all of you for your help and patience! :D
 
Top