Jump to content
wildbill2016

Simple question....Have a generic error in ForEach loop

Recommended Posts

So in the initialization script I defined a unit group like this

townenemy = ["wp1_enemy1","wp1_enemy2","wp1_enemy3","wp1_enemy4","wp1_enemy5","wp1_enemy6"];

and I want to use a trigger to disable their AI, when the player lefts the trigger.

so I use the for each loop and the magic variable. But it always pops up a generic error..

{ _x disableAI "TARGET"; } forEach _townenemy;
{ _x disableAI "TARGET"; } forEach townenemy;
{ _x disableAI "TARGET"; } forEach units townenemy;
{ _x disableAI "TARGET"; } forEach units _townenemy;

None of the above works..

Is that I missed something?

  • Like 1

Share this post


Link to post
Share on other sites

If in doubt, check the wiki.

 

disableAI requires object as first and string as second parameter.

You're passing a string as a first parameter, hence it doesn't work.

 

I guess wp1_enemy1 etc. are the variable names of editor placed units?

Just remove the quotation marks inside townenemy array then.

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

In addition, your second code is the correct one:

{ _x disableAI "TARGET"; } forEach townenemy;

You wouldn't use _townenemy because that's a local variable that you have not defined. Also, units returns the members of a group, and so would only work if townenemy was defined as such.

 

https://community.bistudio.com/wiki/Variables

https://community.bistudio.com/wiki/units

  • Like 2

Share this post


Link to post
Share on other sites
Quote

So in the initialization script I defined a unit group like this

 

 

I guess wp1_enemy1 etc. are group names?

 

so if townenemy is an array of group names and not unit names it would need to look like this

as you will need to loop through all the units in each group as DisableAI only works with objects not groups

 

Syntax: unitName disableAI section

Parameters: unitName: Object - AI unit

 

Just remove the quotation marks inside townenemy array then loop through each unit in each group.

 

you could do something like this

 

townenemy = [wp1_enemy1,wp1_enemy2,wp1_enemy3,wp1_enemy4,wp1_enemy5,wp1_enemy6];

 

{ _x disableAI "TARGET"; } forEach units _x  } forEach townenemy;  

// it will run the red code for all units in selected group (_x)  before continuing on to the next loop in townenemy

//(yes i know there are 2 _Xs that is because each _x is only local to whats between {}  )

 

or

 

for "_i" from 0 to ((count townenemy) - 1) do

{

{ _x disableAI "TARGET"; } forEach units (townenemy select _i);

};

 

or 

 

townenemy_units =  [];  // create an empty array

{townenemy_units pushBack units _x } forEach townenemy; // add all the units from groups into one array

{ _x disableAI "TARGET"; } forEach townenemy_units;  // run code on each unit 

 

 

 

Hope this helps

  • Like 1

Share this post


Link to post
Share on other sites
6 minutes ago, zonekiller said:

I guess wp1_enemy1 etc. are group names?

 

I read it as he was trying to create a group by placing units (wp1_enemy#) into an array (townenemy) , which of course will not work, but which was irrelevant to his process further down the line. I hadn't considered the possibility of the scenario you describe - lots of useful info in your post!

Share this post


Link to post
Share on other sites

 

Quote

I read it as he was trying to create a group by placing units (wp1_enemy#) into an array (townenemy) 

 

that could be that case also

then it would be

 

townenemy = [wp1_enemy1,wp1_enemy2,wp1_enemy3,wp1_enemy4,wp1_enemy5,wp1_enemy6];

 { _x disableAI "TARGET"; } forEach townenemy;

 

Share this post


Link to post
Share on other sites
On 2018/4/22 at 10:53 PM, Grumpy Old Man said:

If in doubt, check the wiki.

 

disableAI requires object as first and string as second parameter.

You're passing a string as a first parameter, hence it doesn't work.

 

I guess wp1_enemy1 etc. are the variable names of editor placed units?

Just remove the quotation marks inside townenemy array then.

 

Cheers

 

On 2018/4/22 at 11:01 PM, Harzach said:

In addition, your second code is the correct one:


{ _x disableAI "TARGET"; } forEach townenemy;

You wouldn't use _townenemy because that's a local variable that you have not defined. Also, units returns the members of a group, and so would only work if townenemy was defined as such.

 

https://community.bistudio.com/wiki/Variables

https://community.bistudio.com/wiki/units

 

On 2018/4/23 at 5:10 PM, zonekiller said:

 

 

I guess wp1_enemy1 etc. are group names?

 

so if townenemy is an array of group names and not unit names it would need to look like this

as you will need to loop through all the units in each group as DisableAI only works with objects not groups

 

Syntax: unitName disableAI section

Parameters: unitName: Object - AI unit

 

Just remove the quotation marks inside townenemy array then loop through each unit in each group.

 

you could do something like this

 

townenemy = [wp1_enemy1,wp1_enemy2,wp1_enemy3,wp1_enemy4,wp1_enemy5,wp1_enemy6];

 

{ _x disableAI "TARGET"; } forEach units _x  } forEach townenemy;  

// it will run the red code for all units in selected group (_x)  before continuing on to the next loop in townenemy

//(yes i know there are 2 _Xs that is because each _x is only local to whats between {}  )

 

or

 

for "_i" from 0 to ((count townenemy) - 1) do

{

{ _x disableAI "TARGET"; } forEach units (townenemy select _i);

};

 

or 

 

townenemy_units =  [];  // create an empty array

{townenemy_units pushBack units _x } forEach townenemy; // add all the units from groups into one array

{ _x disableAI "TARGET"; } forEach townenemy_units;  // run code on each unit 

 

 

 

Hope this helps

 

Hi guys, thanks again (And thanks for the additional info about the loop nesting).

It's the double quotation marks....

And I define the group of townunits in another .sqf file.

Maybe global variables should be defined in certain script like init.?

When I define the array of units in another custom script and tried to access the array from another script, there is an undefined variable error.

It is removed after I copy and paste the array definition to the disable AI execution script..

 

 

Share this post


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

When I define the array of units in another custom script and tried to access the array from another script, there is an undefined variable error.

It is removed after I copy and paste the array definition to the disable AI execution script..

 

 

Most likely, the variable is being defined after is is being called. Sometimes it's tricky to get things initialized at the right time, but this might help:

 

https://community.bistudio.com/wiki/Initialization_Order

Share this post


Link to post
Share on other sites

A simple way to explain it is 

 

_townenemy  would only be local to a script or within {some code};

townenemy is local to every script and can be changed by other scripts

 

 

_townenemy = [wp1_enemy1,wp1_enemy2,wp1_enemy3,wp1_enemy4,wp1_enemy5,wp1_enemy6];

{ _x disableAI "TARGET"; } forEach _townenemy;  // would be local to the script that it is run on and cant be changed by other scripts

 

also what you would have to be careful if your units die and are not respawned

so if  wp1_enemy1 died then that variable no longer exists and will give an error when referenced 

 

one way to get around this would be 

 

townenemy = ["wp1_enemy1","wp1_enemy2","wp1_enemy3","wp1_enemy4","wp1_enemy5","wp1_enemy6"]; // global string array can be read from all scripts if added to an init.sqf script

 

in the script you wish to change the target setting

 

_townenemy =  [];  // create an empty array

{if !(isnil {call compile _x}) then {_townenemy pushBack _x }} forEach townenemy; // add all the alive units into a local array from the global array

{ _x disableAI "TARGET"; } forEach _townenemy;  // would be local to the script that it is run on and cant be changed by other scripts

 

 

 

//(call compile _x) converts a string back to an object,  ie    _object = call compile _string;

// if !(isnil {call compile _x}) // checks if it is a variable that exists

 

 

Share this post


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

{if !(isnil {call compile _x}) then {_townenemy pushBack _x }} forEach townenemy; // add all the alive units into a local array from the global array

 

You're using 4 commands (isNil, call, compile, pushBack) in an if then statement inside a forEach loop, not the most practical way and takes quite some time to run.

Assuming only the last one is alive the above can be condensed as follows:

//original example:
//init array once before performance test
townenemy = ["wp1_enemy1","wp1_enemy2","wp1_enemy3","wp1_enemy4","wp1_enemy5","wp1_enemy6"];

//performance test
{if !(isnil {call compile _x}) then {_townenemy pushBack _x }} forEach townenemy;//runs for 0.0137ms, if only wp1_enemy6 exists in mission

//improved example:
//init array once before performance test
townenemy = [wp1_enemy1,wp1_enemy2,wp1_enemy3,wp1_enemy4,wp1_enemy5,wp1_enemy6];//use objects instead of strings

//performance test
_townenemy = townenemy select {alive _x};//runs for 0.004ms, if only wp1_enemy6 exists in mission

You can use "alive" to check if something exists, it will return nothing if not alive or non existant and the select command acts accordingly.

Improved example takes only 0.004ms, instead of 0.0137, which is a third of the runtime.

 

Cheers

  • Like 1

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

×