Jump to content
Sign in to follow this  
Cyrano

Problem with forEach and join commands

Recommended Posts

Strange little problem outside of my limited Googling skills:

I have this code (below) running in a spawned stand-alone .sqf file. The idea is simple. I have 30 civilian AI scattered around Agia Marina. They are all in cmGroup. When one of them sees the player, that individual civilian should join the other (crGroup) group.

while {(count (units cmGroup)) > 0} do {

{

	if ((_x knowsAbout player) > 1) then {	


		[_x] joinSilent crGroup;
		hint str (count(units crGroup));


	};

} forEach (units cmGroup);

sleep 1;

};

What actually happens is when the player comes across the first civilian, every member of the first group joins the second group all at once.

I'm sure this could be done with triggers and/or in the editor, but since I am trying to make this scalable, and the idea of having dozens of triggers in the wild scares me a little, I tried it this way.

Any idea(s) as to why this causes all units to join instead of the one, or (even better / fingers crossed) code to fix this or do the same another way?

Thanks in advance.

Share this post


Link to post
Share on other sites

knows abou returns numbers 0 up to 4

I believe 1 means groupmember spotted you and 4 they have actual visual contact with you.

Have you tried greater numbers?

if ((_x knowsAbout player) >= 3.0) then {

Edited by Coding

Share this post


Link to post
Share on other sites

Coding, thank you for the reply.

I initially ran it as (> 2), but, as most units are inside buildings, it seems less of an issue of when they see the player and more about how the _x is processed somewhere along the way. The code seems to act as if the _x referenced in the join statement is the whole group, and not an individual member.

Share this post


Link to post
Share on other sites

"for" indicates a loop

"{}" indicates a codeblock

the codeblock is executed for each groupmember once

in the loop the current groupmember serviced (idk if that is the correct word) is referenced with the variable "_x"

so within ~1ms the variable _x had ~30 different values

try the inner loop with a sleep 0.25; and a hintSilent format["%1", _x knowsAbout player];

I really believe "knowsAbout" is the problem

Share this post


Link to post
Share on other sites

Coding,

I'll certainly give that a try first thing in the morning and report back. Thanks.

Share this post


Link to post
Share on other sites

The issue with knowsAbout is that its value is immediately propagated to every member within the group. I don't think there is anyway to turn that off.

The simplest workaround would be use a range check instead of the knowsAbout command. However, this may not be acceptable in your case.

If you want something closer to a visibility test, then the following example may be a starting point.

// fn_knowsAbout.sqf
// usage: [<unit>,<target>,(<range>,<fov>)] call FLAY_fnc_knowsAbout;
// returns true if <unit> can see <target> and <target> is less than <range> meters from <unit>, otherwise returns false.

private ["_unit", "_target", "_range", "_fov", "_inView", "_inSight", "_inRange", "_knowsAbout"];

_unit = [_this,0] call BIS_fnc_param; 
_target = [_this,1] call BIS_fnc_param; 
_range = [_this,2,100,[0]] call BIS_fnc_param; 
_fov = [_this,3,130,[0]] call BIS_fnc_param; 

_knowsAbout = false;
_inRange = (_unit distance _target) < _range; 
if (_inRange) then {
   _inView = [position _unit, getdir _unit, _fov, position _target] call BIS_fnc_inAngleSector; 
   _inSight = count (lineIntersectsWith [eyePos _unit, eyepos _target, _unit, _target]) == 0; 
   _knowsAbout = _inView && _inSight;
};
_knowsAbout;

The code does a very simple visibility test by checking if there's clear path from unit to target in the direction the unit is facing.

E.g. in your case you would, it would be used something like this:

FLAY_fnc_knowsAbout = compile preprocessFile "fn_knowsabout.sqf";
while {(count (units cmGroup)) > 0} do { 
   { 
       _detected = [_x, player] call FLAY_fnc_knowsAbout;
       if (_detected) then {
           [_x] joinSilent crGroup; 
           hint str (count(units crGroup));  
       }; 
   } forEach (units cmGroup); 
   sleep 1; 
};

Share this post


Link to post
Share on other sites

what about a combination of range and knowsAbout?

Does the knowsabout only propagate in a group or in the whole team?

Maybe create smaller groups...

Share this post


Link to post
Share on other sites

mrflay,

works as advertised. Thanks!

Coding,

I've thought about the smaller groups thing, but that would create a cascade effect of coding around this particular problem. If mrflay's code hadn't worked, I may have been forced to go there. But you were right about "knowsAbout" being the problem. Thanks for taking the time to try to help.

Share this post


Link to post
Share on other sites

You might also, alternatively, be able to remove the radio from the AI units, so they cannot communicate with each other. That might actually serve not to propagate knowsabout information.

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
Sign in to follow this  

×