Jump to content

Recommended Posts

Is there is a way to get the type of road a vehicle is on? Asphalt Paved roads show as #GDTSoil, the concrete paved side roads are #GDTConcrete, and dirt roads are #GDTSoil. I've tried different getPos (getPos, getPosASL, getPosATL, getPosATLVisual, etc) I can use isOnRoad to differentiate between road and non-road of same surface, but how do I differentiate between asphalt and dirt roads?

Even weirder, that main orange road that travels through Altis (The dark paved one), isn't even considered a road. When using nearRoads it isn't even identified. However it is identified by isOnRoad.

Edited by mcrow900

Share this post


Link to post
Share on other sites

surfaceType returns the asphalt paved road as #GdtSoil, which is the same thing it returns for dirt road.

Share this post


Link to post
Share on other sites

Sorry, seeing your answer just made me realise you already knew about that function.

The reason it returns GdtSoil is probably because the roads are drawn on top of the surface. What is it you need to accomplish? There might be another way to get the same result.

  • Like 1

Share this post


Link to post
Share on other sites

I want a player to have a random chance to get damaged if they exceed a certain speed on dirt roads.

Share this post


Link to post
Share on other sites

Hmm, no clue I'm afraid. The road commands on the BIKI don't seem to have anything like that. I'm not familiar with vehicles at all but they all detect when they're on different types of surfaces, if you can find out how that works, maybe you can use that.

  • Like 1

Share this post


Link to post
Share on other sites
I think that is because the surfaceType gets the type of the ground. Road are separate entities and not actually part of the ground.

Thats fine, if this is the case, however it does not solve the problem. Either surfaceType should be extended or terrain config should be tweaked, whichever is easier.

  • Like 1

Share this post


Link to post
Share on other sites
IsOnRoad works 100% of the time.

nearRoads only works about 70% of the time

Problem with nearRoads, as you are experiencing, is that the search radius only applies to the center point of each road segment, not the road itself. Unless the radius is set large enough to encompass the center points of two road segments at any given time (like 25m or so), you'll end up flip-flopping an empty array.

What i would like to see is either IsOnRoad return an optional array with both the boolean & road type); a separate command for roadType (meh); or allow typeOf to return a class or p3d name instead of "" - as road segments are objects, but with no configs, so no classname is associated.

