Jump to content

Recommended Posts

Hi, i want to find a random road position to spawn a  checkpoint on.

 

At first i was trying with findsafepos but could never successfully plug it in with the follow up code that has to find a road near that safepos...i always ended up at 0,0,0

 

Then i found this

randomRoadPos =[nil, ["water"],{ isOnRoad _this }] call BIS_fnc_randomPos;

 

which looks perfect on paper and even after giving it a few tries, but somehow it doesn't work all the time....sometimes it returns 0,0,0

 

Many thanks in advance for any insights! 🙂

Share this post


Link to post
Share on other sites

copying from the wiki examples I got this:

 

private _randomPosAroundPlayer = [[[position player, 50]], ["water"]] call BIS_fnc_randomPos;

 

that uses player position as the center to look from and radius of 50

  • Like 1

Share this post


Link to post
Share on other sites

There are several commands to help find roads. The problem is that none of these commands find absolutely all roads. Each of them can find those that the other could not find. So, you should first use different commands to find all the roads in a certain sector, for example, within a 500m radius around the player:

_roads_1 = nearestTerrainObjects [position player, ["Road"], 500];
_roads_2 = (position player) nearRoads 500;

_all_roads = _roads_1 + _roads_2;

To get rid of duplicate road objects, remove them from the array:

_all_roads = _all_roads arrayIntersect _all_roads;

Now you can extract a random object from the array:

_random_road = selectRandom _all_roads;

To get that road position use:

_position = position _random_road;

Most likely you will need the width of the road and its direction:

_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;

_direction = _start getDir _end;

 

  • Like 1

Share this post


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

somehow it doesn't work all the time....sometimes it returns 0,0,0

 

I'm surprised it works even part of the time. It is grabbing a random position from anywhere on the entire map other than water, then checking if it is on a road. If it isn't, it returns the default safe position [0,0,0].

 

In addition to the above, you could grab a random position then pass it to BIS_fnc_nearestRoad to find a road position.

  • Like 2

Share this post


Link to post
Share on other sites
51 minutes ago, Ibragim A said:

 

Most likely you will need the width of the road and its direction:


_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;

_direction = _start getDir _end;

 

 

 

so, helped myself get to here with your initial post

 

_roads_1 = nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500]; 
_roads_2 = [4092.9,4596.33,0] nearRoads 3500; 

_all_roads = _roads_1 + _roads_2; 
_all_roads = _all_roads arrayIntersect _all_roads; 
_random_road = selectRandom _all_roads; 
_dir = getDir _random_road;


chkpnt = createVehicle ["Land_HBarrier_01_big_tower_green_F", _random_road, [], 0, "CAN_COLLIDE"];
sleep 0.1;
chkpnt setDir _dir;
sleep 0.1;


_playertp = chkpnt getRelPos [5, 90];
sleep 0.1;
player setPos _playertp;

 

not sure my way of getting direction is working, i imagined it being perpendicular to the road all the time, but it isnt....  i see youve posted some follow up now in regards to dir so imma check this out 😛

Share this post


Link to post
Share on other sites

aight, got it working real nice now 🙂 many thanks to all 🍻

 

_roads_1 = nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500]; 
_roads_2 = [4092.9,4596.33,0] nearRoads 3500; 

_all_roads = _roads_1 + _roads_2; 
_all_roads = _all_roads arrayIntersect _all_roads; 
_random_road = selectRandom _all_roads; 
_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;
//_dir = getDir _random_road;
_dir = _start getDir _end;



bcn = createVehicle ["Sign_Sphere10cm_F", _random_road, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1; //
_chkpntpos = bcn getRelPos [12, 90];
chkpnt = createVehicle ["Land_HBarrier_01_big_tower_green_F", _chkpntpos, [], 0, "CAN_COLLIDE"];
sleep 0.1;
chkpnt setDir _dir;
sleep 0.1;


_playertp = chkpnt getRelPos [15, 90];
sleep 0.1;
player setPos _playertp;
sleep 0.1;
deletevehicle bcn;

 

its perfect, the direction, the offset 🤙.....ready to be upgraded with animated bargates, mg nest etc etc

 

brr.jpg

 

#edit after further testing......is there a way to blacklist the roads near and on the airport? I want a remote checkpoint not TSA lol

Share this post


Link to post
Share on other sites

If you follow this methodology, then I advise you to create objects on the side (in the sky, over the sea, at position [0,0,0] and so on), then rotate them in the right direction and only after that put them in the right place for you with setPos. So you can avoid the effect of rotating objects at the start of the mission.

  • Like 1

Share this post


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

.is there a way to blacklist the roads near and on the airport?

You could create a trigger and filter out position inside of it. The select command together with inArea should do it. Cant help more on mobile...

  • Like 3

Share this post


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

#edit after further testing......is there a way to blacklist the roads near and on the airport? I want a remote checkpoint not TSA lol

 

Place a marker covering the area where you do not want checkpoints.

_all_roads = _all_roads arrayIntersect _all_roads; 
//something like this:
_bad_roads = _all_roads inAreaArray "markerName";
_all_roads = _all_roads - _bad_roads;
//
_random_road = selectRandom _all_roads;

You can also use a trigger, as @sarogahtyp mentioned, I just prefer markers for this sort of thing.

  • Like 3

Share this post


Link to post
Share on other sites

aight have it like this now

 

_roads_1 = nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500]; 
_roads_2 = [4092.9,4596.33,0] nearRoads 3500; 

"|arfldmrkr|[2203.12,5663.06,0]|Minefield|ELLIPSE|[1100,800]|145|Border|ColorRed|1|Airfield" call BIS_fnc_stringToMarker;
sleep 0.1;

_all_roads = _roads_1 + _roads_2; 
_all_roads = _all_roads arrayIntersect _all_roads; 
_bad_roads = _all_roads inAreaArray "arfldmrkr";
_all_roads = _all_roads - _bad_roads;
_random_road = selectRandom _all_roads; 
_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;
_dir = _start getDir _end;



bcn = createVehicle ["Sign_Sphere10cm_F", _random_road, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1; //
_chkpntpos = bcn getRelPos [15, 90];
chkpnt = createVehicle ["Land_HBarrier_01_big_tower_green_F", _chkpntpos, [], 0, "CAN_COLLIDE"];
sleep 0.1;
chkpnt setDir _dir;
sleep 0.1;

chkpntmg1 = createVehicle ["I_HMG_02_high_F", [0,0,0], [], 0, "CAN_COLLIDE"];
sleep 0.1;
chkpntmg1 attachTo [chkpnt, [0, -2, 1.55]]; 
sleep 0.1;
chkpntmg1 setdir (getDir chkpnt);
sleep 0.1;

_playertp = chkpnt getRelPos [15, 90];
sleep 0.1;
player setPos _playertp;
sleep 0.1;
deletevehicle bcn;
deletemarker "arfldmrkr";

Tbh, it's satisfactory, but if someone asked me to nitpick, id say i really liked the findsafepos gradient parameter. 

It allowed to filter relatively flat terrain which prevented much of this happening:

 

brr.jpg

 

Also, the offset is kinda suspicious...12 meters should be more than enough to not have any bunker parts on the road but sometimes a third of it is on it.

 

The machine gun also never gets oriented exactly the right way, idk why lol...its 45-90 degrees off the direction of the bunker.

Share this post


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

i really liked the findsafepos gradient parameter

 

You can always filter your position candidates further.

 

https://community.bistudio.com/wiki/isFlatEmpty

 

Find a suitable position first, then start the process of spawning your objects there.

 

  • Like 2

Share this post


Link to post
Share on other sites

So, in the meantime ive found composition spawn scripts and have been checking it out.

 

Pretty much a superior, almost off the shelf solution compared to the hassle of spawn testing stuff with getrelpos.

 

Bargate works, mg always oriented the right way etc etc

 

Just the flat terrain to sort out now! 😊

 

brr.jpg

 

 

 

 

Share this post


Link to post
Share on other sites
12 hours ago, Harzach said:

 

You can always filter your position candidates further.

 

https://community.bistudio.com/wiki/isFlatEmpty

 

Find a suitable position first, then start the process of spawning your objects there.

 

 

idk....feels like the same thing when i tried the findsafepos. Couldn't combine it with road code.

 

Same here.....have this now

_roads_1 = nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500]; 
_roads_2 = [4092.9,4596.33,0] nearRoads 3500; 

"|arfldmrkr|[2203.12,5663.06,0]|Minefield|ELLIPSE|[1100,800]|145|Border|ColorRed|1|Airfield" call BIS_fnc_stringToMarker;
sleep 0.1;

_all_roads = _roads_1 + _roads_2; 
_all_roads = _all_roads arrayIntersect _all_roads; 
_bad_roads = _all_roads inAreaArray "arfldmrkr";
_all_roads = _all_roads - _bad_roads;
_random_road = selectRandom _all_roads; 
_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;
_dir = _start getDir _end;

bcn = createVehicle ["Sign_Sphere10cm_F", _random_road, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1;
_chkpntpos = !(position bcn isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
_finalspwnpos = _random_road arrayIntersect _chkpntpos;

bcn2 = createVehicle ["Sign_Sphere10cm_F", _finalspwnpos, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1;

["roadBlock", getPosATL bcn2, [4,0,-0.2], _dir, true, false, false] call LARs_fnc_spawnComp;

_playertp = bcn getRelPos [15, 90];
sleep 0.1;
player setPos _playertp;
sleep 0.1;
deletevehicle bcn;
deletemarker "arfldmrkr";

 and it says this line 

 

_finalspwnpos = _random_road arrayIntersect _chkpntpos;

 

aren't two arrays and it throws an error. says typed object, expected array or something like that.

 

I think it's because _chkpntpos isnt an array at that point, but an already selected singlepoint, but idk for sure..

Share this post


Link to post
Share on other sites
_chkpntpos = !(position bcn isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
_finalspwnpos = _random_road arrayIntersect _chkpntpos;

The above part of the code is wrong.

 

_chkpntpos will result in boolean (true or false) neither of the _chkpntpos and _random_road variables is an array.

 

You need to create a loop for checking random positions, exiting the loop if the random position matches your conditions.

  • Like 2

Share this post


Link to post
Share on other sites

Try something like this:

_all_roads = _all_roads - _bad_roads;

/// From here

_random_road = objNull;

while (true) do 
	{
		_random_road = selectRandom _all_roads;		
		
		_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
		
		if (_isFlat) exitWith {};
	};
	
_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;
_dir = _start getDir _end;

/// To here

bcn = createVehicle ["Sign_Sphere10cm_F", _random_road, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1;

 

  • Like 1

Share this post


Link to post
Share on other sites
43 minutes ago, Ibragim A said:

Try something like this:


_all_roads = _all_roads - _bad_roads;

/// From here

_random_road = objNull;

while (true) do 
	{
		_random_road = selectRandom _all_roads;		
		
		_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
		
		if (_isFlat) exitWith {};
	};
	
_width = (getRoadInfo _random_road) select 1;
_start = (getRoadInfo _random_road) select 6;
_end = (getRoadInfo _random_road) select 7;
_dir = _start getDir _end;

/// To here

bcn = createVehicle ["Sign_Sphere10cm_F", _random_road, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1;

 

 

It's not cooperating! 😴

 

brr.jpg

Share this post


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

Try something like this:

you don't need the exitWith you can just use the condition of the while.

But the bigger problem with that loop is that it can get an endless loop if no suitable position can be found.

Therefore I would recommend a second part for the condition which breaks the loop after 5 seconds or something.

 

@Rok Stuhne never show these messages in the forum because it is always the last error message occuring. Show errror messages copied out of .rpt file!

 

In this case the error comes from the while syntax... just use the wiki.

 

EDIT:

private _isFlat = false;
private _startTime = diag_tickTime;
private _runTime = 5;

while { !_isFlat && diag_tickTime - _startTime < _runTime } do 
{
	_random_road = selectRandom _all_roads;		
		
	_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
};

 

or just breaking when all road segments are not suitable:

private _isFlat = false;

while { not _isFlat and _all_roads isNotEqualTo [] } do 
{
	_random_road = selectRandom _all_roads;		
  
	_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
  
    _all_roads = _all_roads - _random_road;
};

 

Share this post


Link to post
Share on other sites
4 hours ago, Rok Stuhne said:

_roads_1 = nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500]; 
_roads_2 = [4092.9,4596.33,0] nearRoads 3500; 

_all_roads = _roads_1 + _roads_2;
_all_roads = _all_roads arrayIntersect _all_roads;
_bad_roads = _all_roads inAreaArray "arfldmrkr";
_all_roads = _all_roads - _bad_roads;

 

 

This can be done more effective by combining select command with inArea as I told above. now Ive the time to show it:

_all_roads = ( nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500] ) select { not (_x inArea "arfldmrkr") };
_all_roads append ( [4092.9,4596.33,0] nearRoads 3500 ) select { not (_x inArea "arfldmrkr") };
_all_roads = _all_roads arrayIntersect _all_roads;

 

Share this post


Link to post
Share on other sites
56 minutes ago, sarogahtyp said:

But the bigger problem with that loop is that it can get an endless loop if no suitable position can be found

 

18 hours ago, Rok Stuhne said:

Tbh, it's satisfactory, but if someone asked me to nitpick, id say i really liked the findsafepos gradient parameter. 

Yes, that's true, and because of those two things, I wouldn't try to check random roads all over the map at all. I would make it very simple: I would create a hundred or two markers in those places that exactly fit my conditions, and make a random selection from them.

100-200 random positions (rather than thousands) is enough for those who like to randomize everything possible.

  • Like 1

Share this post


Link to post
Share on other sites
6 hours ago, Ibragim A said:

 

Yes, that's true, and because of those two things, I wouldn't try to check random roads all over the map at all. I would make it very simple: I would create a hundred or two markers in those places that exactly fit my conditions, and make a random selection from them.

100-200 random positions (rather than thousands) is enough for those who like to randomize everything possible.

 

 

Ya, maybe you're right and that is something that i would be able to do, but i wanted to try something new and to maybe end up with a technologically better solution than having to place markers, naming them, deleting etc etc...it would also be much simpler to transfer it to other maps.

 

idk, didnt have time to try the new suggestions, will try tomorrow with a fresh mind.

Share this post


Link to post
Share on other sites
On 7/8/2022 at 3:49 PM, sarogahtyp said:

EDIT:


private _isFlat = false;
private _startTime = diag_tickTime;
private _runTime = 5;

while { !_isFlat && diag_tickTime - _startTime < _runTime } do 
{
	_random_road = selectRandom _all_roads;		
		
	_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
};

 

or just breaking when all road segments are not suitable:


private _isFlat = false;

while { not _isFlat and _all_roads isNotEqualTo [] } do 
{
	_random_road = selectRandom _all_roads;		
  
	_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.05, 100, 0, false, player] isEqualTo []);
  
    _all_roads = _all_roads - _random_road;
};

 

 

Hi, im too stupid for this lmaoooo...can i get a hand pls!

 

i cant get _isFlat out of the loop as a location definition for the spawn point.

 

Been trying with this and variations of this, which is probably now completely fucked up because i kept reshuffling blocks hoping the errors would go away lmaoo

"|arfldmrkr|[2203.12,5663.06,0]|Minefield|ELLIPSE|[1100,800]|145|Border|ColorRed|1|Airfield" call BIS_fnc_stringToMarker;
sleep 0.1;

_all_roads = ( nearestTerrainObjects [[4092.9,4596.33,0], ["Road"], 3500] ) select { not (_x inArea "arfldmrkr") };
_all_roads append ( [4092.9,4596.33,0] nearRoads 3500 ) select { not (_x inArea "arfldmrkr") };
_all_roads = _all_roads arrayIntersect _all_roads;
sleep 0.1;
    _random_road = selectRandom _all_roads;	
	_width = (getRoadInfo _random_road) select 1;
    _start = (getRoadInfo _random_road) select 6;
    _end = (getRoadInfo _random_road) select 7;
    _dir = _start getDir _end;

private _isFlat = false;
private _startTime = diag_tickTime;
private _runTime = 5;

while { !_isFlat && diag_tickTime - _startTime < _runTime } do 
{
	_random_road = selectRandom _all_roads;		
		
	_isFlat = !(position _random_road isFlatEmpty  [100, -1, 0.1, 50, 0, false, player] isEqualTo []);
};





bcn = createVehicle ["Sign_Sphere10cm_F", _isFlat, [], 0, "CAN_COLLIDE"];  // placeholder for offset
sleep 0.1;
["roadBlock", getPosATL bcn, [4,0,-0.2], _dir, true, false, false] call LARs_fnc_spawnComp;
sleep 0.1;


_playertp = bcn getRelPos [15, 90];
sleep 0.1;
player setPos _playertp;
sleep 0.1;
deletevehicle bcn;
deletemarker "arfldmrkr";

 

 

rpt file 😕 the relevant bits i think

19:53:53 Bad conversion: array
19:53:53 Error in expression <e, player] isEqualTo []);
};





