Mission fixes and modder detection improvements (#1598)

* feat(protections): improve protections
* fix: fix mission start
This commit is contained in:
maybegreat48 2023-07-05 07:30:06 +00:00 committed by GitHub
parent 167e1f8d54
commit cbc80e6caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 533 additions and 337 deletions

View File

@ -1,5 +1,6 @@
#include "chat_command_context.hpp" #include "chat_command_context.hpp"
#include "fiber_pool.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"

View File

@ -1,6 +1,8 @@
#include "backend/looped/looped.hpp" #include "backend/looped/looped.hpp"
#include "core/scr_globals.hpp" #include "core/scr_globals.hpp"
#include "gta/joaat.hpp" #include "gta/joaat.hpp"
#include "gta/net_array.hpp"
#include "gta_util.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "script_global.hpp" #include "script_global.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
@ -8,6 +10,7 @@
// Credits: QuickNET // Credits: QuickNET
namespace big namespace big
{ {
static float old_percent = NAN;
constexpr char transition_states[][48] = {"TRANSITION_STATE_EMPTY", "Singleplayer Swoop Up", "Multiplayer Swoop Up", "Creator Swoop Up", "Pre-HUD Checks", "Wait HUD Exit", "Wait For Summon", "Singleplayer Swoop Down", "Multiplayer Swoop Down", "Cancel Joining", "Retry Loading", "Retry Loading Slot 1", "Retry Loading Slot 2", "Retry Loading Slot 3", "Retry Loading Slot 4", "Wait On Invite", "Prejoining Freemode Session Checks", "Look For Fresh Join Freemode", "Look To Join Another Session Freemode", "Confirm Freemode Session Joining", "Wait Join Freemode Session", "Creation Enter Session", "Pre-Freemode Launch Script", "Freemode Teamfull Check", "Start Freemode Launch Script", "Freemode Transition Create Player", "Is Freemode And Transition Ready", "Freemode Swoop Down", "Post Bink Video Warp", "Freemode Final Setup Player", "Move Freemode To Running State", "Freemode How To Terminate", "Start Creator Pre-Launch Script Check", "Start Creator Launch Script", "Creator Transition Create Player", "Is Creator And Transition Ready", "Creator Swoop Down", "Creator Final Setup Player", "Move Creator To Running State", "Prejoining Testbed Session Checks", "Look For Fresh Join Testbed", "Look For Fresh Host Testbed", "Look To Join Another Session Testbed", "Look To Host Session Testbed", "Confirm Testbed Session Joining", "Wait Join Testbed Session", "Start Testbed Launch Script", "Testbed Transition Create Player", "Is Testbed And Transition Ready", "Testbed Swoop Down", "Testbed Final Setup Player", "Move Testbed To Running State", "Testbed How To Terminate", "Quit Current Session Prompt", "Wait For Transition Session To Setup", "Terminate Singleplayer", "Wait Terminate Singleplayer", "Kick Terminate Session", "Terminate Session", "Wait Terminate Session", "Terminate Session And Hold", "Terminate Session And Move Into Holding State", "Team Swapping Checks", "Return To Singleplayer", "Wait For Singleplayer To Start", "Waiting For External Termination Call", "Terminate Maintransition", "Wait For Dirty Load Confirm", "DLC Intro Bink", "Spawn Into Personal Vehicle"}; constexpr char transition_states[][48] = {"TRANSITION_STATE_EMPTY", "Singleplayer Swoop Up", "Multiplayer Swoop Up", "Creator Swoop Up", "Pre-HUD Checks", "Wait HUD Exit", "Wait For Summon", "Singleplayer Swoop Down", "Multiplayer Swoop Down", "Cancel Joining", "Retry Loading", "Retry Loading Slot 1", "Retry Loading Slot 2", "Retry Loading Slot 3", "Retry Loading Slot 4", "Wait On Invite", "Prejoining Freemode Session Checks", "Look For Fresh Join Freemode", "Look To Join Another Session Freemode", "Confirm Freemode Session Joining", "Wait Join Freemode Session", "Creation Enter Session", "Pre-Freemode Launch Script", "Freemode Teamfull Check", "Start Freemode Launch Script", "Freemode Transition Create Player", "Is Freemode And Transition Ready", "Freemode Swoop Down", "Post Bink Video Warp", "Freemode Final Setup Player", "Move Freemode To Running State", "Freemode How To Terminate", "Start Creator Pre-Launch Script Check", "Start Creator Launch Script", "Creator Transition Create Player", "Is Creator And Transition Ready", "Creator Swoop Down", "Creator Final Setup Player", "Move Creator To Running State", "Prejoining Testbed Session Checks", "Look For Fresh Join Testbed", "Look For Fresh Host Testbed", "Look To Join Another Session Testbed", "Look To Host Session Testbed", "Confirm Testbed Session Joining", "Wait Join Testbed Session", "Start Testbed Launch Script", "Testbed Transition Create Player", "Is Testbed And Transition Ready", "Testbed Swoop Down", "Testbed Final Setup Player", "Move Testbed To Running State", "Testbed How To Terminate", "Quit Current Session Prompt", "Wait For Transition Session To Setup", "Terminate Singleplayer", "Wait Terminate Singleplayer", "Kick Terminate Session", "Terminate Session", "Wait Terminate Session", "Terminate Session And Hold", "Terminate Session And Move Into Holding State", "Team Swapping Checks", "Return To Singleplayer", "Wait For Singleplayer To Start", "Waiting For External Termination Call", "Terminate Maintransition", "Wait For Dirty Load Confirm", "DLC Intro Bink", "Spawn Into Personal Vehicle"};
eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY; eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY;
@ -24,24 +27,53 @@ namespace big
SCRIPT::SHUTDOWN_LOADING_SCREEN(); SCRIPT::SHUTDOWN_LOADING_SCREEN();
} }
if (last_state == state || state == eTransitionState::TRANSITION_STATE_EMPTY || state > eTransitionState::TRANSITION_STATE_SPAWN_INTO_PERSONAL_VEHICLE) if ((last_state == state && state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER) || state == eTransitionState::TRANSITION_STATE_EMPTY || state > eTransitionState::TRANSITION_STATE_SPAWN_INTO_PERSONAL_VEHICLE)
{ {
return; return;
} }
if (HUD::BUSYSPINNER_IS_ON()) if (state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER && HUD::BUSYSPINNER_IS_ON())
{ {
HUD::BUSYSPINNER_OFF(); HUD::BUSYSPINNER_OFF();
} }
if ((int)state > 0 && (int)state < std::size(transition_states)) if ((int)state > 0 && (int)state < std::size(transition_states))
{
rage::scrThread* freemode{};
if (state == eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER
&& (freemode = gta_util::find_script_thread(RAGE_JOAAT("freemode")), freemode && freemode->m_net_component))
{
int num_array_handlers{};
int received_array_handlers{};
while (auto handler = g_pointers->m_gta.m_get_host_array_handler_by_index(freemode->m_net_component, num_array_handlers++))
if (handler->m_flags & 1)
received_array_handlers++;
if (num_array_handlers == 0)
num_array_handlers = 1;
float percent = round((static_cast<float>(received_array_handlers) / num_array_handlers) * 100);
if (percent != old_percent)
{ {
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING"); HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
auto const spinner_text = std::format("{} | {}", transition_states[(int)state], static_cast<int>(state)); HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(spinner_text.c_str()); std::format("Wait For Host Broadcast Data: {}%", (percent)).c_str());
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5); HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
} }
old_percent = percent;
}
else
{
old_percent = NAN;
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(transition_states[(int)state]);
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
}
}
last_state = state; last_state = state;
} }
} }

View File

@ -36,12 +36,6 @@ namespace big
// perform initial setup // perform initial setup
gta_util::execute_as_script(g.m_dance_thread, [] { gta_util::execute_as_script(g.m_dance_thread, [] {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, 32); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, 32);
scr_functions::init_nightclub_script({}); scr_functions::init_nightclub_script({});
}); });

View File

@ -70,6 +70,9 @@ namespace big
memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(2).as<uint32_t*>(), 0xd2310272)->apply(); memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(2).as<uint32_t*>(), 0xd2310272)->apply();
memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(6).as<uint16_t*>(), 0x9090)->apply(); memory::byte_patch::make(g_pointers->m_gta.m_script_vm_patch_6.add(6).as<uint16_t*>(), 0x9090)->apply();
// Patch script network check
memory::byte_patch::make(g_pointers->m_gta.m_model_spawn_bypass, std::vector{0x90, 0x90})->apply(); // this is no longer integrity checked
} }
byte_patch_manager::byte_patch_manager() byte_patch_manager::byte_patch_manager()

View File

