diff --git a/code/components/extra-natives-five/src/TrackNatives.cpp b/code/components/extra-natives-five/src/TrackNatives.cpp
index 903a00c9aa..53709f934f 100644
--- a/code/components/extra-natives-five/src/TrackNatives.cpp
+++ b/code/components/extra-natives-five/src/TrackNatives.cpp
@@ -149,7 +149,6 @@ static hook::cdecl_stub CTrainTrack__getTrainTrack
return hook::get_call(hook::get_pattern("E8 ? ? ? ? 33 DB 45 0F 57 DB"));
});
-
static int kMaxTracks = xbr::IsGameBuildOrGreater<2545>() ? 127 : 27;
static int32_t FindClosestTrack(rage::Vector3& position, int8_t* outTrack)
@@ -447,7 +446,6 @@ static InitFunction initFunction([]()
context.SetResult(junctionIndex);
g_trackJunctions[junctionIndex] = CTrainJunction(trackIndex, trackNode, newTrackIndex, newTrackNode, direction);
-
});
fx::ScriptEngine::RegisterNativeHandler("REMOVE_TRACK_JUNCTION", [](fx::ScriptContext& context)
@@ -487,6 +485,97 @@ static InitFunction initFunction([]()
context.SetResult(true);
});
+ fx::ScriptEngine::RegisterNativeHandler("IS_TRACK_JUNCTION_ACTIVE", [](fx::ScriptContext& context)
+ {
+ size_t junctionIndex = context.GetArgument(0);
+
+ const std::lock_guard _(g_trackJunctionLock);
+
+ if (!IsTrackJunctionIdValid(junctionIndex))
+ {
+ fx::scripting::Warningf("natives", "IS_TRACK_JUNCTION_ACTIVE: Invalid junction id (%i) provided.\n", junctionIndex);
+ context.SetResult(false);
+ return;
+ }
+
+ context.SetResult(true);
+ *context.GetArgument(1) = g_trackJunctions[junctionIndex].isActive;
+ });
+
+ fx::ScriptEngine::RegisterNativeHandler("GET_TRACK_JUNCTION_INFO", [](fx::ScriptContext& context)
+ {
+ size_t junctionIndex = context.GetArgument(0);
+
+ const std::lock_guard _(g_trackJunctionLock);
+
+ if (!IsTrackJunctionIdValid(junctionIndex))
+ {
+ fx::scripting::Warningf("natives", "GET_TRACK_JUNCTION_INFO: Invalid junction id (%i) provided.\n", junctionIndex);
+ context.SetResult(false);
+ return;
+ }
+
+ context.SetResult(true);
+
+ *context.GetArgument(1) = g_trackJunctions[junctionIndex].onTrack;
+ *context.GetArgument(2) = g_trackJunctions[junctionIndex].onNode;
+ *context.GetArgument(3) = g_trackJunctions[junctionIndex].newTrack;
+ *context.GetArgument(4) = g_trackJunctions[junctionIndex].newNode;
+ *context.GetArgument(5) = g_trackJunctions[junctionIndex].direction;
+ });
+
+ fx::ScriptEngine::RegisterNativeHandler("GET_TRACK_JUNCTION_FROM_NODES", [](fx::ScriptContext& context)
+ {
+ rage::CTrainTrack* testOnTrack = GetAndCheckTrack<0>(context, "GET_TRACK_JUNCTION_FROM_NODES");
+ if (!testOnTrack)
+ {
+ context.SetResult(-1);
+ return;
+ }
+
+ rage::CTrainTrack* testNewTrack = GetAndCheckTrack<2>(context, "GET_TRACK_JUNCTION_FROM_NODES");
+ if (!testNewTrack)
+ {
+ context.SetResult(-1);
+ return;
+ }
+
+ int8_t onTrack = context.GetArgument(0);
+ uint32_t onNode = context.GetArgument(1);
+ int8_t newTrack = context.GetArgument(2);
+ uint32_t newNode = context.GetArgument(3);
+ bool direction = context.GetArgument(4);
+
+ if(!GetAndCheckTrackNode(testOnTrack, onTrack, onNode, "GET_TRACK_JUNCTION_FROM_NODES"))
+ {
+ context.SetResult(-1);
+ return;
+ }
+
+ if(!GetAndCheckTrackNode(testNewTrack, newTrack, newNode, "GET_TRACK_JUNCTION_FROM_NODES"))
+ {
+ context.SetResult(-1);
+ return;
+ }
+
+
+ const std::lock_guard _(g_trackJunctionLock);
+
+ for (auto& [index, junction] : g_trackJunctions)
+ {
+ if (junction.onTrack == onTrack
+ && junction.onNode == onNode
+ && junction.newTrack == newTrack
+ && junction.newNode == newNode
+ && junction.direction == direction)
+ {
+ context.SetResult(index);
+ return;
+ }
+ }
+ context.SetResult(-1);
+ });
+
fx::ScriptEngine::RegisterNativeHandler("GET_TRACK_NODE_COORDS", [](fx::ScriptContext& context)
{
int8_t trackIndex = context.GetArgument(0);
diff --git a/ext/native-decls/GetTrackJunctionFromNodes.md b/ext/native-decls/GetTrackJunctionFromNodes.md
new file mode 100644
index 0000000000..ea0567d2dd
--- /dev/null
+++ b/ext/native-decls/GetTrackJunctionFromNodes.md
@@ -0,0 +1,40 @@
+---
+ns: CFX
+apiset: client
+game: gta5
+---
+## GET_TRACK_JUNCTION_FROM_NODES
+
+```c
+int GET_TRACK_JUNCTION_FROM_NODES(int trackIndex, int trackNode, int newIndex, int newNode, bool direction);
+```
+
+## Examples
+```lua
+local onTrack = 0
+local onNode = 3899
+local newTrack = 1
+local newNode = 83
+local direction = true
+
+local junctionId = RegisterTrackJunction(onTrack, onNode, newTrack, newNode, direction)
+print(("The junctionId is %s"):format(junctionId))
+
+local retrievedJunctionId = GetTrackJunctionFromNodes(onTrack, onNode, newTrack, newNode, direction)
+
+if retrievedJunctionId ~= -1 then
+ print(('The junction is valid, junctionId %i'):format(retrievedJunctionId))
+else
+ print('The junctionId is invalid')
+end
+```
+
+## Parameters
+* **trackIndex**: The track index a train should be on
+* **trackNode**: The node a train should be on
+* **newIndex**: The new track index for a train to be placed on
+* **newNode**: The new track node for a train to be placed on
+* **direction**: The direction a train should be traveling for this junction
+
+## Return value
+Returns the junction id for the given nodes, or -1 if no junction exists.
\ No newline at end of file
diff --git a/ext/native-decls/GetTrackJunctionInfo.md b/ext/native-decls/GetTrackJunctionInfo.md
new file mode 100644
index 0000000000..f449d5b51d
--- /dev/null
+++ b/ext/native-decls/GetTrackJunctionInfo.md
@@ -0,0 +1,41 @@
+---
+ns: CFX
+apiset: client
+game: gta5
+---
+## GET_TRACK_JUNCTION_INFO
+
+```c
+bool GET_TRACK_JUNCTION_INFO(int junctionId, int* trackIndex, int* trackNode, int* newIndex, int* newNode, bool* direction);
+```
+
+## Examples
+
+```lua
+local onTrack = 0
+local onNode = 3899
+local newTrack = 1
+local newNode = 83
+local direction = true
+
+local junctionId = RegisterTrackJunction(onTrack, onNode, newTrack, newNode, direction)
+print(("The junctionId is %s"):format(junctionId))
+
+local isValid, _onTrack, _onNode, _newTrack, _newNode, _direction = GetTrackJunctionInfo(junctionId)
+if isValid then
+ print(('The junction is valid, on track %i, on node %i, new track %i, new node %i, direction %s'):format(_onTrack, _onNode, _newTrack, _newNode, _direction and 'true' or 'false'))
+else
+ print('The junctionId is invalid')
+end
+```
+
+## Parameters
+* **junctionId**: The track junction handle
+* **trackIndex**: The track index a train should be on
+* **trackNode**: The node a train should be on
+* **newIndex**: The new track index for a train to be placed on
+* **newNode**: The new track node for a train to be placed on
+* **direction**: The direction a train should be traveling for this junction
+
+## Return value
+Returns true if junction id is valid, false otherwise.
\ No newline at end of file
diff --git a/ext/native-decls/IsTrackJunctionActive.md b/ext/native-decls/IsTrackJunctionActive.md
new file mode 100644
index 0000000000..cb8b58a15a
--- /dev/null
+++ b/ext/native-decls/IsTrackJunctionActive.md
@@ -0,0 +1,17 @@
+---
+ns: CFX
+apiset: client
+game: gta5
+---
+## IS_TRACK_JUNCTION_ACTIVE
+
+```c
+bool IS_TRACK_JUNCTION_ACTIVE(int junctionId, bool* isActive);
+```
+
+## Parameters
+* **junctionId**: The track junction handle
+* **isActive**: Whether the track junction is active
+
+## Return value
+Returns true if junction id is valid, false otherwise.
\ No newline at end of file