bcn = createVehicle ["Sign_Sphere10cm_F", _isF>
19:53:53   Error position: <createVehicle ["Sign_Sphere10cm_F", _isF>
19:53:53   Error 0 elements provided, 3 expected
19:53:53 File C:\Users\rokst\Documents\Arma 3\missions\test%20composition%20spawn.stratis\Checkpoint5.sqf..., line 29
19:53:53 "COMP - Name: roadBlock, Pos:[0,0,0], Offset: [4,0,-0.2], Rot: 153.435, Align: true"
19:53:53 "ITEMS"

Many thanks in advance for any insight.

 

I'd let it go or maybe go for a less universal solution but i think this combo of dynamically finding nice places that works on any map with no prior setup + Larrow's composition spawn scripts can work really nice together in many other situations. 

Share this post


Link to post
Share on other sites

oooooops can't delete post

 

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

so, after a few days of this gnawing at me and me being totally OCD about it (i rly should be trading lmaoo) i finally came up with something that's 99% of what i wanted. 🤗

 

I went through everything lmaooo, all the road, location combos imaginable lol, some of it had great potential, but would end up at 0,0 ~ every 10 or so attempts (had the script on 0-0-1 and just spammed it)

 

The real breakthrough happened when i realized some of the snippets and functions return objects and not location arrays like i was thinking lol.😂

 

This one below is almost perfect, some unexplainable magic happens with  "_nextRoad = ( roadsConnectedTo _road ) select 0;" making it almost always ending up on a location that has enough room for the structure to not be tilted....idk how to explain it but before using that it ended up on a side of a narrow ridge, tilted way more often. idk

 

It's actually 100%, no 0,0 returns IF i dont specify the blacklist marker. It starts crying sometimes after the addition of the blacklist that it can't find _nextroad....zzzzz....idk maybe ill just have to suffer with having a roadblock at the airfield lmaoooo.

 

#EDIT: with specified whitelist it seems to work better...100% now!

 

Onwards and upwards!!! 💪 🙃 

"|whtlst|[3978.31,4205.47]|Minefield|ELLIPSE|[2120,3870]|194|Border|ColorRed|1|Airfield" call BIS_fnc_stringToMarker;
             _randomPosMapNoWater = [["whtlst"], ["water"]] call BIS_fnc_randomPos; 
             bcn = createVehicle ["Sign_Sphere10cm_F", _randomPosMapNoWater, [], 0, "CAN_COLLIDE"];  
             sleep 0.1;
     	 
	         _nearestRoad = [getPosATL bcn, 2000] call BIS_fnc_nearestRoad; 
	         bcn2 = createVehicle ["Sign_Sphere10cm_F", getpos _nearestRoad, [], 0, "CAN_COLLIDE"];  
             sleep 0.1;  

             _road = roadAt ASLToAGL getPosASL bcn2; 
			 _nextRoad = ( roadsConnectedTo _road ) select 0;
             _dir = _road getDir _nextRoad;

             ["roadBlock", getPosATL bcn2, [3,0,-0.2], _dir, true, false, false] call LARs_fnc_spawnComp;
             sleep 0.1;


             _playertp = bcn2 getRelPos [15, 90];
             sleep 0.1;
             player setPos _playertp;
             sleep 0.1;
             deletevehicle bcn;
             deletevehicle bcn2;
			 deletemarker "whtlst";

 

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

×