@ -7,14 +7,19 @@ namespace big
enum class Infraction enum class Infraction
{ {
DESYNC_PROTECTION, DESYNC_PROTECTION,
BREAKUP_KICK_DETECTED, BREAKUP_KICK_DETECTED, // do not use
LOST_CONNECTION_KICK_DETECTED, LOST_CONNECTION_KICK_DETECTED, // do not use
SPOOFED_ROCKSTAR_ID, SPOOFED_ROCKSTAR_ID, // do not use
TRIGGERED_ANTICHEAT, TRIGGERED_ANTICHEAT,
TRIED_CRASH_PLAYER, TRIED_CRASH_PLAYER, // do not use
TRIED_KICK_PLAYER, TRIED_KICK_PLAYER,
BLAME_EXPLOSION_DETECTED, BLAME_EXPLOSION_DETECTED, // do not use (for now)
ATTACKING_WITH_GODMODE ATTACKING_WITH_GODMODE,
ATTACKING_WITH_INVISIBILITY,
ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST,
SPOOFED_DATA,
SPOOFED_HOST_TOKEN,
INVALID_PLAYER_MODEL
}; };
inline std::unordered_map<Infraction, const char*> infraction_desc = { inline std::unordered_map<Infraction, const char*> infraction_desc = {
@ -26,6 +31,11 @@ namespace big
{Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"}, {Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"},
{Infraction::TRIED_KICK_PLAYER, "Tried to kick you"}, {Infraction::TRIED_KICK_PLAYER, "Tried to kick you"},
{Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"}, {Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"},
{Infraction::ATTACKING_WITH_GODMODE, "Attacked someone when using godmode"}, {Infraction::ATTACKING_WITH_GODMODE, "Attacked someone while using godmode"},
{Infraction::ATTACKING_WITH_INVISIBILITY, "Attacked someone while being invisible"},
{Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, "Attacked someone while being hidden from the player list"},
{Infraction::SPOOFED_DATA, "Had spoofed data"},
{Infraction::SPOOFED_HOST_TOKEN, "Had spoofed their host token"},
{Infraction::INVALID_PLAYER_MODEL, "Had used an invalid player model"},
}; };
} }

View File

@ -392,7 +392,9 @@ namespace big
bool show_cheating_message = false; bool show_cheating_message = false;
bool anonymous_bounty = true; bool anonymous_bounty = true;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, chat_force_clean, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session) bool fast_join = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, chat_force_clean, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join)
} session{}; } session{};
struct settings struct settings

View File

@ -6,6 +6,7 @@ class NetworkGameFilterMatchmakingComponent;
class sCloudFile; class sCloudFile;
class CPlayerGameStateDataNode; class CPlayerGameStateDataNode;
class CVehicleGadgetDataNode; class CVehicleGadgetDataNode;
class CGameScriptHandlerNetComponent;
enum eVehicleGadgetType : uint32_t; enum eVehicleGadgetType : uint32_t;
namespace rage namespace rage
@ -22,6 +23,7 @@ namespace rage
class rlScHandle; class rlScHandle;
class rlQueryPresenceAttributesContext; class rlQueryPresenceAttributesContext;
enum class eThreadState : uint32_t; enum class eThreadState : uint32_t;
class netArrayHandlerBase;
} }
namespace datafile_commands namespace datafile_commands
@ -141,4 +143,6 @@ namespace big::functions
using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team); using handle_chat_message = void (*)(void* chat_data, void*, rage::rlGamerHandle* handle, const char* text, bool is_team);
using update_language = void (*)(bool); using update_language = void (*)(bool);
using get_host_array_handler_by_index = rage::netArrayHandlerBase* (*)(CGameScriptHandlerNetComponent* component, int index);
} }

View File