I have a sneaking suspicion that surfaceType won't be able to return a road type, for the same reason it won't identify a helo pad: both are overlays, and independent of the terrain surface (afair). Perhaps, if the game at minimum returned the road type as part of the object model string for nearRoads (instead of only an object id#) we could at least combine the logic of isonroad == true, near 'Asphalt' segment...probably asphalt.

  • Like 1

Share this post


Link to post
Share on other sites
Well, if isOnRoad is true, you can search for the nearest road and get the type

Do you have a suggestion how to do that? because, like i was saying, its a hardcoded object, for which there are no configs, or classnames. typeOf seems to only return "" for nearestroad segments (as is expected, having no class name)

Share this post


Link to post
Share on other sites

Sorry to resurrect a long-dead thread, but this thread comes up first on the google results, and I found a hacky solution to this issue today:

 

Different road types are different widths, so with a little math, and and a few logic gates, you can estimate the kind of road the object is on. For example, the sealed highways on Malden are ~12m across, the sealed country roads are ~9.5m and so on... Using that knowledge, you can use isOnRoad to get five points: object position, and 5.5m in front, behind, left, and right of the object. If at least four of these return true, you're on a sealed highway, if not, check again at 4.5m, if four of those return true, you're on the country road and so on. Here's the code that'll do it:

 

EDIT: I'm a dumb-dumb. You can get the road directly and work from there

You can use isOnRoad and NearRoad to test 4 points around the road at various radii to get the width of the road more accurately. If all 4 return true, you know what size the road is. Keep in mind that all road pieces return North for GetRelPos [X, 0] and so on, so occasionally you might not get the right answer.
 

It's worth noting that this is not a perfect solution. Intersections will return "highway" when they're actually gravel roads, and some angles may return "no road", but it'll work fine in most situations aside from that.

_radii = [0, 3, 4.2, 5.75];
_types = ["no road", "gravel road", "sealed road", "highway"];


_type = (_types select 0);
_currentTest = 1;
while {(_currentTest < count _radii)}do{
	
	_nearestRoad = ((vehicle player) nearRoads (_radii select (count _radii - 1))*2.5) select 0;
	if(isNil "_nearestRoad")ExitWith {};
	
	_left = isOnRoad (_nearestRoad getRelPos [(_radii select _currentTest), 270]);
	_right = isOnRoad (_nearestRoad getRelPos [(_radii select _currentTest), 90]);
	_behind = isOnRoad (_nearestRoad getRelPos [(_radii select _currentTest), 180]);
	_front = isOnRoad (_nearestRoad getRelPos [(_radii select _currentTest), 0]);

	if (_left && _right && _behind && _front) then{
		_type = _types select _currentTest;
	};
	_currentTest = _currentTest + 1;
};

hint format ["player is on %1", _type];

 

  • Like 5

Share this post


Link to post
Share on other sites
5 hours ago, killzone_kid said:

Seems roadAt is much more suitable for this than just isOnRoad

Not especially, the only difference is isOnRoad returns boolean, and roadAt returns the road object itself. Using roadAt would only increase the number of checks to make.

  • Like 2

Share this post


Link to post
Share on other sites

@syhrus,

 

you deserve a medal for that idea. Even though I might not stick to your code 1:1, your idea of checking the size of the road element solved a problem I had for ages ... I would have never thought about something so simple but effective to identify a road type. Little troubles with road crossings etc aside, this works very reliably!

 

Thank you for sharing it!!! If I come up with an improved version regarding scripting speed or reliability I will post it here.

  • Like 3

Share this post


Link to post
Share on other sites

i also came across this thread and your idea to use isOnRoad is very good!

So I made a similar function. It takes into account the direction of a road, then starts probing it with isOnRoad in both directions orthogonal to the direction of the road and returns decent results for segments of a road facing anywhere. I hope it's of any help.

Also an interesting thing I've learned, the position returned by nearRoads is not always in the middle of the road, but the isOnRoad does its job well(in terms of symmetry). On the picture, blue arrow is the middle point returned by getPos road, and pink arrows show how isOnRoad works.

Picture link: steam screenshot

/*
Measures the width of a road object with given precision
paramerets: [_road, _precision, _maxWidth]
	_road - road object acquired by nearRoads
	_precision - the precision with which to find the width
	_maxWidth - the maximum width. If the road is wider, the return value will max at _maxWidth
return value: number, road width or 0 if wrong road object was given
Author: Sparker
*/

params [["_road", objNull, [objNull]], "_precision", "_maxWidth"];

if(isNull _road) exitWith {"Road is null"}; //Wrong data was given

private _connectedRoads = roadsConnectedTo _road;

private _numConnectedRoads = count _connectedRoads;
if (_numConnectedRoads == 0) exitWith {"Road is not connected to anything"}; //Connected road not found, can't calculate direction

private _direction = 0;
if(_numConnectedRoads == 1) then //If it's the end of the road
{
	_direction = _road getDir (_connectedRoads select 0);
	diag_log "Detected one connected road";
}
else //Else approximate the direction by the direction between two nearest segments
{
	_direction = (_connectedRoads select 0) getDir (_connectedRoads select 1);
	diag_log "Detected two connected roads";
};

//Spawn an arrow facing the road
private _roadPos = getPos _road;
//Create arrow for debug
//_arrow = "Sign_Arrow_Blue_F" createVehicle _roadPos;
//_arrow setVectorDirAndUp [[0, 0, 1], [sin _direction, cos _direction, 0]];

//Get orthogonal direction
private _cos = cos (_direction+90);
private _sin = sin (_direction+90);
private _vectorDir = [_sin, _cos, 0];

//Find road width in one direction
private _checkPos = _roadPos;
private _testWidth = 0;
private _width = 0;
while {(_width <= _maxWidth) && (isOnRoad _checkPos)} do
{
	_width = _width + _precision;
	_testWidth = _testWidth + _precision;
	_checkPos = _roadPos vectorAdd (_vectorDir vectorMultiply _testWidth);

	//Create arrow for debug
	//"Sign_Arrow_Pink_F" createVehicle _checkPos;
};


//Find road width in another direction
_testWidth = 0;
_vectorDir = [-_sin, -_cos, 0]; //Rotate the vector 180 degrees
_checkPos = _roadPos;
while {(_width <= _maxWidth) && (isOnRoad _checkPos)} do
{
	_width = _width + _precision;
	_testWidth = _testWidth + _precision;
	_checkPos = _roadPos vectorAdd (_vectorDir vectorMultiply _testWidth);

	//Create arrow for debug
	//"Sign_Arrow_Pink_F" createVehicle _checkPos;
};

_width

 

  • Like 2

Share this post


Link to post
Share on other sites
5 hours ago, sparker said:

i also came across this thread and your idea to use isOnRoad is very good!

So I made a similar function. It takes into account the direction of a road, then starts probing it with isOnRoad in both directions orthogonal to the direction of the road and returns decent results for segments of a road facing anywhere. I hope it's of any help.

Also an interesting thing I've learned, the position returned by nearRoads is not always in the middle of the road, but the isOnRoad does its job well(in terms of symmetry). On the picture, blue arrow is the middle point returned by getPos road, and pink arrows show how isOnRoad works.

Picture link: steam screenshot

 

 

Oh Nice! I couldn't work out a way to get the road's direction. That's super helpful!

  • Like 1

Share this post


Link to post
Share on other sites

I was fiddling around with a command that returned something about how sound was generated at a given position, but because I was beered up at the time, I'm damned if I can remember what it was, but I do recall it being useful for working out what sort of surface I was standing on.

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

×