Skip to content

Commit

Permalink
feat(extra-natives/five): CPortalTracker ScRT
Browse files Browse the repository at this point in the history
CPortalTracker probeLength adjustments via custom ScRT Native

Co-authored-by: nikez <[email protected]>
Co-authored-by: okqut <[email protected]>
  • Loading branch information
3 people committed Feb 1, 2024
1 parent 88a0a6c commit 50788c2
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
36 changes: 36 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,7 @@
#include <atPool.h>
#include <DirectXMath.h>
#include <CrossBuildRuntime.h>
#include <GameInit.h>

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

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 handlings in CPortalTracker::vft0x8
// joat('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);

fx::ScriptEngine::RegisterNativeHandler("SET_INTERIOR_PROBE_LENGTH", [=](fx::ScriptContext& context)
{
auto length = context.GetArgument<float>(0);
if (std::isnan(length) || std::isinf(length))
return false;

g_interiorProbeLengthOverride = std::clamp(length, 0.0f, 150.0f);
return true;
});

OnKillNetworkDone.Connect([]()
{
g_interiorProbeLengthOverride = 0.0f;
});
}

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

Expand Down
39 changes: 39 additions & 0 deletions ext/native-decls/SetInteriorProbeLength.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
ns: CFX
apiset: client
---
## 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)

0 comments on commit 50788c2

Please sign in to comment.