@ -29,46 +29,47 @@ namespace rage
class netSyncDataUnit_Dynamic class netSyncDataUnit_Dynamic
{ {
public: public:
virtual ~netSyncDataUnit_Dynamic() = default;// 0x00 virtual ~netSyncDataUnit_Dynamic() = default; // 0x00
virtual void _0x08() = 0; virtual void _0x08() = 0;
virtual void _0x10() = 0; virtual void _0x10() = 0;
virtual void set_data_counter(int index, uint16_t counter) = 0;// 0x18 virtual void set_data_counter(int index, uint16_t counter) = 0; // 0x18
virtual void reset_data_counter(int index) = 0;// 0x20 virtual void reset_data_counter(int index) = 0; // 0x20
// ... // ...
int m_players_need_ack; // 0x08 int m_players_need_ack; // 0x08
int m_players_need_sync;// 0x0C int m_players_need_sync; // 0x0C
}; };
class netSyncData_Dynamic class netSyncData_Dynamic
{ {
public: public:
virtual ~netSyncData_Dynamic() = default;// 0x00 virtual ~netSyncData_Dynamic() = default; // 0x00
virtual rage::datBitBuffer* _0x08() = 0; virtual rage::datBitBuffer* _0x08() = 0;
virtual rage::datBitBuffer* _0x10() = 0; virtual rage::datBitBuffer* _0x10() = 0;
virtual int get_num_receivers() = 0;// 0x18 virtual int get_num_receivers() = 0; // 0x18
virtual int _0x20() = 0; virtual int _0x20() = 0;
virtual void _0x28() = 0;// same as get_sync_unit_for_element virtual void _0x28() = 0; // same as get_sync_unit_for_element
virtual netSyncDataUnit_Dynamic* get_sync_unit_for_element(uint32_t element) = 0;// 0x30 virtual netSyncDataUnit_Dynamic* get_sync_unit_for_element(uint32_t element) = 0; // 0x30
// ... // ...
}; };
#pragma pack(push, 1)
class netArrayHandlerBase class netArrayHandlerBase
{ {
public: public:
virtual ~netArrayHandlerBase() = default;// 0x00 virtual ~netArrayHandlerBase() = default; // 0x00
virtual void _0x08() = 0; virtual void _0x08() = 0;
@ -82,124 +83,124 @@ namespace rage
virtual void _0x30() = 0; virtual void _0x30() = 0;
virtual void _0x38() = 0;// virtual void _0x38() = 0; //
virtual void _0x40() = 0;// virtual void _0x40() = 0; //
virtual int _0x48(CNetGamePlayer* player, int max_size, uint32_t* a3, uint32_t* a4) = 0;// virtual int _0x48(CNetGamePlayer* player, int max_size, uint32_t* a3, uint32_t* a4) = 0; //
virtual int get_size(CNetGamePlayer* player, int max_size, uint32_t element) = 0;// 0x50 virtual int get_size(CNetGamePlayer* player, int max_size, uint32_t element) = 0; // 0x50
virtual int pack_array_data(CNetGamePlayer* player, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent) = 0;// 0x58 virtual int pack_array_data(CNetGamePlayer* player, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent) = 0; // 0x58
virtual void _0x60() = 0;// virtual void _0x60() = 0; //
virtual bool _0x68(CNetGamePlayer* player) = 0;// is_player_out_of_scope or something like that virtual bool _0x68(CNetGamePlayer* player) = 0; // is_player_out_of_scope or something like that
virtual void _0x70() = 0;// virtual void _0x70() = 0; //
virtual bool can_send_update(CNetGamePlayer* player) = 0;// 0x78 virtual bool can_send_update(CNetGamePlayer* player) = 0; // 0x78
virtual void _0x80() = 0;// virtual void _0x80() = 0; //
virtual void _0x88() = 0;// virtual void _0x88() = 0; //
virtual void* get_identifier() = 0;// 0x90 virtual void* get_identifier() = 0; // 0x90
virtual void* _0x98() = 0;// same as get_identifier virtual void* _0x98() = 0; // same as get_identifier
virtual void _0xA0() = 0;// virtual void _0xA0() = 0; //
virtual bool can_verify_array_data() = 0;// 0xA8 virtual bool can_verify_array_data() = 0; // 0xA8
virtual void _0xB0() = 0;// virtual void _0xB0() = 0; //
virtual void _0xB8() = 0;// virtual void _0xB8() = 0; //
virtual void should_sync_element(uint32_t element) = 0;// 0xC0 virtual void should_sync_element(uint32_t element) = 0; // 0xC0
virtual void _0xC8() = 0;// virtual void _0xC8() = 0; //
virtual void _0xD0() = 0;// virtual void _0xD0() = 0; //
virtual bool are_all_elements_in_scope() = 0;// 0xD8 virtual bool are_all_elements_in_scope() = 0; // 0xD8
virtual void _0xE0() = 0;// virtual void _0xE0() = 0; //
virtual void verify_array_data() = 0;// 0xE8 virtual void verify_array_data() = 0; // 0xE8
virtual void _0xF0() = 0;// virtual void _0xF0() = 0; //
virtual char* get_name() = 0;// 0xF8 virtual char* get_name() = 0; // 0xF8
virtual bool is_local_player_owner_of_array() = 0;// 0x100 virtual bool is_local_player_owner_of_array() = 0; // 0x100
virtual CNetGamePlayer* get_owner_of_array() = 0;// 0x108 virtual CNetGamePlayer* get_owner_of_array() = 0; // 0x108
virtual void _0x110() = 0; virtual void _0x110() = 0;
virtual uint32_t get_array_hash() = 0; virtual uint32_t get_array_hash() = 0;
virtual int _0x120() = 0;// gets array size for hashing virtual int _0x120() = 0; // gets array size for hashing
virtual netSyncData_Dynamic* _0x128() = 0;// same as get_dynamic_sync_data virtual netSyncData_Dynamic* _0x128() = 0; // same as get_dynamic_sync_data
virtual netSyncData_Dynamic* get_dynamic_sync_data() = 0;// 0x130 virtual netSyncData_Dynamic* get_dynamic_sync_data() = 0; // 0x130
virtual void _0x138() = 0; virtual void _0x138() = 0;
virtual bool is_element_in_scope(uint32_t element, CNetGamePlayer* player) = 0;// 0x140 virtual bool is_element_in_scope(uint32_t element, CNetGamePlayer* player) = 0; // 0x140
virtual int get_receiver_index_from_player(CNetGamePlayer*) = 0;// 0x148 virtual int get_receiver_index_from_player(CNetGamePlayer*) = 0; // 0x148
virtual void _0x150() = 0; virtual void _0x150() = 0;
virtual void _0x158() = 0; virtual void _0x158() = 0;
// pasted from fivem // pasted from fivem
virtual bool is_element_empty(uint32_t element) = 0;// 0x160 virtual bool is_element_empty(uint32_t element) = 0; // 0x160
virtual void set_element_empty(uint32_t element) = 0;// 0x168 virtual void set_element_empty(uint32_t element) = 0; // 0x168
virtual void write_element_index(rage::datBitBuffer& buffer, uint32_t) = 0;// 0x170 virtual void write_element_index(rage::datBitBuffer& buffer, uint32_t) = 0; // 0x170
virtual void read_element_index(rage::datBitBuffer& buffer, uint32_t&) = 0;// 0x178 virtual void read_element_index(rage::datBitBuffer& buffer, uint32_t&) = 0; // 0x178
virtual bool is_valid_index(uint32_t) = 0;// 0x180 virtual bool is_valid_index(uint32_t) = 0; // 0x180
virtual void recalculate_dirty_elements() = 0;// 0x188 virtual void recalculate_dirty_elements() = 0; // 0x188
virtual void reset_element_sync_data(uint32_t element) = 0;// 0x190 virtual void reset_element_sync_data(uint32_t element) = 0; // 0x190
virtual void do_post_read_processing() = 0;// 0x198 virtual void do_post_read_processing() = 0; // 0x198
virtual void do_post_element_read_processing(uint32_t element) = 0;// 0x1A0 virtual void do_post_element_read_processing(uint32_t element) = 0; // 0x1A0
virtual bool can_apply_element_data(uint32_t element, const rage::netPlayer& sender, bool force) = 0;// 0x1A8 virtual bool can_apply_element_data(uint32_t element, const rage::netPlayer& sender, bool force) = 0; // 0x1A8
virtual void extract_data_for_serializing(uint32_t elem) = 0;// 0x1B0 virtual void extract_data_for_serializing(uint32_t elem) = 0; // 0x1B0
virtual void write_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0;// 0x1B8 virtual void write_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1B8
virtual void read_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0;// 0x1C0 virtual void read_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1C0
virtual void log_element(uint32_t elem, void* logger) = 0;// 0x1C8 virtual void log_element(uint32_t elem, void* logger) = 0; // 0x1C8
virtual uint32_t get_current_element_size_in_bits(uint32_t elem) = 0;// 0x1D0 virtual uint32_t get_current_element_size_in_bits(uint32_t elem) = 0; // 0x1D0
virtual void apply_element_data(uint32_t element, const rage::netPlayer& sender) = 0;// 0x1D8 virtual void apply_element_data(uint32_t element, const rage::netPlayer& sender) = 0; // 0x1D8
virtual void _0x1E0() = 0; virtual void _0x1E0() = 0;
virtual void _0x1E8(bool) = 0;// very important! changes send function to use some kind of cached buffer that prevents us from modifing array data per player virtual void _0x1E8(bool) = 0;
void* m_something;// 0x10 void* m_something; // 0x10
netArrayHandlerBase* m_next;// 0x18 netArrayHandlerBase* m_next; // 0x18
uint8_t m_pad[100 - 0x18];// +8 uint8_t m_pad[100 - 0x18]; // +8
uint32_t m_hash; uint32_t m_hash;
uint8_t m_pad2[244 - 104];// +8 uint8_t m_pad2[244 - 104]; // +8
uint16_t m_index; // 244 uint16_t m_index; // 244
uint16_t m_count; // 246 uint16_t m_count; // 246
uint8_t m_max_elements; // 248 uint8_t m_max_elements; // 248
@ -207,27 +208,9 @@ namespace rage
uint8_t m_element_size_2; // 250 uint8_t m_element_size_2; // 250
uint8_t m_pad3[13]; // 251 uint8_t m_pad3[13]; // 251
void* m_array; // 264 void* m_array; // 264
uint8_t m_pad4[341 - (264 + 8)];
#if 0 char m_flags; // 341
static inline netArrayHandlerBase* get_by_data(void* data)
{
if (auto array_mgr = *big::g_pointers->m_gta.m_game_array_mgr)
{
if (auto handler = array_mgr->m_start)
{
do
{
if (handler->m_array == data)
return handler;
}
while (handler = handler->m_next);
}
}
return nullptr;
}
#endif
}; };
#pragma pack(pop)
static_assert(sizeof(netArrayHandlerBase) == 272); static_assert(sizeof(netArrayHandlerBase) == 342);
} }

View File

@ -203,8 +203,6 @@ namespace big
PVOID m_serialize_take_off_ped_variation_task; PVOID m_serialize_take_off_ped_variation_task;
PVOID m_create_script_handler;
functions::encode_session_info m_encode_session_info; functions::encode_session_info m_encode_session_info;
functions::decode_session_info m_decode_session_info; functions::decode_session_info m_decode_session_info;
functions::decode_peer_info m_decode_peer_info; functions::decode_peer_info m_decode_peer_info;
@ -263,6 +261,10 @@ namespace big
int* m_language; int* m_language;
functions::update_language m_update_language{}; functions::update_language m_update_language{};
PVOID m_model_spawn_bypass{};
functions::get_host_array_handler_by_index m_get_host_array_handler_by_index;
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");

View File

@ -84,8 +84,6 @@ namespace big
detour_hook_helper::add<hooks::serialize_take_off_ped_variation_task>("STOPVT", g_pointers->m_gta.m_serialize_take_off_ped_variation_task); detour_hook_helper::add<hooks::serialize_take_off_ped_variation_task>("STOPVT", g_pointers->m_gta.m_serialize_take_off_ped_variation_task);
detour_hook_helper::add<hooks::create_script_handler>("CSH", g_pointers->m_gta.m_create_script_handler);
detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_gta.m_queue_dependency); detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_gta.m_queue_dependency);
detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_gta.m_prepare_metric_for_sending); detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_gta.m_prepare_metric_for_sending);
@ -141,12 +139,6 @@ namespace big
detour_hook_helper->m_detour_hook->enable(); detour_hook_helper->m_detour_hook->enable();
} }
for (auto& thread : *g_pointers->m_gta.m_script_threads)
{
if (thread->m_handler)
hook_script_handler((CGameScriptHandler*)thread->m_handler);
}
MH_ApplyQueued(); MH_ApplyQueued();
m_enabled = true; m_enabled = true;
@ -171,7 +163,6 @@ namespace big
delete detour_hook_helper; delete detour_hook_helper;
} }
m_detour_hook_helpers.clear(); m_detour_hook_helpers.clear();
m_handler_hooks.clear();
} }
hooking::detour_hook_helper::~detour_hook_helper() hooking::detour_hook_helper::~detour_hook_helper()
@ -195,8 +186,6 @@ namespace big
bool hooks::run_script_threads(std::uint32_t ops_to_execute) bool hooks::run_script_threads(std::uint32_t ops_to_execute)
{ {
g_native_invoker.cache_handlers();
if (g_running) if (g_running)
{ {
g_script_mgr.tick(); g_script_mgr.tick();

View File

@ -123,10 +123,6 @@ namespace big
static void serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer); static void serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer);
static CGameScriptHandler* create_script_handler(CGameScriptHandlerMgr* this_, void* unk);
static bool script_handler_is_networked(CGameScriptHandler* this_);
static bool script_handler_dtor(CGameScriptHandler* this_, bool free_memory);
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 void queue_dependency(void* dependency); static void queue_dependency(void* dependency);
static void prepare_metric_for_sending(rage::datBitBuffer* bit_buffer, int unk, int time, rage::rlMetric* metric); static void prepare_metric_for_sending(rage::datBitBuffer* bit_buffer, int unk, int time, rage::rlMetric* metric);
@ -241,9 +237,6 @@ namespace big
return detour_hook_helper::hook_to_detour_hook_helper<detour_function>::m_detour_hook->get_original<decltype(detour_function)>(); return detour_hook_helper::hook_to_detour_hook_helper<detour_function>::m_detour_hook->get_original<decltype(detour_function)>();
} }
void hook_script_handler(CGameScriptHandler* handler);
std::unordered_map<CGameScriptHandler*, std::unique_ptr<vmt_hook>> m_handler_hooks;
private: private:
bool m_enabled{}; bool m_enabled{};
minhook_keepalive m_minhook_keepalive; minhook_keepalive m_minhook_keepalive;

View File

@ -1,12 +1,61 @@
#include "gta/net_game_event.hpp" #include "gta/net_game_event.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include "util/globals.hpp"
#include "util/misc.hpp"
#include "util/session.hpp" #include "util/session.hpp"
#include <entities/CDynamicEntity.hpp> #include <entities/CDynamicEntity.hpp>
#include <script/globals/GPBD_FM.hpp>
#include <script/globals/GlobalPlayerBD.hpp>
namespace big namespace big
{ {
inline bool is_invincible(big::player_ptr player)
{
return player->get_ped() && (player->get_ped()->m_damage_bits & (1 << 8));
}
inline bool is_invisible(big::player_ptr player)
{
if (!player->get_ped())
return false;
if (!NETWORK::NETWORK_ARE_PLAYERS_IN_SAME_TUTORIAL_SESSION(self::id, player->id()))
return false; // probably not
if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].IsInvisible)
return true;
if ((player->get_current_vehicle() && player->get_current_vehicle()->m_driver == player->get_ped())
|| PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
return false; // can't say
return false; // TODO! have to get data from CPhysicalGameStateDataNode
//return (player->get_ped()->m_flags & (int)rage::fwEntity::EntityFlags::IS_VISIBLE) == 0;
}
inline bool is_hidden_from_player_list(big::player_ptr player)
{
return scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].CayoPericoFlags & 1;
}
inline bool is_using_rc_vehicle(big::player_ptr player)
{
if (misc::has_bit_set(&scr_globals::gpbd_fm_1.as<GPBD_FM*>()->Entries[player->id()].PropertyData.PAD_0365, 29))
return true; // bandito
if (misc::has_bit_set(&scr_globals::gpbd_fm_1.as<GPBD_FM*>()->Entries[player->id()].PropertyData.ArcadeData.AppearanceBitset2, 16))
return true; // tank
return false;
}
inline bool is_using_orbital_cannon(big::player_ptr player)
{
return scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].OrbitalBitset.IsSet(eOrbitalBitset::kOrbitalCannonActive);
}
void hooks::get_network_event_data(int64_t unk, rage::CEventNetwork* net_event) void hooks::get_network_event_data(int64_t unk, rage::CEventNetwork* net_event)
{ {
switch (net_event->get_type()) switch (net_event->get_type())
@ -21,7 +70,9 @@ namespace big
rage::sEntityDamagedData damage_data; rage::sEntityDamagedData damage_data;
net_event->get_extra_information(&damage_data, sizeof(damage_data)); net_event->get_extra_information(&damage_data, sizeof(damage_data));
if (damage_data.m_weapon_used == RAGE_JOAAT("weapon_explosion")) if (damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_STICKYBOMB") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_KINETIC_RC")
|| damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_EMP_RC") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_KINETIC")
|| damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_EMP") || damage_data.m_weapon_used == RAGE_JOAAT("VEHICLE_WEAPON_MINE_SPIKE"))
break; break;
if (auto damager = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_damager_index); if (auto damager = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_damager_index);
@ -30,13 +81,60 @@ namespace big
if (auto player = g_player_service->get_by_host_token( if (auto player = g_player_service->get_by_host_token(
reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token)) reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token))
{ {
if (auto victim = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_victim_index); if (PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
victim && victim->m_entity_type == 4 && reinterpret_cast<CPed*>(victim)->m_player_info)
{ {
if (reinterpret_cast<CPed*>(damager)->m_damage_bits & (1 << 8)) if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].PlayerBlip.PlayerVehicleBlipType == eBlipType::SUBMARINE)
break;
if (is_using_rc_vehicle(player))
break;
}
else
{
if (auto vehicle = player->get_current_vehicle())
if (auto model_info = vehicle->m_model_info)
if (model_info->m_hash == RAGE_JOAAT("rcbandito") || model_info->m_hash == RAGE_JOAAT("minitank")
|| model_info->m_hash == RAGE_JOAAT("kosatka"))
break;
}
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
break;
if (globals::get_interior_from_player(player->id()) != 0)
break;
if (player->get_player_info() && player->get_player_info()->m_game_state == eGameState::InMPCutscene)
break;
if (auto victim = g_pointers->m_gta.m_handle_to_ptr(damage_data.m_victim_index); victim && victim->m_entity_type == 4)
{
if (is_invincible(player))
{ {
session::add_infraction(player, Infraction::ATTACKING_WITH_GODMODE); session::add_infraction(player, Infraction::ATTACKING_WITH_GODMODE);
} }
if (is_invisible(player))
{
if (!reinterpret_cast<CPed*>(victim)->m_player_info)
break;
if (damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_EXPLOSION") || damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_RAMMED_BY_CAR")
|| damage_data.m_weapon_used == RAGE_JOAAT("WEAPON_RUN_OVER_BY_CAR"))
break;
session::add_infraction(player, Infraction::ATTACKING_WITH_INVISIBILITY);
}
if (is_hidden_from_player_list(player))
{
session::add_infraction(player, Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST);
}
if (is_using_orbital_cannon(player))
{
session::add_infraction(player, Infraction::SPOOFED_DATA);
}
} }
} }
} }

View File

@ -8,12 +8,20 @@
#include "services/player_database/player_database_service.hpp" #include "services/player_database/player_database_service.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include "util/session.hpp"
#include <network/Network.hpp> #include <network/Network.hpp>
namespace big namespace big
{ {
inline bool is_spoofed_host_token(std::uint64_t token)
{
if (token < 200'000'000)
return true;
return false;
}
void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index) void* hooks::assign_physical_index(CNetworkPlayerMgr* netPlayerMgr, CNetGamePlayer* player, uint8_t new_index)
{ {
@ -83,9 +91,8 @@ namespace big
} }
auto id = player->m_player_id; auto id = player->m_player_id;
bool lock_session = g.session.lock_session;
g_fiber_pool->queue_job([id, lock_session] { g_fiber_pool->queue_job([id] {
if (auto plyr = g_player_service->get_by_id(id)) if (auto plyr = g_player_service->get_by_id(id))
{ {
if (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0) if (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0)
@ -106,32 +113,30 @@ namespace big
} }
} }
} }
if (plyr->block_join) if (plyr->block_join)
{ {
if (g_player_service->get_self()->is_host()) if (g_player_service->get_self()->is_host())
{ {
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {});
g_notification_service->push_warning("Block Join",
std::format("Block Join method failed for {}, sending breakup kick instead...",
plyr->get_net_data()->m_name));
LOG(WARNING) << "Sending Breakup Kick due to block join failure... ";
} }
else else
{ {
g_notification_service->push_warning("Block Join",
std::format("Block Join method failed for {}, can't send breakup without host...\n trying Desync",
plyr->get_net_data()->m_name));
LOG(WARNING) << "Failed blocking join due to not being host... trying Desync ";
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("desync")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("desync")))->call(plyr, {});
} }
} }
if (lock_session && g_player_service->get_self()->is_host())
if (g.session.lock_session && g_player_service->get_self()->is_host())
{ {
dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {}); dynamic_cast<player_command*>(command::get(RAGE_JOAAT("breakup")))->call(plyr, {});
g_notification_service->push_warning("Lock Session", g_notification_service->push_warning("Lock Session",
std::format("A player with the name of {} has been denied entry", plyr->get_net_data()->m_name)); std::format("A player with the name of {} has been denied entry", plyr->get_net_data()->m_name));
} }
if (is_spoofed_host_token(plyr->get_net_data()->m_host_token))
{
session::add_infraction(plyr, Infraction::SPOOFED_HOST_TOKEN);
}
} }
}); });
} }

