Jump to content

Recommended Posts

Is there any more elegant way of either getting a list of units that know about player/unit or just a bool if a side knows about a player/unit than checking knowsAbout with forEach allUnits?

I'm currently using side knowsAbout player but it stays at 4 for some time even after the group that spotted the player dies. I'm thinking of using something like this

_alertedUnits = [];
{if (alive _x && _x knowsAbout player == 4 && _x getHideFrom player distance player < 50 && side _x == independent) then {_alertedUnits pushback _x}} forEach allUnits;

and have it a while loop with some delay in a repeatable trigger activated by independent knowsAbout player == 4 but it seems like a horrible solution since I have a lot of active units at once. Is there some event handler or BIS function that solves this? Or will the performance impact be ok?

Share this post


Link to post
Share on other sites

it is the correct behavior that enemy side knows bout u some time after u killed the spotter... the reason is that the enemy already knows where u r. so i dont get ur problem with that.

Share this post


Link to post
Share on other sites

it is the correct behavior that enemy side knows bout u some time after u killed the spotter... the reason is that the enemy already knows where u r. so i dont get ur problem with that.

That's only the secondary problem. The question really was if there is a better way of getting enemies that know about you other than looping through all of them.

Share this post


Link to post
Share on other sites

its all in the knowsAbout wiki entry:

Description:

Checks if a group or a side knows about target. If who is a unit, unit's group is considered, if who is a vehicle, commander's group is considered.

that means something like this is enough to check if side independent knows u:

if (independent knowsAbout player) then ...

Share this post


Link to post
Share on other sites

its all in the knowsAbout wiki entry:

Description:

Checks if a group or a side knows about target. If who is a unit, unit's group is considered, if who is a vehicle, commander's group is considered.

that means something like this is enough to check if side independent knows u:

if (independent knowsAbout player) then ...

That's already included in my first post (and the second one, too).

 

Anyway, thanks for all the answers, it seems there's no better way than checking all units (or groups at least).

Share this post


Link to post
Share on other sites

u could loop through all units of one side:

_allOfEast =[];

{

{

_allOfEast pushBack _x;

} count (units _x);

}count (allGroups select {side _x == east});

after that u ve all east units in the array

but u can just use the inner loop to do ur wanted stuff because it iterates through all east units.

Share this post


Link to post
Share on other sites

u could loop through all units of one side:

*snip*

Yeah, I thought about that too but I'd have to include some check to add spawned and remove killed units/groups (probably with the killed EH) and the difference in performance wouldn't be all that great.

Share this post


Link to post
Share on other sites

What exactly stops you from hopping into single player editor,

placing 100 rifle squads and then hit the code performance button in the debug window?

Also why killed eventhandler and adding spawned units? allUnits includes all living units, no matter if spawned or editor placed. Dead units aren't even in there.

 

Done with 800 opfor units in 100 groups:

{_x knowsabout player > 0} count allunits //1.40845 ms
{_x knowsabout player > 0} count allgroups //0.162866 ms

Performance increase is pretty significant I'd say.

 

Cheers

Share this post


Link to post
Share on other sites

to precise grumpys post...

u only need to iterate through all east groups as I did in the example before and use knowsAbout with each of those groups and if a group knows about player then u can do ur wanted stuff with each unit of that group. this is much better than iterating through all units...

edit:

or use select for smart filtering

{

{

//do ur stuff here because it will be done for east units which knows about player only

} count (units _x);

}count (allGroups select {side _x == east && (_x knowsAbout player == 4)});

Edited by sarogahtyp

Share this post


Link to post
Share on other sites

The "detected by side" triggers are nice, easy and rather quick but it depends on what you want to do there.

 

Do you really need a list of units or do you just want to check for detection?

Share this post


Link to post
Share on other sites

I too thought of that answer. However he wants a lust of every unit who has detected him.

.

Share this post


Link to post
Share on other sites

Well, if he really needs a list, then looping through the units is the only way.

 

The loop can be made a bit more efficient though:

_alertedUnits = [];
{
	if (side _x isEqualTo independent) then {
		if (_x knowsAbout player == 4) then {
			if (((_x getHideFrom player) distanceSqr player) < 2500) then {
				_alertedUnits pushback _x;
			};
		};
	};
} forEach allUnits;

Share this post


Link to post
Share on other sites

Well, if he really needs a list, then looping through the units is the only way. The loop can be made a bit more efficient though:

_alertedUnits = [];
{
	if (side _x isEqualTo independent) then {
		if (_x knowsAbout player == 4) then {
			if (((_x getHideFrom player) distanceSqr player) < 2500) then {
				_alertedUnits pushback _x;
			};
		};
	};
} forEach allUnits;

its d3finetly not neccessary to loop through all units! knows about used with a unit checks the units group. therefore its enough to loop through all groups.

i recommend to use a smart filte4 with select command as i mentioned above already.

 

Edit (booted desktop pc up now because mobiles r a pain :) :

_alertedUnits = [];
{
 {
  _alertedUnits pushback _x;
 } count ((units _x) select {((_x getHideFrom player) distanceSqr player) < 2500});
} count ((allGroups select {side _x isEqualTo independent}) select {(_x knowsAbout player == 4)});

what is that doing?

1. select all independent groups from allGroups

2. select all groups which knows about player and then loop through them with count

3. select all units from that group which fullfill ur desired range condition and loop through those units

4. pushback that wanted units to the array.

 

Thats the fastest way I can think off...

Edited by sarogahtyp

Share this post


Link to post
Share on other sites

@sarogahtyp: What's up with your keyboard? :yay:

 

There is absolutely no need to iterate through allUnits,

since knowsAbout is shared within a group.

Once one unit knowsAbout someone, the entire group knowsAbout the same unit to the same value almost instantly (probably on the same frame),

the units side will get the knowsAbout increased shortly thereafter, like 1-2 seconds.

Test:

    addMissionEventHandler ["Draw3D", {
{

_drawicon = "";
_drawicon = gettext (configFile/"CfgVehicles"/typeOf  _x/"Icon");
_color = [1,1,1,1];
drawIcon3D [
_drawicon,
_color,
[(visiblePosition _x) select 0,(visiblePosition _x) select 1,3],
1,
1,
0,
format ["unit:%1 group:%2 side:%3",_x knowsAbout player,group _x knowsabout player,side _x knowsabout player],
1,
0.03,
"PuristaLight"

];} foreach (allunits) }];

 

Now the interesting: If a side knowsAbout a unit there can still be groups and units from the side that have a knowsAbout of 0, whatever purpose that may serve.

 

Just a waste of CPU cycles, go for the allGroups solution and pushback the groups units instead.

_groupsKnowAboutMe = allGroups select {side _x isEqualTo west AND _x knowsAbout player isEqualTo 4};
_unitsKnowAboutMe = [];
_groupsKnowAboutMe apply {_unitsKnowAboutMe pushBack units _x};

0.21363 ms for 100 groups, 800 units. Seems okay for a one time check, even for onEachFrame considering at 60 fps one frame takes 16something ms.

 

Cheers

Share this post


Link to post
Share on other sites

@sarogahtyp: What's up with your keyboard? :yay:

 

I was on mobile...

could u speed test my solution against urs pls? I wont start arma at my slow machine now... its a pain

Share this post


Link to post
Share on other sites

Sure, filtering is better but I'd still stack the condition in seperate if-blocks instead of using &&

 

I know that knowsAbout is equal for all groupmembers but I'm not sure if that also applies to getHideFrom. So groups may or may not work for that. Have you tried that?

_alertedUnits = allGroups select {
	if (side _x isEqualTo independent) then {
		if (_x knowsAbout player == 4) then {
			if (((leader _x getHideFrom player) distanceSqr player) < 2500) then {
				true
			};
		};
	};
};

Share this post


Link to post
Share on other sites

 

Sure, filtering is better but I'd still stack the condition in seperate if-blocks instead of using &&

 

I know that knowsAbout is equal for all groupmembers but I'm not sure if that also applies to getHideFrom. So groups may or may not work for that. Have you tried that?

_alertedUnits = allGroups select {
	if (side _x isEqualTo independent) then {
		if (_x knowsAbout player == 4) then {
			if (((leader _x getHideFrom player) distanceSqr player) < 2500) then {
				true
			};
		};
	};
};

look at my last edit in this post. everything solved there with chained filtering...

Share this post


Link to post
Share on other sites

Yup, saw it.

Are multiple selects faster than one select with stacked ifs ?

Share this post


Link to post
Share on other sites

Yup, saw it.

Are multiple selects faster than one select with stacked ifs ?

idk and it makes no sense to test that with my maching. its to slow to get valuable results...

Share this post


Link to post
Share on other sites

idk and it makes no sense to test that with my maching. its to slow to get valuable results...

No problem as long as you compare it to other results done on the same machine.

 

Cheers

Share this post


Link to post
Share on other sites

No problem as long as you compare it to other results done on the same machine.

 

Cheers

its a problem. I tried that several times u get strange results. sometimes solution A is faster than B and sometimes its vice versa. I think it depends on the current system load influenced by background processes of windows...

Share this post


Link to post
Share on other sites

That's clear but not a problem, since you don't want to test code performance on a system that's nearly bursting up in flames.

Last time I had windows affect my systems performance was back with win98 I think.

 

Cheers

Share this post


Link to post
Share on other sites

you don't want to test code performance on a system that's nearly bursting up in flames

you got it :D thats the reason why I dont want test code performance on my system

Share this post


Link to post
Share on other sites

its d3finetly not neccessary to loop through all units! knows about used with a unit checks the units group. therefore its enough to loop through all groups.

i recommend to use a smart filte4 with select command as i mentioned above already.

 

Edit (booted desktop pc up now because mobiles r a pain :) :

_alertedUnits = [];
{
 {
  _alertedUnits pushback _x;
 } count ((units _x) select {((_x getHideFrom player) distanceSqr player) < 2500});
} count ((allGroups select {side _x isEqualTo independent}) select {(_x knowsAbout player == 4)});

what is that doing?

1. select all independent groups from allGroups

2. select all groups which knows about player and then loop through them with count

3. select all units from that group which fullfill ur desired range condition and loop through those units

4. pushback that wanted units to the array.

 

Thats the fastest way I can think off...

This took 0.264131 ms, tested for east side (800 units, 100 groups).

 

Modified it into this:

_alertedUnits = [];
_side = east;
_unit = player;
_distSqr = 2500;
_knowValue = 4;

{

    {

        _alertedUnits pushback _x;

    } count ((units _x) select {((_x getHideFrom _unit) distanceSqr _unit) < _distSqr});

} count ((allGroups select {side _x isEqualTo _side}) select {(_x knowsAbout _unit isEqualTo _knowValue)});

For 800 units in 100 groups: 0.227946 ms. -- fastest of all three

For 80 units in 10 groups: 0.0281 ms. -- fastest of all three

 

 

 

Sure, filtering is better but I'd still stack the condition in seperate if-blocks instead of using &&

 

I know that knowsAbout is equal for all groupmembers but I'm not sure if that also applies to getHideFrom. So groups may or may not work for that. Have you tried that?

_alertedUnits = allGroups select {
	if (side _x isEqualTo independent) then {
		if (_x knowsAbout player == 4) then {
			if (((leader _x getHideFrom player) distanceSqr player) < 2500) then {
				true
			};
		};
	};
};

0.282885 ms tested for east (800 units, 100 groups).

 

Modified it into this:

_alertedUnits = [];
_side = east;
_unit = player;
_distSqr = 2500;
_knowValue = 4;
_alertedUnits = allGroups select {
    if (side _x isEqualTo _side) then {
        if (_x knowsAbout _unit == _knowValue) then {
            if (((leader _x getHideFrom _unit) distanceSqr _unit) < _distSqr) then {
                true
            };
        };
    };
};

For 800 units in 100 groups: 0.248818 ms. -- second fastest of all three

For 80 units in 10 groups: 0.032 ms. -- last place

 

My modified solution:

_alertedUnits = [];
_side = east;
_unit = player;
_distSqr = 2500;
_knowValue = 4;
_groupsKnowAboutMe = allGroups select {side _x isEqualTo _side AND {_x knowsAbout _unit isEqualTo _knowValue} AND {((leader _x getHideFrom _unit) distanceSqr _unit < _distSqr)}};
_alertedUnits = [];
_groupsKnowAboutMe apply {_alertedUnits pushBack units _x};

For 800 units in 100 groups: 0.253229 ms. -- last place

For 80 units in 10 groups: 0.0306 ms. -- second fastest for all three

 

Each test took the average of 10000 iterations, using BIS_fnc_codePerformance.

 

The performance difference between the solutions seem to be within 16% of each other, ranging between 0.22ms and 0.25ms for huge unit sizes,

for small and more realistic scenarios the modified solution from sarogahtyp seems to pull away, being 6% (0.002ms) faster than my solution.

 

Cheers

  • Like 5

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

×