Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(extra-natives/five): Add SET_INTERIOR_PROBE_LENGTH for FiveM #2371

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions code/components/extra-natives-five/src/InteriorExtraNatives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <atPool.h>
#include <DirectXMath.h>
#include <CrossBuildRuntime.h>
#include <GameInit.h>

#include "GameValueStub.h"

#define DECLARE_ACCESSOR(x) \
decltype(impl.m2060.x)& x() \
Expand Down Expand Up @@ -303,8 +306,37 @@ static int GetInteriorRoomIdByHash(CMloModelInfo* arch, int searchHash)
return -1;
}

static GameValueStub<float> g_emitterAudioEntityProbeLength;
static float g_interiorProbeLengthOverride = 0.0;

static bool (*g_CPortalTracker__Probe)(Vector3* pos, CInteriorInst** ppInteriorInstance, int* roomId, Vector3* traceImpactPoint, float traceLength);
static bool 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<void>("E8 ? ? ? ? 40 8A F8 49 ? ? E8");
hook::set_call(&g_CPortalTracker__Probe, location);
hook::call(location, CPortalTracker__Probe);
}

{
auto location = hook::get_pattern<uint32_t>("33 ED 39 A9 ? ? ? ? 0F 86 ? ? ? ? F3", 18);
g_emitterAudioEntityProbeLength.Init(*hook::get_address<float*>(location));
g_emitterAudioEntityProbeLength.SetLocation(location);
}

{
auto location = hook::get_pattern<char>("BA A1 85 94 52 41 B8 01", 0x34);

Expand Down Expand Up @@ -389,6 +421,30 @@ static HookFunction initFunction([]()
});
#endif

fx::ScriptEngine::RegisterNativeHandler("SET_INTERIOR_PROBE_LENGTH", [=](fx::ScriptContext& context)
{
auto length = context.GetArgument<float>(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<float>(0);
if (!std::isfinite(length))
{
return false;
}

g_emitterAudioEntityProbeLength.Set(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<int>(0);
Expand Down Expand Up @@ -865,4 +921,11 @@ static HookFunction initFunction([]()

return true;
});

// Sharing OnKillNetworkDone for probe lengths
OnKillNetworkDone.Connect([]()
{
g_interiorProbeLengthOverride = 0.0f;
g_emitterAudioEntityProbeLength.Reset();
});
});
34 changes: 34 additions & 0 deletions ext/native-decls/SetEmitterProbeLength.md
Original file line number Diff line number Diff line change
@@ -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)
40 changes: 40 additions & 0 deletions ext/native-decls/SetInteriorProbeLength.md
Original file line number Diff line number Diff line change
@@ -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)
Loading