diff --git a/red4ext/EdgeWeightGPS/src/Main.cpp b/red4ext/EdgeWeightGPS/src/Main.cpp index 8674d45..f42678e 100644 --- a/red4ext/EdgeWeightGPS/src/Main.cpp +++ b/red4ext/EdgeWeightGPS/src/Main.cpp @@ -99,7 +99,7 @@ constexpr uint32_t kGameStateRunning = 2; constexpr bool kEnableVerboseJournalListenerHooks = false; constexpr bool kEnableVerboseRouteObserverHooks = false; constexpr bool kEnableVerboseMappinRouteState = false; -constexpr bool kEnableGpsMultiplierHooks = false; +constexpr bool kEnableGpsMultiplierHooks = true; constexpr bool kEnableGpsCostTablePatch = false; constexpr bool kEnableGpsProviderClassPatch = false; constexpr bool kEnableGpsProviderClassPatchTrace = false; @@ -208,6 +208,9 @@ constexpr uint16_t kTrafficLaneFlagGpsOnly = 0x0200; constexpr uint16_t kTrafficLaneFlagNoAiDriving = 0x2000; constexpr uint16_t kTrafficLaneFlagHighway = 0x4000; constexpr uint16_t kTrafficLaneFlagNoAutodrive = 0x8000; +constexpr float kGpsSolverHighwayMultiplier = 0.35f; +constexpr float kGpsSolverGpsOnlyMultiplier = 1.10f; +constexpr float kGpsSolverPavementMultiplier = 1.25f; constexpr bool kGpsSpatialPatchRequiresRouteProducer = true; constexpr float kGpsSpatialHighwayMultiplier = 0.62f; constexpr float kGpsSpatialRoadMultiplier = 1.0f; @@ -306,6 +309,7 @@ uint32_t gGpsResolveHandleLogCount = 0; uint32_t gGpsEdgeCostLogCount = 0; uint32_t gGpsAuxMultiplierLogCount = 0; uint32_t gGpsNodeMultiplierLogCount = 0; +LONG gGpsSolverNodeWeightPatchLogCount = 0; uint32_t gGpsCostTablePatchLogCount = 0; uint32_t gGpsProviderClassPatchLogCount = 0; std::array gGpsResolveHandleRetLogCounts{}; @@ -4174,6 +4178,24 @@ const char* TrafficLaneCategory(uint16_t aFlags) return "other"; } +float GpsSolverNodeWeightMultiplier(uint16_t aFlags) +{ + if ((aFlags & kTrafficLaneFlagHighway) != 0) + { + return kGpsSolverHighwayMultiplier; + } + if ((aFlags & kTrafficLaneFlagGpsOnly) != 0) + { + return kGpsSolverGpsOnlyMultiplier; + } + if ((aFlags & kTrafficLaneFlagPavement) != 0) + { + return kGpsSolverPavementMultiplier; + } + + return 1.0f; +} + float TrafficEdgeScoreMultiplier(uint16_t aFlags, bool aDriving) { if (!aDriving) @@ -4850,7 +4872,54 @@ float DetourGpsNodeMultiplier(void* aJob, void* aNode) result = gOriginalGpsNodeMultiplier(aJob, aNode); } - LogGpsMultiplierSignature("GPSNodeMultiplier", kGpsNodeMultiplierRva, false, aJob, aNode, result, + const auto vanillaResult = result; + uint32_t mode = 0; + uint32_t retry = 0; + uint16_t nodeFlags = 0; + const auto jobAddress = reinterpret_cast(aJob); + const auto nodeAddress = reinterpret_cast(aNode); + const auto hasMode = aJob && TryReadMemory(reinterpret_cast(jobAddress + 0xC4), mode); + const auto hasFlags = aNode && TryReadMemory(reinterpret_cast(nodeAddress + 0x88), nodeFlags); + if (aJob) + { + TryReadMemory(reinterpret_cast(jobAddress + 0x54), retry); + } + + if (hasMode && hasFlags && mode == 2 && std::isfinite(result)) + { + const auto patchMultiplier = GpsSolverNodeWeightMultiplier(nodeFlags); + if (patchMultiplier != 1.0f) + { + result *= patchMultiplier; + + constexpr LONG kMaxLoggedCalls = 96; + LONG callCount = -1; + if (InterlockedCompareExchange(&gGpsSolverNodeWeightPatchLogCount, 0, 0) < kMaxLoggedCalls) + { + callCount = InterlockedIncrement(&gGpsSolverNodeWeightPatchLogCount) - 1; + } + + if (callCount >= 0 && callCount < kMaxLoggedCalls) + { + std::ostringstream line; + const auto flags = line.flags(); + const auto precision = line.precision(); + line << "hook GPSNodeMultiplierPatch 0x" << std::hex << kGpsNodeMultiplierRva << std::dec + << " call=" << callCount << " category=" << TrafficLaneCategory(nodeFlags) + << " mode=" << mode << " retry=" << retry << " flags88=0x" << std::hex << nodeFlags + << std::dec << " vanilla=" << std::fixed << std::setprecision(3) << vanillaResult + << " multiplier=" << patchMultiplier << " result=" << result; + line.flags(flags); + line.precision(precision); + AppendPointerWithRva(line, "job", aJob); + AppendPointerWithRva(line, "node", aNode); + AppendReturnRva(line, __builtin_return_address(0)); + LogRed4ext(line.str()); + } + } + } + + LogGpsMultiplierSignature("GPSNodeMultiplier", kGpsNodeMultiplierRva, false, aJob, aNode, vanillaResult, __builtin_return_address(0)); return result; }