Skip to content

Commit

Permalink
feat(client/five): have GetIsTaskActive recognize CTaskCombatRoll
Browse files Browse the repository at this point in the history
Fixes #2401
  • Loading branch information
gottfriedleibniz committed Mar 10, 2024
1 parent 5a7de00 commit f2f9858
Showing 1 changed file with 104 additions and 0 deletions.
104 changes: 104 additions & 0 deletions code/components/extra-natives-five/src/NativeEdits.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,111 @@
#include <StdInc.h>
#include <GameInit.h>

#include <Hooking.h>

#include <ScriptEngine.h>
#include <scrEngine.h>

namespace rage
{
class aiTaskTree
{
public:
bool FindActiveTaskByType(int taskIndex);
};
};

class CPedIntelligence
{
public:
inline static ptrdiff_t kMotionTreeOffset;
inline static ptrdiff_t kPedIntelligenceOffset;

public:
inline rage::aiTaskTree* GetMotionTaskTree()
{
auto location = reinterpret_cast<char*>(this) + kMotionTreeOffset;
return *reinterpret_cast<rage::aiTaskTree**>(location);
}

inline bool HasMotionTaskByType(int32_t taskIndex)
{
if (auto tree = GetMotionTaskTree())
{
return tree->FindActiveTaskByType(taskIndex);
}
return false;
}

// Utility function that should eventually be moved to CPed
static inline CPedIntelligence* GetIntelligence(CPed* ped)
{
auto location = reinterpret_cast<char*>(ped) + kPedIntelligenceOffset;
return *reinterpret_cast<CPedIntelligence**>(location);
}
};

static hook::cdecl_stub<bool(rage::aiTaskTree*, int)> _findTaskByType([]()
{
return hook::get_pattern("83 79 10 FF 74 20 48 63 41 10 48 8B 4C C1");
});

bool rage::aiTaskTree::FindActiveTaskByType(int taskIndex)
{
return _findTaskByType(this, taskIndex);
}

// GH-2401: Have GET_IS_TASK_ACTIVE search the motion-tree for TASK_COMBAT_ROLL.
// CTaskCombatRoll is used only as a subtask of CTaskMotionAiming which will not
// be exposed via GET_IS_TASK_ACTIVE.
static void EditIsTaskActive()
{
constexpr uint64_t GET_IS_TASK_ACTIVE = 0xB0760331C7AA4155;

const auto originalHandler = fx::ScriptEngine::GetNativeHandler(GET_IS_TASK_ACTIVE);
if (!originalHandler)
{
return;
}

const auto handler = *originalHandler;
fx::ScriptEngine::RegisterNativeHandler(GET_IS_TASK_ACTIVE, [handler](fx::ScriptContext& ctx)
{
constexpr int32_t TASK_COMBAT_ROLL = 0x3;
uint32_t pedHandle = ctx.GetArgument<uint32_t>(0);
uint32_t taskIndex = ctx.GetArgument<uint32_t>(1);

handler(ctx);
if (taskIndex != TASK_COMBAT_ROLL || ctx.GetResult<bool>())
{
return;
}

// Could not find TASK_COMBAT_ROLL check the peds motion task tree.
auto ped = rage::fwScriptGuid::GetBaseFromGuid(pedHandle);
if (ped && ped->IsOfType<CPed>())
{
if (auto intelligence = CPedIntelligence::GetIntelligence(reinterpret_cast<CPed*>(ped)))
{
if (intelligence->HasMotionTaskByType(TASK_COMBAT_ROLL))
{
ctx.SetResult<bool>(true);
}
}
}
});
}

static bool* g_ropesCreateNetworkWorldState;

static HookFunction hookFunction([]()
{
{
auto location = hook::get_pattern<char>("84 C0 0F 84 ? ? ? ? 48 8B 82 ? ? ? ? BA");
CPedIntelligence::kPedIntelligenceOffset = *reinterpret_cast<int32_t*>(location + 0xB);
CPedIntelligence::kMotionTreeOffset = *reinterpret_cast<int32_t*>(location + 0x17);
}

g_ropesCreateNetworkWorldState = (bool*)hook::AllocateStubMemory(1);
*g_ropesCreateNetworkWorldState = false;

Expand All @@ -24,4 +123,9 @@ static HookFunction hookFunction([]()
{
*g_ropesCreateNetworkWorldState = false;
});

rage::scrEngine::OnScriptInit.Connect([]()
{
EditIsTaskActive();
});
});

0 comments on commit f2f9858

Please sign in to comment.