feat(anticheat): Anticheat bypass improvements (#2463)

- Add more metrics to bad_metrics set
- Add MM Filtering (This metric shouldnt be normally called anyway)
- Improve QD Hook to increase AC verifier delay when detected
- Removed gameskeleton hook in favor of patching ac at init
- Added tamperactions check to gameskeleton patcher
This commit is contained in:
yubie 2023-11-30 04:47:39 -05:00 committed by GitHub
parent f0302ab135
commit 062c95b374
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 173 additions and 133 deletions

View File

@ -3,7 +3,7 @@ include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
gtav_classes gtav_classes
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
GIT_TAG 3c7763fcf996f53f891e40f12bbfa8115fd612a7 GIT_TAG 9e76175d28b3de21c24a69e71bee779d704d8304
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""

View File

@ -64,7 +64,7 @@ namespace big::functions
using ptr_to_handle = Entity (*)(void*); using ptr_to_handle = Entity (*)(void*);
using handle_to_ptr = rage::CDynamicEntity* (*)(Entity); using handle_to_ptr = rage::CDynamicEntity* (*)(Entity);
using set_gravity_level = void(*)(int level); using set_gravity_level = void (*)(int level);
using check_chat_profanity = int(__int64 chat_type, const char* input, const char** output); using check_chat_profanity = int(__int64 chat_type, const char* input, const char** output);
using write_player_game_state_data_node = bool (*)(rage::netObject* plr, CPlayerGameStateDataNode* node); using write_player_game_state_data_node = bool (*)(rage::netObject* plr, CPlayerGameStateDataNode* node);
@ -120,9 +120,9 @@ namespace big::functions
using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, int num_handles, rage::rlQueryPresenceAttributesContext** contexts, int count, rage::rlScTaskStatus* state); using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, int num_handles, rage::rlQueryPresenceAttributesContext** contexts, int count, rage::rlScTaskStatus* state);
using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount);
using invite_player_by_gamer_handle = bool(*)(uint64_t config, rage::rlGamerHandle* handle, int unk1, int unk2, int unk3, int unk4); using invite_player_by_gamer_handle = bool (*)(uint64_t config, rage::rlGamerHandle* handle, int unk1, int unk2, int unk3, int unk4);
using add_friend_by_gamer_handle = void(*)(rage::rlGamerHandle* handle, const char* unk); using add_friend_by_gamer_handle = void (*)(rage::rlGamerHandle* handle, const char* unk);
using show_profile_by_gamer_handle = void(*)(rage::rlGamerHandle* handle); using show_profile_by_gamer_handle = void (*)(rage::rlGamerHandle* handle);
using generate_uuid = bool (*)(uint64_t* uuid); using generate_uuid = bool (*)(uint64_t* uuid);
@ -194,9 +194,9 @@ namespace big::functions
using delete_vehicle = bool (*)(CVehicle* veh); using delete_vehicle = bool (*)(CVehicle* veh);
using delete_object = bool (*)(CObject* object, bool unk); using delete_object = bool (*)(CObject* object, bool unk);
using decal_manager_remove = void(*)(PVOID manager, rage::fwEntity*, DWORD a3, DWORD64 a4, DWORD ignore_bitset); using decal_manager_remove = void (*)(PVOID manager, rage::fwEntity*, DWORD a3, DWORD64 a4, DWORD ignore_bitset);
using remove_player_from_sender_list = bool(*)(void* list, uint64_t* rockstar_id); using remove_player_from_sender_list = bool (*)(void* list, uint64_t* rockstar_id);
using get_ped_bone = bool(*)(CPed* ped_ptr, rage::fvector4& output, PedBones bone); using get_ped_bone = bool (*)(CPed* ped_ptr, rage::fvector4& output, PedBones bone);
} }

View File

@ -18,12 +18,11 @@ namespace rage
buffer(_buffer), buffer(_buffer),
maxlen(_length) maxlen(_length)
{ {
unk0 unk0 = 0;
= 0; unk1 = 0;
unk1 = 0; curlen = 0;
curlen = 0; unk4 = 1;
unk4 = 1; flags = 0;
flags = 0;
} }
inline char* get_string() const inline char* get_string() const

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <memory/handle.hpp>
#include "function_types.hpp" #include "function_types.hpp"
#include <memory/handle.hpp>
class CCommunications; class CCommunications;
class FriendRegistry; class FriendRegistry;
class CNetworkPlayerMgr; class CNetworkPlayerMgr;
@ -27,6 +28,7 @@ namespace rage
class RageSecurity; class RageSecurity;
class netTime; class netTime;
class rlGamerInfo; class rlGamerInfo;
struct game_skeleton;
} }
template<typename T> template<typename T>
@ -71,6 +73,8 @@ namespace big
CPedFactory** m_ped_factory; CPedFactory** m_ped_factory;
CNetworkPlayerMgr** m_network_player_mgr; CNetworkPlayerMgr** m_network_player_mgr;
CNetworkObjectMgr** m_network_object_mgr; CNetworkObjectMgr** m_network_object_mgr;
rage::game_skeleton* m_game_skeleton;
void (*m_nullsub)();
functions::ptr_to_handle m_ptr_to_handle; functions::ptr_to_handle m_ptr_to_handle;
functions::handle_to_ptr m_handle_to_ptr; functions::handle_to_ptr m_handle_to_ptr;
@ -353,8 +357,6 @@ namespace big
bool* m_is_social_club_overlay_active; bool* m_is_social_club_overlay_active;
PVOID m_game_skeleton_update;
functions::get_ped_bone m_get_ped_bone; functions::get_ped_bone m_get_ped_bone;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "gta/script_thread.hpp" #include "gta/script_thread.hpp"
#include "script/tlsContext.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "script/tlsContext.hpp"
#include <network/CNetworkPlayerMgr.hpp> #include <network/CNetworkPlayerMgr.hpp>
#include <ped/CPedFactory.hpp> #include <ped/CPedFactory.hpp>

View File

@ -147,8 +147,6 @@ namespace big
detour_hook_helper::add<hooks::read_bits_single>("RBS", g_pointers->m_gta.m_read_bits_single); detour_hook_helper::add<hooks::read_bits_single>("RBS", g_pointers->m_gta.m_read_bits_single);
detour_hook_helper::add<hooks::game_skeleton_update>("GSU", g_pointers->m_gta.m_game_skeleton_update);
g_hooking = this; g_hooking = this;
} }

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "MinHook.h" #include "MinHook.h"
#include "call_hook.hpp"
#include "common.hpp" #include "common.hpp"
#include "detour_hook.hpp" #include "detour_hook.hpp"
#include "gta/enums.hpp" #include "gta/enums.hpp"
#include "gta/fwddec.hpp" #include "gta/fwddec.hpp"
#include "gta/script_thread.hpp"
#include "gta/json_serializer.hpp" #include "gta/json_serializer.hpp"
#include "gta/script_thread.hpp"
#include "vmt_hook.hpp" #include "vmt_hook.hpp"
#include "vtable_hook.hpp" #include "vtable_hook.hpp"
#include "call_hook.hpp"
#include <network/netConnection.hpp> #include <network/netConnection.hpp>
@ -128,7 +128,7 @@ namespace big
static void serialize_parachute_task(__int64 info, rage::CSyncDataBase* serializer); static void serialize_parachute_task(__int64 info, rage::CSyncDataBase* serializer);
static int nt_query_virtual_memory(void* _this, HANDLE handle, PVOID base_addr, int info_class, MEMORY_BASIC_INFORMATION* info, int size, size_t* return_len); static int nt_query_virtual_memory(void* _this, HANDLE handle, PVOID base_addr, int info_class, MEMORY_BASIC_INFORMATION* info, int size, size_t* return_len);
static int queue_dependency(void* a1, int a2, void* dependency); static int queue_dependency(void* a1, int a2, int64_t dependency);
static bool prepare_metric_for_sending(rage::json_serializer* bit_buffer, int unk, int time, rage::rlMetric* metric); static bool prepare_metric_for_sending(rage::json_serializer* bit_buffer, int unk, int time, rage::rlMetric* metric);
static bool http_start_request(void* request, const char* uri); static bool http_start_request(void* request, const char* uri);
@ -185,7 +185,6 @@ namespace big
static bool sync_reader_serialize_array(void* _this, void* array, int size); static bool sync_reader_serialize_array(void* _this, void* array, int size);
static bool remove_player_from_sender_list(void* list, uint64_t rockstar_id); static bool remove_player_from_sender_list(void* list, uint64_t rockstar_id);
static void game_skeleton_update(__int64 skeleton, int type);
}; };
class minhook_keepalive class minhook_keepalive

View File

@ -3,7 +3,7 @@
namespace big namespace big
{ {
const auto bad_metrics = std::unordered_set<std::string>({ const auto bad_metrics = std::unordered_set<std::string_view>({
"REPORTER", "REPORTER",
"REPORT_INVALIDMODEL", "REPORT_INVALIDMODEL",
"MEM_NEW", "MEM_NEW",
@ -36,6 +36,7 @@ namespace big
"GSINT", "GSINT",
"EARN", "EARN",
"GARAGE_TAMPER", "GARAGE_TAMPER",
"DUPE_DETECT",
"LAST_VEH", "LAST_VEH",
"FAIL_SERV", "FAIL_SERV",
"CCF_UPDATE", "CCF_UPDATE",
@ -43,25 +44,72 @@ namespace big
"COLLECTIBLE", "COLLECTIBLE",
"FIRST_VEH", "FIRST_VEH",
"MM", "MM",
"RDEV",
"RQA",
"RANK_UP",
}); });
std::string hex_encode(std::string_view input) {
const char* hex_chars = "0123456789ABCDEF";
std::string output;
output.reserve(input.length() * 2); // Pre-allocate memory for efficiency
for (unsigned char c : input) {
output.push_back(hex_chars[c >> 4]); // Extract the high nibble (4 bits)
output.push_back(hex_chars[c & 0x0F]); // Extract the low nibble
}
return output;
}
std::string remove_module_from_mmlist(std::string_view input, std::string_view element_to_remove) {
std::string result(input);
std::string delimiter = "|";
size_t start_pos = 0;
while (true) {
size_t delimiter_pos = result.find(delimiter, start_pos);
if (delimiter_pos == std::string::npos) {
break;
}
std::string current_element = result.substr(start_pos, delimiter_pos - start_pos);
if (current_element == element_to_remove) {
result.erase(start_pos, delimiter_pos - start_pos + delimiter.length());
break;
}
start_pos = delimiter_pos + delimiter.length();
}
return result;
}
bool hooks::prepare_metric_for_sending(rage::json_serializer* serializer, int unk, int time, rage::rlMetric* metric) bool hooks::prepare_metric_for_sending(rage::json_serializer* serializer, int unk, int time, rage::rlMetric* metric)
{ {
const auto ret = g_hooking->get_original<prepare_metric_for_sending>()(serializer, unk, time, metric); char metric_json_buffer [256] {};
rage::json_serializer yim_serializer(metric_json_buffer, sizeof(metric_json_buffer));
const auto is_bad_metric = bad_metrics.contains(metric->get_name()); metric->serialize(&yim_serializer);
const bool is_bad_metric = bad_metrics.contains(metric->get_name());
if (is_bad_metric) if (is_bad_metric)
{ {
LOG(WARNING) << "BAD METRIC: " << metric->get_name() << "; DATA: " << serializer->get_string(); LOG(WARNING) << "BAD METRIC: " << metric->get_name() << "; DATA: " << yim_serializer.get_string();
if(strcmp(metric->get_name(), "MM") == 0)
{
std::string data = std::string(reinterpret_cast<char*>(metric) + 0x18);
char module_name[MAX_PATH];
GetModuleFileNameA(g_hmodule, module_name, sizeof(module_name));
std::string encoded_module_name = hex_encode(std::filesystem::path(module_name).filename().string());
std::string result = remove_module_from_mmlist(data, encoded_module_name + "00");
if(result.size() != data.size())
LOG(INFO) << "Removed YimMenu DLL from MM metric";
strncpy(reinterpret_cast<char*>(metric) + 0x18, result.c_str(), 0x900);
return g_hooking->get_original<prepare_metric_for_sending>()(serializer, unk, time, metric);
}
return false; return false;
} }
if (!is_bad_metric && g.debug.logs.metric_logs) if (!is_bad_metric && g.debug.logs.metric_logs)
{ {
LOG(INFO) << "METRIC: " << metric->get_name() << "; DATA: " << serializer->get_string(); LOG(INFO) << "METRIC: " << metric->get_name() << "; DATA: " << yim_serializer.get_string();
} }
return ret; return g_hooking->get_original<prepare_metric_for_sending>()(serializer, unk, time, metric);
} }
} }

View File

@ -1,63 +0,0 @@
#include "hooking.hpp"
// rage::gameSkeleton -> modes (does not derive from updateBase?) -> groups -> items
namespace big
{
class game_skeleton_update_group;
class game_skeleton_item;
#pragma pack(push, 8)
struct game_skeleton_update_mode
{
int m_type; // 0x00
game_skeleton_update_group* m_groups; // 0x08
game_skeleton_update_mode* m_next; // 0x10
};
static_assert(sizeof(game_skeleton_update_mode) == 0x18);
struct game_skeleton_update_group
{
virtual ~game_skeleton_update_group() = default;
virtual void run() = 0; // 0x08
char pad[0x10]; // 0x08
game_skeleton_update_group* m_next; // 0x18
game_skeleton_item* m_items; // 0x20
};
static_assert(sizeof(game_skeleton_update_group) == 0x28);
struct game_skeleton_item
{
virtual ~game_skeleton_item() = default;
virtual void run() = 0; // 0x08
char m_pad[0x8]; // 0x08
uint32_t m_hash; // 0x10
game_skeleton_item* m_next; // 0x18
};
static_assert(sizeof(game_skeleton_item) == 0x20);
#pragma pack(pop)
void hooks::game_skeleton_update(__int64 skeleton, int type)
{
for (auto mode = *(game_skeleton_update_mode**)(skeleton + 0x140); mode; mode = mode->m_next)
{
if (mode && mode->m_type == type)
{
for (auto group = mode->m_groups; group; group = group->m_next)
{
for (auto item = group->m_items; item; item = item->m_next)
{
if (item->m_hash != 0xA0F39FB6)
{
item->run();
}
}
}
break;
}
}
}
}

View File

@ -1,15 +1,17 @@
#include "hooking.hpp" #include "hooking.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "security/ObfVar.hpp"
#include <Psapi.h> #include <Psapi.h>
namespace big namespace big
{ {
bool inline is_address_in_game_region(uint64_t address) bool inline is_address_in_game_region(int64_t address)
{ {
static uint64_t moduleBase = NULL; if(!address)
static uint64_t moduleSize = NULL; return false;
if ((!moduleBase) || (!moduleSize)) static int64_t moduleBase = NULL;
static int64_t moduleSize = NULL;
if (!moduleBase || !moduleSize)
{ {
MODULEINFO info; MODULEINFO info;
if (!GetModuleInformation(GetCurrentProcess(), GetModuleHandle(0), &info, sizeof(info))) if (!GetModuleInformation(GetCurrentProcess(), GetModuleHandle(0), &info, sizeof(info)))
@ -19,31 +21,34 @@ namespace big
} }
else else
{ {
moduleBase = (uint64_t)GetModuleHandle(0); moduleBase = (int64_t)GetModuleHandle(0);
moduleSize = (uint64_t)info.SizeOfImage; moduleSize = (int64_t)info.SizeOfImage;
} }
} }
return address > moduleBase && address < (moduleBase + moduleSize); return address > moduleBase && address < (moduleBase + moduleSize);
} }
bool is_jump(__int64 fptr) struct ac_verifier
{ {
if (!is_address_in_game_region(fptr)) virtual ~ac_verifier() = 0;
virtual bool run() = 0;
rage::Obf32 m_last_time; // 0x8
rage::Obf32 m_delay; // 0x18
};
bool is_unwanted_dependency(int64_t cb)
{
int64_t f1 = *reinterpret_cast<int64_t*>(cb + 0x60);
int64_t f2 = *reinterpret_cast<int64_t*>(cb + 0x100);
int64_t f3 = *reinterpret_cast<int64_t*>(cb + 0x1A0);
if (!is_address_in_game_region(f1) || !is_address_in_game_region(f2) || !is_address_in_game_region(f3))
return false; return false;
auto value = *(uint8_t*)(fptr); if(*reinterpret_cast<uint8_t*>(f1) != 0xE9)
return value == 0xE9;
}
bool is_unwanted_dependency(__int64 cb)
{
auto f1 = *(__int64*)(cb + 0x60);
auto f2 = *(__int64*)(cb + 0x100);
if (!is_address_in_game_region(f1) || (f2 && !is_address_in_game_region(f2)))
return false; return false;
return is_jump(f1) || is_jump(f2); return true;
} }
static bool nullsub() static bool nullsub()
@ -51,12 +56,16 @@ namespace big
return true; // returning false would cause the dependency to requeue return true; // returning false would cause the dependency to requeue
} }
int hooks::queue_dependency(void* a1, int a2, void* dependency) int hooks::queue_dependency(void* a1, int a2, int64_t dependency)
{ {
if (is_unwanted_dependency((__int64)dependency)) if (is_unwanted_dependency(dependency))
{ {
*(void**)((__int64)dependency + 0x60) = nullsub; LOG(INFO) << "Blocking AC Verifier " << std::hex << *reinterpret_cast<int64_t*>(dependency + 0x60) - reinterpret_cast<int64_t>(GetModuleHandleA(0));
*(void**)((__int64)dependency + 0x100) = nullsub; ac_verifier* verifier = reinterpret_cast<ac_verifier*>(dependency - 0x30);
verifier->m_delay = INT_MAX; // makes it so these won't queue in the future
*reinterpret_cast<void**>(dependency + 0x60) = nullsub;
*reinterpret_cast<void**>(dependency + 0x100) = nullsub;
*reinterpret_cast<void**>(dependency + 0x1A0) = nullsub;
} }
return g_hooking->get_original<hooks::queue_dependency>()(a1, a2, dependency); return g_hooking->get_original<hooks::queue_dependency>()(a1, a2, dependency);

View File

@ -9,6 +9,7 @@
#include "lua/lua_manager.hpp" #include "lua/lua_manager.hpp"
#include "native_hooks/native_hooks.hpp" #include "native_hooks/native_hooks.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "rage/gameSkeleton.hpp"
#include "renderer.hpp" #include "renderer.hpp"
#include "script_mgr.hpp" #include "script_mgr.hpp"
#include "services/api/api_service.hpp" #include "services/api/api_service.hpp"
@ -36,6 +37,41 @@
#include "thread_pool.hpp" #include "thread_pool.hpp"
#include "version.hpp" #include "version.hpp"
namespace big
{
void disable_anticheat_skeleton()
{
for (rage::game_skeleton_update_mode* mode = g_pointers->m_gta.m_game_skeleton->m_update_modes; mode; mode = mode->m_next)
{
for (rage::game_skeleton_update_base* update_node = mode->m_head; update_node; update_node = update_node->m_next)
{
if (update_node->m_hash != RAGE_JOAAT("Common Main"))
continue;
rage::game_skeleton_update_group* group = reinterpret_cast<rage::game_skeleton_update_group*>(update_node);
for (rage::game_skeleton_update_base* group_child_node = group->m_head; group_child_node;
group_child_node = group_child_node->m_next)
{
// TamperActions is a leftover from the old AC, but still useful to block anyway
if (group_child_node->m_hash != 0xA0F39FB6 && group_child_node->m_hash != RAGE_JOAAT("TamperActions"))
continue;
//LOG(INFO) << "Patching problematic skeleton update";
reinterpret_cast<rage::game_skeleton_update_element*>(group_child_node)->m_function =
g_pointers->m_gta.m_nullsub;
}
break;
}
}
for (rage::skeleton_data& i : g_pointers->m_gta.m_game_skeleton->m_sys_data)
{
if (i.m_hash != 0xA0F39FB6 && i.m_hash != RAGE_JOAAT("TamperActions"))
continue;
//LOG(INFO) << "Patching problematic skeleton init/shutdown";
i.m_init_func = reinterpret_cast<uint64_t>(g_pointers->m_gta.m_nullsub);
i.m_shutdown_func = reinterpret_cast<uint64_t>(g_pointers->m_gta.m_nullsub);
}
}
}
BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
{ {
@ -75,6 +111,9 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
auto pointers_instance = std::make_unique<pointers>(); auto pointers_instance = std::make_unique<pointers>();
LOG(INFO) << "Pointers initialized."; LOG(INFO) << "Pointers initialized.";
disable_anticheat_skeleton();
LOG(INFO) << "Disabled anticheat gameskeleton.";
auto byte_patch_manager_instance = std::make_unique<byte_patch_manager>(); auto byte_patch_manager_instance = std::make_unique<byte_patch_manager>();
LOG(INFO) << "Byte Patch Manager initialized."; LOG(INFO) << "Byte Patch Manager initialized.";
@ -85,8 +124,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
auto fiber_pool_instance = std::make_unique<fiber_pool>(11); auto fiber_pool_instance = std::make_unique<fiber_pool>(11);
LOG(INFO) << "Fiber pool initialized."; LOG(INFO) << "Fiber pool initialized.";
g_http_client.init(g_file_manager.get_project_file("./proxy_settings.json")); g_http_client.init(g_file_manager.get_project_file("./proxy_settings.json"));
LOG(INFO) << "HTTP Client initialized."; LOG(INFO) << "HTTP Client initialized.";
g_translation_service.init(); g_translation_service.init();
LOG(INFO) << "Translation Service initialized."; LOG(INFO) << "Translation Service initialized.";

View File

@ -4,6 +4,7 @@
#include "hooking.hpp" #include "hooking.hpp"
#include "memory/all.hpp" #include "memory/all.hpp"
#include "rage/atSingleton.hpp" #include "rage/atSingleton.hpp"
#include "rage/gameSkeleton.hpp"
#include "sc_pointers_layout_info.hpp" #include "sc_pointers_layout_info.hpp"
#include "security/RageSecurity.hpp" #include "security/RageSecurity.hpp"
@ -1722,13 +1723,22 @@ namespace big
g_pointers->m_gta.m_is_social_club_overlay_active = ptr.add(2).rip().as<bool*>(); g_pointers->m_gta.m_is_social_club_overlay_active = ptr.add(2).rip().as<bool*>();
} }
}, },
// Game Skeleton Update // Game Skeleton
{ {
"GSU", "GS",
"40 53 48 83 EC 20 48 8B 81 40 01", "48 8D 0D ? ? ? ? BA ? ? ? ? 74 05 BA ? ? ? ? E8 ? ? ? ? E8 ? ? ? ? C6 05 ? ? ? ? ? 48 8D 0D ? ? ? ? BA ? ? ? ? 84 DB 75 05 BA ? ? ? ? E8 ? ? ? ? 48 8B CD C6 05 ? ? ? ? ? E8 ? ? ? ? 84",
[](memory::handle ptr) [](memory::handle ptr)
{ {
g_pointers->m_gta.m_game_skeleton_update = ptr.as<PVOID>(); g_pointers->m_gta.m_game_skeleton = ptr.add(3).rip().as<rage::game_skeleton*>();
}
},
// Nullsub
{
"NS",
"C3",
[](memory::handle ptr)
{
g_pointers->m_gta.m_nullsub = ptr.as<void(*)()>();
} }
}, },
// Get Ped Bone // Get Ped Bone

