Switch Roads (#1103)
This commit is contained in:
parent
931177ec43
commit
8853a890d4
|
|
@ -7,6 +7,8 @@
|
|||
#include "StdInc.h"
|
||||
#include "PathFind.h"
|
||||
|
||||
#include <reversiblebugfixes/Bugs.hpp>
|
||||
|
||||
// TODO: Move into the class itself
|
||||
CVector& s_pathsNeededPosn = *(CVector*)0x977B70;
|
||||
bool& s_bLoadPathsNeeded = *(bool*)0x96F030;
|
||||
|
|
@ -63,9 +65,9 @@ void CPathFind::InjectHooks() {
|
|||
//RH_ScopedInstall(AddDynamicLinkBetween2Nodes, 0x4512D0);
|
||||
RH_ScopedOverloadedInstall(LoadPathFindData, "Area", 0x452F40, void(CPathFind::*)(int32));
|
||||
RH_ScopedOverloadedInstall(LoadPathFindData, "FromStream", 0x4529F0, void(CPathFind::*)(RwStream*, int32));
|
||||
//RH_ScopedInstall(SwitchPedRoadsOffInArea, 0x452F00);
|
||||
//RH_ScopedInstall(SwitchRoadsOffInArea, 0x452C80);
|
||||
//RH_ScopedInstall(SwitchRoadsOffInAreaForOneRegion, 0x452820);
|
||||
RH_ScopedInstall(SwitchPedRoadsOffInArea, 0x452F00);
|
||||
RH_ScopedInstall(SwitchRoadsOffInArea, 0x452C80);
|
||||
RH_ScopedInstall(SwitchRoadsOffInAreaForOneRegion, 0x452820);
|
||||
RH_ScopedInstall(ComputeRoute, 0x452760, { .reversed = false });
|
||||
//RH_ScopedInstall(CompleteNewInterior, 0x452270);
|
||||
RH_ScopedInstall(SwitchOffNodeAndNeighbours, 0x452160);
|
||||
|
|
@ -114,7 +116,7 @@ void CPathFind::Init() {
|
|||
ZoneScoped;
|
||||
|
||||
static int32 NumTempExternalNodes = 0; // Unused
|
||||
m_nNumForbiddenAreas = 0;
|
||||
m_nNumNodeSwitches = 0;
|
||||
m_loadAreaRequestPending = false;
|
||||
|
||||
for (auto i = 0u; i < NUM_TOTAL_PATH_NODE_AREAS; ++i) {
|
||||
|
|
@ -124,7 +126,7 @@ void CPathFind::Init() {
|
|||
m_pLinkLengths[i] = nullptr;
|
||||
m_pPathIntersections[i] = nullptr;
|
||||
m_pNaviLinks[i] = nullptr; // BUG: Out of array bounds write, same as in original code
|
||||
m_aUnused[i] = nullptr; // BUG: Out of array bounds write, same as in original code
|
||||
m_aTempNodes[i] = nullptr; // BUG: Out of array bounds write, same as in original code
|
||||
}
|
||||
|
||||
rng::fill(m_interiorIDs, (uint32)-1);
|
||||
|
|
@ -132,7 +134,7 @@ void CPathFind::Init() {
|
|||
|
||||
// 0x44E4E0
|
||||
void CPathFind::ReInit() {
|
||||
m_nNumForbiddenAreas = 0;
|
||||
m_nNumNodeSwitches = 0;
|
||||
m_loadAreaRequestPending = false;
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +203,7 @@ bool CPathFind::ThisNodeWillLeadIntoADeadEnd(CPathNode* startNode, CPathNode* en
|
|||
|
||||
// 0x44D3B0
|
||||
void CPathFind::TidyUpNodeSwitchesAfterMission() {
|
||||
m_nNumForbiddenAreas = std::min(54u, m_nNumForbiddenAreas); // todo: magic number
|
||||
m_nNumNodeSwitches = std::min(54u, m_nNumNodeSwitches); // todo: magic number
|
||||
}
|
||||
|
||||
// 0x44D400
|
||||
|
|
@ -584,10 +586,38 @@ void CPathFind::MarkRoadNodeAsDontWander(float x, float y, float z) {
|
|||
}
|
||||
|
||||
// 0x452820
|
||||
void CPathFind::SwitchRoadsOffInAreaForOneRegion(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bLowTraffic, uint8 nodeType, int32 areaId,
|
||||
uint8 bUnused) {
|
||||
return plugin::CallMethod<0x452820, CPathFind*, float, float, float, float, float, float, bool, char, int32, bool>(this, xMin, xMax, yMin, yMax, zMin, zMax, bLowTraffic,
|
||||
nodeType, areaId, bUnused);
|
||||
void CPathFind::SwitchRoadsOffInAreaForOneRegion(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bCars, int areaId, bool bBackToOriginal) {
|
||||
assert(areaId >= 0 && areaId < NUM_PATH_MAP_AREAS);
|
||||
|
||||
if (!IsAreaLoaded(areaId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto start = bCars ? 0 : m_anNumVehicleNodes[areaId];
|
||||
auto end = bCars ? m_anNumVehicleNodes[areaId] : m_anNumNodes[areaId];
|
||||
|
||||
for (auto nodeIdx = start; nodeIdx < end; ++nodeIdx) {
|
||||
CPathNode& node = m_pPathNodes[areaId][nodeIdx];
|
||||
const auto position = node.GetPosition();
|
||||
|
||||
if (position.x < xMin || position.x > xMax || position.y < yMin || position.y > yMax || position.z < zMin || position.z > zMax) {
|
||||
continue;
|
||||
}
|
||||
if (!ThisNodeHasToBeSwitchedOff(&node) || node.m_isSwitchedOff == (bBackToOriginal ? node.m_isSwitchedOffOriginal : bSwitchOff)) {
|
||||
continue;
|
||||
}
|
||||
CPathNode* next1{};
|
||||
CPathNode* next2{};
|
||||
|
||||
SwitchOffNodeAndNeighbours(&node, next1, &next2, bSwitchOff, bBackToOriginal);
|
||||
|
||||
for (auto iter = next1; iter;) {
|
||||
SwitchOffNodeAndNeighbours(iter, iter, nullptr, bSwitchOff, bBackToOriginal);
|
||||
}
|
||||
for (auto iter = next2; iter;) {
|
||||
SwitchOffNodeAndNeighbours(iter, iter, nullptr, bSwitchOff, bBackToOriginal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTSA
|
||||
|
|
@ -659,12 +689,12 @@ void CPathFind::LoadPathFindData(RwStream* stream, int32 areaId) {
|
|||
|
||||
for (auto i = 0u; i < numNodes; ++i) {
|
||||
auto& node = m_pPathNodes[areaId][i];
|
||||
node.m_isOriginallyOnDeadEnd = node.m_onDeadEnd;
|
||||
node.m_isSwitchedOffOriginal = node.m_isSwitchedOff;
|
||||
}
|
||||
|
||||
for (auto i = 0u; i < m_nNumForbiddenAreas; ++i) {
|
||||
auto& area = m_aForbiddenAreas[i];
|
||||
SwitchRoadsOffInAreaForOneRegion(area.m_fXMin, area.m_fXMax, area.m_fYMin, area.m_fYMax, area.m_fZMin, area.m_fZMax, area.m_bEnable, area.m_nType, areaId, false);
|
||||
for (auto i = 0u; i < m_nNumNodeSwitches; ++i) {
|
||||
auto& area = m_aNodeSwitches[i];
|
||||
SwitchRoadsOffInAreaForOneRegion(area.xMin, area.xMax, area.yMin, area.yMax, area.zMin, area.zMax, area.isOff, area.isCars, areaId, false);
|
||||
}
|
||||
for (auto i = 0u; i < NUM_DYNAMIC_LINKS_PER_AREA; ++i) {
|
||||
rng::fill(m_aDynamicLinksBaseIds[i], -1);
|
||||
|
|
@ -966,8 +996,8 @@ CNodeAddress CPathFind::FindNodeClosestToCoorsFavourDirection(CVector pos, ePath
|
|||
|
||||
// 0x5D34C0
|
||||
bool CPathFind::Save() {
|
||||
CGenericGameStorage::SaveDataToWorkBuffer(m_nNumForbiddenAreas);
|
||||
for (auto& area : std::span{ m_aForbiddenAreas, m_nNumForbiddenAreas }) {
|
||||
CGenericGameStorage::SaveDataToWorkBuffer(m_nNumNodeSwitches);
|
||||
for (auto& area : std::span{ m_aNodeSwitches, m_nNumNodeSwitches }) {
|
||||
CGenericGameStorage::SaveDataToWorkBuffer(area);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -975,8 +1005,8 @@ bool CPathFind::Save() {
|
|||
|
||||
// 0x5D3500
|
||||
bool CPathFind::Load() {
|
||||
CGenericGameStorage::LoadDataFromWorkBuffer(m_nNumForbiddenAreas);
|
||||
for (auto& area : std::span{ m_aForbiddenAreas, m_nNumForbiddenAreas }) {
|
||||
CGenericGameStorage::LoadDataFromWorkBuffer(m_nNumNodeSwitches);
|
||||
for (auto& area : std::span{ m_aNodeSwitches, m_nNumNodeSwitches }) {
|
||||
CGenericGameStorage::LoadDataFromWorkBuffer(area);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1040,11 +1070,8 @@ float CPathFind::FindNodeOrientationForCarPlacement(CNodeAddress nodeInfo) {
|
|||
}
|
||||
|
||||
// 0x452160
|
||||
void CPathFind::SwitchOffNodeAndNeighbours(CPathNode* node, CPathNode*& outNext1, CPathNode** outNext2, bool isOnDeadEnd, bool setIsDeadEndToOriginal) {
|
||||
const auto isNodeOnDeadEnd = setIsDeadEndToOriginal
|
||||
? node->m_isOriginallyOnDeadEnd
|
||||
: isOnDeadEnd;
|
||||
node->m_onDeadEnd = isNodeOnDeadEnd;
|
||||
void CPathFind::SwitchOffNodeAndNeighbours(CPathNode* node, CPathNode*& outNext1, CPathNode** outNext2, bool bWhatToSwitchTo, bool bBackToOriginal) {
|
||||
node->m_isSwitchedOff = bBackToOriginal ? node->m_isSwitchedOffOriginal : bWhatToSwitchTo;
|
||||
|
||||
outNext1 = nullptr;
|
||||
if (outNext2) {
|
||||
|
|
@ -1059,7 +1086,7 @@ void CPathFind::SwitchOffNodeAndNeighbours(CPathNode* node, CPathNode*& outNext1
|
|||
if (!linked.HasToBeSwitchedOff()) {
|
||||
continue;
|
||||
}
|
||||
if (linked.m_onDeadEnd == isNodeOnDeadEnd) {
|
||||
if (linked.m_isSwitchedOff == bWhatToSwitchTo) {
|
||||
continue;
|
||||
}
|
||||
if (CountNeighboursToBeSwitchedOff(*node) > 2) {
|
||||
|
|
@ -1248,3 +1275,63 @@ void CPathFind::AddNodeToList(CPathNode* node, int32 distFromOrigin) {
|
|||
|
||||
m_totalNumNodesInPathFindHashTable++;
|
||||
}
|
||||
|
||||
// 0x452C80
|
||||
void CPathFind::SwitchRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bCars, bool bBackToOriginal) {
|
||||
for (auto areaId = 0u; areaId < NUM_PATH_MAP_AREAS; ++areaId) {
|
||||
SwitchRoadsOffInAreaForOneRegion(xMin, xMax, yMin, yMax, zMin, zMax, bSwitchOff, bCars, areaId, bBackToOriginal);
|
||||
}
|
||||
|
||||
for (auto i = 0u; i < m_nNumNodeSwitches; ++i) {
|
||||
auto* pArea = &m_aNodeSwitches[i];
|
||||
|
||||
if (notsa::bugfixes::CPathFind_SwitchRoadsOffInArea_StrayAreas) {
|
||||
// some missions create both types of switches at the same area, so we store them separately
|
||||
if (pArea->isCars != bCars) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// avoid creating stray areas, potentially leaving no space for important areas later in game
|
||||
// ideally, the script would use SWITCH_ROADS_BACK_TO_ORIGINAL or SWITCH_PED_ROADS_BACK_TO_ORIGINAL but that's not always the case
|
||||
// so we consider toggling the same area as "back to original"
|
||||
if (pArea->xMin == xMin && pArea->yMin == yMin && pArea->zMin == zMin && pArea->xMax == xMax && pArea->yMax == yMax && pArea->zMax == zMax && pArea->isOff != bSwitchOff) {
|
||||
bBackToOriginal = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the existing area is completely inside the area we are switching off, remove it
|
||||
if (pArea->xMin < xMin || pArea->yMin < yMin || pArea->zMin < zMin || pArea->xMax > xMax || pArea->yMax > yMax || pArea->zMax > zMax) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto j = i; j < m_nNumNodeSwitches - 1; ++j) {
|
||||
if (notsa::bugfixes::CPathFind_SwitchRoadsOffInArea_StrayAreas) {
|
||||
m_aNodeSwitches[j] = m_aNodeSwitches[j + 1];
|
||||
} else {
|
||||
// R* bug, they messed up with the index
|
||||
m_aNodeSwitches[i] = m_aNodeSwitches[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
--m_nNumNodeSwitches;
|
||||
--i;
|
||||
}
|
||||
|
||||
if (!bBackToOriginal && m_nNumNodeSwitches < NUM_PATH_MAP_AREAS) {
|
||||
auto& area = m_aNodeSwitches[m_nNumNodeSwitches];
|
||||
area.xMin = xMin;
|
||||
area.xMax = xMax;
|
||||
area.yMin = yMin;
|
||||
area.yMax = yMax;
|
||||
area.zMin = zMin;
|
||||
area.zMax = zMax;
|
||||
area.isOff = bSwitchOff;
|
||||
area.isCars = bCars;
|
||||
m_nNumNodeSwitches++;
|
||||
}
|
||||
}
|
||||
|
||||
// 0x452F00
|
||||
void CPathFind::SwitchPedRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bBackToOriginal) {
|
||||
SwitchRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, bSwitchOff, false, bBackToOriginal);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,18 +34,18 @@ enum eTrafficLevel {
|
|||
TRAFFIC_LOW = 3,
|
||||
};
|
||||
|
||||
class CForbiddenArea {
|
||||
class CNodesSwitchedOnOrOff {
|
||||
public:
|
||||
float m_fXMin;
|
||||
float m_fXMax;
|
||||
float m_fYMin;
|
||||
float m_fYMax;
|
||||
float m_fZMin;
|
||||
float m_fZMax;
|
||||
bool m_bEnable;
|
||||
uint8 m_nType;
|
||||
float xMin;
|
||||
float xMax;
|
||||
float yMin;
|
||||
float yMax;
|
||||
float zMin;
|
||||
float zMax;
|
||||
bool isOff;
|
||||
bool isCars;
|
||||
};
|
||||
VALIDATE_SIZE(CForbiddenArea, 0x1C);
|
||||
VALIDATE_SIZE(CNodesSwitchedOnOrOff, 0x1C);
|
||||
|
||||
class CCarPathLinkAddress {
|
||||
public:
|
||||
|
|
@ -137,7 +137,7 @@ public:
|
|||
uint32 m_bWaterNode : 1;
|
||||
|
||||
// byte 1
|
||||
uint32 m_isOriginallyOnDeadEnd : 1;
|
||||
uint32 m_isSwitchedOffOriginal : 1;
|
||||
uint32 unk1 : 1; // not used in paths data files
|
||||
uint32 m_bDontWander : 1;
|
||||
uint32 unk2 : 1; // not used in paths data files
|
||||
|
|
@ -202,8 +202,7 @@ public:
|
|||
uint8* m_pLinkLengths[NUM_TOTAL_PATH_NODE_AREAS]; // 0xB64
|
||||
CPathIntersectionInfo* m_pPathIntersections[NUM_TOTAL_PATH_NODE_AREAS]; // 0xC84
|
||||
CCarPathLinkAddress* m_pNaviLinks[NUM_PATH_MAP_AREAS]; // 0xDA4
|
||||
void* m_aUnused[22]; // 0xEA4
|
||||
uint32 m_aUnk[NUM_PATH_MAP_AREAS - 22]; // 0xEFC
|
||||
void* m_aTempNodes[NUM_PATH_MAP_AREAS]; // 0xEA4
|
||||
uint32 m_anNumNodes[NUM_TOTAL_PATH_NODE_AREAS]; // 0xFA4
|
||||
uint32 m_anNumVehicleNodes[NUM_TOTAL_PATH_NODE_AREAS]; // 0x10C4
|
||||
uint32 m_anNumPedNodes[NUM_TOTAL_PATH_NODE_AREAS]; // 0x11E4
|
||||
|
|
@ -213,8 +212,8 @@ public:
|
|||
int32 m_aDynamicLinksIds[NUM_PATH_MAP_AREAS][NUM_DYNAMIC_LINKS_PER_AREA];
|
||||
uint32 m_totalNumNodesInPathFindHashTable; // Number of items in total in all buckets of `m_pathFindHashTable`
|
||||
uint32 m_interiorIDs[NUM_PATH_INTERIOR_AREAS];
|
||||
uint32 m_nNumForbiddenAreas;
|
||||
CForbiddenArea m_aForbiddenAreas[NUM_PATH_MAP_AREAS];
|
||||
uint32 m_nNumNodeSwitches;
|
||||
CNodesSwitchedOnOrOff m_aNodeSwitches[NUM_PATH_MAP_AREAS];
|
||||
|
||||
bool m_loadAreaRequestPending; /// Whenever an area to be loaded was requested via `MakeRequestForNodesToBeLoaded`
|
||||
// TODO: Replace below with CRect
|
||||
|
|
@ -290,9 +289,9 @@ public:
|
|||
bool ThisNodeHasToBeSwitchedOff(CPathNode* node);
|
||||
size_t CountNeighboursToBeSwitchedOff(const CPathNode& node);
|
||||
void SwitchOffNodeAndNeighbours(CPathNode* node, CPathNode*& outNext1, CPathNode** outNext2, bool lowTraffic, bool backToOriginal);
|
||||
void SwitchRoadsOffInAreaForOneRegion(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bLowTraffic, uint8 nodeType, int areaId, uint8 bUnused);
|
||||
void SwitchRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bLowTraffic, uint8 nodeType, bool bForbidden);
|
||||
void SwitchPedRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bLowTraffic, uint8 nodeType);
|
||||
void SwitchRoadsOffInAreaForOneRegion(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bCars, int areaId, bool bBackToOriginal);
|
||||
void SwitchRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bCars, bool bBackToOriginal);
|
||||
void SwitchPedRoadsOffInArea(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax, bool bSwitchOff, bool bBackToOriginal);
|
||||
void LoadPathFindData(RwStream* stream, int32 areaId);
|
||||
void LoadPathFindData(int32 areaId);
|
||||
void UnMarkAllRoadNodesAsDontWander();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace math { void RegisterHandlers(); };
|
|||
namespace mission { void RegisterHandlers(); };
|
||||
namespace object { void RegisterHandlers(); };
|
||||
namespace pad { void RegisterHandlers(); };
|
||||
namespace path { void RegisterHandlers(); };
|
||||
namespace ped { void RegisterHandlers(); };
|
||||
namespace player { void RegisterHandlers(); };
|
||||
namespace script { void RegisterHandlers(); };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
#include <StdInc.h>
|
||||
|
||||
#include "Commands.hpp"
|
||||
#include <CommandParser/Parser.hpp>
|
||||
#include "PathFind.h"
|
||||
using namespace notsa::script;
|
||||
|
||||
/*!
|
||||
* Various path commands
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
/// SWITCH_ROADS_ON(01E7)
|
||||
void SwitchRoadsOn(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, false, true, false);
|
||||
}
|
||||
|
||||
/// SWITCH_ROADS_OFF(01E8)
|
||||
void SwitchRoadsOff(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, true, true, false);
|
||||
}
|
||||
|
||||
/// SWITCH_ROADS_BACK_TO_ORIGINAL(091D)
|
||||
void SwitchRoadsBackToOriginal(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, false, true, true);
|
||||
}
|
||||
|
||||
/// SWITCH_PED_ROADS_ON(022A)
|
||||
void SwitchPedRoadsOn(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchPedRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, false, false);
|
||||
}
|
||||
|
||||
/// SWITCH_PED_ROADS_OFF(022B)
|
||||
void SwitchPedRoadsOff(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchPedRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, true, false);
|
||||
}
|
||||
|
||||
/// SWITCH_PED_ROADS_BACK_TO_ORIGINAL(091E)
|
||||
void SwitchPedRoadsBackToOriginal(float xA, float yA, float zA, float xB, float yB, float zB) {
|
||||
const auto xMin = std::min(xA, xB);
|
||||
const auto xMax = std::max(xA, xB);
|
||||
const auto yMin = std::min(yA, yB);
|
||||
const auto yMax = std::max(yA, yB);
|
||||
const auto zMin = std::min(zA, zB);
|
||||
const auto zMax = std::max(zA, zB);
|
||||
ThePaths.SwitchPedRoadsOffInArea(xMin, xMax, yMin, yMax, zMin, zMax, false, true);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void notsa::script::commands::path::RegisterHandlers() {
|
||||
REGISTER_COMMAND_HANDLER_BEGIN("Path");
|
||||
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_ROADS_ON, SwitchRoadsOn);
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_ROADS_OFF, SwitchRoadsOff);
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_ROADS_BACK_TO_ORIGINAL, SwitchRoadsBackToOriginal);
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_PED_ROADS_ON, SwitchPedRoadsOn);
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_PED_ROADS_OFF, SwitchPedRoadsOff);
|
||||
REGISTER_COMMAND_HANDLER(COMMAND_SWITCH_PED_ROADS_BACK_TO_ORIGINAL, SwitchPedRoadsBackToOriginal);
|
||||
}
|
||||
|
|
@ -69,4 +69,9 @@ inline const ReversibleBugFix CAEVehicleAudioEntity_PlayAircraftSound_VolumeFix{
|
|||
.Description = "Original code didn't account for event base volume",
|
||||
.Credit = "Pirulax"
|
||||
};
|
||||
inline const ReversibleBugFix CPathFind_SwitchRoadsOffInArea_StrayAreas{
|
||||
.Name = "CPathFind::SwitchRoadsOffInArea Stray-Areas",
|
||||
.Description = "Fix multiple issues related to saving unused path areas after missions",
|
||||
.Credit = "Contributors"
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue