Jump to content
Tankbuster

opposite of apply. how to remove array elements?

Recommended Posts

It's not a great topic title, so I'll press ahead and hopefully it will become clearer.

 

In lieu of the non existent nearestentities command, I'm using near entities and then sorting them. The sort biki page has a great working example, posted below.

_buildings = player nearObjects ["Land_Cargo_Patrol_V1_F", 500];
_buildings = _buildings apply { [_x distance player, _x] };
_buildings sort false;
hint format [
	"Most distant building is at %1, distance %2 m", 
	getPos (_buildings select 0 select 1),
	round (_buildings select 0 select 0)
];

This is nice and importantly, it's quick and cheap on the CPU, provided you don't go mental with the radius, of course. :)

 

Anyhow, I'd like to write this up into a function that returns an array of objects, sorted nearest to furthest. But apply adds a distance so the above code will return something like

[[100, buildinga], [2.5, buildingq], [1, buildingr]]

the number being the distance. Given that the function will be provided an array of objects, that's what I like it to return is this;

[buildinga, buildingq, buildingr]

I've mashed it up using a foreach and pushback'ing only the first element of each one, but was wondering if there's a more efficient way?

 

Thanks in advance,

 

Tanky -Paul-

Share this post


Link to post
Share on other sites
fnc_nearestEntities = {
      params ["_pos","_rad","_type"];
      _entities = _pos nearEntities [_type,_rad];
      _entities = _entities apply {[(_x distance _pos), _x]};
      _entities sort true;
      _entities apply {_x select 1};
};

maybe that?  I don't know if that works, but I don't think you even need to do this.  If you just want a list of objects by type, within a radius, sorted by distance but don't need the actual distance of each object, then use "nearestObjects." 

 

 

_sortedListOfMenAndTanks = nearestObjects [_pos, ["Man","Tank"], _rad];

Share this post


Link to post
Share on other sites

I think you meant

fnc_nearestEntities = {
      params ["_pos","_rad","_type"];
      _entities = _pos nearEntities [_type,_rad];
      _entities = _entities apply {[(_x distance _pos), _x]};
      _entities sort true;
      _entities = _entities apply {_x select 1};
};

which works! Really cool. I did wonder if the apply command could work it's magic in the opposite way. Thank you so much. :)

Share this post


Link to post
Share on other sites

I think you meant

fnc_nearestEntities = {
      params ["_pos","_rad","_type"];
      _entities = _pos nearEntities [_type,_rad];
      _entities = _entities apply {[(_x distance _pos), _x]};
      _entities sort true;
      _entities = _entities apply {_x select 1};
};

which works! Really cool. I did wonder if the apply command could work it's magic in the opposite way. Thank you so much. :)

 

 

 

leaving out "_entities =" on the last line should cause the function to return the list of entities rather than store it in the local variable "_entities".  Otherwise, calling the function stores the sorted list of entities in the local variable "_entities", returns nothing, and then the function scope is exited so _entities is lost.

fnc_nearestEntities = {
      params ["_pos","_rad","_type"];
      _entities = _pos nearEntities [_type,_rad];
      _entities = _entities apply {[(_x distance _pos), _x]};
      _entities sort true;
      _entities apply {_x select 1}
};

//now you can use this anywhere in your script
_someDudes = [player, 150, "Man"] call fnc_nearestEntities;
_someCars = [(_someDudes select ((_size _someDudes) - 1)), 200, "Car"] call fnc_nearestEntities;

//_someDudes is now a list of living men within 150m of the player, sorted from nearest to furthest.
//_someCars is now a list of non-destroyed cars within 200m of the most distant man in the _someDudes array, sorted from nearest to the man to furthest from the man.

But why cant you just use nearestObjects?  It basically does the same thing, unless you are trying to only get a list of living objects.  

Share this post


Link to post
Share on other sites

Ah yes... the last line will make it return that to the caller. I see now. :)

 

I haven't compiled it up into a function yet, am just fiddling with it to see if there's any other features I can put in it.

 

I can use nearestobjects, but sometimes I need a big radius, and its expensive on the cpu and stutters the server when you ask it for them. Nearentities is much cheaper.

Share this post


Link to post
Share on other sites

Those are both useful, but they only remove array elements. They'd still leave the array within the array, though, so they aren't ideal why particular application. They great thing about apply select 1 in this function is that it returns the array in exactly the same state it receives it, execpt that it's sorted.

 

BTW, I've done some fnc_code_performance tests. Using nearentities and then sorting is a LOT faster than using nearestobjects. And the performance differential gets more pronounced as the radius increases. As ever, the trick(s) is to keep the radius as tight as possible and to filter the object types you're looking for.

Share this post


Link to post
Share on other sites

Depending on how often you need to know the nearest buildings of a certain type,

it's best to run a function once on mission start to grab all the buildings needed and save the info in a global variable.

 

Shouldn't take too long in the init.sqf or even during preInit.

 

You can take it a step further and save all positions of wanted buildings in a sqf file as an array,

if you need to access the building later during the mission simply filter the position array as you like and use nearestbuilding _position.

 

Cheers

Share this post


Link to post
Share on other sites

I used buildings in the example because that's what's used in the biki page example.

 

I do actually do some building finding in the mission and it's done initserver. The application I'm using this for is actually looking for LandVehicle, so it has to be done as required.

Share this post


Link to post
Share on other sites

Remember to always use distanceSqr if you're just comparing/sorting distances. That's quite a bit faster.

  • Like 2

Share this post


Link to post
Share on other sites

Remember to always use distanceSqr if you're just comparing/sorting distances. That's quite a bit faster.

 

distanceSqr is also quite useful in any script where you need to continually check if the distance between two points is less than or greater than a hard value.  Whatever your value is that you are using, simply square it ONCE and then compare the new value to distanceSqr in your loop.  

_maxDist = ((paramsArray select 4) ^ 2);  //using a value from mission parameters, for example viewdistance or something
waitUntil {
  if ((_obj1 distanceSqr _obj2) <= _maxDist) then {
    //do stuff
  };
  false
};
  • Like 1

Share this post


Link to post
Share on other sites

Why not using bis_fnc_sortBy instead of apply? Unless you absolutely need to return the distance?

Because, I'm embarrassed to admit, I didn't read about it when I saw it in the functions page. I think I saw a the command and the function and decided to use the command. As you say, the function has much more functionality and suits my needs much better. Thank you! 

  • Like 1

Share this post


Link to post
Share on other sites

HI guys I am totally NOOB to scripting, and im not doing very well, i have my missions setup spawning in no problems bar 2 how to make the mission give a bonus to the player or players in group or area who completed it like an eventhandler  and second how do i use one script to clear missions from my server once they are completed so they can re start ....while i was searching the internet i came accros "nearentities" which brought me here any help would be greatly appreciated

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

×