natives icon indicating copy to clipboard operation
natives copied to clipboard

Updating node documentation

Open lfshr opened this issue 2 years ago • 18 comments

Been doing some node research. Here are the findings.

lfshr avatar May 19 '22 11:05 lfshr

Need to validate the forward and backward lanes before merging. I've made an assumption about which is which.

lfshr avatar May 19 '22 11:05 lfshr

image

Validated. Green is src, red is dest. LanesBackward relates to dest > src lanes.

lfshr avatar May 19 '22 11:05 lfshr

image

Example of bidirectional road with a width set (gap in the middle)

lfshr avatar May 19 '22 11:05 lfshr

image

Validated. Green is src, red is dest. LanesBackward relates to dest > src lanes.

I had the fuckers mixed up. Validated it's wrong lmao

lfshr avatar May 19 '22 11:05 lfshr

image

Fixed and validated src and dest nodes order. Blue is the node I'm passing to GET_CLOSEST_ROAD Green is src Red is dest

lfshr avatar May 19 '22 11:05 lfshr

The purple line is the node heading though which is a bit weird, so maybe it's returning links connecting to the node in the opposite direction? Will check CW

lfshr avatar May 19 '22 12:05 lfshr

image

Can confirm. src and dest were fine before. The node you're testing against is sometimes the src, sometimes the dest

lfshr avatar May 19 '22 12:05 lfshr

Unsure that n should be considered as such. It's only ever 1 in the rockstar scripts. In GTA IV it was 1 or 2 depending on the location of pos

lfshr avatar May 19 '22 22:05 lfshr

I don't have much of CPathFind documented, so these are my rough notes on this batch of natives. Unsure how valuable they will be to continue your research:

0x132F52BBA570FE92:

p3 looks like a node radius and is used to supplement n, likely leading to your "A bit broken as it returns a random edge after n" comment. For example, and using your naming convention, here is an outline of one of the distance checks:

if ((nodeForwardLanes + nodeBackwardLanes < n) || distance(node, linkedNode) <= p3)
    closestDistance = rootManhattanDistance
else {
    closestDistance = nodeManhattanDistance // (dy + dx) + (dz * 3.0)
    ...
}

0x80CA6A8B6C094CC4:

nodeType looks like a bitfield/flag not an explicit type.

0x0568566ACBB5DEDC:

Some additional things to check:

0x10  -> Also used in interiors; 'Tunnels' may be a specific instance of this flag.
0x20  -> Maybe a combination of "Block If No Lanes" and "Narrowroad"? Grep script usage: iVar4 & 32 == 0 && iVar4 & 4 == 0?
0x100 -> Stop/TrafficLightStop
0x200 -> Intersection/Crosswalk
0x400 -> Water

If you are using Codewalker, here are the YndNode mappings (I think):

0x1 = ((RawData.Flags0 & 8) != 0)
0x2 = ((RawData.Flags0 & 0x10) != 0)
0x4 = ((RawData.Flags0 & 0x20) != 0)
0x8 = ((RawData.Flags2 & 0x80) != 0)
0x10 = ((RawData.Flags3 & 1) != 0)
0x20 = ((RawData.Flags4 & 0x70) != 0)
0x40 = ((RawData.Flags2 & 0x40) != 0 && (RawData.Flags2 & 0x20) == 0)
0x80 = ((RawData.LinkCountFlags & 0x1) != 0)
0x100 = ((RawData.Flags1 & 0xF8) == 0x78)
0x200 = ((RawData.Flags1 & 0xF8) == 0x80)
0x400 = ((RawData.Flags2 & 0x20) != 0)

gottfriedleibniz avatar May 20 '22 02:05 gottfriedleibniz

I don't have much of CPathFind documented, so these are my rough notes on this batch of natives. Unsure how valuable they will be to continue your research:

0x132F52BBA570FE92:

p3 looks like a node radius and is used to supplement n, likely leading to your "A bit broken as it returns a random edge after n" comment. For example, and using your naming convention, here is an outline of one of the distance checks:

if ((nodeForwardLanes + nodeBackwardLanes < n) || distance(node, linkedNode) <= p3)
    closestDistance = rootManhattanDistance
else {
    closestDistance = nodeManhattanDistance // (dy + dx) + (dz * 3.0)
    ...
}

0x80CA6A8B6C094CC4:

