Patch traffic edge score weighting

This commit is contained in:
2026-06-20 22:45:25 -05:00
parent 2db6eefebd
commit 8a0f23dee8
+137
View File
@@ -102,6 +102,7 @@ constexpr bool kEnableGpsProviderClassPatchTrace = false;
constexpr bool kEnableGpsTraceHooks = true;
constexpr bool kEnableGpsQueryLifecycleHooks = true;
constexpr bool kEnableGpsAsyncTrafficProbe = true;
constexpr bool kEnableGpsTrafficEdgeWeightPatch = true;
constexpr bool kEnableGpsRouteJobLifecycleHooks = false;
constexpr bool kEnableGpsRouteJobStartTrace = false;
constexpr bool kEnableGpsLocalSearchHooks = false;
@@ -165,6 +166,7 @@ constexpr uintptr_t kGpsMapRouteSubmitReturnRva = 0x08D20D4;
constexpr uintptr_t kGpsDispatchAdvanceRva = 0x08D17D8;
constexpr uintptr_t kGpsTrafficResultTakeRva = 0x0709D5C;
constexpr uintptr_t kGpsRoutePostprocessRva = 0x044830C;
constexpr uintptr_t kGpsTrafficEdgeScoreRva = 0x08D46CC;
constexpr uintptr_t kGpsAsyncWorkerTickRva = 0x0126B28;
constexpr uintptr_t kGpsRouteJobStartRva = 0x0818928;
constexpr uintptr_t kGpsRouteJobPollRva = 0x0883CD8;
@@ -189,6 +191,12 @@ constexpr std::array<float, 7> kGpsPatchedCostMultipliers = {
12.0f, 7.0f, 2.5f, 0.0f, 3.0f, 2.0f, 1.25f,
};
constexpr size_t kGpsProviderClassCount = 64;
constexpr uint16_t kTrafficLaneFlagPavement = 0x0008;
constexpr uint16_t kTrafficLaneFlagRoad = 0x0010;
constexpr uint16_t kTrafficLaneFlagGpsOnly = 0x0200;
constexpr uint16_t kTrafficLaneFlagNoAiDriving = 0x2000;
constexpr uint16_t kTrafficLaneFlagHighway = 0x4000;
constexpr uint16_t kTrafficLaneFlagNoAutodrive = 0x8000;
struct GpsProviderClassOverride
{
@@ -268,6 +276,7 @@ uint32_t gGpsQueryStatusLogCount = 0;
uint32_t gGpsDispatchAdvanceLogCount = 0;
uint32_t gGpsTrafficResultTakeLogCount = 0;
uint32_t gGpsRoutePostprocessLogCount = 0;
LONG gGpsTrafficEdgeScoreLogCount = 0;
uint32_t gGpsAsyncWorkerTickLogCount = 0;
uint32_t gGpsRouteJobStartLogCount = 0;
uint32_t gGpsRouteJobPollLogCount = 0;
@@ -423,6 +432,7 @@ using GpsDispatchAdvanceFunc = void (*)(void* aRouteSystem, void* aRuntimeQuery,
using GpsTrafficResultTakeFunc = void* (*)(void* aTrafficService, void* aOutResult, uint32_t aTicket,
void* aOutMeta);
using GpsRoutePostprocessFunc = void (*)(void* aOutPath, void* aTrafficResult, void* aRouteRecords, float aScale);
using GpsTrafficEdgeScoreFunc = float (*)(void* aSearchContext, void* aCandidate, void* aReferencePoint);
using GpsAsyncWorkerTickFunc = void (*)(void* aRouteSystem);
using GpsRouteJobStartFunc = bool (*)(void* aRouteSystem, void* aActiveEntry, float aDelta, void* aOutLocal);
using GpsRouteJobPollFunc = bool (*)(void* aRouteSystem, void* aActiveEntry);
@@ -492,6 +502,7 @@ GpsQueryStatusFunc gOriginalGpsQueryStatus = nullptr;
GpsDispatchAdvanceFunc gOriginalGpsDispatchAdvance = nullptr;
GpsTrafficResultTakeFunc gOriginalGpsTrafficResultTake = nullptr;
GpsRoutePostprocessFunc gOriginalGpsRoutePostprocess = nullptr;
GpsTrafficEdgeScoreFunc gOriginalGpsTrafficEdgeScore = nullptr;
GpsAsyncWorkerTickFunc gOriginalGpsAsyncWorkerTick = nullptr;
GpsRouteJobStartFunc gOriginalGpsRouteJobStart = nullptr;
GpsRouteJobPollFunc gOriginalGpsRouteJobPoll = nullptr;
@@ -3759,6 +3770,122 @@ void DetourGpsRoutePostprocess(void* aOutPath, void* aTrafficResult, void* aRout
}
}
const char* TrafficLaneCategory(uint16_t aFlags)
{
if ((aFlags & kTrafficLaneFlagHighway) != 0)
{
return "highway";
}
if ((aFlags & kTrafficLaneFlagRoad) != 0)
{
return "road";
}
if ((aFlags & kTrafficLaneFlagPavement) != 0)
{
return "pavement";
}
if ((aFlags & kTrafficLaneFlagGpsOnly) != 0)
{
return "gpsonly";
}
return "other";
}
float TrafficEdgeScoreMultiplier(uint16_t aFlags, bool aDriving)
{
if (!aDriving)
{
return 1.0f;
}
if ((aFlags & kTrafficLaneFlagHighway) != 0)
{
return 0.35f;
}
if ((aFlags & kTrafficLaneFlagRoad) != 0)
{
return 0.70f;
}
if ((aFlags & kTrafficLaneFlagGpsOnly) != 0)
{
return 1.35f;
}
if ((aFlags & kTrafficLaneFlagPavement) != 0)
{
return 2.75f;
}
return 1.50f;
}
float DetourGpsTrafficEdgeScore(void* aSearchContext, void* aCandidate, void* aReferencePoint)
{
float baseScore = 0.0f;
if (gOriginalGpsTrafficEdgeScore)
{
baseScore = gOriginalGpsTrafficEdgeScore(aSearchContext, aCandidate, aReferencePoint);
}
void* query = nullptr;
void* lane = nullptr;
uint8_t queryMode = 0xFF;
uint16_t laneFlags = 0;
if (aSearchContext)
{
query = *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(aSearchContext) + 0x10);
}
if (query)
{
queryMode = *reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(query) + 0x41);
}
if (aCandidate)
{
lane = *reinterpret_cast<void**>(aCandidate);
}
if (lane)
{
laneFlags = *reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(lane) + 0x88);
}
const auto driving = queryMode == 0;
const auto multiplier = TrafficEdgeScoreMultiplier(laneFlags, driving);
const auto patchedScore = baseScore * multiplier;
constexpr LONG kMaxLoggedCalls = 256;
LONG callCount = -1;
if (gGpsTrafficEdgeScoreLogCount < kMaxLoggedCalls)
{
callCount = InterlockedIncrement(&gGpsTrafficEdgeScoreLogCount) - 1;
}
if (callCount >= 0 && callCount < kMaxLoggedCalls)
{
std::ostringstream line;
const auto flags = line.flags();
const auto precision = line.precision();
line << "hook GPSTrafficEdgeScore 0x8d46cc call=" << callCount
<< " category=" << TrafficLaneCategory(laneFlags)
<< " driving=" << static_cast<uint32_t>(driving)
<< " query41=" << static_cast<uint32_t>(queryMode)
<< " laneFlags88=0x" << std::hex << laneFlags << std::dec
<< " base=" << std::fixed << std::setprecision(3) << baseScore
<< " multiplier=" << multiplier
<< " result=" << patchedScore;
line.flags(flags);
line.precision(precision);
AppendPointerWithRva(line, "ctx", aSearchContext);
AppendPointerWithRva(line, "query", query);
AppendPointerWithRva(line, "candidate", aCandidate);
AppendPointerWithRva(line, "lane", lane);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
return patchedScore;
}
void DetourGpsAsyncWorkerTick(void* aRouteSystem)
{
constexpr uint32_t kMaxCalls = 192;
@@ -4667,6 +4794,12 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
reinterpret_cast<void*>(&DetourGpsRoutePostprocess),
reinterpret_cast<void**>(&gOriginalGpsRoutePostprocess));
}
if (kEnableGpsTrafficEdgeWeightPatch)
{
AttachProbeHook("GPSTrafficEdgeScore 0x8d46cc", kGpsTrafficEdgeScoreRva,
reinterpret_cast<void*>(&DetourGpsTrafficEdgeScore),
reinterpret_cast<void**>(&gOriginalGpsTrafficEdgeScore));
}
if (kEnableGpsRouteJobLifecycleHooks)
{
AttachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva,
@@ -4853,6 +4986,10 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
DetachProbeHook("GPSTrafficResultTake 0x709d5c", kGpsTrafficResultTakeRva);
DetachProbeHook("GPSRoutePostprocess 0x44830c", kGpsRoutePostprocessRva);
}
if (kEnableGpsTrafficEdgeWeightPatch)
{
DetachProbeHook("GPSTrafficEdgeScore 0x8d46cc", kGpsTrafficEdgeScoreRva);
}
if (kEnableGpsRouteJobLifecycleHooks)
{
DetachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva);