Jump to content

Recommended Posts

Hello again BI forums! I come to you in a time of great need

Im making an ai script but it keeps giving me an error, and it makes 0 sense. ANy help is appreciated

 

The Script in question:

[] spawn {
  while {true} do {
    {
      _x setVariable ["HAF_spawned",true];
      _x setSkill ["courage", 1.0];
      _x enableAttack false;
      _x setCombatBehaviour "AWARE";
      _x call BIS_fnc_enemyTargets;
      getPosATL _targets
        if (_targets > 2) then {
                                _x setBehaviour "CARELESS";
                                _x suppressFor 10;
                                _x doMove (PosATL _targets); 
                                Sleep 11;
                                _x setBehaviour "AWARE"
                                }; 
        else {
            _x setCombatBehaviour "AWARE";
             };
     } forEach (allUnits select {isNil {_x getVariable "HAF_spawned"} && side _x == WEST});
    uiSleep 12;
  };
};

And the error (line 36 is the "if (_targets..." one): 

'...IS_fnc_enemyTargets;

getPasATL _targets

|#|if (_targets > 2) then

{

_x setBehaviou...'

(FIlename and directory fo SQF), line 36

Error Missing ;

Share this post


Link to post
Share on other sites

The error is because of getPosATL _targets. You're not saving it as a variable or using it as a condition, so it doesn't make any sense. As for the error, I suspect there's more than one error happening here. From a quick glance it seems you haven't defined _targets anywhere, the previous line in question doesn't end with a ; and the following if......then check will fail because _targets isn't defined. You may need to look at your .rpt to see where things are going wrong in the first instance, and solve the issues one at a time. 

Share this post


Link to post
Share on other sites
17 minutes ago, beno_83au said:

The error is because of getPosATL _targets. You're not saving it as a variable or using it as a condition, so it doesn't make any sense. As for the error, I suspect there's more than one error happening here. From a quick glance it seems you haven't defined _targets anywhere, the previous line in question doesn't end with a ; and the following if......then check will fail because _targets isn't defined. You may need to look at your .rpt to see where things are going wrong in the first instance, and solve the issues one at a time. 

Thanks for the feedback! I'm attempting to get the position of nearby enemy units using call BIS_fnc_enemyTargets;, changing the previous line to "_targets = _x call BIS_fnc_enemyTargets;" and adding the semi-colon after the getpos line. is this a step in the right direction? 

[] spawn {
  while {true} do {
    {
      _x setVariable ["HAF_spawned",true];
      _x setSkill ["courage", 1.0];
      _x enableAttack false;
      _x setCombatBehaviour "AWARE";
      _targets = _x call BIS_fnc_enemyTargets;
      EmemPos = getPosATL _targets;
        if (_targets > 2) then {
                                _x setBehaviour "CARELESS";
                                _x suppressFor 10;
                                _x doMove (EmemPos); 
                                Sleep 11;
                                _x setBehaviour "AWARE"
                                }; 
        else {
            _x setCombatBehaviour "AWARE";
             };
     } forEach (allUnits select {isNil {_x getVariable "HAF_spawned"} && side _x == WEST});
    uiSleep 12;
  };
};

When testing this the "else {" line now is getting the semi-colon error

Share this post


Link to post
Share on other sites

There's still a number of errors in that example. You should be looking at how each command and function works here:

https://community.bistudio.com/wiki/Category:Arma_3:_Scripting_Commands

https://community.bistudio.com/wiki/Category:Arma_3:_Functions

 

For example, BIS_fnc_enemyTargets returns an array (of enemy units), which you have saved/declared as _targets. But then you try to use _targets with getPosATL which only takes on object, not an array (same idea as with doMove). So you need to work out what you're trying to achieve with that (e.g. are you trying to get just one unit's position?).

 

But you also need to look at what the error is telling you, and you need to read the error report to be sure you get the right info. The on-screen error reports will overlap each other if there is more than one, and in the past I've been guilty of getting stuck on a problem when I didn't realise two errors were overlapping (it is not always obvious). So it's important that you check your error report for the details. And as is the case in your situation, you've only seen the error about the else statement, when there's still another error before that. That's why you check the .rpt and solve the first occurrence of any errors before moving on (as sometimes later errors are fixed when an earlier error is fixed).

 

In the case of the else statement, you've basically written:

}; else {

Which is incorrect, as the error states, and proper examples are given in the above linked wiki. The exact error report can sometimes be a little misleading, as it is here (I assume), but it is pointing you to the correct area of that specific error and so looking at the command in the wiki will show you why it's throwing an error.

 

Also, not an error, but you can declare EmemPos as a local variable (_EmemPos) throughout this script if it is not being used anywhere else. Not a biggie, but it will save on a small amount of resources if it is only declared locally to the script.

  • Like 2

Share this post


Link to post
Share on other sites
57 minutes ago, beno_83au said:

There's still a number of errors in that example. You should be looking at how each command and function works here:

https://community.bistudio.com/wiki/Category:Arma_3:_Scripting_Commands

https://community.bistudio.com/wiki/Category:Arma_3:_Functions

 

For example, BIS_fnc_enemyTargets returns an array (of enemy units), which you have saved/declared as _targets. But then you try to use _targets with getPosATL which only takes on object, not an array (same idea as with doMove). So you need to work out what you're trying to achieve with that (e.g. are you trying to get just one unit's position?).

 

But you also need to look at what the error is telling you, and you need to read the error report to be sure you get the right info. The on-screen error reports will overlap each other if there is more than one, and in the past I've been guilty of getting stuck on a problem when I didn't realise two errors were overlapping (it is not always obvious). So it's important that you check your error report for the details. And as is the case in your situation, you've only seen the error about the else statement, when there's still another error before that. That's why you check the .rpt and solve the first occurrence of any errors before moving on (as sometimes later errors are fixed when an earlier error is fixed).

 

In the case of the else statement, you've basically written:


}; else {

Which is incorrect, as the error states, and proper examples are given in the above linked wiki. The exact error report can sometimes be a little misleading, as it is here (I assume), but it is pointing you to the correct area of that specific error and so looking at the command in the wiki will show you why it's throwing an error.

 

Also, not an error, but you can declare EmemPos as a local variable (_EmemPos) throughout this script if it is not being used anywhere else. Not a biggie, but it will save on a small amount of resources if it is only declared locally to the script.

Alright! Thanks again for responding. I've got past the syntax errors manually after digging through my 3 thousand line (im running mods) RTP, so now I think I know what I need. is there any way to select an object from an array, cause right now I've only gotten as far as selecting it as a code reference. I'm wanting to select an OPFOR unit at random. Here's the updated code. [

] spawn {
  while {true} do {
    {
      _x setVariable ["HAF_spawned",true];
      _x setSkill ["courage", 1.0];
      _x enableAttack false;
      _x setCombatBehaviour "AWARE";
      _unitsEast = units opfor;
      _obj = getPosATL _x;
      targets = {selectRandom _unitsEast} findNearestEnemy _obj;
        if (_targets > 2) then {
                                _x setBehaviour "CARELESS";
                                _x suppressFor 10;
                                _x doMove (targets); 
                                Sleep 11;
                                _x setBehaviour "AWARE"
                                }; 
     } forEach (allUnits select {isNil {_x getVariable "HAF_spawned"} && side _x == WEST});
    uiSleep 12;
  };
};

The selectrandom is the best command I could find, but I have no way to make what it spits out as an object (which is what the array is, multiple units). Right now it's just spitting it out as code (according to the RTP). Any help is appreciated, already Leagues further than I was before. 

Share this post


Link to post
Share on other sites

This kind of code can't work for multiple reasons:

targets is a command. (see biki). So you can't write targets = ....

say you want a local variable (working) : _targets = selectRandom _unitsEast findNearestEnemy _obj;

findNearestEnemy doesn't work as you think (see biki) selecting at random an enemy is worth nothing in this case and the returned value in not an array (so _targets is an object)

It's weird to shift from careless to aware every 12 sec if you pick at random an east unit.... but you also have a problem as units opfor doesn't work

units apply to a group (or object, see biki). Perhaps you want something like allUnits select {side _x == east}....

Not sure of what you're trying to do with all of that. (I have an idea but it's weird).

  • Like 1

Share this post


Link to post
Share on other sites

Was writing, but pierre covered most of it (I was going to mention there is also selectRandomWeighted). But to reinforce the points already made, the biki should be your #1 reference point for learning how to use the commands and figuring out what is wrong.

 

And, each time you return to the editor you can delete the rpt file to start fresh, then just search "error" and skip down until you're at the first script error. 

Share this post


Link to post
Share on other sites