View File

@ -16,6 +16,7 @@
#include "netsync/nodes/player/CPlayerAppearanceDataNode.hpp" #include "netsync/nodes/player/CPlayerAppearanceDataNode.hpp"
#include "netsync/nodes/player/CPlayerCreationDataNode.hpp" #include "netsync/nodes/player/CPlayerCreationDataNode.hpp"
#include "netsync/nodes/player/CPlayerGameStateDataNode.hpp" #include "netsync/nodes/player/CPlayerGameStateDataNode.hpp"
#include "netsync/nodes/player/CPlayerGamerDataNode.hpp"
#include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp" #include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp"
#include "netsync/nodes/train/CTrainGameStateDataNode.hpp" #include "netsync/nodes/train/CTrainGameStateDataNode.hpp"
#include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp" #include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp"
@ -25,6 +26,7 @@
#include "network/netObject.hpp" #include "network/netObject.hpp"
#include "util/model_info.hpp" #include "util/model_info.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include "util/session.hpp"
#include "vehicle/CVehicleModelInfo.hpp" #include "vehicle/CVehicleModelInfo.hpp"
namespace big namespace big
@ -547,10 +549,45 @@ namespace big
constexpr uint32_t crash_objects[] = {RAGE_JOAAT("prop_dummy_01"), RAGE_JOAAT("prop_dummy_car"), RAGE_JOAAT("prop_dummy_light"), RAGE_JOAAT("prop_dummy_plane"), RAGE_JOAAT("prop_distantcar_night"), RAGE_JOAAT("prop_distantcar_day"), RAGE_JOAAT("hei_bh1_08_details4_em_night"), RAGE_JOAAT("dt1_18_sq_night_slod"), RAGE_JOAAT("ss1_12_night_slod"), -1288391198, RAGE_JOAAT("h4_prop_bush_bgnvla_med_01"), RAGE_JOAAT("h4_prop_bush_bgnvla_lrg_01"), RAGE_JOAAT("h4_prop_bush_buddleia_low_01"), RAGE_JOAAT("h4_prop_bush_ear_aa"), RAGE_JOAAT("h4_prop_bush_ear_ab"), RAGE_JOAAT("h4_prop_bush_fern_low_01"), RAGE_JOAAT("h4_prop_bush_fern_tall_cc"), RAGE_JOAAT("h4_prop_bush_mang_ad"), RAGE_JOAAT("h4_prop_bush_mang_low_aa"), RAGE_JOAAT("h4_prop_bush_mang_low_ab"), RAGE_JOAAT("h4_prop_bush_seagrape_low_01"), RAGE_JOAAT("prop_h4_ground_cover"), RAGE_JOAAT("h4_prop_weed_groundcover_01"), RAGE_JOAAT("h4_prop_grass_med_01"), RAGE_JOAAT("h4_prop_grass_tropical_lush_01"), RAGE_JOAAT("h4_prop_grass_wiregrass_01"), RAGE_JOAAT("h4_prop_weed_01_plant"), RAGE_JOAAT("h4_prop_weed_01_row"), RAGE_JOAAT("urbanweeds02_l1"), RAGE_JOAAT("proc_forest_grass01"), RAGE_JOAAT("prop_small_bushyba"), RAGE_JOAAT("v_res_d_dildo_a"), RAGE_JOAAT("v_res_d_dildo_b"), RAGE_JOAAT("v_res_d_dildo_c"), RAGE_JOAAT("v_res_d_dildo_d"), RAGE_JOAAT("v_res_d_dildo_e"), RAGE_JOAAT("v_res_d_dildo_f"), RAGE_JOAAT("v_res_skateboard"), RAGE_JOAAT("prop_battery_01"), RAGE_JOAAT("prop_barbell_01"), RAGE_JOAAT("prop_barbell_02"), RAGE_JOAAT("prop_bandsaw_01"), RAGE_JOAAT("prop_bbq_3"), RAGE_JOAAT("v_med_curtainsnewcloth2"), RAGE_JOAAT("bh1_07_flagpoles"), 92962485}; constexpr uint32_t crash_objects[] = {RAGE_JOAAT("prop_dummy_01"), RAGE_JOAAT("prop_dummy_car"), RAGE_JOAAT("prop_dummy_light"), RAGE_JOAAT("prop_dummy_plane"), RAGE_JOAAT("prop_distantcar_night"), RAGE_JOAAT("prop_distantcar_day"), RAGE_JOAAT("hei_bh1_08_details4_em_night"), RAGE_JOAAT("dt1_18_sq_night_slod"), RAGE_JOAAT("ss1_12_night_slod"), -1288391198, RAGE_JOAAT("h4_prop_bush_bgnvla_med_01"), RAGE_JOAAT("h4_prop_bush_bgnvla_lrg_01"), RAGE_JOAAT("h4_prop_bush_buddleia_low_01"), RAGE_JOAAT("h4_prop_bush_ear_aa"), RAGE_JOAAT("h4_prop_bush_ear_ab"), RAGE_JOAAT("h4_prop_bush_fern_low_01"), RAGE_JOAAT("h4_prop_bush_fern_tall_cc"), RAGE_JOAAT("h4_prop_bush_mang_ad"), RAGE_JOAAT("h4_prop_bush_mang_low_aa"), RAGE_JOAAT("h4_prop_bush_mang_low_ab"), RAGE_JOAAT("h4_prop_bush_seagrape_low_01"), RAGE_JOAAT("prop_h4_ground_cover"), RAGE_JOAAT("h4_prop_weed_groundcover_01"), RAGE_JOAAT("h4_prop_grass_med_01"), RAGE_JOAAT("h4_prop_grass_tropical_lush_01"), RAGE_JOAAT("h4_prop_grass_wiregrass_01"), RAGE_JOAAT("h4_prop_weed_01_plant"), RAGE_JOAAT("h4_prop_weed_01_row"), RAGE_JOAAT("urbanweeds02_l1"), RAGE_JOAAT("proc_forest_grass01"), RAGE_JOAAT("prop_small_bushyba"), RAGE_JOAAT("v_res_d_dildo_a"), RAGE_JOAAT("v_res_d_dildo_b"), RAGE_JOAAT("v_res_d_dildo_c"), RAGE_JOAAT("v_res_d_dildo_d"), RAGE_JOAAT("v_res_d_dildo_e"), RAGE_JOAAT("v_res_d_dildo_f"), RAGE_JOAAT("v_res_skateboard"), RAGE_JOAAT("prop_battery_01"), RAGE_JOAAT("prop_barbell_01"), RAGE_JOAAT("prop_barbell_02"), RAGE_JOAAT("prop_bandsaw_01"), RAGE_JOAAT("prop_bbq_3"), RAGE_JOAAT("v_med_curtainsnewcloth2"), RAGE_JOAAT("bh1_07_flagpoles"), 92962485};
inline CObject* get_game_object(rage::netObject* object) constexpr uint32_t valid_player_models[] = {
{ RAGE_JOAAT("mp_m_freemode_01"),
return *(CObject**)((__int64)object + 0x50); RAGE_JOAAT("mp_f_freemode_01"),
} RAGE_JOAAT("u_m_m_filmdirector"),
RAGE_JOAAT("player_zero"),
RAGE_JOAAT("player_one"),
RAGE_JOAAT("player_two"),
// peyote
RAGE_JOAAT("A_C_Boar"),
RAGE_JOAAT("A_C_Cat_01"),
RAGE_JOAAT("A_C_Cow"),
RAGE_JOAAT("A_C_Coyote"),
RAGE_JOAAT("A_C_Deer"),
RAGE_JOAAT("A_C_Husky"),
RAGE_JOAAT("A_C_MtLion"),
RAGE_JOAAT("A_C_Pig"),
RAGE_JOAAT("A_C_Poodle"),
RAGE_JOAAT("A_C_Pug"),
RAGE_JOAAT("A_C_Rabbit_01"),
RAGE_JOAAT("A_C_Retriever"),
RAGE_JOAAT("A_C_Rottweiler"),
RAGE_JOAAT("A_C_shepherd"),
RAGE_JOAAT("A_C_Westy"),
RAGE_JOAAT("A_C_Chickenhawk"),
RAGE_JOAAT("A_C_Cormorant"),
RAGE_JOAAT("A_C_Crow"),
RAGE_JOAAT("A_C_Hen"),
RAGE_JOAAT("A_C_Pigeon"),
RAGE_JOAAT("A_C_Seagull"),
RAGE_JOAAT("A_C_Dolphin"),
RAGE_JOAAT("A_C_Fish"),
RAGE_JOAAT("A_C_KillerWhale"),
RAGE_JOAAT("A_C_SharkHammer"),
RAGE_JOAAT("A_C_SharkTiger"),
RAGE_JOAAT("A_C_Stingray"),
RAGE_JOAAT("IG_Orleans"),
RAGE_JOAAT("A_C_Chop"),
RAGE_JOAAT("A_C_HumpBack"),
};
inline bool is_crash_ped(uint32_t model) inline bool is_crash_ped(uint32_t model)
{ {
@ -566,9 +603,11 @@ namespace big
{ {
if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133)) if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133))
return true; return true;
for (auto iterator : crash_vehicles) for (auto iterator : crash_vehicles)
if (iterator == model) if (iterator == model)
return true; return true;
return false; return false;
} }
@ -576,28 +615,81 @@ namespace big
{ {
if (!model_info::get_model(model)) if (!model_info::get_model(model))
return false; return false;
if (!model_info::is_model_of_type(model, eModelType::Object, eModelType::Time, eModelType::Weapon, eModelType::Destructable, eModelType::WorldObject, eModelType::Sprinkler, eModelType::Unk65, eModelType::Plant, eModelType::LOD, eModelType::Unk132, eModelType::Building)) if (!model_info::is_model_of_type(model, eModelType::Object, eModelType::Time, eModelType::Weapon, eModelType::Destructable, eModelType::WorldObject, eModelType::Sprinkler, eModelType::Unk65, eModelType::Plant, eModelType::LOD, eModelType::Unk132, eModelType::Building))
return true; return true;
for (auto iterator : crash_objects) for (auto iterator : crash_objects)
if (iterator == model) if (iterator == model)
return true; return true;
return false; return false;
} }
inline bool is_attachment_infinite(rage::CDynamicEntity* object, uint16_t attached_to_net_id) inline bool is_valid_player_model(uint32_t model)
{
for (auto iterator : valid_player_models)
if (iterator == model)
return true;
return false;
}
inline void check_player_model(player_ptr player, uint32_t model)
{
if (!player)
return;
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
return;
if (!is_valid_player_model(model))
{
session::add_infraction(player, Infraction::INVALID_PLAYER_MODEL);
}
}
// the game function does weird stuff that we don't want
inline CObject* get_entity_attached_to(CObject* entity)
{
if (!entity)
return nullptr;
if (!entity->gap50)
return nullptr;
__int64 component = *(__int64*)((__int64)(entity->gap50) + 0x48);
if (!component)
return nullptr;
int unk_count = *(int*)(component + 0x5C) & 0xF;
if (unk_count < 2)
return nullptr;
return *(CObject**)(component);
}
inline bool is_attachment_infinite(rage::netObject* object, uint16_t attached_to_net_id, int from_bone, int to_bone)
{ {
if (object == nullptr) if (object == nullptr)
return false; return false;
constexpr size_t reasonable_limit = 150; auto target = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attached_to_net_id, false);
size_t i = 0;
while (object && i < reasonable_limit) while (target)
{ {
if (object->m_net_object && object->m_net_object->m_object_id == attached_to_net_id) if (target == object)
return true; return true;
object = g_pointers->m_gta.m_get_entity_attached_to(object); auto next = get_entity_attached_to(target->GetGameObject());
i++;
if (!next)
return false;
if (!next->m_net_object)
return false;
target = next->m_net_object;
} }
return false; return false;
@ -629,6 +721,26 @@ namespace big
return false; return false;
} }
inline bool is_sane_override_pos(float x, float y, float z)
{
if (isnan(x) || isnan(y) || isnan(z))
return false;
if (isinf(x) || isinf(y) || isinf(z))
return false;
if (x > 5000.0f || x < -5000.0f)
return false;
if (y > 8500.0f || y < -5000.0f)
return false;
if (z > 1600.0f || z < -700.0f)
return false;
return true;
}
bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object) bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object)
{ {
if (node->IsParentNode()) if (node->IsParentNode())
@ -642,9 +754,13 @@ namespace big
else if (node->IsDataNode()) else if (node->IsDataNode())
{ {
const auto vft = *(uintptr_t*)node; const auto vft = *(uintptr_t*)node;
auto sender_plyr = g_player_service->get_by_id(sender->m_player_id);
for (const sync_node_id node_id : sync_node_finder::find((eNetObjType)object->m_object_type, vft)) for (const sync_node_id node_id : sync_node_finder::find((eNetObjType)object->m_object_type, vft))
{ {
if ((((CProjectBaseSyncDataNode*)node)->flags & 1) == 0)
continue;
switch (node_id) switch (node_id)
{ {
case sync_node_id("CVehicleCreationDataNode"): case sync_node_id("CVehicleCreationDataNode"):
@ -681,17 +797,13 @@ namespace big
{ {
const auto attach_node = (CPhysicalAttachDataNode*)(node); const auto attach_node = (CPhysicalAttachDataNode*)(node);
// TODO: Find a better method to avoid false positives if (attach_node->m_attached
auto model_hash = get_game_object(object) ? get_game_object(object)->m_model_info->m_hash : 0; && is_attachment_infinite(object,
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id && (model_hash != RAGE_JOAAT("hauler2") && model_hash != RAGE_JOAAT("phantom3"))) attach_node->m_attached_to,
attach_node->m_attach_bone,
attach_node->m_other_attach_bone))
{ {
// notify::crash_blocked(sender, "infinite physical attachment"); notify::crash_blocked(sender, "infinite physical attachment");
return true;
}
else if (attach_node->m_attached
&& is_attachment_infinite((rage::CDynamicEntity*)get_game_object(object), attach_node->m_attached_to))
{
// notify::crash_blocked(sender, "recursive infinite physical attachment");
return true; return true;
} }
@ -715,16 +827,15 @@ namespace big
case sync_node_id("CPedAttachDataNode"): case sync_node_id("CPedAttachDataNode"):
{ {
const auto attach_node = (CPedAttachDataNode*)(node); const auto attach_node = (CPedAttachDataNode*)(node);
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id) if (attach_node->m_attached
&& is_attachment_infinite(object,
attach_node->m_attached_to,
attach_node->m_attachment_bone,
attach_node->m_attachment_bone))
{ {
notify::crash_blocked(sender, "infinite ped attachment"); notify::crash_blocked(sender, "infinite ped attachment");
return true; return true;
} }
else if (attach_node->m_attached && is_attachment_infinite(get_game_object(object), attach_node->m_attached_to))
{
// notify::crash_blocked(sender, "recursive infinite ped attachment");
return true;
}
break; break;
} }
@ -746,6 +857,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (appearance node)"); notify::crash_blocked(sender, "invalid player model (appearance node)");
return true; return true;
} }
check_player_model(sender_plyr, player_appearance_node->m_model_hash);
break; break;
} }
case sync_node_id("CPlayerCreationDataNode"): case sync_node_id("CPlayerCreationDataNode"):
@ -756,6 +868,7 @@ namespace big
notify::crash_blocked(sender, "invalid player model (creation node)"); notify::crash_blocked(sender, "invalid player model (creation node)");
return true; return true;
} }
check_player_model(sender_plyr, player_creation_node->m_model);
break; break;
} }
case sync_node_id("CSectorDataNode"): case sync_node_id("CSectorDataNode"):
@ -771,8 +884,10 @@ namespace big
case sync_node_id("CPlayerGameStateDataNode"): case sync_node_id("CPlayerGameStateDataNode"):
{ {
const auto game_state_node = (CPlayerGameStateDataNode*)(node); const auto game_state_node = (CPlayerGameStateDataNode*)(node);
if (game_state_node->m_population_control_sphere_x == 712 || game_state_node->m_population_control_sphere_y == 712 if (game_state_node->m_is_overriding_population_control_sphere
|| game_state_node->m_population_control_sphere_z == 712) && !is_sane_override_pos(game_state_node->m_population_control_sphere_x,
game_state_node->m_population_control_sphere_y,
game_state_node->m_population_control_sphere_z))
{ {
notify::crash_blocked(sender, "invalid sector position (player game state node)"); notify::crash_blocked(sender, "invalid sector position (player game state node)");
return true; return true;
@ -784,7 +899,7 @@ namespace big
const auto train_node = (CTrainGameStateDataNode*)(node); const auto train_node = (CTrainGameStateDataNode*)(node);
if (train_node->m_track_id < 0 || train_node->m_track_id >= 27) if (train_node->m_track_id < 0 || train_node->m_track_id >= 27)
{ {
notify::crash_blocked(sender, "out of bound train track index"); notify::crash_blocked(sender, "out of bounds train track index");
return true; return true;
} }
break; break;
@ -808,6 +923,24 @@ namespace big
break; break;
} }
case sync_node_id("CPlayerGamerDataNode"):
{
const auto gamer_node = (CPlayerGamerDataNode*)(node);
if (sender_plyr)
{
if (gamer_node->m_clan_data.m_clan_id > 0 && gamer_node->m_clan_data.m_clan_id_2 > 0)
{
auto len = strlen(gamer_node->m_clan_data.m_clan_tag);
if (len <= 2)
{
session::add_infraction(sender_plyr, Infraction::SPOOFED_DATA);
}
}
}
break;
}
} }
} }
} }

