Jump to content
Haymaker

selectBestPlaces to only return places on land?

Recommended Posts

Looking for the best way to get selectBestPlaces to return a value that is only on land, to avoid my script from spawning units underwater, if possible without having to create another loop.

 

Thanks for the help!

 

-Haymaker

Share this post


Link to post
Share on other sites

After selectBestPlaces returns an array, you can use surfaceIsWater to test each position, and skip those positions where surfaceIsWater is true.

Share this post


Link to post
Share on other sites

Yup, as @johnnyboy said. You can use forEach to do that as well.

_positions = [];
{
	if (!surfaceIsWater _x) then
	{
		_positions pushBack _x;
	};
} forEach (selectBestPlaces [position player, 50, "meadow + 2*hills", 1, 5]); // default example from Wiki

EDIT: Ah, you will need to use select or add params in there as well. select 0? It is late (02:50 am) and I'm tired, time for sleep. Will reply tomorrow.

  • Like 1

Share this post


Link to post
Share on other sites
11 hours ago, Grumpy Old Man said:

Or simply try...

 

In my experience you always want to double-check and filter results returned by selectBestPlaces, a surfaceIsWater test in particular. Even if you penalize "sea" as you suggest (or even heavier), you still might end up with a rather wet position on a funny dice roll... (at least in A3 we don't have to check for ponds any longer... :dozingoff:).

And once you start filtering with more and more restrictions (e.g. min. distance to a location, or a road, or what not), you probably also want to have a retry-loop (with weaker and weaker restrictions) or some other kind of failsafe.

Anyways... always cook up a tiny test-mission only for such commands, and see how they work in action (onMapSingleClick comes in handy here). Problems should become obvious pretty quickly. Depending on the map, tiny islands, or just badly connected landmasses could also pose a problem for your idea.

  • Like 1

Share this post


Link to post
Share on other sites
21 hours ago, rübe said:

 

In my experience you always want to double-check and filter results returned by selectBestPlaces, a surfaceIsWater test in particular. Even if you penalize "sea" as you suggest (or even heavier), you still might end up with a rather wet position on a funny dice roll... (at least in A3 we don't have to check for ponds any longer... :dozingoff:).

And once you start filtering with more and more restrictions (e.g. min. distance to a location, or a road, or what not), you probably also want to have a retry-loop (with weaker and weaker restrictions) or some other kind of failsafe.

Anyways... always cook up a tiny test-mission only for such commands, and see how they work in action (onMapSingleClick comes in handy here). Problems should become obvious pretty quickly. Depending on the map, tiny islands, or just badly connected landmasses could also pose a problem for your idea.

Since the thread author didn't want another loop that's the best bet.

Out of 10000 runs returning 500000 positions in total, only ~8 of them were on water.

That's a 0.0016% chance.

Was standing on a 20m island surrounded by water in tanoa @ [4600.07,7483.92,0.00141668].

Following snippet was used:

_onWaterTotal = 0;
_totalPositions = 0;
_runs = 10000;
for "_i" from 0 to _runs do {

_positions = selectBestPlaces [position player, 2500, "meadow + 2*hills", 50, 50] apply {_x select 0};
_positionsOnWater = {surfaceIsWater _x} count _positions;
_totalPositions = _totalPositions + count _positions;
_onWaterTotal = _onWaterTotal + _positionsOnWater;

};

systemchat format ["%1 runs, %2 positions on water out of total %3 positions",_runs,_onWaterTotal,_totalPositions];

 

So a safe bet while staying clear of loops would be:

_positions = (selectBestPlaces [position player, 2500, "meadow + 2*hills", 50, 50] apply {_x select 0}) select {!surfaceIsWater _x};

Cheers

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites
7 minutes ago, Grumpy Old Man said:

That's a 0.0016% chance.

 

hehe, nice. As said, always do a little experiment if you're about to use these commands (in particular with some fancy requirements (or just a gradient/isFlatEmpty check. gradients are the worst), or just a different map; e.g. messing around with some "forest" expression on Altis vs. Tanoa will yield quite different results for obvious reasons).

But you clearly got this. :rthumb:

  • Like 1

Share this post


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

"sea" expression doesn't work? (not tested).

It does.

It's just extremely dependent on where you use the command and which map it is, since meadows and hills near sea tend to be rare on tanoa, might get different results on altis as @rübe stated.

On top of that it rarely returns the same positions even when called 2 times using the exact same input parameters.

Been using selectBestPlaces for quite some time now and it has never failed me, heh.

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites
8 minutes ago, Grumpy Old Man said:

Been using selectBestPlaces for quite some time now and it has never failed me, heh.

Other than looking for a helicopter landing spot, what are some mission use cases for using selectBestPlaces ? 

Share this post


Link to post
Share on other sites
Just now, johnnyboy said:

Other than looking for a helicopter landing spot, what are some mission use cases for using selectBestPlaces ? 

Randomization in general.

You can use it to spawn small outposts to capture, get a specific location somewhere on the map to hide a suitcase for the players to retrieve, that kinda stuff.

You can set the precision value to 50+ without having much influence on the results as far as I've seen, helps speeding up the command so you can reliably use it during mission runtime. Precision 1 tends to be CPU heavy when used in a radius of 100m+.

 

Cheers

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
14 minutes ago, johnnyboy said:

what are some mission use cases for using selectBestPlaces ?

 

To give an example I'm currently working on:

  1. find forest position (selectBestPlaces with "(10*forest) + (5*trees) - (50*houses) - (100*meadow) - (999*sea)", requiring a min. score of 9.0)
  2. make sure the forest is of a certain min. size/area (since the player will have to search for this thing)
  3. find (multiple nearby) flat spot(s) inside that forest area (isFlatEmpty not regarding any objects on the map)
  4. delete all existing objects at these positions and spawn my own stuff, e.g. a camp, a hidden research facility, or what not

This also incorporates min. distance checks to locations and roads, and so I can only conditionally agree with Grumps:

 

32 minutes ago, Grumpy Old Man said:

On top of that it rarely returns the same positions even when called 2 times using the exact same input parameters.

 

...since, all too often I run into the problem of having such strong requirements (with all the filters and checks), that I end up with only a few and always the same positions in certain areas... and then it's a battle of weakening my requirements (they exist for a reason...). Spawning a bit larger structures on Tanoa can be rather hard if you want them to be next to each other too, since it's all so terribly steep and cliffy (don't get me wrong; I love it!!). Well, at least if you want to spawn something deep in the forest, that is.  :don16:

 

But maybe the best example is the wildlife in Arma. All animals are spawned according to such selectBestPlaces expressions (note the available "rain", "windy", "deadBody", or "night" variables).

 

In conclusion the lesson to learn here is to keep it simple stupid, and don't try to be way too fucking clever, or you'll end up like me, fighting one stupid battle (no, not with guns :icon_cry:) after the other.:sigh:

Share this post


Link to post
Share on other sites
16 minutes ago, rübe said:

In conclusion the lesson to learn here is to keep it simple stupid, and don't try to be way too fucking clever, or you'll end up like me, fighting one stupid battle (no, not with guns :icon_cry:) after the other.:sigh:

Haha, that's my problem too.  I get an idea and won't let it go until it works, so it takes me freakin' forever to finish a mission.

 

Thanks for the informative post. 

 

Question:  For my JBOY Dog, I want to reduce his enemy detection range conditionally, when he is in dense forest or jungle (otherwise he senses an enemy so far away its useless to the player).  What's a good position test command to determine if the dog is in the jungle or trees (and hopefully not just on the edge of the forest, but in at least 10 meters or so)?

 

Sorry if this is thread hijacking, but it seems like a similar problem as to what is being discussed here.

  • Like 1

Share this post


Link to post
Share on other sites
3 minutes ago, johnnyboy said:

What's a good position test

 

You can do this with a single call to selectBestPlaces and a small radius (e.g. 6m). I often use the following script for such "point" evaluations of selectBestPlaces expressions (where I'm interested in the returned score, not so much about random places. In your case just use the expression "forest" and demand a score of at least 0.95 or something):

 

Spoiler

scriptName "RUBE3\functions\Environment\fn_getPosExpValue.sqf";
/*
   Author:
    rübe
    
   Description:
    evaluates a custom expression (see selectBestPlaces) at a given
    position and returns the value.
    
   Parameter(s):
    _this select 0: position (position)
    _this select 1: expression (string)
                    - keywords (maybe not complete, but known to be working):
                      [
                         forest, trees, meadow, hills, houses, sea,
						 waterDepth, camDepth,
                         night, rain, windy, deadBody
                      ]
					- operators:
						randomGen N				(float from 0 to N) 
						factor[p,q]				(V-p/q-p)
						interpolate[p,q,r,s]	(V-p/q-p)*(s-r) + r
    _this select 2: sample radius (scalar)
                    - optional, default = 6
    _this select 3: sample precision (scalar)
                    - optional, default = 3
    
   Returns:
    scalar
*/

private ["_sample", "_radius", "_precision"];

_radius = 6;
if ((count _this) > 2) then
{
   _radius = _this select 2;
};

_precision = 3;
if ((count _this) > 3) then
{
   _precision = _this select 2;
};

_sample = selectBestPlaces[
   (_this select 0),
   _radius,
   (_this select 1),
   _precision,
   1
];

if ((count _sample) < 1) exitWith
{
   -1
};

// return value
((_sample select 0) select 1)

 

 

3 minutes ago, johnnyboy said:

not just on the edge of the forest, but in at leat 10 meters or so

 

You can take e.g 3-4 more samples/probes around the actual position (and at a certain distance) and require them also to be considered inside the forest. Shouldn't cost too much as long as you maybe don't run the check every frame. You could spread out the individual samples/probes over some frames too (with a sleep inbetween each call), if you're concerned about performance. I take it the dog doesn't move *that* fast.

 

  • Like 1

Share this post


Link to post
Share on other sites

For finding say a helicopter land pos (safe) - Just wondering as I don't recall ever using selectBestPlaces command before: What are the benefits of using this instead of isFlatEmpty (command) / findSafePos (function)? (or vice versa)

Share this post


Link to post
Share on other sites
1 hour ago, HazJ said:

instead of isFlatEmpty

 

No, not instead of. But you can easily combined them to find a nice landing position: 1) find meadow with selectBestPlaces, then 2) make sure to get a flat and empty spot there. You could also favor positions with meadows and houses in step one, to make sure there's some hard cover around... or if you prefer hills. :don16:

  • Thanks 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

×