nodeType looks like a bitfield/flag not an explicit type.

0x0568566ACBB5DEDC:

Some additional things to check:

0x10  -> Also used in interiors; 'Tunnels' may be a specific instance of this flag.
0x20  -> Maybe a combination of "Block If No Lanes" and "Narrowroad"? Grep script usage: iVar4 & 32 == 0 && iVar4 & 4 == 0?
0x100 -> Stop/TrafficLightStop
0x200 -> Intersection/Crosswalk
0x400 -> Water

If you are using Codewalker, here are the YndNode mappings (I think):

0x1 = ((RawData.Flags0 & 8) != 0)
0x2 = ((RawData.Flags0 & 0x10) != 0)
0x4 = ((RawData.Flags0 & 0x20) != 0)
0x8 = ((RawData.Flags2 & 0x80) != 0)
0x10 = ((RawData.Flags3 & 1) != 0)
0x20 = ((RawData.Flags4 & 0x70) != 0)
0x40 = ((RawData.Flags2 & 0x40) != 0 && (RawData.Flags2 & 0x20) == 0)
0x80 = ((RawData.LinkCountFlags & 0x1) != 0)
0x100 = ((RawData.Flags1 & 0xF8) == 0x78)
0x200 = ((RawData.Flags1 & 0xF8) == 0x80)
0x400 = ((RawData.Flags2 & 0x20) != 0)

Thanks for replying. I've actually done a fair bit of extensive research on them that was never merged (need to touch base with dexy to figure out where it is). It was all figured out by cross referencing the incomplete paths.xml so the flags names should be accurate. Junction is also Flags2 & 4. I've yet to push that up. https://github.com/dexyfex/CodeWalker/pull/70/files

The flags enum was figured out by cross referencing the node properties with this branch of codewalker.

Re. p3. I'm not sure. It may be the minimum length of the edge. I'd need to do more testing. Rockstar never use it, it's always 0.0f in their scripts.

Re. NodeType. I just copy pastad that from another native document. I've not put any research into it, but happy to do so. Rockstar do the following in their taxi script when the taxi is trying to find the point at the side of the road. So I think you could be right re. bitfield:

nodeType = 1;
if (!IsZoneSomething(pos))
{
	nodeType = 9;
}
int IsZoneSomething(struct<3> Param0)
{
	char* sVar0;
	
	sVar0 = ZONE::GET_NAME_OF_ZONE(Param0);
	if (((((((((((((((((((((((((((((((((((((((((((((MISC::ARE_STRINGS_EQUAL("SanAnd", sVar0) || MISC::ARE_STRINGS_EQUAL("Alamo", sVar0)) || MISC::ARE_STRINGS_EQUAL("ArmyB", sVar0)) || MISC::ARE_STRINGS_EQUAL("BhamCa", sVar0)) || MISC::ARE_STRINGS_EQUAL("Baytre", sVar0)) || MISC::ARE_STRINGS_EQUAL("BradT", sVar0)) || MISC::ARE_STRINGS_EQUAL("BradP", sVar0)) || MISC::ARE_STRINGS_EQUAL("CANNY", sVar0)) || MISC::ARE_STRINGS_EQUAL("CCreak", sVar0)) || MISC::ARE_STRINGS_EQUAL("ChamH", sVar0)) || MISC::ARE_STRINGS_EQUAL("CHU", sVar0)) || MISC::ARE_STRINGS_EQUAL("COSI", sVar0)) || MISC::ARE_STRINGS_EQUAL("CMSW", sVar0)) || MISC::ARE_STRINGS_EQUAL("Cypre", sVar0)) || MISC::ARE_STRINGS_EQUAL("Desrt", sVar0)) || MISC::ARE_STRINGS_EQUAL("ELGorl", sVar0)) || MISC::ARE_STRINGS_EQUAL("Galli", sVar0)) || MISC::ARE_STRINGS_EQUAL("Galfish", sVar0)) || MISC::ARE_STRINGS_EQUAL("Harmo", sVar0)) || MISC::ARE_STRINGS_EQUAL("HumLab", sVar0)) || MISC::ARE_STRINGS_EQUAL("Jail", sVar0)) || MISC::ARE_STRINGS_EQUAL("LAct", sVar0)) || MISC::ARE_STRINGS_EQUAL("LDam", sVar0)) || MISC::ARE_STRINGS_EQUAL("Lago", sVar0)) || MISC::ARE_STRINGS_EQUAL("MTChil", sVar0)) || MISC::ARE_STRINGS_EQUAL("MTJose", sVar0)) || MISC::ARE_STRINGS_EQUAL("MTGordo", sVar0)) || MISC::ARE_STRINGS_EQUAL("NCHU", sVar0)) || MISC::ARE_STRINGS_EQUAL("Oceana", sVar0)) || MISC::ARE_STRINGS_EQUAL("Palmpow", sVar0)) || MISC::ARE_STRINGS_EQUAL("PBluff", sVar0)) || MISC::ARE_STRINGS_EQUAL("Paleto", sVar0)) || MISC::ARE_STRINGS_EQUAL("PalCov", sVar0)) || MISC::ARE_STRINGS_EQUAL("PalFor", sVar0)) || MISC::ARE_STRINGS_EQUAL("PalHigh", sVar0)) || MISC::ARE_STRINGS_EQUAL("RTRAK", sVar0)) || MISC::ARE_STRINGS_EQUAL("Rancho", sVar0)) || MISC::ARE_STRINGS_EQUAL("SANDY", sVar0)) || MISC::ARE_STRINGS_EQUAL("TongvaH", sVar0)) || MISC::ARE_STRINGS_EQUAL("TongvaV", sVar0)) || MISC::ARE_STRINGS_EQUAL("Zenora", sVar0)) || MISC::ARE_STRINGS_EQUAL("Slab", sVar0)) || MISC::ARE_STRINGS_EQUAL("WindF", sVar0)) || MISC::ARE_STRINGS_EQUAL("Zancudo", sVar0)) || MISC::ARE_STRINGS_EQUAL("SanChia", sVar0)) || MISC::ARE_STRINGS_EQUAL("zQ_UAR", sVar0))
	{
		return 1;
	}
	return 0;
}