View File

@ -4,6 +4,8 @@
#include "gta_util.hpp" #include "gta_util.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "script_local.hpp" #include "script_local.hpp"
#include "services/players/player_service.hpp"
#include "util/misc.hpp"
#include "util/notify.hpp" #include "util/notify.hpp"
#include <script/globals/GlobalPlayerBD.hpp> #include <script/globals/GlobalPlayerBD.hpp>
@ -59,7 +61,7 @@ namespace big
} }
} }
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[sender->m_player_id].RemoteWantedLevelPlayer = -1;// reset locally scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[sender->m_player_id].RemoteWantedLevelPlayer = -1; // reset locally
} }
if (array->m_array == scr_globals::gsbd.as<void*>() && *scr_globals::gsbd.as<eFreemodeState*>() == eFreemodeState::CLOSING) if (array->m_array == scr_globals::gsbd.as<void*>() && *scr_globals::gsbd.as<eFreemodeState*>() == eFreemodeState::CLOSING)

View File

@ -1,57 +0,0 @@
#include "gta/script_handler.hpp"
#include "pointers.hpp"
#include "hooking.hpp"
namespace big
{
void hooking::hook_script_handler(CGameScriptHandler* handler)
{
Hash script_hash = handler->m_script_thread->m_context.m_script_hash;
{
auto hook = std::make_unique<vmt_hook>(handler, 20);
hook->hook(0, &hooks::script_handler_dtor);
hook->hook(6, &hooks::script_handler_is_networked);
hook->enable();
g_hooking->m_handler_hooks[handler] = std::move(hook);
}
}
CGameScriptHandler* hooks::create_script_handler(CGameScriptHandlerMgr* _this, void* unk)
{
auto handler = g_hooking->get_original<hooks::create_script_handler>()(_this, unk);
if (handler == nullptr || handler->m_script_thread == nullptr)
return handler;
g_hooking->hook_script_handler(handler);
return handler;
};
bool hooks::script_handler_is_networked(CGameScriptHandler* _this)
{
return *g_pointers->m_gta.m_is_session_started;
}
bool hooks::script_handler_dtor(CGameScriptHandler* _this, bool free_memory)
{
vmt_hook* hook;
if (g_hooking->m_handler_hooks.count(_this))
{
hook = g_hooking->m_handler_hooks[_this].get();
if (!hook)
return false;
hook->disable();
auto og_func = hook->get_original<decltype(&script_handler_dtor)>(0);
g_hooking->m_handler_hooks.erase(_this);
return og_func(_this, free_memory);
}
else
{
return false;
}
}
};