thanks a billion to you both, ill hit this fresh in the morning. The concept is to have one ai every 12 seconds both suppress an enemy position while moving towards them to FORCE them to move under fire (so engagements don't turn into shooting ranges of static targets). I'm clearly not the best but ill keep at it. 

Share this post


Link to post
Share on other sites

It can take a while to wrap your head around some of the different concepts. This is especially true if, like me, you were starting from scratch as someone without any experience in this. And speaking from experience, the best thing you can do is break everything down into it's individual parts and make each step work on it's own, while at the same time understating why it works, generally through relying heavily on the biki. When figuring commands out it's not a bad idea to either hint or systemChat your results:

 

systemChat str (selectRandom (units opfor));

 

It's a basic one, but apply the idea to the commands you don't understand, or when you get weird results. Maybe even "opfor" turns out to be wrong? Then you check that. Moving on from that method (and only a little more advanced) is the use of the diag_log command. 

 

So at the end of the day if A, B, C and D are not working, get A working first. 

 

I swear this is only the second edit I've made to this post. But it should also be mentioned that bald people should avoid trying to script the AI, because you'll usually need that hair for pulling it out. 

  • Like 2
  • Haha 3

Share this post


Link to post
Share on other sites

I tried using the hints to check the script's progress, and it looks like system chat doesn't want to work rill i get the errors fixed either. Might as well ask for pointers, as here's what I got from RPT:

10:15:16 Error in expression <enableAttack false;
systemChat str _sup = allUnits selectRandom {side _x == east>
10:15:16   Error position: <= allUnits selectRandom {side _x == east>
10:15:16   Error Missing ;
10:15:16 File C:\Users\14064\Documents\Arma 3 - Other Profiles\CC%20Zeus\mpmissions\Droid%20Script%20Testing.VR\Droid.sqf..., line 37
10:15:16 Error in expression <enableAttack false;
systemChat str _sup = allUnits selectRandom {side _x == east>
10:15:16   Error position: <= allUnits selectRandom {side _x == east>
10:15:16   Error Missing ;
10:15:16 File C:\Users\14064\Documents\Arma 3 - Other Profiles\CC%20Zeus\mpmissions\Droid%20Script%20Testing.VR\Droid.sqf..., line 37


 

Share this post


Link to post
Share on other sites

@BluBoi,

This topic reminds me of myself.

Here is your script running without errors,

Spoiler

missionNameSpace setVariable ["manage_npcs", true];
[] spawn {
	waitUntil {sleep 1;
		if !(missionNameSpace getVariable ["manage_npcs", false]) then {false} else {
systemChat "started";
			{
				_x setVariable ["HAF_spawned",true];
				_x setSkill ["courage", 1.0];
				_x enableAttack false;
				_x setCombatBehaviour "AWARE";

				private _target = _x findNearestEnemy (getPosATL _x);
systemChat str _target;
				if !isNull _target then {
					_x setBehaviour "CARELESS";
					_x suppressFor 10;
					_x doMove position _target; 
					_x spawn {sleep 10; _this setBehaviour "AWARE"};
				}
			} forEach (allUnits select { !(_x getVariable ["HAF_spawned", false]) && side _x == WEST});
			sleep 12;
			false
		}
	}
};

 

However there are still a number of problems (I don't think it does what you want it to do).

Like was said before,
1) system chat stuff to debug your script
2) read the wiki 10x for each command you use
3) make little experiments instead of full blown scripts (then compile successes together)

Have fun!

  • Like 3

Share this post


Link to post
Share on other sites
5 hours ago, BluBoi said:

 


10:15:16 Error in expression <enableAttack false;
systemChat str _sup = allUnits selectRandom {side _x == east>
10:15:16   Error position: <= allUnits selectRandom {side _x == east>
10:15:16   Error Missing ;
10:15:16 File C:\Users\14064\Documents\Arma 3 - Other Profiles\CC%20Zeus\mpmissions\Droid%20Script%20Testing.VR\Droid.sqf..., line 37
10:15:16 Error in expression <enableAttack false;
systemChat str _sup = allUnits selectRandom {side _x == east>
10:15:16   Error position: <= allUnits selectRandom {side _x == east>
10:15:16   Error Missing ;
10:15:16 File C:\Users\14064\Documents\Arma 3 - Other Profiles\CC%20Zeus\mpmissions\Droid%20Script%20Testing.VR\Droid.sqf..., line 37

 

 

Ok, one last shot. https://community.bistudio.com/wiki/selectRandom is how you use selectRandom, not the way you have here. So, like before, you have to check the commands to see how to use them. Otherwise you will keep making the same mistakes and keep getting nowhere:

 

_sup = selectRandom (allUnits select {side _x == EAST});

systemChat str _sup;

  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, beno_83au said:

 

Ok, one last shot. https://community.bistudio.com/wiki/selectRandom is how you use selectRandom, not the way you have here. So, like before, you have to check the commands to see how to use them. Otherwise you will keep making the same mistakes and keep getting nowhere:

 

_sup = selectRandom (allUnits select {side _x == EAST});

systemChat str _sup;

Apologies for not fixing everything at once, I'm just taking it error by error and looking for help when I get stuck. Any ideas on what commands I SHOULD use to get the position of a nearby enemy unit, and then make an ai move to and suppress that position?

Share this post


Link to post
Share on other sites

You can use targetsQuery command instead of findNearestEnemy. That will make sense for a random selection.

Then, the move is already written by @wogz187  At this level, all units are chasing the same enemy. You need to divide these enemies up.

  • Like 2

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×