lfshr avatar May 20 '22 07:05 lfshr

0x132F52BBA570FE92: p3 looks like a node radius and is used to supplement n, likely leading to your "A bit broken as it returns a random edge after n" comment. For example, and using your naming convention, here is an outline of one of the distance checks:

if ((nodeForwardLanes + nodeBackwardLanes < n) || distance(node, linkedNode) <= p3) closestDistance = rootManhattanDistance else { closestDistance = nodeManhattanDistance // (dy + dx) + (dz * 3.0) ... }

Interesting... 🤔

lfshr avatar May 20 '22 12:05 lfshr

@gottfriedleibniz here are some examples of enumeraing "n" until the response is 0 (p3 = 0.0f). To me it looks like it gives relating nodes, like upcoming junctions/joins etc. What do you think?

image image image image image image image

But it also returns random ones: image

lfshr avatar May 20 '22 12:05 lfshr

@gottfriedleibniz I tried out your theory during lunch. You're bang on the money. p3 is minEdgeLength and n is minLaneCount. Shall post the evidence after work.

lfshr avatar May 20 '22 14:05 lfshr

At the bottom of the screen you see my characters heading * 0.1. In the middle of the edge is the edge length. As you can see when the heading below the length of the edge, the edge is returned. When the heading goes above it's no longer valid and is not returned. Proving that p3 is minLength.

image image

lfshr avatar May 20 '22 20:05 lfshr

In this one the white number is n. The red number is forwardLanes + backwardLanes. As you can see they match. A lane will also be returned if it has 4 total lanes, and I've entered n = 2. Proving that n is actually minLanes

image

lfshr avatar May 20 '22 20:05 lfshr

@gottfriedleibniz started work on the nodeType bitfield if you're interested. 0x1 is AllowDisabled, 0x2 seems unused, and 0x4 excludes Junction, LeftTurnOnly, Stop, SlipRoad as well as edge Merges/Splits including Shortcut splits. (Maybe secondary nodes?) A very useful flag!

Example of 0x4 is below. Green = inclusive, Red = Excluded

image

lfshr avatar May 21 '22 19:05 lfshr

@AvarianKnight updated as per comments

lfshr avatar May 22 '22 14:05 lfshr

I'm going to be updating the other path natives with the search flags. Do you want me to do that in this PR?

lfshr avatar May 22 '22 14:05 lfshr