View File

@ -26,14 +26,5 @@ namespace big
strcpy(node->m_clan_data.m_clan_name, "Rockstar"); strcpy(node->m_clan_data.m_clan_name, "Rockstar");
} }
} }
node->m_is_cheater = g.spoofing.spoof_cheater;
// spoof r* dev and qa only when spoofing rid because every player in the session will send metrics if you join with that enabled
/*if (g.spoofing.spoof_rockstar_id)
{
node->m_is_rockstar_dev = g.spoofing.spoof_rockstar_dev;
node->m_is_rockstar_qa = g.spoofing.spoof_rockstar_qa;
}*/
} }
} }

View File

@ -36,6 +36,9 @@ namespace big
void native_invoker::end_call(rage::scrNativeHash hash) void native_invoker::end_call(rage::scrNativeHash hash)
{ {
if (!m_handlers_cached)
cache_handlers();
if (auto it = m_handler_cache.find(hash); it != m_handler_cache.end()) if (auto it = m_handler_cache.find(hash); it != m_handler_cache.end())
{ {
rage::scrNativeHandler handler = it->second; rage::scrNativeHandler handler = it->second;

View File

@ -5,6 +5,7 @@
#include "hooking.hpp" #include "hooking.hpp"
#include "native_hooks.hpp" #include "native_hooks.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "util/notify.hpp"
#include "util/scripts.hpp" #include "util/scripts.hpp"
namespace big namespace big
@ -25,13 +26,10 @@ namespace big
void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src) void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src)
{ {
if (rage::scrThread::get() && rage::scrThread::get()->m_handler) if (src->get_arg<int>(2) >= 0x100)
{ {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get()) notify::crash_blocked(nullptr, "out of bounds instance id");
{ return;
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
} }
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2)); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2));
@ -39,13 +37,11 @@ namespace big
void NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src) void NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src)
{ {
if (rage::scrThread::get() && rage::scrThread::get()->m_handler) if (src->get_arg<int>(2) >= 0x100)
{ {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)rage::scrThread::get()->m_handler].get()) notify::crash_blocked(nullptr, "out of bounds instance id");
{ src->set_return_value<BOOL>(FALSE);
hook->disable(); return;
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
}
} }
src->set_return_value<BOOL>(NETWORK::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2))); src->set_return_value<BOOL>(NETWORK::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(src->get_arg<int>(0), src->get_arg<BOOL>(1), src->get_arg<int>(2)));

View File

@ -71,27 +71,26 @@ namespace big
} }
else else
{ {
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g.session.force_script_host) if (g.session.force_script_host && (g.session.fast_join || NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA()))
{ {
g_fiber_pool->queue_job([] { auto hash = SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME();
scripts::force_host(RAGE_JOAAT("freemode")); g_fiber_pool->queue_job([hash] {
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component) scripts::force_host(hash);
if (auto script = gta_util::find_script_thread(hash); script && script->m_net_component)
script->m_net_component->block_host_migration(true); script->m_net_component->block_host_migration(true);
}); });
} }
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("fmmc_launcher") && g.session.force_script_host) if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g.session.fast_join)
{ {
g_fiber_pool->queue_job([] {
scripts::force_host(RAGE_JOAAT("fmmc_launcher"));
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("fmmc_launcher")); script && script->m_net_component)
script->m_net_component->block_host_migration(true);
});
}
scr_functions::set_freemode_session_active({}); scr_functions::set_freemode_session_active({});
src->set_return_value<BOOL>(TRUE); src->set_return_value<BOOL>(TRUE);
} }
else
{
src->set_return_value<BOOL>(NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA());
}
}
} }
} }
} }

View File

@ -842,15 +842,6 @@ namespace big
g_pointers->m_gta.m_sc_info = ptr.sub(4).rip().as<ScInfo*>(); g_pointers->m_gta.m_sc_info = ptr.sub(4).rip().as<ScInfo*>();
} }
}, },
// Create Script Handler
{
"CSH",
"48 8D 05 ? ? ? ? 4C 8D 0D ? ? ? ? 41 83 C8 FF 48 89 03 89 53 70 88 53 74 4C 89 4B 68 48 89 93",
[](memory::handle ptr)
{
g_pointers->m_gta.m_create_script_handler = *(ptr.add(3).rip().as<std::uint64_t**>() + 8);
}
},
// Invalid Decal Crash // Invalid Decal Crash
{ {
"IDC", "IDC",
@ -1223,6 +1214,15 @@ namespace big
g_pointers->m_gta.m_update_language = ptr.add(0x38).rip().as<functions::update_language>(); g_pointers->m_gta.m_update_language = ptr.add(0x38).rip().as<functions::update_language>();
} }
}, },
// Get Host Array Handler By Index
{
"GHAHBI",
"48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 8A 81 8F",
[](memory::handle ptr)
{
g_pointers->m_gta.m_get_host_array_handler_by_index = ptr.as<functions::get_host_array_handler_by_index>();
}
},
// Max Wanted Level // Max Wanted Level
{ {
"MWL", "MWL",
@ -1341,6 +1341,15 @@ namespace big
g_pointers->m_gta.m_script_vm_patch_5 = ptr; g_pointers->m_gta.m_script_vm_patch_5 = ptr;
g_pointers->m_gta.m_script_vm_patch_6 = ptr.add(0x26); g_pointers->m_gta.m_script_vm_patch_6 = ptr.add(0x26);
} }
},
// CTheScripts::GetHandlerCheckNetwork patch (aka Model Spawn Bypass)
{
"CTSHP",
"48 8B C8 FF 52 30 84 C0 74 05 48",
[](memory::handle ptr)
{
g_pointers->m_gta.m_model_spawn_bypass = ptr.add(8).as<PVOID>();
}
} }
>(); // don't leave a trailing comma at the end >(); // don't leave a trailing comma at the end

