Jump to content
randy andy tw1

Detect if SEA is within an area

Recommended Posts

hello

 

I have been using the BIS function BIS_fnc_findSafePos to locate a random point from a position, which is great as it finds me a position within the search area specified, that is not in water

 

however, I am using it to find a position to move an area marker down which is 300 x 300. the area of this marker will, at some point overlap some areas of the coast/sea.  

 

_positions = [selection1, A, B, 0, 0, 0, 0] call BIS_fnc_findSafePos;

I am trying to ensure that the marker area, will never be over the sea, as this will be used as a paradrop area. 

 

Any ideas?

Share this post


Link to post
Share on other sites

Yup. It is set to 0. The single point is indeed not in water

 

But when i move the marker to that point, the area of the marker can still be in water.

 

Is there a way to direct the area of the marker away from water? Ive thought about the black list option too but im struggling to find the right expression/commands to help with it.

Share this post


Link to post
Share on other sites

okay I ve an idea for this.

1. find the position as u did. lets call it dry_pos

2. now use dry_pos as origin to find another position (lets call it wet_pos) but this time with the condition that it has to be in the water. min distance should be a very small value and max distance should be the distance to the border of ur area marker.

if the function doesnt find a wet_pos then dry_pos is exactly what u r looking for.

if the function find such a wet_pos then there is water in the area and dry_pos is not ur desired position for the center of ur marker.

Share this post


Link to post
Share on other sites

actually... thats a great shout there. didnt think about flipping it. tunnel vision!

 

will post up if i get somewhere. thanks Sarogahtyp

Share this post


Link to post
Share on other sites

 

okay, i might be going about this the wrong way, but im struggling for an IF condition for a loop in a function

private ["_fncactive","_dps","_wps"];

_fncactive = 0;
zone = getpos player;
while {_fncactive < 1} do
{
	_dps = [position,750,750,0,0,0,0,[],[getPos player, getPos player]] call BIS_fnc_findSafePos;

	_wps = [_Dps,300,300,0,2,0,0] call BIS_fnc_findSafePos;

	if ( condition     ) 
	then
	{
	hint "no water";
	_fncactive +1;
	}
	else 	
	{
	hint "water";
	};
};

 

Share this post


Link to post
Share on other sites
surfaceIsWater someposition;

I this is not helping because op seeks an area without water

 

sent from mobile using Tapatalk

 

 

 

Share this post


Link to post
Share on other sites

 

im having a problem with my IF condition. In theory, _DPS will find a position, _WPS checks this position 300x300 if there is water. if NO water is found, bis_fnc_findsafepos, will use the default which is defined as my players pos (as a test)

 

then _WPS should equal player pos (which i have named zone as a test at the start of the fnc) if there is NO water.

 

however, looking at how the markers move, it keeps looping, even when it find positions that dont have water.

 

any ideas where i am going wrong?

private ["_fncactive","_dps","_wps","_test"];

