1642 lines
62 KiB
C++
1642 lines
62 KiB
C++
// Rage headers
|
|
#include "fwscene/world/worldlimits.h"
|
|
#include "script/wrapper.h"
|
|
|
|
// Game headers
|
|
#include "control/gps.h"
|
|
#include "Network/Network.h"
|
|
#include "network/networkinterface.h"
|
|
#include "pathserver/pathserver.h"
|
|
#include "peds/pedpopulation.h"
|
|
#include "physics/WorldProbe/worldprobe.h"
|
|
#include "scene/world/gameworld.h"
|
|
#include "scene/world/gameworldheightmap.h"
|
|
#include "script/script.h"
|
|
#include "script/script_helper.h"
|
|
#include "vehicleai/junctions.h"
|
|
#include "vehicleai/pathfind.h"
|
|
#include "vehicleai/task/TaskVehicleThreePointTurn.h"
|
|
#include "ai/debug/system/AIDebugLogManager.h"
|
|
|
|
SCRIPT_OPTIMISATIONS ()
|
|
AI_OPTIMISATIONS ()
|
|
AI_VEHICLE_OPTIMISATIONS ()
|
|
|
|
namespace path_commands
|
|
{
|
|
|
|
|
|
void SetRoadsInArea (const scrVector & scrVecMin, const scrVector & scrVecMax, bool bActive, bool bNetwork)
|
|
{
|
|
float temp_float;
|
|
Vector3 VecPosMin = Vector3 (scrVecMin);
|
|
Vector3 VecPosMax = Vector3 (scrVecMax);
|
|
// Maybe allow "main" script to call this command too
|
|
// Keith needs to call this in other scripts to turn bridges off/on so I've removed this assert
|
|
|
|
if (VecPosMin.x > VecPosMax.x)
|
|
{
|
|
temp_float = VecPosMin.x;
|
|
VecPosMin.x = VecPosMax.x;
|
|
VecPosMax.x = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.y > VecPosMax.y)
|
|
{
|
|
temp_float = VecPosMin.y;
|
|
VecPosMin.y = VecPosMax.y;
|
|
VecPosMax.y = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.z > VecPosMax.z)
|
|
{
|
|
temp_float = VecPosMin.z;
|
|
VecPosMin.z = VecPosMax.z;
|
|
VecPosMax.z = temp_float;
|
|
}
|
|
|
|
if (bActive)
|
|
{
|
|
ThePaths.SwitchRoadsOffInArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), VecPosMin.x, VecPosMax.x, VecPosMin.y, VecPosMax.y, VecPosMin.z, VecPosMax.z, FALSE, true, false, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road on in area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road on in area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
NetworkInterface::SwitchRoadNodesOnOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), VecPosMin, VecPosMax);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ThePaths.SwitchRoadsOffInArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), VecPosMin.x, VecPosMax.x, VecPosMin.y, VecPosMax.y, VecPosMin.z, VecPosMax.z, TRUE, true, false, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road off in area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road off in area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
NetworkInterface::SwitchRoadNodesOffOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), VecPosMin, VecPosMax);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SetRoadsInAngledArea (const scrVector & scrVecCoors1, const scrVector & scrVecCoors2, float AreaWidth, bool UNUSED_PARAM(HighlightArea), bool bActive, bool bNetwork)
|
|
{
|
|
Vector3 EntityPos;
|
|
|
|
Vector3 vStart = Vector3 (scrVecCoors1);
|
|
Vector3 vEnd = Vector3 (scrVecCoors2);
|
|
|
|
if (bActive)
|
|
{
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road on in angled area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f) Width: %.2f",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z,
|
|
AreaWidth);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
|
|
ThePaths.SwitchRoadsOffInAngledArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vStart, vEnd, AreaWidth, FALSE, true, false, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if !__FINAL
|
|
scriptDebugf1("%s: Switching road on in angled area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f) Width: %.2f",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z,
|
|
AreaWidth);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // !__FINAL
|
|
NetworkInterface::SwitchRoadNodesOnOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), vStart, vEnd, AreaWidth);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road off in angled area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f) Width: %.2f",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z,
|
|
AreaWidth);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
|
|
ThePaths.SwitchRoadsOffInAngledArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vStart, vEnd, AreaWidth, TRUE, true, false, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road off in angled area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f) Width: %.2f",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z,
|
|
AreaWidth);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
NetworkInterface::SwitchRoadNodesOffOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), vStart, vEnd, AreaWidth);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CommandSetPedPathsInArea (const scrVector & scrVecMin, const scrVector & scrVecMax, bool bActive, bool bForceAbortCurrentPath)
|
|
{
|
|
// Optionally abort any path-requests which might otherwise occupy the pathserver thread
|
|
if(bForceAbortCurrentPath)
|
|
CPathServer::ForceAbortCurrentPathRequest();
|
|
|
|
Vector3 VecPosMin, VecPosMax;
|
|
|
|
VecPosMin.x = Min(scrVecMin.x, scrVecMax.x);
|
|
VecPosMin.y = Min(scrVecMin.y, scrVecMax.y);
|
|
VecPosMin.z = Min(scrVecMin.z, scrVecMax.z);
|
|
|
|
VecPosMax.x = Max(scrVecMin.x, scrVecMax.x);
|
|
VecPosMax.y = Max(scrVecMin.y, scrVecMax.y);
|
|
VecPosMax.z = Max(scrVecMin.z, scrVecMax.z);
|
|
|
|
if(SCRIPT_VERIFY((VecPosMax-VecPosMin).Mag() > 0.1f, "Invalid (zero-sized) area specified in SET_PED_PATHS_IN_AREA"))
|
|
{
|
|
if (bActive)
|
|
{
|
|
CPathServer::SwitchPedsOnInArea(VecPosMin, VecPosMax, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId());
|
|
}
|
|
else
|
|
{
|
|
CPathServer::SwitchPedsOffInArea(VecPosMin, VecPosMax, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId());
|
|
}
|
|
|
|
CTheScripts::GetCurrentGtaScriptThread()->SetHasUsedPedPathCommand(true);
|
|
}
|
|
}
|
|
|
|
void CommandDisableNavMeshInArea (const scrVector & scrVecMin, const scrVector & scrVecMax, bool bDisable )
|
|
{
|
|
Vector3 VecPosMin, VecPosMax;
|
|
|
|
VecPosMin.x = Min(scrVecMin.x, scrVecMax.x);
|
|
VecPosMin.y = Min(scrVecMin.y, scrVecMax.y);
|
|
VecPosMin.z = Min(scrVecMin.z, scrVecMax.z);
|
|
|
|
VecPosMax.x = Max(scrVecMin.x, scrVecMax.x);
|
|
VecPosMax.y = Max(scrVecMin.y, scrVecMax.y);
|
|
VecPosMax.z = Max(scrVecMin.z, scrVecMax.z);
|
|
|
|
if(SCRIPT_VERIFY((VecPosMax-VecPosMin).Mag() > 0.1f, "Invalid (zero-sized) area specified in DISABLE_NAVMESH_IN_AREA"))
|
|
{
|
|
if (bDisable)
|
|
{
|
|
CPathServer::DisableNavMeshInArea(VecPosMin, VecPosMax, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId());
|
|
}
|
|
else
|
|
{
|
|
CPathServer::ReEnableNavMeshInArea(VecPosMin, VecPosMax, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId());
|
|
}
|
|
|
|
CTheScripts::GetCurrentGtaScriptThread()->SetHasUsedPedPathCommand(true);
|
|
}
|
|
}
|
|
|
|
|
|
enum GetSafePositionFlags
|
|
{
|
|
// Only navmesh polygons marked as pavement
|
|
GSC_FLAG_ONLY_PAVEMENT = 1,
|
|
// Only navmesh polygons not marked as "isolated"
|
|
GSC_FLAG_NOT_ISOLATED = 2,
|
|
// No navmesh polygons created from interiors
|
|
GSC_FLAG_NOT_INTERIOR = 4,
|
|
// No navmesh polygons marked as water
|
|
GSC_FLAG_NOT_WATER = 8,
|
|
// Only navmesh polygons marked as "network spawn candidate"
|
|
GSC_FLAG_ONLY_NETWORK_SPAWN = 16,
|
|
// Specify whether to use a flood-fill from the starting position, as opposed to scanning all polygons within the search volume
|
|
GSC_FLAG_USE_FLOOD_FILL = 32
|
|
};
|
|
|
|
|
|
|
|
// This function replaces CommandGetClosestCharNode. It uses the NavMesh code.
|
|
// Return Coords will be the same as Input Coords if this function returns false
|
|
bool CommandGetSafePositionForPed(const scrVector & scrVecCoors, bool bOnlyOnPavement, Vector3& vecReturn, int iGetSafePositionFlags)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
if (VecPos.z <= INVALID_MINIMUM_WORLD_Z)
|
|
{
|
|
VecPos.z = WorldProbe::FindGroundZForCoord(BOTTOM_SURFACE, VecPos.x, VecPos.y);
|
|
}
|
|
|
|
const Vector3 vecIn(VecPos.x, VecPos.y, VecPos.z);
|
|
|
|
static const float fFindPolySearchDist = 25.0f;
|
|
|
|
u32 iFlags = GetClosestPos_ClearOfObjects;
|
|
if(bOnlyOnPavement)
|
|
iFlags |= GetClosestPos_OnlyPavement;
|
|
|
|
if((iGetSafePositionFlags & GSC_FLAG_ONLY_PAVEMENT)!=0)
|
|
iFlags |= GetClosestPos_OnlyPavement;
|
|
if((iGetSafePositionFlags & GSC_FLAG_NOT_ISOLATED)!=0)
|
|
iFlags |= GetClosestPos_OnlyNonIsolated;
|
|
if((iGetSafePositionFlags & GSC_FLAG_NOT_INTERIOR)!=0)
|
|
iFlags |= GetClosestPos_NotInteriors;
|
|
if((iGetSafePositionFlags & GSC_FLAG_NOT_WATER)!=0)
|
|
iFlags |= GetClosestPos_NotWater;
|
|
if((iGetSafePositionFlags & GSC_FLAG_ONLY_NETWORK_SPAWN)!=0)
|
|
iFlags |= GetClosestPos_OnlyNetworkSpawn;
|
|
if ((iGetSafePositionFlags & GSC_FLAG_USE_FLOOD_FILL) != 0)
|
|
iFlags |= GetClosestPos_UseFloodFill;
|
|
|
|
EGetClosestPosRet eRet = CPathServer::GetClosestPositionForPed(vecIn, vecReturn, fFindPolySearchDist, iFlags);
|
|
bool LatestCmpFlagResult = (eRet!=ENoPositionFound);
|
|
|
|
return LatestCmpFlagResult;
|
|
}
|
|
|
|
enum GetClosestNodeFlags
|
|
{
|
|
GCNF_INCLUDE_SWITCHED_OFF_NODES = 0x1,
|
|
GCNF_INCLUDE_BOAT_NODES = 0x2,
|
|
GCNF_IGNORE_SLIPLANES = 0x4,
|
|
GCNF_IGNORE_SWITCHED_OFF_DEADENDS = 0x8,
|
|
|
|
// Not in the script enum
|
|
GCNF_GET_HEADING = 0x100,
|
|
GCNF_FAVOUR_FACING = 0x200
|
|
};
|
|
|
|
|
|
bool BaseGetClosestNode(const Vector3 &VecPos_, const Vector3 &VecFace_, Vector3& vecReturn, float & headingReturn,
|
|
int & numLanes, int nodeNum, int nodeFlags, CNodeAddress &ResultNode, const float zMeasureMult, const float zTolerance)
|
|
{
|
|
Vector3 VecPos = VecPos_;
|
|
ResultNode.SetEmpty();
|
|
bool LatestCmpFlagResult;
|
|
|
|
float DirX(0.0f);
|
|
float DirY(0.0f);
|
|
|
|
const bool bIgnoreSliplanes = (nodeFlags & GCNF_IGNORE_SLIPLANES) != 0;
|
|
const bool bIgnoreSwitchedOffDeadEnds = (nodeFlags & GCNF_IGNORE_SWITCHED_OFF_DEADENDS) != 0;
|
|
|
|
if ( nodeFlags & GCNF_FAVOUR_FACING )
|
|
{
|
|
Vector3 FaceCoors = VecFace_;
|
|
DirX = FaceCoors.x - VecPos.x;
|
|
DirY = FaceCoors.y - VecPos.y;
|
|
float Length = rage::Sqrtf(DirX*DirX + DirY*DirY);
|
|
if ( SCRIPT_VERIFY( (Length != 0.0f), "GET..._NODE... - A favoured aim at point was specified that exactly matched the specified point."))
|
|
{
|
|
DirX /= Length;
|
|
DirY /= Length;
|
|
}
|
|
else
|
|
{
|
|
nodeFlags &= ~GCNF_FAVOUR_FACING;
|
|
}
|
|
}
|
|
|
|
if (VecPos.z <= INVALID_MINIMUM_WORLD_Z)
|
|
{
|
|
VecPos.z = WorldProbe::FindGroundZForCoord(TOP_SURFACE, VecPos.x, VecPos.y);
|
|
}
|
|
|
|
if ( nodeNum == 0 )
|
|
{
|
|
CPathFind::NodeConsiderationType eNodeConsiderationType =
|
|
(nodeFlags & GCNF_INCLUDE_SWITCHED_OFF_NODES ) ? CPathFind::IncludeSwitchedOffNodes : CPathFind::IgnoreSwitchedOffNodes;
|
|
|
|
ResultNode = ThePaths.FindNodeClosestToCoors(VecPos, 999999.9f, eNodeConsiderationType,
|
|
false, (nodeFlags & GCNF_INCLUDE_BOAT_NODES) ? true : false, false, false,
|
|
(nodeFlags & GCNF_FAVOUR_FACING) ? true : false, DirX, DirY, zMeasureMult, zTolerance, -1, false, false, NULL, bIgnoreSliplanes, bIgnoreSwitchedOffDeadEnds);
|
|
|
|
}
|
|
else
|
|
{
|
|
bool bIgnoreSwitchedOffNodes = (nodeFlags & GCNF_INCLUDE_SWITCHED_OFF_NODES ) ? false : true;
|
|
ResultNode = ThePaths.FindNthNodeClosestToCoors(VecPos, 999999.9f, bIgnoreSwitchedOffNodes, (nodeNum - 1),
|
|
(nodeFlags & GCNF_INCLUDE_BOAT_NODES) ? true : false, NULL,
|
|
(nodeFlags & GCNF_FAVOUR_FACING) ? true : false, DirX, DirY, zMeasureMult, zTolerance, -1, bIgnoreSliplanes, bIgnoreSwitchedOffDeadEnds);
|
|
}
|
|
bool bSuccess;
|
|
Vector3 Temp = ThePaths.FindNodeCoorsForScript(ResultNode, &bSuccess);
|
|
headingReturn = 0.0f;
|
|
numLanes = 0;
|
|
if (bSuccess)
|
|
{
|
|
vecReturn = Temp;
|
|
LatestCmpFlagResult = true;
|
|
if ( nodeFlags & GCNF_GET_HEADING )
|
|
{
|
|
// Try and find the orientation that makes most sense.
|
|
float dirX;
|
|
float dirY;
|
|
if ( nodeFlags & GCNF_FAVOUR_FACING )
|
|
{
|
|
dirX = DirX;
|
|
dirY = DirY;
|
|
}
|
|
else
|
|
{
|
|
Vector3 nodeCoors;
|
|
ThePaths.FindNodePointer(ResultNode)->GetCoors(nodeCoors);
|
|
dirX = nodeCoors.x - VecPos.x;
|
|
dirY = nodeCoors.y - VecPos.y;
|
|
|
|
}
|
|
headingReturn = ThePaths.FindNodeOrientationForCarPlacement(ResultNode, dirX, dirY, &numLanes );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vecReturn.Zero();
|
|
LatestCmpFlagResult = false;
|
|
}
|
|
return LatestCmpFlagResult;
|
|
}
|
|
|
|
bool CommandGetClosestVehicleNode(const scrVector & scrVecCoors, Vector3 &vecReturn, int nodeFlags, float zMeasureMult, float zTolerance)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
CNodeAddress resultNode;
|
|
float dummyAngle;
|
|
int dummyLanes;
|
|
return BaseGetClosestNode(VecPos, VecFaceDummy, vecReturn, dummyAngle, dummyLanes, 0, nodeFlags, resultNode, zMeasureMult, zTolerance);
|
|
}
|
|
|
|
bool CommandGetClosestMajorVehicleNode(const scrVector & scrVecCoors, Vector3 &vecReturn, float zMeasureMult, float zTolerance)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
CNodeAddress resultNode;
|
|
float dummyAngle;
|
|
int dummyLanes;
|
|
// For prostitute script, we want to find the closest road node that is switched on and only start the script if
|
|
// it is far away
|
|
return BaseGetClosestNode(VecPos, VecFaceDummy, vecReturn, dummyAngle, dummyLanes, 0, GCNF_INCLUDE_SWITCHED_OFF_NODES, resultNode, zMeasureMult, zTolerance);
|
|
}
|
|
|
|
bool CommandGetVehicleNodeProperties(const scrVector & vInCoords, int & Out_iDensity, int & Out_iPropertyFlags)
|
|
{
|
|
#if __ASSERT
|
|
Vector3 vAssertPos(vInCoords);
|
|
Assertf( !vAssertPos.IsClose(VEC3_ZERO, 0.1f), "You are passing in (0,0,0) to GET_VEHICLE_NODE_PROPERTIES");
|
|
#endif
|
|
|
|
Out_iDensity = 0;
|
|
Out_iPropertyFlags = 0;
|
|
|
|
// Be sure to keep this enum in sync with VEHICLE_NODE_PROPERTIES in "commands_path.sch"
|
|
enum
|
|
{
|
|
VNP_OFF_ROAD = 1, // node has been flagged as 'off road', suitable only for 4x4 vehicles, etc
|
|
VNP_ON_PLAYERS_ROAD = 2, // node has been dynamically marked as somewhere ahead, possibly on (or near to) the player's current road
|
|
VNP_NO_BIG_VEHICLES = 4, // node has been marked as not suitable for big vehicles
|
|
VNP_SWITCHED_OFF = 8, // node is switched off for ambient population
|
|
VNP_TUNNEL_OR_INTERIOR = 16, // node is in a tunnel or an interior
|
|
VNP_LEADS_TO_DEAD_END = 32, // node is, or leads to, a dead end
|
|
VNP_HIGHWAY = 64, // node is marked as highway
|
|
VNP_JUNCTION = 128, // node qualifies as junction
|
|
VNP_TRAFFIC_LIGHT = 256, // node's special function is traffic-light
|
|
VNP_GIVE_WAY = 512, // node's special function is give-way
|
|
VNP_WATER = 1024 // node is water/boat
|
|
};
|
|
|
|
CNodeAddress nodeAddress = ThePaths.FindNodeClosestToCoors(vInCoords, 9999.0f, CPathFind::IncludeSwitchedOffNodes);
|
|
if(nodeAddress.IsEmpty())
|
|
return false;
|
|
|
|
const CPathNode * pPathNode = ThePaths.FindNodePointerSafe(nodeAddress);
|
|
if(!pPathNode)
|
|
return false;
|
|
|
|
Out_iDensity = pPathNode->m_2.m_density;
|
|
|
|
if(pPathNode->m_1.m_Offroad) Out_iPropertyFlags |= VNP_OFF_ROAD;
|
|
if(pPathNode->m_1.m_onPlayersRoad) Out_iPropertyFlags |= VNP_ON_PLAYERS_ROAD;
|
|
if(pPathNode->m_1.m_noBigVehicles) Out_iPropertyFlags |= VNP_NO_BIG_VEHICLES;
|
|
if(pPathNode->m_2.m_switchedOff) Out_iPropertyFlags |= VNP_SWITCHED_OFF;
|
|
if(pPathNode->m_2.m_inTunnel) Out_iPropertyFlags |= VNP_TUNNEL_OR_INTERIOR;
|
|
if(pPathNode->m_2.m_deadEndness != 0) Out_iPropertyFlags |= VNP_LEADS_TO_DEAD_END;
|
|
if(pPathNode->IsHighway()) Out_iPropertyFlags |= VNP_HIGHWAY;
|
|
if(pPathNode->IsJunctionNode()) Out_iPropertyFlags |= VNP_JUNCTION;
|
|
if(pPathNode->m_1.m_specialFunction == SPECIAL_TRAFFIC_LIGHT) Out_iPropertyFlags |= VNP_TRAFFIC_LIGHT;
|
|
if(pPathNode->m_1.m_specialFunction == SPECIAL_GIVE_WAY) Out_iPropertyFlags |= VNP_GIVE_WAY;
|
|
if(pPathNode->m_2.m_waterNode) Out_iPropertyFlags |= VNP_WATER;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CommandGetClosestVehicleNodeWithHeading(const scrVector & scrVecCoors, Vector3 &vecReturn, float &ReturnHeading, int nodeFlags, float zMeasureMult, float zTolerance)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
CNodeAddress resultNode;
|
|
int dummyLanes;
|
|
return BaseGetClosestNode( VecPos, VecFaceDummy, vecReturn, ReturnHeading, dummyLanes, 0, nodeFlags | GCNF_GET_HEADING, resultNode, zMeasureMult, zTolerance);
|
|
}
|
|
|
|
bool CommandGetNthClosestVehicleNode(const scrVector & scrVecCoors, int NodeNumber, Vector3 &vecReturn, int nodeFlags, float zMeasureMult, float zTolerance)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
CNodeAddress resultNode;
|
|
float dummyAngle;
|
|
int dummyLanes;
|
|
return BaseGetClosestNode( VecPos, VecFaceDummy, vecReturn, dummyAngle, dummyLanes, NodeNumber, nodeFlags, resultNode, zMeasureMult, zTolerance );
|
|
}
|
|
|
|
s32 CommandGetNthClosestVehicleNodeId(const scrVector & scrVecCoors, int NodeNumber, int nodeFlags, float zMeasureMult, float zTolerance)
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
float dummyAngle;
|
|
CNodeAddress resultNode;
|
|
int dummyLanes;
|
|
Vector3 posDummy;
|
|
BaseGetClosestNode( VecPos, VecFaceDummy, posDummy, dummyAngle, dummyLanes, NodeNumber, nodeFlags, resultNode, zMeasureMult, zTolerance);
|
|
s32 ret;
|
|
resultNode.ToInt(ret);
|
|
return ret;
|
|
}
|
|
|
|
bool CommandGetNthClosestVehicleNodeWithHeading(const scrVector & scrVecCoors, int NodeNumber, Vector3 &vecReturn, float &ReturnHeading, int &ReturnNumLanes, int nodeFlags, float zMeasureMult, float zTolerance)
|
|
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
CNodeAddress resultNode;
|
|
return BaseGetClosestNode( VecPos, VecFaceDummy, vecReturn, ReturnHeading, ReturnNumLanes, NodeNumber, nodeFlags | GCNF_GET_HEADING, resultNode, zMeasureMult, zTolerance);
|
|
}
|
|
|
|
s32 CommandGetNthClosestVehicleNodeIdWithHeading(const scrVector & scrVecCoors, int NodeNumber, float &ReturnHeading, int &ReturnNumLanes, int nodeFlags, float zMeasureMult, float zTolerance )
|
|
{
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
Vector3 VecFaceDummy;
|
|
Vector3 posDummy;
|
|
CNodeAddress resultNode;
|
|
BaseGetClosestNode( VecPos, VecFaceDummy, posDummy, ReturnHeading, ReturnNumLanes, NodeNumber, nodeFlags | GCNF_GET_HEADING, resultNode, zMeasureMult, zTolerance );
|
|
s32 ret;
|
|
resultNode.ToInt(ret);
|
|
return ret;
|
|
}
|
|
|
|
bool CommandGetNthClosestVehicleNodeWithHeadingOnIsland(const scrVector & scrVecCoors, int NodeNumber, int mapAreaIndex/*Island*/, Vector3 &vecReturn, float &ReturnHeading, int &numLanes, float zMeasureMult, float zTolerance)
|
|
{
|
|
CNodeAddress ResultNode;
|
|
bool LatestCmpFlagResult = false;
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
|
|
if (VecPos.z <= INVALID_MINIMUM_WORLD_Z)
|
|
{
|
|
VecPos.z = WorldProbe::FindGroundZForCoord(TOP_SURFACE, VecPos.x, VecPos.y);
|
|
}
|
|
if(SCRIPT_VERIFY( (NodeNumber > 0), "GET_NTH_CLOSEST_Vehicle_NODE_WITH_HEADING - Node number must be greater than 0"))
|
|
{
|
|
ResultNode = ThePaths.FindNthNodeClosestToCoors(VecPos, 999999.9f, false, (NodeNumber - 1), false, NULL, false, 0, 0, zMeasureMult, zTolerance, mapAreaIndex);
|
|
|
|
bool bSuccess;
|
|
Vector3 Temp = ThePaths.FindNodeCoorsForScript(ResultNode, &bSuccess);
|
|
if (bSuccess)
|
|
{
|
|
vecReturn = Temp;
|
|
ReturnHeading = ThePaths.FindNodeOrientationForCarPlacement(ResultNode, 0.0f, 0.0f, &numLanes);
|
|
LatestCmpFlagResult = true;
|
|
}
|
|
else
|
|
{
|
|
vecReturn.Zero();
|
|
ReturnHeading = 0.0f;
|
|
numLanes = 0;
|
|
LatestCmpFlagResult = false;
|
|
}
|
|
}
|
|
return LatestCmpFlagResult;
|
|
}
|
|
|
|
bool CommandGetNextClosestVehicleNodeWithHeadingOnIsland(const scrVector & scrVecCoors, int mapAreaIndex/*Island*/, Vector3 &vecReturn, float &ReturnHeading, float zMeasureMult, float zTolerance)
|
|
{
|
|
CNodeAddress ResultNode;
|
|
bool LatestCmpFlagResult;
|
|
Vector3 VecPos = Vector3 (scrVecCoors);
|
|
|
|
if (VecPos.z <= INVALID_MINIMUM_WORLD_Z)
|
|
{
|
|
VecPos.z = WorldProbe::FindGroundZForCoord(TOP_SURFACE, VecPos.x, VecPos.y);
|
|
}
|
|
|
|
ResultNode = ThePaths.FindNextNodeClosestToCoors(VecPos, 999999.9f, false, false, false, 0, 0, zMeasureMult, zTolerance, mapAreaIndex );
|
|
|
|
bool bSuccess;
|
|
Vector3 Temp = ThePaths.FindNodeCoorsForScript(ResultNode, &bSuccess);
|
|
if (bSuccess)
|
|
{
|
|
vecReturn = Temp;
|
|
ReturnHeading = ThePaths.FindNodeOrientationForCarPlacement(ResultNode);
|
|
LatestCmpFlagResult = true;
|
|
}
|
|
else
|
|
{
|
|
vecReturn.Zero();
|
|
ReturnHeading = 0.0f;
|
|
LatestCmpFlagResult = false;
|
|
}
|
|
return LatestCmpFlagResult;
|
|
}
|
|
|
|
bool CommandGetNthClosestVehicleNodeFavourDirection(const scrVector & scrInCoors, const scrVector & scrFaceCoors, int NodeNumber, Vector3 &ReturnCoors, float &ReturnHeading,
|
|
int nodeFlags, float zMeasureMult, float zTolerance)
|
|
{
|
|
|
|
Vector3 InCoors = Vector3(scrInCoors);
|
|
Vector3 FaceCoors = Vector3(scrFaceCoors);
|
|
CNodeAddress resultNode;
|
|
int dummyLanes;
|
|
return BaseGetClosestNode( InCoors, FaceCoors, ReturnCoors, ReturnHeading, dummyLanes, NodeNumber, (nodeFlags | GCNF_FAVOUR_FACING | GCNF_GET_HEADING), resultNode, zMeasureMult, zTolerance);
|
|
}
|
|
|
|
bool CommandIsVehicleNodeIdValid(s32 node)
|
|
{
|
|
CNodeAddress addy;
|
|
addy.FromInt(node);
|
|
return !addy.IsEmpty();
|
|
}
|
|
|
|
void CommandGetVehicleNodePosition(s32 node, Vector3 &vecReturn)
|
|
{
|
|
CNodeAddress addy;
|
|
addy.FromInt(node);
|
|
if ( SCRIPT_VERIFY( !addy.IsEmpty(), "GET_VEHICLE_NODE_POSITION: Command used with an invalid node ID. Missing a IS_VEHICLE_NODE_ID_VALID?." ))
|
|
{
|
|
const CPathNode *pNode = ThePaths.FindNodePointerSafe(addy);
|
|
pNode->GetCoors(vecReturn);
|
|
}
|
|
else
|
|
{
|
|
vecReturn.Zero();
|
|
}
|
|
}
|
|
|
|
bool CommandGetVehicleNodeIsGpsAllowed(s32 node)
|
|
{
|
|
CNodeAddress addy;
|
|
addy.FromInt(node);
|
|
if ( SCRIPT_VERIFY( !addy.IsEmpty(), "GET_VEHICLE_NODE_IS_GPS_ALLOWED: Command used with an invalid node ID. Missing a IS_VEHICLE_NODE_ID_VALID?." ))
|
|
{
|
|
const CPathNode *pNode = ThePaths.FindNodePointerSafe(addy);
|
|
return !( pNode->m_2.m_noGps);
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CommandGetVehicleNodeIsSwitchedOff(s32 node)
|
|
{
|
|
CNodeAddress addy;
|
|
addy.FromInt(node);
|
|
if ( SCRIPT_VERIFY( !addy.IsEmpty(), "GET_VEHICLE_NODE_IS_SWITCHED_OFF: Command used with an invalid node ID. Missing a IS_VEHICLE_NODE_ID_VALID?." ))
|
|
{
|
|
const CPathNode *pNode = ThePaths.FindNodePointerSafe(addy);
|
|
return ( pNode->m_2.m_switchedOff);
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CommandGetClosestRoad(const scrVector & scrTestCoors, float MinLength, int MinLanes, Vector3 &SouthEndNode, Vector3 &NorthEndNode, int &LanesGoingSouth, int &LanesGoingNorth, float &CentralReservationWidth, bool bIgnoreSwitchedOffNodes)
|
|
{
|
|
CNodeAddress NodeSouth, NodeNorth;
|
|
float Orientation;
|
|
|
|
Vector3 TestCoors = Vector3(scrTestCoors);
|
|
|
|
ThePaths.FindNodePairClosestToCoors(TestCoors, &NodeSouth, &NodeNorth, &Orientation, MinLength, 99999.9f, bIgnoreSwitchedOffNodes, false, false, false, MinLanes, &LanesGoingNorth, &LanesGoingSouth, &CentralReservationWidth);
|
|
|
|
const CPathNode *pNodeS = ThePaths.FindNodePointerSafe(NodeSouth);
|
|
const CPathNode *pNodeN = ThePaths.FindNodePointerSafe(NodeNorth);
|
|
|
|
if (!pNodeS || !pNodeN)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pNodeS->GetCoors(SouthEndNode);
|
|
pNodeN->GetCoors(NorthEndNode);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CommandLoadAllPathNodes(bool bLoadAll)
|
|
{
|
|
if(bLoadAll == false)
|
|
{
|
|
GtaThread::ClearHasLoadedAllPathNodes( ASSERT_ONLY(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId()) );
|
|
}
|
|
else
|
|
{
|
|
GtaThread::SetHasLoadedAllPathNodes( CTheScripts::GetCurrentGtaScriptThread()->GetThreadId() );
|
|
}
|
|
|
|
ThePaths.bLoadAllRegions = bLoadAll;
|
|
|
|
return (ThePaths.CPathFind::AreNodesLoadedForArea(WORLDLIMITS_REP_XMIN, WORLDLIMITS_REP_XMAX, WORLDLIMITS_REP_YMIN, WORLDLIMITS_REP_YMAX));
|
|
}
|
|
|
|
void CommandSetAllowStreamPrologueNodes(bool bAllow)
|
|
{
|
|
ThePaths.bWillTryAndStreamPrologueNodes = bAllow;
|
|
}
|
|
|
|
void CommandSetAllowStreamHeistIslandNodes(bool bAllow)
|
|
{
|
|
ThePaths.bStreamHeistIslandNodes = bAllow;
|
|
}
|
|
|
|
bool CommandAreNodesLoadedForArea(float MinX, float MinY, float MaxX, float MaxY)
|
|
{
|
|
return (ThePaths.CPathFind::AreNodesLoadedForArea(MinX, MaxX, MinY, MaxY));
|
|
}
|
|
|
|
bool CommandRequestPathNodesInAreaThisFrame(float MinX, float MinY, float MaxX, float MaxY)
|
|
{
|
|
Vector3 vMin(MinX, MinY, 0.0f);
|
|
Vector3 vMax(MaxX, MaxY, 0.0f);
|
|
return ThePaths.AddNodesRequiredRegionThisFrame( CPathFind::CPathNodeRequiredArea::CONTEXT_SCRIPT, vMin, vMax, CTheScripts::GetCurrentGtaScriptThread()->GetScriptName() );
|
|
}
|
|
|
|
void CommandSwitchRoadsBackToOriginal(const scrVector & scrVecMin, const scrVector & scrVecMax, bool bNetwork)
|
|
{
|
|
// Maybe allow "main" script to call this command too
|
|
// Keith needs to call this in other scripts to turn bridges off/on so I've removed this assert
|
|
Vector3 VecPosMin = Vector3 (scrVecMin);
|
|
Vector3 VecPosMax = Vector3 (scrVecMax);
|
|
|
|
float temp_float;
|
|
|
|
if (VecPosMin.x > VecPosMax.x)
|
|
{
|
|
temp_float = VecPosMin.x;
|
|
VecPosMin.x = VecPosMax.x;
|
|
VecPosMax.x = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.y > VecPosMax.y)
|
|
{
|
|
temp_float = VecPosMin.y;
|
|
VecPosMin.y = VecPosMax.y;
|
|
VecPosMax.y = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.z > VecPosMax.z)
|
|
{
|
|
temp_float = VecPosMin.z;
|
|
VecPosMin.z = VecPosMax.z;
|
|
VecPosMax.z = temp_float;
|
|
}
|
|
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road back to original in area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
|
|
ThePaths.SwitchRoadsOffInArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), VecPosMin.x, VecPosMax.x, VecPosMin.y, VecPosMax.y, VecPosMin.z, VecPosMax.z, FALSE, TRUE, TRUE, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road back to original in area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
NetworkInterface::SetRoadNodesToOriginalOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), VecPosMin, VecPosMax);
|
|
}
|
|
}
|
|
|
|
|
|
void CommandSwitchRoadsBackToOriginalInAngledArea(const scrVector & scrVecCoors1, const scrVector & scrVecCoors2, float AreaWidth, bool bNetwork)
|
|
{
|
|
Vector3 EntityPos;
|
|
|
|
Vector3 vStart = Vector3 (scrVecCoors1);
|
|
Vector3 vEnd = Vector3 (scrVecCoors2);
|
|
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road back to original in area locally: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
|
|
ThePaths.SwitchRoadsOffInAngledArea(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vStart, vEnd, AreaWidth, FALSE, TRUE, TRUE, CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript);
|
|
|
|
if(NetworkInterface::IsGameInProgress() && bNetwork)
|
|
{
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road back to original in area over network: (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f)",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
vStart.x, vStart.y, vStart.z,
|
|
vEnd.x, vEnd.y, vEnd.z);
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
NetworkInterface::SetRoadNodesToOriginalOverNetwork(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptId(), vStart, vEnd, AreaWidth);
|
|
}
|
|
}
|
|
|
|
void CommandSwitchPedRoadsBackToOriginal(const scrVector & scrVecMin, const scrVector & scrVecMax, bool bForceAbortCurrentPath)
|
|
{
|
|
Vector3 VecPosMin = Vector3 (scrVecMin);
|
|
Vector3 VecPosMax = Vector3 (scrVecMax);
|
|
float temp_float;
|
|
|
|
if (VecPosMin.x > VecPosMax.x)
|
|
{
|
|
temp_float = VecPosMin.x;
|
|
VecPosMin.x = VecPosMax.x;
|
|
VecPosMax.x = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.y > VecPosMax.y)
|
|
{
|
|
temp_float = VecPosMin.y;
|
|
VecPosMin.y = VecPosMax.y;
|
|
VecPosMax.y = temp_float;
|
|
}
|
|
|
|
if (VecPosMin.z > VecPosMax.z)
|
|
{
|
|
temp_float = VecPosMin.z;
|
|
VecPosMin.z = VecPosMax.z;
|
|
VecPosMax.z = temp_float;
|
|
}
|
|
|
|
const Vector3 MinVec(VecPosMin);
|
|
const Vector3 MaxVec(VecPosMax);
|
|
|
|
// Abort any path-requests which might otherwise occupy the pathserver thread
|
|
if(bForceAbortCurrentPath)
|
|
CPathServer::ForceAbortCurrentPathRequest();
|
|
|
|
#if __BANK
|
|
scriptDebugf1("%s: Switching road back to original (CommandSwitchPedRoadsBackToOriginal): (%.2f, %.2f, %.2f)->(%.2f, %.2f, %.2f), bForceAbortCurrentPath - %s",
|
|
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
|
|
VecPosMin.x, VecPosMin.y, VecPosMin.z,
|
|
VecPosMax.x, VecPosMax.y, VecPosMax.z,
|
|
AILogging::GetBooleanAsString(bForceAbortCurrentPath));
|
|
scrThread::PrePrintStackTrace();
|
|
#endif // __BANK
|
|
|
|
CPathServer::ClearPedSwitchAreas(MinVec, MaxVec);
|
|
}
|
|
|
|
void CommandSetAmbientPedRangeMultiplierThisFrame(float fMultiplier)
|
|
{
|
|
CPedPopulation::SetScriptedRangeMultiplierThisFrame(fMultiplier);
|
|
}
|
|
|
|
void CommandAdjustAmbientPedSpawnDensitiesThisFrame(int iModifier, const scrVector & vMin, const scrVector & vMax)
|
|
{
|
|
Assert(vMax.x > vMin.x);
|
|
Assert(vMax.y > vMin.y);
|
|
Assert(vMax.z > vMin.z);
|
|
|
|
Assert(iModifier != 0);
|
|
Assert(iModifier >= -MAX_PED_DENSITY);
|
|
Assert(iModifier <= MAX_PED_DENSITY);
|
|
|
|
iModifier = Clamp(iModifier, -MAX_PED_DENSITY, MAX_PED_DENSITY);
|
|
|
|
CPedPopulation::SetAdjustPedSpawnPointDensityThisFrame(iModifier, vMin, vMax);
|
|
}
|
|
|
|
void CommandFindStreetNameAtPosition(const scrVector & scrInCoors, int& streetNameHash1, int& streetNameHash2)
|
|
{
|
|
Vector3 vecIn = Vector3(scrInCoors);
|
|
u32 hash1, hash2;
|
|
|
|
ThePaths.FindStreetNameAtPosition(vecIn, hash1, hash2 );
|
|
streetNameHash1 = (int)hash1;
|
|
streetNameHash2 = (int)hash2;
|
|
}
|
|
|
|
//****************************************************************************
|
|
// CommandAddNavMeshRequiredRegion
|
|
// Adds a region around which navmeshes need to be loaded. There are a
|
|
// maximum of NAVMESH_MAX_REQUIRED_REGIONS allowed. They *must* be removed
|
|
// again after use. Memory consumption is an issue to watch for!
|
|
//****************************************************************************
|
|
void CommandAddNavMeshRequiredRegion(float fOriginX, float fOriginY, float fRadius)
|
|
{
|
|
Displayf("ADD_NAVMESH_REQUIRED_REGION - at (%.1f, %.1f) radius %.1f. Script : %s", fOriginX, fOriginY, fRadius, CTheScripts::GetCurrentGtaScriptThread()->GetScriptName());
|
|
|
|
Assertf(CTheScripts::GetCurrentGtaScriptThread()->IsThisAMissionScript || CNetwork::IsGameInProgress(), "ADD_NAVMESH_REQUIRED_REGION - Can only call this command in a mission or network script (scriptname:%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter());
|
|
ASSERT_ONLY(bool bAddedOk = ) CPathServer::AddNavMeshRegion( NMR_Script, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), fOriginX, fOriginY, fRadius );
|
|
Assert(bAddedOk);
|
|
}
|
|
|
|
//****************************************************************************
|
|
// CommandRemoveNavMeshRequiredRegion
|
|
// Removes a region previously added with CommandRemoveNavMeshRequiredRegion
|
|
//****************************************************************************
|
|
void CommandRemoveNavMeshRequiredRegions()
|
|
{
|
|
Displayf("REMOVE_NAVMESH_REQUIRED_REGIONS - Script: %s", CTheScripts::GetCurrentGtaScriptThread()->GetScriptName());
|
|
|
|
ASSERT_ONLY(bool bRemovedOk = ) CPathServer::RemoveNavMeshRegion( NMR_Script, CTheScripts::GetCurrentGtaScriptThread()->GetThreadId() );
|
|
Assert(bRemovedOk);
|
|
}
|
|
|
|
bool CommandIsNavMeshRequiredRegionInUse()
|
|
{
|
|
return (CPathServer::GetNavmeshMeshRegionScriptID() != THREAD_INVALID);
|
|
}
|
|
|
|
//****************************************************************************
|
|
// Checks whether all required navmesh regions are loaded. This includes all
|
|
// the user-defined regions added with the commands above AND the default
|
|
// region which is always loaded around the player.
|
|
//****************************************************************************
|
|
bool CommandAreAllNavMeshRegionsLoaded(void)
|
|
{
|
|
bool bAllLoaded = CPathServer::AreAllNavMeshRegionsLoaded();
|
|
return bAllLoaded;
|
|
}
|
|
|
|
bool CommandIsNavMeshLoadedInArea(const scrVector & vScrMin, const scrVector & vScrMax)
|
|
{
|
|
const Vector3 vMin = vScrMin;
|
|
const Vector3 vMax = vScrMax;
|
|
|
|
LOCK_IMMEDIATE_DATA;
|
|
|
|
Vector3 vTestPos = vMin;
|
|
const float fStep = CPathServerExtents::GetSizeOfNavMesh();
|
|
|
|
for(vTestPos.x=vMin.x; vTestPos.x<=vMax.x; vTestPos.x+=fStep)
|
|
{
|
|
for(vTestPos.y=vMin.y; vTestPos.y<=vMax.y; vTestPos.y+=fStep)
|
|
{
|
|
const TNavMeshIndex iMesh = CPathServer::GetNavMeshIndexFromPosition(vTestPos, kNavDomainRegular);;
|
|
CNavMesh * pNavMesh = CPathServer::GetNavMeshFromIndex(iMesh, kNavDomainRegular);
|
|
if(!pNavMesh)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
s32 CommandGetNumNavMeshesExistingInArea(const scrVector & vScrMin, const scrVector & vScrMax)
|
|
{
|
|
const Vector3 vMin = vScrMin;
|
|
const Vector3 vMax = vScrMax;
|
|
|
|
s32 iNumNavMeshes = 0;
|
|
aiNavMeshStore * pStore = CPathServer::GetNavMeshStore(kNavDomainRegular);
|
|
|
|
LOCK_IMMEDIATE_DATA;
|
|
|
|
Vector3 vTestPos = vMin;
|
|
const float fStep = CPathServerExtents::GetSizeOfNavMesh();
|
|
|
|
for(vTestPos.x=vMin.x; vTestPos.x<=vMax.x; vTestPos.x+=fStep)
|
|
{
|
|
for(vTestPos.y=vMin.y; vTestPos.y<=vMax.y; vTestPos.y+=fStep)
|
|
{
|
|
const TNavMeshIndex iMesh = CPathServer::GetNavMeshIndexFromPosition(vTestPos, kNavDomainRegular);
|
|
if(iMesh != NAVMESH_NAVMESH_INDEX_NONE)
|
|
{
|
|
if( pStore->GetIsMeshInImage(iMesh) )
|
|
{
|
|
iNumNavMeshes++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return iNumNavMeshes;
|
|
}
|
|
|
|
s32 CommandGetNumNavMeshesLoadedInArea(const scrVector & vScrMin, const scrVector & vScrMax)
|
|
{
|
|
const Vector3 vMin = vScrMin;
|
|
const Vector3 vMax = vScrMax;
|
|
|
|
s32 iNumNavMeshes = 0;
|
|
|
|
LOCK_IMMEDIATE_DATA;
|
|
|
|
Vector3 vTestPos = vMin;
|
|
const float fStep = CPathServerExtents::GetSizeOfNavMesh();
|
|
|
|
for(vTestPos.x=vMin.x; vTestPos.x<=vMax.x; vTestPos.x+=fStep)
|
|
{
|
|
for(vTestPos.y=vMin.y; vTestPos.y<=vMax.y; vTestPos.y+=fStep)
|
|
{
|
|
const TNavMeshIndex iMesh = CPathServer::GetNavMeshIndexFromPosition(vTestPos, kNavDomainRegular);;
|
|
CNavMesh * pNavMesh = CPathServer::GetNavMeshFromIndex(iMesh, kNavDomainRegular);
|
|
if(pNavMesh)
|
|
{
|
|
iNumNavMeshes++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return iNumNavMeshes;
|
|
}
|
|
|
|
|
|
// see "commands_path.sch" for the script enum, which must match below
|
|
enum BLOCKING_OBJECT_FLAGS
|
|
{
|
|
BLOCKING_OBJECT_DEFAULT = 0,
|
|
BLOCKING_OBJECT_WANDERPATH = 1, // Blocking object will block wander paths
|
|
BLOCKING_OBJECT_SHORTESTPATH = 2, // Blocking object will block (regular) shortest-paths
|
|
BLOCKING_OBJECT_FLEEPATH = 4, // Blocking object will block flee paths
|
|
|
|
BLOCKING_OBJECT_ALLPATHS = 7
|
|
};
|
|
|
|
s32 CommandAddNavMeshBlockingObject(const scrVector & vPosition, const scrVector & vSizeXYZ, float fHeading, bool bPermanent, s32 iFlags)
|
|
{
|
|
s32 iBlockingFlags = 0;
|
|
if((iFlags & BLOCKING_OBJECT_WANDERPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_WANDERPATH;
|
|
if((iFlags & BLOCKING_OBJECT_SHORTESTPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_SHORTESTPATH;
|
|
if((iFlags & BLOCKING_OBJECT_FLEEPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_FLEEPATH;
|
|
|
|
// Don't allow scripters to add permanent objects - this is asking for trouble
|
|
Assertf(!bPermanent, "ADD_NAVMESH_BLOCKING_OBJECT - the 'bPermanent' parameter is being deprecated, please set it to FALSE in this script (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter());
|
|
bPermanent = false;
|
|
|
|
const scrThreadId iScriptId = bPermanent ? static_cast<scrThreadId>(0xffffffff) : CTheScripts::GetCurrentGtaScriptThread()->GetThreadId();
|
|
s32 iObjectIndex = CPathServerGta::AddScriptedBlockingObject( iScriptId, vPosition, vSizeXYZ, fHeading, iBlockingFlags );
|
|
|
|
Assertf( iObjectIndex >= 0, "Couldn't add object in command ADD_NAVMESH_BLOCKING_OBJECT");
|
|
scriptAssertf( !Vector3(vPosition).IsZero(), "Script %s addding a navmesh blocking object at the origin (0,0,0) - this is most likely uninitialised script variables.", CTheScripts::GetCurrentScriptNameAndProgramCounter());
|
|
Displayf("ADD_NAVMESH_BLOCKING_OBJECT : object %i at (%.1f, %.1f, %.1f)", iObjectIndex, vPosition.x, vPosition.y, vPosition.z);
|
|
|
|
return iObjectIndex;
|
|
}
|
|
|
|
void CommandUpdateNavMeshBlockingObject(int iObjectHandle, const scrVector & vPosition, const scrVector & vSizeXYZ, float fHeading, s32 iFlags)
|
|
{
|
|
s32 iBlockingFlags = 0;
|
|
if((iFlags & BLOCKING_OBJECT_WANDERPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_WANDERPATH;
|
|
if((iFlags & BLOCKING_OBJECT_SHORTESTPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_SHORTESTPATH;
|
|
if((iFlags & BLOCKING_OBJECT_FLEEPATH)!=0)
|
|
iBlockingFlags |= TDynamicObject::BLOCKINGOBJECT_FLEEPATH;
|
|
|
|
const scrThreadId iScriptId = CTheScripts::GetCurrentGtaScriptThread()->GetThreadId();
|
|
ASSERT_ONLY(bool bUpdated =) CPathServerGta::UpdateScriptedBlockingObject( iScriptId, iObjectHandle, vPosition, vSizeXYZ, fHeading, iBlockingFlags );
|
|
|
|
Assertf( bUpdated, "Couldn't update object %i in command UPDATE_NAVMESH_BLOCKING_OBJECT", iObjectHandle);
|
|
}
|
|
|
|
void CommandRemoveNavMeshBlockingObject(s32 iObjectIndex)
|
|
{
|
|
OUTPUT_ONLY(bool bRemoved =) CPathServerGta::RemoveScriptedBlockingObject( CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), iObjectIndex );
|
|
|
|
Displayf("REMOVE_NAVMESH_BLOCKING_OBJECT : object %i removed = %s", iObjectIndex, bRemoved ? "true":"false");
|
|
}
|
|
|
|
bool CommandDoesNavMeshBlockingObjectExist(s32 iObjectIndex)
|
|
{
|
|
return CPathServerGta::DoesScriptedBlockingObjectExist( CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), iObjectIndex );
|
|
}
|
|
|
|
scrVector CommandGenerateDirections_OutPos(const scrVector & vDestination, int iFlags, int & iOut_Directions, int & iOut_StreetNameHash, float & fOut_ApproxDistance)
|
|
{
|
|
u32 iHash = 0;
|
|
s32 iDir = 0;
|
|
float fDist = 10.f;
|
|
|
|
iOut_StreetNameHash = iHash;
|
|
|
|
Vector3 vDest = Vector3(vDestination.x, vDestination.y, vDestination.z);
|
|
CGpsSlot& GpsSlot = CGps::GetSlot(GPS_SLOT_DISCRETE);
|
|
if (iFlags & GPS_FLAG_AVOID_HIGHWAY)
|
|
GpsSlot.m_iGpsFlags |= GPS_FLAG_AVOID_HIGHWAY;
|
|
else
|
|
GpsSlot.m_iGpsFlags &= (~GPS_FLAG_AVOID_HIGHWAY);
|
|
|
|
if (!vDest.IsClose(GpsSlot.m_Destination, 0.5f))
|
|
GpsSlot.Start(vDest, NULL, 0, false, GPS_SLOT_DISCRETE, Color_magenta);
|
|
|
|
Vector3 vVector3OutPos(VEC3_ZERO);
|
|
if (GpsSlot.GetStatus() == CGpsSlot::STATUS_WORKING)
|
|
{
|
|
ThePaths.GenerateDirections(iDir, iHash, fDist, GpsSlot.m_NodeAdress, GpsSlot.m_NumNodes, vVector3OutPos);
|
|
|
|
iOut_Directions = iDir;
|
|
fOut_ApproxDistance = fDist;
|
|
}
|
|
|
|
return scrVector(vVector3OutPos);
|
|
}
|
|
|
|
int CommandGenerateDirections(const scrVector & vDestination, int iFlags, int & iOut_Directions, int & iOut_StreetNameHash, float & fOut_ApproxDistance)
|
|
{
|
|
CommandGenerateDirections_OutPos(vDestination, iFlags, iOut_Directions, iOut_StreetNameHash, fOut_ApproxDistance);
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Can be used to tell the player which way to go.
|
|
// 0 = straight on, 1 = left, 2 = right.
|
|
//
|
|
|
|
void CommandCreateDirections(const scrVector & destination, int& direction, int& streetNameHash)
|
|
{
|
|
u32 iHash = 0;
|
|
//s32 iDir = 0;
|
|
float fDist = 10.f;
|
|
|
|
streetNameHash = iHash;
|
|
|
|
CommandGenerateDirections(destination, 0, direction, streetNameHash, fDist);
|
|
|
|
int ScriptDirections[CPathFind::DIRECTIONS_MAX] =
|
|
{
|
|
0, //DIRECTIONS_UNKNOWN
|
|
0, //DIRECTIONS_WRONG_WAY
|
|
3, //DIRECTIONS_KEEP_DRIVING
|
|
1, //DIRECTIONS_LEFT_AT_JUNCTION
|
|
2, //DIRECTIONS_RIGHT_AT_JUNCTION
|
|
3, //DIRECTIONS_STRAIGHT_THROUGH_JUNCTION
|
|
5, //DIRECTIONS_KEEP_LEFT
|
|
6, //DIRECTIONS_KEEP_RIGHT
|
|
7, //DIRECTIONS_UTURN
|
|
};
|
|
|
|
Assert(direction >= 0 && direction < CPathFind::DIRECTIONS_MAX);
|
|
direction = ScriptDirections[direction];
|
|
}
|
|
|
|
void CommandSetIgnoreNoGpsFlag(bool bValue)
|
|
{
|
|
ThePaths.bIgnoreNoGpsFlag = bValue;
|
|
}
|
|
|
|
void CommandSetIgnoreNoGpsFlagUntilFirstNode(bool bValue)
|
|
{
|
|
ThePaths.bIgnoreNoGpsFlagUntilFirstNode = bValue;
|
|
}
|
|
|
|
int CommandGetNextAvailableGpsDisabledZoneIndex()
|
|
{
|
|
return ThePaths.GetNextAvailableGpsBlockingRegionForScript();
|
|
}
|
|
|
|
void CommandSetGpsDisabledZoneAtIndex( const scrVector & vScriptMin, const scrVector & vScriptMax, int iIndex )
|
|
{
|
|
Vector3 vMin, vMax;
|
|
vMin.x = Min(vScriptMin.x, vScriptMax.x);
|
|
vMin.y = Min(vScriptMin.y, vScriptMax.y);
|
|
vMin.z = Min(vScriptMin.z, vScriptMax.z);
|
|
vMax.x = Max(vScriptMin.x, vScriptMax.x);
|
|
vMax.y = Max(vScriptMin.y, vScriptMax.y);
|
|
vMax.z = Max(vScriptMin.z, vScriptMax.z);
|
|
|
|
ThePaths.SetGpsBlockingRegionForScript(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vMin, vMax, iIndex );
|
|
}
|
|
|
|
void CommandClearGpsDisabledZoneAtIndex(int iIndex)
|
|
{
|
|
ThePaths.ClearGpsBlockingRegionForScript( iIndex );
|
|
}
|
|
|
|
void CommandSetGpsDisabledZone( const scrVector & vScriptMin, const scrVector & vScriptMax )
|
|
{
|
|
Vector3 vMin, vMax;
|
|
vMin.x = Min(vScriptMin.x, vScriptMax.x);
|
|
vMin.y = Min(vScriptMin.y, vScriptMax.y);
|
|
vMin.z = Min(vScriptMin.z, vScriptMax.z);
|
|
vMax.x = Max(vScriptMin.x, vScriptMax.x);
|
|
vMax.y = Max(vScriptMin.y, vScriptMax.y);
|
|
vMax.z = Max(vScriptMin.z, vScriptMax.z);
|
|
|
|
ThePaths.SetGpsBlockingRegionForScript(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vMin, vMax, 0 );
|
|
}
|
|
|
|
bool CommandGetRandomVehicleNode(const scrVector & scrVecCentrePoint, float radius, s32 minLanes, bool bAvoidDeadEnds, bool bAvoidHighways, Vector3 &vecReturn, s32 &intNodeAddress )
|
|
{
|
|
|
|
Vector3 centrePoint = Vector3(scrVecCentrePoint);
|
|
CNodeAddress node;
|
|
const bool bAvoidSwitchedOff = true;
|
|
if (ThePaths.GetRandomCarNode(centrePoint, radius, false, minLanes, bAvoidDeadEnds, bAvoidHighways, bAvoidSwitchedOff, vecReturn, node))
|
|
{
|
|
node.ToInt(intNodeAddress);
|
|
return true;
|
|
}
|
|
intNodeAddress = 0;
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CommandGetRandomVehcleNodeIncludingSwitchedOffNodes(const scrVector & scrVecCentrePoint, float radius, s32 minLanes, bool bAvoidDeadEnds, bool bAvoidHighways, Vector3 &vecReturn, s32 &intNodeAddress )
|
|
{
|
|
Vector3 centrePoint = Vector3(scrVecCentrePoint);
|
|
CNodeAddress node;
|
|
const bool bAvoidSwitchedOff = false;
|
|
if (ThePaths.GetRandomCarNode(centrePoint, radius, false, minLanes, bAvoidDeadEnds, bAvoidHighways, bAvoidSwitchedOff, vecReturn, node))
|
|
{
|
|
node.ToInt(intNodeAddress);
|
|
return true;
|
|
}
|
|
intNodeAddress = 0;
|
|
return false;
|
|
}
|
|
|
|
bool CommandGetRandomWaterNode(const scrVector & scrVecCentrePoint, float radius, s32 minLanes, bool bAvoidDeadEnds, bool bAvoidHighways, Vector3 &vecReturn, s32 &intNodeAddress )
|
|
{
|
|
Vector3 centrePoint = Vector3(scrVecCentrePoint);
|
|
CNodeAddress node;
|
|
if (ThePaths.GetRandomCarNode(centrePoint, radius, true, minLanes, bAvoidDeadEnds, bAvoidHighways, true, vecReturn, node))
|
|
{
|
|
node.ToInt(intNodeAddress);
|
|
return true;
|
|
}
|
|
intNodeAddress = 0;
|
|
return false;
|
|
}
|
|
|
|
void CommandGetSpawnCoordinatesForVehicleNode(s32 NodeAddress, const scrVector & scrVecTowardsPos, Vector3 &vecReturn, float &orientation )
|
|
{
|
|
if(SCRIPT_VERIFY(NodeAddress!=0, "GET_SPAWN_COORDINATES_FOR_VEHICLE_NODE called with empty node (First param = 0)"))
|
|
{
|
|
Vector3 towardsPos = Vector3(scrVecTowardsPos);
|
|
CNodeAddress node;
|
|
node.FromInt(NodeAddress);
|
|
if(SCRIPT_VERIFY(!node.IsEmpty(), "GET_SPAWN_COORDINATES_FOR_VEHICLE_NODE called with empty node"))
|
|
{
|
|
if(SCRIPT_VERIFY(node.GetRegion() < PATHFINDREGIONS, "GET_SPAWN_COORDINATES_FOR_VEHICLE_NODE called with invalid node"))
|
|
{
|
|
ThePaths.GetSpawnCoordinatesForCarNode(node, towardsPos, vecReturn, orientation);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// name: CommandGetGpsBlipRouteLength
|
|
// description: Gets the length of a gps route, returns 0 if no route
|
|
s32 CommandGetGpsBlipRouteLength()
|
|
{
|
|
return CGps::GetRouteLength(GPS_SLOT_RADAR_BLIP);
|
|
}
|
|
|
|
//
|
|
// name: CommandGetWaypointRouteEnd
|
|
// description: Gets the length of a gps route, returns 0 if no route
|
|
bool CommandGetWaypointRouteEnd(Vector3& vecReturn)
|
|
{
|
|
CGpsSlot& GpsSlot = CGps::GetSlot(GPS_SLOT_WAYPOINT);
|
|
if (GpsSlot.IsOn() && GpsSlot.m_NumNodes > 0)
|
|
{
|
|
vecReturn = GpsSlot.GetRouteEnd();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// name: CommandGetWaypointRouteEnd
|
|
// description: Gets the position along a GPS route, returns 0 if no route
|
|
bool CommandGetPosAlongGPSRoute(Vector3& vecReturn, bool bStartAtPlayerPos, float fDistanceAlongRoute)
|
|
{
|
|
CGpsSlot& GpsSlot = CGps::GetSlot(GPS_SLOT_WAYPOINT);
|
|
if (GpsSlot.IsOn() && GpsSlot.m_NumNodes > 0)
|
|
{
|
|
vecReturn = GpsSlot.GetNextNodePositionAlongRoute(bStartAtPlayerPos, fDistanceAlongRoute);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//does same as CommandGetPosAlongGPSRoute but allows gps slot type to be provided
|
|
bool CommandGetPosAlongGPSRouteType(Vector3& vecReturn, bool bStartAtPlayerPos, float fDistanceAlongRoute, int slotType)
|
|
{
|
|
if(SCRIPT_VERIFY(slotType < GPS_NUM_SLOTS && slotType >= 0, "GET_POS_ALONG_GPS_TYPE_ROUTE called with invalid slot type"))
|
|
{
|
|
CGpsSlot& GpsSlot = CGps::GetSlot((s32)slotType);
|
|
if (GpsSlot.IsOn() && GpsSlot.m_NumNodes > 0)
|
|
{
|
|
vecReturn = GpsSlot.GetNextNodePositionAlongRoute(bStartAtPlayerPos, fDistanceAlongRoute);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// name: CommandGetGpsDiscreteRouteLength
|
|
// description: Gets the length of the gps discrete route, returns 0 if no route
|
|
s32 CommandGetGpsDiscreteRouteLength(const scrVector & vDestination)
|
|
{
|
|
Vector3 vDest = Vector3(vDestination);
|
|
CGpsSlot& GpsSlot = CGps::GetSlot(GPS_SLOT_DISCRETE);
|
|
if (!vDest.IsClose(GpsSlot.m_Destination, 0.5f))
|
|
GpsSlot.Start(vDest, NULL, 0, false, GPS_SLOT_DISCRETE, Color_magenta);
|
|
|
|
if (GpsSlot.GetStatus() != CGpsSlot::STATUS_WORKING)
|
|
return 0;
|
|
|
|
return CGps::GetRouteLength(GPS_SLOT_DISCRETE);
|
|
}
|
|
|
|
//
|
|
// name: CommandGetGpsBlipRouteFound
|
|
// description: Returns true if a blip route has been found and is being displayed
|
|
bool CommandGetGpsBlipRouteFound()
|
|
{
|
|
return CGps::GetRouteLength(GPS_SLOT_RADAR_BLIP) != 0;
|
|
}
|
|
|
|
bool GetRoadBoundaryUsingHeading(const scrVector & scrVecNodePosition, float fHeading, Vector3 & vPositionByRoad)
|
|
{
|
|
Vector3 vNodePosition(scrVecNodePosition);
|
|
|
|
CNodeAddress nodeAddress = ThePaths.FindNodeClosestToCoors(vNodePosition, 9999.0f, CPathFind::IncludeSwitchedOffNodes);
|
|
if(nodeAddress.IsEmpty())
|
|
return false;
|
|
|
|
const CPathNode * pNode = ThePaths.FindNodePointerSafe(nodeAddress);
|
|
if(!pNode)
|
|
return false;
|
|
|
|
if(!pNode->NumLinks())
|
|
return false;
|
|
|
|
s32 iLinkIndex = ThePaths.FindBestLinkFromHeading(nodeAddress, fHeading);
|
|
CPathNodeLink& link = ThePaths.GetNodesLink(pNode, iLinkIndex);
|
|
|
|
//calculate total road width at this point
|
|
float fLeft, fRight;
|
|
ThePaths.FindRoadBoundaries(link, fLeft, fRight);
|
|
|
|
CPathNode* pNextNode = ThePaths.GetNodesLinkedNode(pNode, iLinkIndex);
|
|
if (!pNextNode)
|
|
return false;
|
|
|
|
Vector3 nextNodePos;
|
|
pNextNode->GetCoors(nextNodePos);
|
|
Vector3 nodePos;
|
|
pNode->GetCoors(nodePos);
|
|
|
|
//get side vector
|
|
Vector2 side = Vector2(nextNodePos.y - nodePos.y, -(nextNodePos.x - nodePos.x));
|
|
side.Normalize();
|
|
|
|
//calculate road extreme
|
|
vPositionByRoad = Vector3((side.x * fRight),(side.y * fRight), 0.0f) + nodePos;
|
|
return true;
|
|
}
|
|
|
|
bool GetPositionBySideOfRoadUsingHeading(const scrVector & scrVecNodePosition, float fHeading, Vector3 & vPositionByRoad)
|
|
{
|
|
Vector3 vNodePosition(scrVecNodePosition);
|
|
return ThePaths.GetPositionBySideOfRoad(vNodePosition, fHeading, vPositionByRoad);
|
|
}
|
|
|
|
bool GetPositionBySideOfRoad(const scrVector & scrVecNodePosition, int iDirection, Vector3 & vPositionByRoad)
|
|
{
|
|
Vector3 vNodePosition(scrVecNodePosition);
|
|
|
|
Assert(iDirection==0 || iDirection==1 || iDirection==-1);
|
|
|
|
return ThePaths.GetPositionBySideOfRoad(vNodePosition, iDirection, vPositionByRoad);
|
|
}
|
|
|
|
bool CommandIsPointOnRoad(const scrVector& scrVecPos, int VehicleIndex)
|
|
{
|
|
CVehicle* pVehicle = CTheScripts::GetEntityToModifyFromGUID<CVehicle>(VehicleIndex,0); // don't assert if no vehicle
|
|
//pVehicle might be NULL, and that's ok! IsPointOnRoad checks it
|
|
|
|
Vector3 vPos(scrVecPos);
|
|
return CTaskVehicleThreePointTurn::IsPointOnRoad(vPos, pVehicle);
|
|
}
|
|
|
|
s32 Junctions_GetPhaseCount(const scrVector & scrVecJunctionPos)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex( iJunction );
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
return pJunction->GetNumLightPhases();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool Junctions_ActivatePhase(const scrVector & scrVecJunctionPos, s32 iPhase, float fLightDuration)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex( iJunction );
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
Assertf(iPhase >= 0 && iPhase < pJunction->GetNumLightPhases(), "Phase index is out of range (%i..%i)", 0, pJunction->GetNumLightPhases());
|
|
if(iPhase >= 0 && iPhase < pJunction->GetNumLightPhases())
|
|
{
|
|
pJunction->SetLightPhase(iPhase);
|
|
|
|
if(fLightDuration > 0.0f)
|
|
{
|
|
pJunction->SetLightTimeRemaining(fLightDuration);
|
|
}
|
|
else
|
|
{
|
|
float fDuration = pJunction->GetLightPhaseDuration(iPhase);
|
|
pJunction->SetLightTimeRemaining(fDuration);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 Junctions_GetEntranceCount(const scrVector & scrVecJunctionPos)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex(iJunction);
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
return pJunction->GetNumEntrances();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool Junctions_GetEntranceInfo(const scrVector & scrVecJunctionPos, s32 iEntrance, Vector3 & vEntrancePosition, float & fEntranceHeading, s32 & iPhase, s32 & iFilterLeftPhase, s32 & bFiltersLeftOnly, s32 & bFiltersRight, s32 & bRightLaneRightOnly)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex( iJunction );
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
CJunctionEntrance & entrance = pJunction->GetEntrance(iEntrance);
|
|
|
|
vEntrancePosition = entrance.m_vPositionOfNode;
|
|
fEntranceHeading = fwAngle::GetRadianAngleBetweenPoints(entrance.m_vEntryDir.x, entrance.m_vEntryDir.y, 0.0f, 0.0f);
|
|
fEntranceHeading *= RtoD;
|
|
while(fEntranceHeading < 0.0f) fEntranceHeading += 360.0f;
|
|
while(fEntranceHeading >= 360.0f) fEntranceHeading -= 360.0f;
|
|
iPhase = entrance.m_iPhase;
|
|
iFilterLeftPhase = entrance.m_iLeftFilterPhase;
|
|
bFiltersLeftOnly = entrance.m_bLeftLaneIsAheadOnly;
|
|
bFiltersRight = entrance.m_bCanTurnRightOnRedLight;
|
|
bRightLaneRightOnly = entrance.m_bRightLaneIsRightOnly;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Junctions_Restore(const scrVector & scrVecJunctionPos)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex( iJunction );
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
pJunction->SetToMalfunction(false);
|
|
|
|
int iPhase = pJunction->GetLightPhase();
|
|
float fDuration = pJunction->GetLightPhaseDuration(iPhase);
|
|
pJunction->SetLightTimeRemaining(fDuration);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Junctions_Malfunction(const scrVector & scrVecJunctionPos, bool b)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
int iJunction = CJunctions::GetJunctionAtPosition(vJunctionPos);
|
|
Assertf(iJunction != -1, "No active junction at this position!");
|
|
CJunction * pJunction = CJunctions::GetJunctionByIndex( iJunction );
|
|
Assertf(pJunction, "No junction found");
|
|
if(pJunction)
|
|
{
|
|
Assertf(pJunction->GetTemplateIndex()!=-1, "This is not a templated junction & can't be manipulated by script.");
|
|
if(pJunction->GetTemplateIndex()!=-1)
|
|
{
|
|
pJunction->SetToMalfunction(b);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Junctions_CreateTemplatedJunctionForScript(const scrVector & scrVecJunctionPos)
|
|
{
|
|
Vector3 vJunctionPos(scrVecJunctionPos);
|
|
return CJunctions::CreateTemplatedJunctionForScript(CTheScripts::GetCurrentGtaScriptThread()->GetThreadId(), vJunctionPos);
|
|
}
|
|
|
|
float CommandGetApproxHeightForPoint(float x, float y)
|
|
{
|
|
return CGameWorldHeightMap::GetMaxHeightFromWorldHeightMap(x,y);
|
|
}
|
|
|
|
float CommandGetApproxHeightForArea(float x0, float y0, float x1, float y1)
|
|
{
|
|
return CGameWorldHeightMap::GetMaxHeightFromWorldHeightMap(x0, y0, x1, y1);
|
|
}
|
|
|
|
float CommandGetApproxFloorForPoint(float x, float y)
|
|
{
|
|
return CGameWorldHeightMap::GetMinHeightFromWorldHeightMap(x,y);
|
|
}
|
|
|
|
float CommandGetApproxFloorForArea(float x0, float y0, float x1, float y1)
|
|
{
|
|
return CGameWorldHeightMap::GetMinHeightFromWorldHeightMap(x0, y0, x1, y1);
|
|
}
|
|
|
|
float CommandCalculateTravelDistanceBetweenPoints(const scrVector & scrVecNode1Pos, const scrVector & scrVecNode2Pos)
|
|
{
|
|
Vector3 vNode1Pos(scrVecNode1Pos);
|
|
Vector3 vNode2Pos(scrVecNode2Pos);
|
|
|
|
return ThePaths.CalculateTravelDistanceBetweenNodes(vNode1Pos.x, vNode1Pos.y, vNode1Pos.z, vNode2Pos.x, vNode2Pos.y, vNode2Pos.z);
|
|
}
|
|
|
|
|
|
void SetupScriptCommands()
|
|
{
|
|
SCR_REGISTER_SECURE(SET_ROADS_IN_AREA,0x286addbe501ff4c2, SetRoadsInArea);
|
|
SCR_REGISTER_SECURE(SET_ROADS_IN_ANGLED_AREA,0x208b14ca225dc5a0, SetRoadsInAngledArea);
|
|
SCR_REGISTER_SECURE(SET_PED_PATHS_IN_AREA,0x780d33653803d9b0, CommandSetPedPathsInArea);
|
|
|
|
SCR_REGISTER_SECURE(GET_SAFE_COORD_FOR_PED,0x1555f0fa7ba4fe0f, CommandGetSafePositionForPed);
|
|
SCR_REGISTER_SECURE(GET_CLOSEST_VEHICLE_NODE,0xdfcbbd9528dc1828, CommandGetClosestVehicleNode);
|
|
SCR_REGISTER_SECURE(GET_CLOSEST_MAJOR_VEHICLE_NODE,0x5fcf1af649a7db39, CommandGetClosestMajorVehicleNode);
|
|
SCR_REGISTER_SECURE(GET_CLOSEST_VEHICLE_NODE_WITH_HEADING,0x0fbea22dbe03ac23, CommandGetClosestVehicleNodeWithHeading);
|
|
SCR_REGISTER_SECURE(GET_NTH_CLOSEST_VEHICLE_NODE,0x29579bc5971ca4b6, CommandGetNthClosestVehicleNode);
|
|
SCR_REGISTER_SECURE(GET_NTH_CLOSEST_VEHICLE_NODE_ID,0xea3e64155da5f4d9, CommandGetNthClosestVehicleNodeId);
|
|
SCR_REGISTER_SECURE(GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING,0x15cedab46d800682, CommandGetNthClosestVehicleNodeWithHeading);
|
|
SCR_REGISTER_SECURE(GET_NTH_CLOSEST_VEHICLE_NODE_ID_WITH_HEADING,0x67a3682c37778785, CommandGetNthClosestVehicleNodeIdWithHeading);
|
|
SCR_REGISTER_UNUSED(GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING_ON_ISLAND,0x597f081e6e24c8b9, CommandGetNthClosestVehicleNodeWithHeadingOnIsland);
|
|
SCR_REGISTER_UNUSED(GET_NEXT_CLOSEST_VEHICLE_NODE_WITH_HEADING_ON_ISLAND,0xee1c4f8ee4c60c4d, CommandGetNextClosestVehicleNodeWithHeadingOnIsland);
|
|
SCR_REGISTER_SECURE(GET_NTH_CLOSEST_VEHICLE_NODE_FAVOUR_DIRECTION,0x1b51bebb1f321733, CommandGetNthClosestVehicleNodeFavourDirection);
|
|
SCR_REGISTER_SECURE(GET_VEHICLE_NODE_PROPERTIES,0x4c1eef24cf4b2752, CommandGetVehicleNodeProperties);
|
|
SCR_REGISTER_SECURE(IS_VEHICLE_NODE_ID_VALID,0x958ac759881d0b58, CommandIsVehicleNodeIdValid);
|
|
SCR_REGISTER_SECURE(GET_VEHICLE_NODE_POSITION,0x1b54427560dfe3c3, CommandGetVehicleNodePosition);
|
|
SCR_REGISTER_SECURE(GET_VEHICLE_NODE_IS_GPS_ALLOWED,0xa202f3522092063d, CommandGetVehicleNodeIsGpsAllowed);
|
|
SCR_REGISTER_SECURE(GET_VEHICLE_NODE_IS_SWITCHED_OFF,0x535e2ca2f0da34d4, CommandGetVehicleNodeIsSwitchedOff);
|
|
SCR_REGISTER_SECURE(GET_CLOSEST_ROAD,0x13fd00a258a58752, CommandGetClosestRoad);
|
|
SCR_REGISTER_SECURE(LOAD_ALL_PATH_NODES,0xd268dae911420879, CommandLoadAllPathNodes);
|
|
SCR_REGISTER_SECURE(SET_ALLOW_STREAM_PROLOGUE_NODES,0x3204a8f8ff77eeca, CommandSetAllowStreamPrologueNodes);
|
|
SCR_REGISTER_SECURE(SET_ALLOW_STREAM_HEIST_ISLAND_NODES,0x744c775b133c9131, CommandSetAllowStreamHeistIslandNodes);
|
|
SCR_REGISTER_SECURE(ARE_NODES_LOADED_FOR_AREA,0xf8805443c3db6256, CommandAreNodesLoadedForArea);
|
|
SCR_REGISTER_SECURE(REQUEST_PATH_NODES_IN_AREA_THIS_FRAME,0x2ee5fff3e1e3400d, CommandRequestPathNodesInAreaThisFrame);
|
|
SCR_REGISTER_SECURE(SET_ROADS_BACK_TO_ORIGINAL,0x83e10da4845841b7, CommandSwitchRoadsBackToOriginal);
|
|
SCR_REGISTER_SECURE(SET_ROADS_BACK_TO_ORIGINAL_IN_ANGLED_AREA,0x13a2865660b9b033, CommandSwitchRoadsBackToOriginalInAngledArea);
|
|
SCR_REGISTER_SECURE(SET_AMBIENT_PED_RANGE_MULTIPLIER_THIS_FRAME,0xa8307d8c8abe6270, CommandSetAmbientPedRangeMultiplierThisFrame);
|
|
SCR_REGISTER_SECURE(ADJUST_AMBIENT_PED_SPAWN_DENSITIES_THIS_FRAME,0x2e5c7227cf316022, CommandAdjustAmbientPedSpawnDensitiesThisFrame);
|
|
|
|
SCR_REGISTER_SECURE(SET_PED_PATHS_BACK_TO_ORIGINAL,0x7bfef556f237e70a, CommandSwitchPedRoadsBackToOriginal);
|
|
SCR_REGISTER_SECURE(GET_RANDOM_VEHICLE_NODE,0x5b0e3f68e96beb2f, CommandGetRandomVehicleNode);
|
|
SCR_REGISTER_UNUSED(GET_RANDOM_VEHICLE_NODE_INCLUDE_SWITCHED_OFF_NODES, 0x3d6947a3, CommandGetRandomVehcleNodeIncludingSwitchedOffNodes);
|
|
SCR_REGISTER_UNUSED(GET_RANDOM_WATER_NODE,0x2653d2e73d846b21, CommandGetRandomWaterNode);
|
|
SCR_REGISTER_UNUSED(GET_SPAWN_COORDS_FOR_VEHICLE_NODE,0x90facaa3ecb5be0a, CommandGetSpawnCoordinatesForVehicleNode);
|
|
SCR_REGISTER_SECURE(GET_STREET_NAME_AT_COORD,0x05e7aefd2137bb91, CommandFindStreetNameAtPosition);
|
|
SCR_REGISTER_UNUSED(CREATE_DIRECTIONS_TO_COORD,0x029c059238a17c06, CommandCreateDirections);
|
|
SCR_REGISTER_UNUSED(GENERATE_DIRECTIONS_TO_COORD_OUTPOS,0x343d9e70c8b4f39e, CommandGenerateDirections_OutPos);
|
|
SCR_REGISTER_SECURE(GENERATE_DIRECTIONS_TO_COORD,0x34caae581d7e2318, CommandGenerateDirections);
|
|
|
|
SCR_REGISTER_SECURE(SET_IGNORE_NO_GPS_FLAG,0xac60fc9ab1b2cc70, CommandSetIgnoreNoGpsFlag);
|
|
SCR_REGISTER_SECURE(SET_IGNORE_NO_GPS_FLAG_UNTIL_FIRST_NORMAL_NODE,0x517f19588645defb, CommandSetIgnoreNoGpsFlagUntilFirstNode);
|
|
SCR_REGISTER_SECURE(SET_GPS_DISABLED_ZONE,0x27ac9e8977e369dd, CommandSetGpsDisabledZone);
|
|
SCR_REGISTER_SECURE(GET_GPS_BLIP_ROUTE_LENGTH,0x8748276d7c932108, CommandGetGpsBlipRouteLength);
|
|
SCR_REGISTER_UNUSED(GET_GPS_WAYPOINT_ROUTE_END,0xcc72e9ac0b3a99b6, CommandGetWaypointRouteEnd);
|
|
SCR_REGISTER_UNUSED(GET_POS_ALONG_GPS_ROUTE,0xe2d65a98f8322e88, CommandGetPosAlongGPSRoute);
|
|
SCR_REGISTER_SECURE(GET_POS_ALONG_GPS_TYPE_ROUTE,0xc97d1ceb93adebbc, CommandGetPosAlongGPSRouteType);
|
|
SCR_REGISTER_UNUSED(GET_GPS_DISCRETE_ROUTE_LENGTH,0x8746ddfee6b3b3a8, CommandGetGpsDiscreteRouteLength);
|
|
SCR_REGISTER_SECURE(GET_GPS_BLIP_ROUTE_FOUND,0x718f1e0d4400c7a0, CommandGetGpsBlipRouteFound);
|
|
SCR_REGISTER_SECURE(GET_ROAD_BOUNDARY_USING_HEADING,0x3748f54b0aec5219, GetRoadBoundaryUsingHeading);
|
|
SCR_REGISTER_SECURE(GET_POSITION_BY_SIDE_OF_ROAD,0xe245e7da125485ec, GetPositionBySideOfRoad);
|
|
SCR_REGISTER_UNUSED(GET_POSITION_BY_SIDE_OF_ROAD_USING_HEADING,0xe11e1d153a55b04b, GetPositionBySideOfRoadUsingHeading);
|
|
SCR_REGISTER_SECURE(IS_POINT_ON_ROAD,0x9598a4bd9a1f848f, CommandIsPointOnRoad);
|
|
SCR_REGISTER_SECURE(GET_NEXT_GPS_DISABLED_ZONE_INDEX,0x708a07ba6f801ce6, CommandGetNextAvailableGpsDisabledZoneIndex);
|
|
SCR_REGISTER_SECURE(SET_GPS_DISABLED_ZONE_AT_INDEX,0x344973f34eb71696, CommandSetGpsDisabledZoneAtIndex);
|
|
SCR_REGISTER_SECURE(CLEAR_GPS_DISABLED_ZONE_AT_INDEX,0xef3f1764ed2dee8a, CommandClearGpsDisabledZoneAtIndex);
|
|
|
|
SCR_REGISTER_SECURE(ADD_NAVMESH_REQUIRED_REGION,0x862852388ae23818, CommandAddNavMeshRequiredRegion);
|
|
SCR_REGISTER_SECURE(REMOVE_NAVMESH_REQUIRED_REGIONS,0x0f02061f6faeb6c1, CommandRemoveNavMeshRequiredRegions);
|
|
SCR_REGISTER_SECURE(IS_NAVMESH_REQUIRED_REGION_IN_USE,0x221808c6caa5935e, CommandIsNavMeshRequiredRegionInUse);
|
|
SCR_REGISTER_SECURE(DISABLE_NAVMESH_IN_AREA,0xb2c3d985489123f0, CommandDisableNavMeshInArea);
|
|
SCR_REGISTER_SECURE(ARE_ALL_NAVMESH_REGIONS_LOADED,0x6d56c86cdb6269ae, CommandAreAllNavMeshRegionsLoaded);
|
|
SCR_REGISTER_SECURE(IS_NAVMESH_LOADED_IN_AREA,0x422c66e6b46d5aef, CommandIsNavMeshLoadedInArea);
|
|
|
|
SCR_REGISTER_SECURE(GET_NUM_NAVMESHES_EXISTING_IN_AREA,0xe64c2e86eac945dd, CommandGetNumNavMeshesExistingInArea);
|
|
SCR_REGISTER_UNUSED(GET_NUM_NAVMESHES_LOADED_IN_AREA,0xf4ec7530e9772cd0, CommandGetNumNavMeshesLoadedInArea);
|
|
|
|
SCR_REGISTER_SECURE(ADD_NAVMESH_BLOCKING_OBJECT,0x7afc31f33cb9b8d5, CommandAddNavMeshBlockingObject);
|
|
SCR_REGISTER_SECURE(UPDATE_NAVMESH_BLOCKING_OBJECT,0x3ff379bef70564fc, CommandUpdateNavMeshBlockingObject);
|
|
SCR_REGISTER_SECURE(REMOVE_NAVMESH_BLOCKING_OBJECT,0xb251ddfa99084c56, CommandRemoveNavMeshBlockingObject);
|
|
SCR_REGISTER_SECURE(DOES_NAVMESH_BLOCKING_OBJECT_EXIST,0x046b574e2cf3f2cc, CommandDoesNavMeshBlockingObjectExist);
|
|
|
|
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_GET_PHASE_COUNT,0x7a21ed424da0e6ca, Junctions_GetPhaseCount);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_ACTIVATE_PHASE,0xb37eae203a0c60bf, Junctions_ActivatePhase);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_GET_ENTRANCE_COUNT,0x74c72db3d1bd5cec, Junctions_GetEntranceCount);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_GET_ENTRANCE_INFO,0xa5d4826b23edd623, Junctions_GetEntranceInfo);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_RESTORE,0x38de0601e64f7688, Junctions_Restore);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_MALFUNCTION,0xd78e13bcef173f7a, Junctions_Malfunction);
|
|
SCR_REGISTER_UNUSED(JUNCTIONS_CREATE_TEMPLATED_JUNCTION_FOR_SCRIPT,0x6a4305d4c1697307, Junctions_CreateTemplatedJunctionForScript);
|
|
|
|
SCR_REGISTER_SECURE(GET_APPROX_HEIGHT_FOR_POINT,0xe11e41ec1840ab62, CommandGetApproxHeightForPoint);
|
|
SCR_REGISTER_SECURE(GET_APPROX_HEIGHT_FOR_AREA,0x23555349ef1f5ebe, CommandGetApproxHeightForArea);
|
|
|
|
SCR_REGISTER_SECURE(GET_APPROX_FLOOR_FOR_POINT,0x1ada868ded581c1d, CommandGetApproxFloorForPoint);
|
|
SCR_REGISTER_SECURE(GET_APPROX_FLOOR_FOR_AREA,0xc0f26bf4fdb0b07c, CommandGetApproxFloorForArea);
|
|
|
|
SCR_REGISTER_SECURE(CALCULATE_TRAVEL_DISTANCE_BETWEEN_POINTS,0x0035bf2ca9a27b39, CommandCalculateTravelDistanceBetweenPoints);
|
|
}
|
|
} // end of namespace path_commands
|
|
|
|
|