View File

@ -95,12 +95,6 @@ namespace big
bool script_connection::set_script_as_networked() bool script_connection::set_script_as_networked()
{ {
gta_util::execute_as_script(m_thread, [this] { gta_util::execute_as_script(m_thread, [this] {
if (auto hook = g_hooking->m_handler_hooks[(CGameScriptHandler*)m_thread->m_handler].get())
{
hook->disable();
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)m_thread->m_handler);
}
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, m_instance_id); NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, true, m_instance_id);
}); });

View File

@ -5,7 +5,6 @@
#include "network/ChatData.hpp" #include "network/ChatData.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "script.hpp" #include "script.hpp"
#include "session.hpp"
#include <script/HudColor.hpp> #include <script/HudColor.hpp>
@ -31,14 +30,6 @@ namespace big::notify
{ {
g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash)); g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash));
} }
if (player)
{
if (auto plyr = g_player_service->get_by_id(player->m_player_id))
{
session::add_infraction(plyr, Infraction::TRIED_CRASH_PLAYER);
}
}
} }
// Shows a busy spinner till the value at the address equals the value passed or if timeout is hit // Shows a busy spinner till the value at the address equals the value passed or if timeout is hit

View File

@ -1,11 +1,12 @@
#pragma once #pragma once
#include "entity.hpp" #include "entity.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "outfit.hpp"
#include "services/players/player_service.hpp"
#include "math.hpp"
#include "gta/enums.hpp" #include "gta/enums.hpp"
#include "local_player.hpp"
#include "math.hpp"
#include "natives.hpp"
#include "outfit.hpp"
#include "pointers.hpp"
#include "services/players/player_service.hpp"
namespace big::ped namespace big::ped
{ {
@ -498,14 +499,16 @@ namespace big::ped
inline void kill_ped(const Ped ped) inline void kill_ped(const Ped ped)
{ {
if (entity::take_control_of(ped)) if (entity::take_control_of(ped, 0))
PED::APPLY_DAMAGE_TO_PED(ped, PED::GET_PED_MAX_HEALTH(ped) * 2, false, 0); ENTITY::SET_ENTITY_HEALTH(ped, 0, self::ped);
} else
inline void kill_ped_by_relation(Ped ped, int relation_id)
{ {
if (PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, PLAYER::PLAYER_PED_ID()) == relation_id) auto ptr = g_pointers->m_gta.m_handle_to_ptr(ped);
kill_ped(ped); if (!ptr)
return;
g_pointers->m_gta.m_send_network_damage(g_player_service->get_self()->get_ped(), ptr, ptr->get_position(), 0, true, RAGE_JOAAT("weapon_explosion"), 10000.0f, 2, 0, (1 << 4), 0, 0, 0, false, false, true, true, nullptr);
}
} }
inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true) inline Ped spawn(ePedType pedType, Hash hash, Hash clone, Vector3 location, float heading, bool is_networked = true)
@ -568,7 +571,7 @@ namespace big::ped
return nullptr; return nullptr;
} }
inline bool load_animation_dict (const char* dict) inline bool load_animation_dict(const char* dict)
{ {
if (STREAMING::HAS_ANIM_DICT_LOADED(dict)) if (STREAMING::HAS_ANIM_DICT_LOADED(dict))
return true; return true;
@ -596,7 +599,8 @@ namespace big::ped
{ {
if (entity::take_control_of(ped)) if (entity::take_control_of(ped))
{ {
if (ENTITY::DOES_ENTITY_EXIST(veh)) { if (ENTITY::DOES_ENTITY_EXIST(veh))
{
if (math::distance_between_vectors(ENTITY::GET_ENTITY_COORDS(ped, 0), ENTITY::GET_ENTITY_COORDS(veh, 0)) < 15.f) if (math::distance_between_vectors(ENTITY::GET_ENTITY_COORDS(ped, 0), ENTITY::GET_ENTITY_COORDS(veh, 0)) < 15.f)
TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL); TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL);
else else

View File

@ -265,6 +265,14 @@ namespace big
script->m_net_component->block_host_migration(true); script->m_net_component->block_host_migration(true);
}); });
} }
if (ImGui::IsItemHovered())
ImGui::SetTooltip("This might break freemode missions and interiors. Use with caution");
ImGui::SameLine();
ImGui::Checkbox("Fast Join", &g.session.fast_join);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("This WILL break jobs");
ImGui::Spacing(); ImGui::Spacing();

View File

@ -115,8 +115,10 @@ namespace big
false, false,
"Interior"); "Interior");
if (g_player_service->get_selected()->get_ped())
{
static float new_location[3]; static float new_location[3];
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->m_navigation->get_position()); auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->get_position());
components::small_text("Custom TP"); components::small_text("Custom TP");
ImGui::SetNextItemWidth(400); ImGui::SetNextItemWidth(400);
@ -129,6 +131,7 @@ namespace big
{ {
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location)); std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
} }
}
ImGui::EndListBox(); ImGui::EndListBox();
} }

View File

@ -23,7 +23,7 @@ namespace big
player_icons += FONT_ICON_HOST; player_icons += FONT_ICON_HOST;
if (plyr->is_friend()) if (plyr->is_friend())
player_icons += FONT_ICON_FRIEND; player_icons += FONT_ICON_FRIEND;
if (const auto ped = plyr->get_ped(); ped != nullptr && ped->m_ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING) if (const auto ped = plyr->get_ped(); (ped != nullptr && ped->m_ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING))
player_icons += FONT_ICON_VEHICLE; player_icons += FONT_ICON_VEHICLE;
const auto player_iconsc = player_icons.c_str(); const auto player_iconsc = player_icons.c_str();
@ -53,9 +53,11 @@ namespace big
g_gui_service->set_selected(tabs::PLAYER); g_gui_service->set_selected(tabs::PLAYER);
g.window.switched_view = true; g.window.switched_view = true;
} }
if (ImGui::IsItemHovered() && g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id) != nullptr) if (ImGui::IsItemHovered()
&& g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id) != nullptr)
{ {
auto sorted_player = g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id); auto sorted_player =
g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle.m_rockstar_id);
if (!sorted_player->infractions.empty()) if (!sorted_player->infractions.empty())
{ {

View File

@ -14,7 +14,6 @@ namespace big
} }
ImGui::SeparatorText("Peds"); ImGui::SeparatorText("Peds");
// Nearby Ped Actions
components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] { components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] {
for (auto peds : entity::get_entities(false, true)) for (auto peds : entity::get_entities(false, true))
@ -26,10 +25,14 @@ namespace big
ImGui::SameLine(); ImGui::SameLine();
components::button<ImVec2(110, 0), ImVec4(0.76078f, 0.f, 0.03529f, 1.f)>("Kill Enemies", [] { components::button<ImVec2(110, 0), ImVec4(0.76078f, 0.f, 0.03529f, 1.f)>("Kill Enemies", [] {
for (auto peds : entity::get_entities(false, true)) for (auto ped : entity::get_entities(false, true))
{ {
if (!PED::IS_PED_A_PLAYER(peds)) if (!PED::IS_PED_A_PLAYER(ped))
ped::kill_ped_by_relation(peds, 4 || 5); {
auto relation = PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, self::ped);
if (relation == 4 || relation == 5)
ped::kill_ped(ped);
}
} }
}); });
@ -104,12 +107,13 @@ namespace big
quantity = list.size(); quantity = list.size();
remaining = quantity; remaining = quantity;
g_notification_service->push("Entity deletion", std::format("Deleting {} entities", quantity)); g_notification_service->push("Entity Deletion", std::format("Deleting {} entities", quantity));
deleting = true; deleting = true;
int failed = 0; int failed = 0;
for (auto ent : list) for (auto ent : list)
{ {
if (ent == self::ped) if (PED::IS_PED_A_PLAYER(ent))
continue; continue;
if (ENTITY::DOES_ENTITY_EXIST(ent)) if (ENTITY::DOES_ENTITY_EXIST(ent))
@ -122,8 +126,6 @@ namespace big
entity::delete_entity(ent); entity::delete_entity(ent);
} }
script::get_current()->yield(5ms);
if (ENTITY::DOES_ENTITY_EXIST(ent)) if (ENTITY::DOES_ENTITY_EXIST(ent))
failed++; failed++;
else else
@ -131,7 +133,7 @@ namespace big
} }
if (failed > 0) if (failed > 0)
g_notification_service->push_warning("Entity deletion", std::format("Failed deleting {} entities", failed)); g_notification_service->push_warning("Entity Deletion", std::format("Failed deleting {} entities", failed));
deleting = false; deleting = false;
}); });