View File

@ -7,7 +7,7 @@ namespace big
{ {
public: public:
constexpr script_global(std::size_t index) : constexpr script_global(std::size_t index) :
m_index(index) m_index(index)
{ {
} }
@ -35,6 +35,5 @@ namespace big
private: private:
void* get() const; void* get() const;
std::size_t m_index; std::size_t m_index;
}; };
} }

View File

@ -18,8 +18,8 @@ namespace big
} }
script_local::script_local(std::size_t index) : script_local::script_local(std::size_t index) :
m_index(index), m_index(index),
m_stack(nullptr) m_stack(nullptr)
{ {
} }

View File

@ -2,10 +2,10 @@
#include "common.hpp" #include "common.hpp"
#include "gta/script_thread.hpp" #include "gta/script_thread.hpp"
#include "script/tlsContext.hpp"
#include "gta_util.hpp" #include "gta_util.hpp"
#include "invoker.hpp" #include "invoker.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "script/tlsContext.hpp"
namespace big namespace big
{ {

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "script.hpp"
#include "lua/lua_manager.hpp" #include "lua/lua_manager.hpp"
#include "script.hpp"
namespace big namespace big
{ {

View File

@ -4,8 +4,8 @@ namespace big
{ {
thread_pool::thread_pool(const std::size_t preallocated_thread_count) : thread_pool::thread_pool(const std::size_t preallocated_thread_count) :
m_accept_jobs(true), m_accept_jobs(true),
m_allocated_thread_count(preallocated_thread_count), m_allocated_thread_count(preallocated_thread_count),
m_busy_threads(0) m_busy_threads(0)
{ {
rescale_thread_pool(); rescale_thread_pool();