From aab84c45c090246f5d7f333abda0f0fe0ea90c5c Mon Sep 17 00:00:00 2001 From: z3t4s <26795431+z3t4s@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:55:40 +0100 Subject: [PATCH] feat(extra-natives/five): CPortalTracker ScRT CPortalTracker probeLength adjustments via custom ScRT Native Co-authored-by: nikez <1504588+nikez@users.noreply.github.com> Co-authored-by: okqut <38298546+okqut@users.noreply.github.com> --- .../src/InteriorExtraNatives.cpp | 61 +++++++++++++++++++ ext/native-decls/SetEmitterProbeLength.md | 34 +++++++++++ ext/native-decls/SetInteriorProbeLength.md | 40 ++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 ext/native-decls/SetEmitterProbeLength.md create mode 100644 ext/native-decls/SetInteriorProbeLength.md diff --git a/code/components/extra-natives-five/src/InteriorExtraNatives.cpp b/code/components/extra-natives-five/src/InteriorExtraNatives.cpp index 910e53df60..8706f17294 100644 --- a/code/components/extra-natives-five/src/InteriorExtraNatives.cpp +++ b/code/components/extra-natives-five/src/InteriorExtraNatives.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #define DECLARE_ACCESSOR(x) \ decltype(impl.m2060.x)& x() \ @@ -303,8 +304,37 @@ static int GetInteriorRoomIdByHash(CMloModelInfo* arch, int searchHash) return -1; } +float* g_emitterAudioEntityProbeLength = nullptr; +static float g_interiorProbeLengthOverride = 0.0; + +static bool (*g_CPortalTracker__Probe)(Vector3* pos, CInteriorInst** ppInteriorInstance, int* roomId, Vector3* traceImpactPoint, float traceLength); +bool __fastcall CPortalTracker__Probe(Vector3* pos, CInteriorInst** ppInteriorInstance, int* roomId, Vector3* traceImpactPoint, float traceLength) +{ + // game code has a lot of different special case handling in CPortalTracker::vft0x8 + // joaat('xs_arena_interior') seems to be the case with the longest traceLength override (150.f) + // + if (g_interiorProbeLengthOverride > 0.0f && traceLength < g_interiorProbeLengthOverride) + { + traceLength = g_interiorProbeLengthOverride; + } + + return g_CPortalTracker__Probe(pos, ppInteriorInstance, roomId, traceImpactPoint, traceLength); +} + static HookFunction initFunction([]() { + { + auto location = hook::get_pattern("E8 ? ? ? ? 40 8A F8 49 ? ? E8"); + hook::set_call(&g_CPortalTracker__Probe, location); + hook::call(location, CPortalTracker__Probe); + } + + { + auto location = hook::get_pattern("33 ED 39 A9 ? ? ? ? 0F 86 ? ? ? ? F3", 18); + g_emitterAudioEntityProbeLength = (float*) hook::AllocateStubMemory(sizeof(float)); + hook::put(location, (intptr_t)g_emitterAudioEntityProbeLength - (intptr_t)location - 4); + } + { auto location = hook::get_pattern("BA A1 85 94 52 41 B8 01", 0x34); @@ -389,6 +419,30 @@ static HookFunction initFunction([]() }); #endif + fx::ScriptEngine::RegisterNativeHandler("SET_INTERIOR_PROBE_LENGTH", [=](fx::ScriptContext& context) + { + auto length = context.GetArgument(0); + if (!std::isfinite(length)) + { + return false; + } + + g_interiorProbeLengthOverride = std::clamp(length, 0.0f, 150.0f); + return true; + }); + + fx::ScriptEngine::RegisterNativeHandler("SET_EMITTER_PROBE_LENGTH", [=](fx::ScriptContext& context) + { + auto length = context.GetArgument(0); + if (!std::isfinite(length)) + { + return false; + } + + *g_emitterAudioEntityProbeLength = std::clamp(length, 20.0f, 150.0f); + return true; + }); + fx::ScriptEngine::RegisterNativeHandler("GET_INTERIOR_ROOM_INDEX_BY_HASH", [=](fx::ScriptContext& context) { auto interiorId = context.GetArgument(0); @@ -865,4 +919,11 @@ static HookFunction initFunction([]() return true; }); + + // Sharing OnKillNetworkDone for probe lengths + OnKillNetworkDone.Connect([]() + { + g_interiorProbeLengthOverride = 0.0f; + *g_emitterAudioEntityProbeLength = 0.0f; + }); }); diff --git a/ext/native-decls/SetEmitterProbeLength.md b/ext/native-decls/SetEmitterProbeLength.md new file mode 100644 index 0000000000..cfa6bb44e4 --- /dev/null +++ b/ext/native-decls/SetEmitterProbeLength.md @@ -0,0 +1,34 @@ +--- +ns: CFX +apiset: client +game: gta5 +--- +## SET_EMITTER_PROBE_LENGTH + +```c +void SET_EMITTER_PROBE_LENGTH(float probeLength); +``` + +Allows StaticEmitter's without a linked entity to make use of environment features like occlusion and reverb even if they are located higher than 20.0 units above any static collision inside interiors. + +This native allows you to extend the probe range up to 150.0 units. + +## Examples + +```lua +RegisterCommand("setEmitterProbeLength", function(src, args, raw) + local probeLength = (tonumber(args[1]) + 0.0) + + print("Extending emitter probes to: ", probeLength) + SetEmitterProbeLength(probeLength) +end) + +RegisterCommand("resetEmitterProbeLength", function() + print("Resetting emitter probes to default settings") + SetEmitterProbeLength(20.0) +end) +``` + + +## Parameters +* **probeLength**: The desired probe length (20.0 - 150.0) \ No newline at end of file diff --git a/ext/native-decls/SetInteriorProbeLength.md b/ext/native-decls/SetInteriorProbeLength.md new file mode 100644 index 0000000000..ba90aec590 --- /dev/null +++ b/ext/native-decls/SetInteriorProbeLength.md @@ -0,0 +1,40 @@ +--- +ns: CFX +apiset: client +game: gta5 +--- +## SET_INTERIOR_PROBE_LENGTH + +```c +void SET_INTERIOR_PROBE_LENGTH(float probeLength); +``` + +Overwrite the games default CPortalTracker interior detection range. +This fixes potentially unwanted behaviour in the base game and allows you to build custom interiors with larger ceiling heights without running into graphical glitches. + +By default CPortalTracker will probe 4 units downward trying to reach collisions that are part of the interior the entity is in. +If no collision can be found 16 units are used in some circumstances. + +There are 30+ hard coded special cases, only some of them exposed via script (for example `ENABLE_STADIUM_PROBES_THIS_FRAME`). + +This native allows you to extend the probe range up to 150 units which is the same value the game uses for the `xs_arena_interior` + +## Examples + +```lua +RegisterCommand("setInteriorProbeLength", function(src, args, raw) + local probeLength = (tonumber(args[1]) + 0.0) + + print("Extending interior detection probes to: ", probeLength) + SetInteriorProbeLength(probeLength) +end) + +RegisterCommand("resetInteriorProbeLength", function() + print("Resetting interior detection probes to default settings") + SetInteriorProbeLength(0.0) +end) +``` + + +## Parameters +* **probeLength**: The desired probe length (0.0 - 150.0) \ No newline at end of file