_fncactive = 0;
zone = getpos player;
while {_fncactive < 1} do
{
	_dps = [activezone,1750,1750,0,0,0,0,["marker"],[getPos player, getPos player]] call BIS_fnc_findSafePos; // will find a random pos 1750 from active zone, will avoid marker.
sleep 0.1;

	_wps = [_dps,300,300,0,2,0,0,[],[getPos player, getPos player]] call BIS_fnc_findSafePos; // will return player pos if this does not find water
	sleep 1;

	if (_wps isequalto zone) // in theory if _wps does NOT find water, _WPS should default to getplayerpos
	then
	{
	hint "no water";
	_fncactive = _fncactive +1; // stops the loop
	sleep 1;
	"markerpara2" setmarkerpos _dps;
	"markerpara" setmarkerpos _wps;
	}
	else 	
	{
	hint "water";
	sleep 1;
	"markerpara" setmarkerpos _wps;
	"markerpara2" setmarkerpos _dps;
	};

 

Share this post


Link to post
Share on other sites

solved

I was using getPos player as a default, which doesnt work as it is a command.

fixed by using _default = [0,0,0];

 

now

_dps will look for a position

_wps will check this position

if water is found within this position, it returns _default

if _wps isequal to _default (which means if it found water) then it stops the loop 

 

private ["_loop","_dps","_wps","_default"];
_loop = 1;
_default = [0,0,0];
while {_loop > 0} do
{
    _dps = [activezone,1750,1750,0,0,0,0,["marker"],[_default,_default]] call BIS_fnc_findSafePos; // will find a random pos 1750 from my active zone, will avoid looking at the area of marker.
sleep 0.5;
    _wps = [_dps,300,300,0,2,0,0,[],[_default,_default]] call BIS_fnc_findSafePos; // will return _default if this does NOT find water
    sleep 1;
    if (_wps isequalto _default)         // checks if _wps isequalto _default
    then
    {
    hint "no water";
    _loop = _loop -1;                     // stops the loop when condition is met
    sleep 1;
    "markerpara" setmarkerpos _wps;     // places a marker at _Wps found location 
    "markerpara2" setmarkerpos _dps;     // places a marker at _DPS found location
    }
    else     
    {
    hint "water";
    sleep 1;                           
    "markerpara" setmarkerpos _wps;     // places a marker at _Wps found location 
    "markerpara2" setmarkerpos _dps;     // places a marker at _DPS found location
    };
    sleep 1;
};

 

Share this post


Link to post
Share on other sites

Depending on how/where you are using this, your script could potentially become stuck in a loop if no dry position without water within 300m is found.

 

with debug

Spoiler

Where debug markers are...

  • Green: original check from position
  • Red: Dry position with water within 300m
  • Blue: Water position of Dry check
  • Black Area: Blacklist Area added to Dry position check
  • Yellow: Found position: Dry position without water within 300m

h = [ getPos player ] spawn {
	private ["_dps","_wps"];
	params[ "_position" ];
	
	_maxTries = 20;
	_try = 0;
	_blacklist = [];
	
	if !( isNull ( findDisplay 313 )) then {
		for "_mrkNum" from _try to _maxTries do {
			{
				_mrkName = format[ "%1%2", _x, _mrkNum ];
				if !( getMarkerPos _mrkName isEqualTo [0,0,0] ) then {
					deleteMarker _mrkName;
				};
			}forEach [ "dps", "wps", "bl" ];
		};
		{
			if !( getMarkerPos _x isEqualTo [0,0,0] ) then {
				deleteMarker _x;
			};
		}forEach [ "orig", "found" ];
		
		openMap true;
		
		_origMrk = createMarker[ "orig", _position ];
		_origMrk setMarkerShape "ICON";
		_origMrk setMarkerType "hd_dot";
		_origMrk setMarkerColor "ColorGreen";
	};
	
	waitUntil {
		waitUntil {
			_dps = [ _position,750,750,0,0,0,0,_blacklist,[ _position, _position ]] call BIS_fnc_findSafePos;
			
			if ( !( _dps isEqualTo _position ) && !isNull ( findDisplay 313 )) then {
				_dpsMrk = createMarker[ format[ "dps%1", _try ], _dps ];
				_dpsMrk setMarkerShape "ICON";
				_dpsMrk setMarkerType "hd_dot";
				_dpsMrk setMarkerColor "ColorRed";
			};
			
			systemChat format[ "Try: %1", _try ];
			_try = _try + 1;
			!( _dps isEqualTo _position ) || { _try >= _maxTries }
		};
		
		if !( _try >= _maxTries ) then {
			_wps = [_dps,300,300,0,2,0,0,[],[ _position, _position ]] call BIS_fnc_findSafePos;
	
			if ( !( _wps isEqualTo _position ) && !isNull ( findDisplay 313 ) ) then {
				
				_wpsMrk = createMarker[ format[ "wps%1", _try ], _wps ];
				_wpsMrk setMarkerShape "ICON";
				_wpsMrk setMarkerType "hd_dot";
				_wpsMrk setMarkerColor "ColorBlue";
				
				_waterPos = for "_dist" from 0 to 300 do {
					_pos = _dps getPos[ _dist, _dps getDir _wps ];
					if ( surfaceIsWater _pos ) exitWith { _pos };
					_wps
				};
				
				_blMrk = createMarker[ format[ "bl%1", _try ], _waterPos ];
				_blMrk setMarkerShape "ELLIPSE";
				_blMrk setMarkerSize[ 300, 300 ];
				_blMrk setMarkerColor "ColorBlack";
				_blMrk setMarkerAlpha 0.25;
				
				_nul = _blacklist pushBack format[ "bl%1", _try ];
			};

		};
		
		_try >= _maxTries || { _wps isEqualTo _position }
	};
		
	if ( _try < _maxTries ) then {
		hint format[ "found in %1 attempts", _try ];
		if !( isNull ( findDisplay 313 )) then {
			_foundMrk = createMarker[ "found", _dps ];
			_foundMrk setMarkerShape "ICON";
			_foundMrk setMarkerType "hd_dot";
			_foundMrk setMarkerColor "ColorYellow";
		};
	}else{
		hint "Run out of trys";
	};
};

 

 

without debug

Spoiler

h = [ getPos player ] spawn {
	private ["_dps","_wps"];
	params[ "_position" ];
	
	_maxTries = 20;
	_try = 0;
	_blacklist = [];
	
	waitUntil {
		waitUntil {
			_dps = [ _position,750,750,0,0,0,0,_blacklist,[ _position, _position ]] call BIS_fnc_findSafePos;
			
			_try = _try + 1;
			!( _dps isEqualTo _position ) || { _try >= _maxTries }
		};
		
		if !( _try >= _maxTries ) then {
			_wps = [_dps,300,300,0,2,0,0,[],[ _position, _position ]] call BIS_fnc_findSafePos;
	
			if ( !( _wps isEqualTo _position ) && !isNull ( findDisplay 313 ) ) then {
				
				_waterPos = for "_dist" from 0 to 300 do {
					_pos = _dps getPos[ _dist, _dps getDir _wps ];
					if ( surfaceIsWater _pos ) exitWith { _pos };
					_wps
				};
				
				_blMrk = createMarker[ format[ "bl%1", _try ], _waterPos ];
				_blMrk setMarkerShape "ELLIPSE";
				_blMrk setMarkerSize[ 300, 300 ];
				_blMrk setMarkerAlpha 0;
				
				_nul = _blacklist pushBack format[ "bl%1", _try ];
			};

		};
		
		_try >= _maxTries || { _wps isEqualTo _position }
	};
	
	for "_mrkNum" from 1 to _try do {
		_mrkName = format[ "bl%1", _mrkNum ];
		if !( getMarkerPos _mrkName isEqualTo [0,0,0] ) then {
			deleteMarker _mrkName;
		};
	};
		
	if ( _try < _maxTries ) then {
		hint format[ "found in %1 attempts", _try ];
	}else{
		hint "Run out of trys";
	};
	
};

 

 

For each water position that is found an invisible marker is placed at the nearest water position to the dry position, which is then feed back into the dry position search so you are not getting any redundant results from the dry position test on positions we know have water within 300m.

dryPositions.png?raw=1

Share this post


Link to post
Share on other sites

 

2 hours ago, Larrow said:

if no dry position without water within 300m is found.

I have safeguarded this with the black list of "marker".

Marker coveres an area of sea.

 

basically a beach Lz is created > it then selects a predefined inland position which will always be on land > it then kicks in the above for a paradrop position.

 

Would you agree this would work with what i have?

 

Is the version you posted worth me using? (not trying to be rude, I am asking from a very naive point of view)

 

thank you

Share this post


Link to post
Share on other sites
1 hour ago, randy andy tw1 said:

basically a beach Lz is created > it then selects a predefined inland position which will always be on land > it then kicks in the above for a paradrop position.

 

Would you agree this would work with what i have?

If you have already made sure that there is no chance of being stuck in a loop then it sounds like you are all set.

My code was just a general place it anywhere and get a position based on your conditions.

Share this post


Link to post
Share on other sites

Here is my 2 cent code.

Just choose any position (on any map) and a radius (range) to be dry.

 

MGI_dryCheck = compileFinal "
  _pos = _this select 0;
  _posWet = [];
  _range = _this select 1;
  _deltaR = _range / 3600;
  for '_i' from 0 to 3600 step 10 do {
    _ckPos = _pos getPos [_deltaR*_i,_i];
    if (surfaceIsWater _ckPos) exitWith {_posWet = _ckPos}
  };
  _posWet
";

MGI_wetCheck = compileFinal "
  _pos = _this select 0;
  _posDry = [];
  _range = _this select 1;
  _deltaR = _range / 3600;
  for '_i' from 0 to 3600 step 10 do {
    _ckPos = _pos getPos [_deltaR*_i,_i];
    if !(surfaceIsWater _ckPos) exitWith {_posDry = _ckPos}
  };
  _posDry
";

MGI_dryArea = {
  _pos0 = _this select 0;
  _range = _this select 1;
  _pos = _pos0;
  _cnt = 0;
  if (surfaceIsWater _pos0) then {
    _posDry = [_pos,_range] call MGI_wetCheck;
     while {(_posDry isEqualTo [])} do {
    _pos =  _pos vectorAdd ((_pos vectorFromTo [worldSize/2,worldSize/2,0]) vectorMultiply _range);
    _posDry = [_pos,_range] call MGI_wetCheck;
    };
    _pos0 = _posDry;
    _pos = _pos0;
  };  
  _posWet = [_pos,_range] call MGI_dryCheck;
  while {!(_posWet isEqualTo [])} do {
    _cnt = _cnt + 1;
    _pos = _pos vectorAdd ((_poswet vectorFromTo _pos) vectorMultiply (_range - (_pos distance _posWet)));
    _posWet = [_pos,_range] call MGI_dryCheck;
    if (_cnt == 20) exitWith {
      _range = _range * 0.66;
      [_pos0,_range] call MGI_dryArea;
    };
  };
  deleteMarker "dry drop";
  _mk = createMarker ["dry drop",_pos];
  _mk setMarkerShape "ellipse";
  _mk setMarkerSize [_range max 50,_range max 50]
};

[any position,range] call MGI_dryArea;

 

How it works:

first checking if in water or on ground;

spiraling for touching any ground

if  water only, close the ground in direction of the center of the map, for a distance equal to the range you chose;

check if any ground by spiraling;

....

reaching a ground, check for shore by spiraling,

if any shore, move away to opposite direction for range - distance to shore,

check if any shore in a 20 round loop,

if no more shore, tada, you've got the exact dry area with range radius.

if no joy, shrink the radius to 0.66 of the former one and test again. (you are in a tiny island with a too big radius)

 

Performances are not too bad.

Hope this help.

  • 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

×