Mission fixes and modder detection improvements (#1598)
* feat(protections): improve protections * fix: fix mission start
This commit is contained in:
parent
167e1f8d54
commit
cbc80e6caf
@ -1,5 +1,6 @@
|
||||
#include "chat_command_context.hpp"
|
||||
|
||||
#include "fiber_pool.hpp"
|
||||
#include "hooking.hpp"
|
||||
#include "util/notify.hpp"
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "backend/looped/looped.hpp"
|
||||
#include "core/scr_globals.hpp"
|
||||
#include "gta/joaat.hpp"
|
||||
#include "gta/net_array.hpp"
|
||||
#include "gta_util.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "script_global.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
@ -8,6 +10,7 @@
|
||||
// Credits: QuickNET
|
||||
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"};
|
||||
|
||||
eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY;
|
||||
@ -24,22 +27,51 @@ namespace big
|
||||
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;
|
||||
}
|
||||
|
||||
if (HUD::BUSYSPINNER_IS_ON())
|
||||
if (state != eTransitionState::TRANSITION_STATE_FM_TRANSITION_CREATE_PLAYER && HUD::BUSYSPINNER_IS_ON())
|
||||
{
|
||||
HUD::BUSYSPINNER_OFF();
|
||||
}
|
||||
|
||||
if ((int)state > 0 && (int)state < std::size(transition_states))
|
||||
{
|
||||
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(spinner_text.c_str());
|
||||
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(5);
|
||||
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::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(
|
||||
std::format("Wait For Host Broadcast Data: {}%", (percent)).c_str());
|
||||
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;
|
||||
|
@ -36,12 +36,6 @@ namespace big
|
||||
|
||||
// perform initial setup
|
||||
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);
|
||||
scr_functions::init_nightclub_script({});
|
||||
});
|
||||
|
@ -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(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()
|
||||
|
@ -7,14 +7,19 @@ namespace big
|
||||
enum class Infraction
|
||||
{
|
||||
DESYNC_PROTECTION,
|
||||
BREAKUP_KICK_DETECTED,
|
||||
LOST_CONNECTION_KICK_DETECTED,
|
||||
SPOOFED_ROCKSTAR_ID,
|
||||
BREAKUP_KICK_DETECTED, // do not use
|
||||
LOST_CONNECTION_KICK_DETECTED, // do not use
|
||||
SPOOFED_ROCKSTAR_ID, // do not use
|
||||
TRIGGERED_ANTICHEAT,
|
||||
TRIED_CRASH_PLAYER,
|
||||
TRIED_CRASH_PLAYER, // do not use
|
||||
TRIED_KICK_PLAYER,
|
||||
BLAME_EXPLOSION_DETECTED,
|
||||
ATTACKING_WITH_GODMODE
|
||||
BLAME_EXPLOSION_DETECTED, // do not use (for now)
|
||||
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 = {
|
||||
@ -26,6 +31,11 @@ namespace big
|
||||
{Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"},
|
||||
{Infraction::TRIED_KICK_PLAYER, "Tried to kick you"},
|
||||
{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"},
|
||||
};
|
||||
}
|
@ -392,7 +392,9 @@ namespace big
|
||||
bool show_cheating_message = false;
|
||||
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{};
|
||||
|
||||
struct settings
|
||||
|
@ -6,6 +6,7 @@ class NetworkGameFilterMatchmakingComponent;
|
||||
class sCloudFile;
|
||||
class CPlayerGameStateDataNode;
|
||||
class CVehicleGadgetDataNode;
|
||||
class CGameScriptHandlerNetComponent;
|
||||
enum eVehicleGadgetType : uint32_t;
|
||||
|
||||
namespace rage
|
||||
@ -22,6 +23,7 @@ namespace rage
|
||||
class rlScHandle;
|
||||
class rlQueryPresenceAttributesContext;
|
||||
enum class eThreadState : uint32_t;
|
||||
class netArrayHandlerBase;
|
||||
}
|
||||
|
||||
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 update_language = void (*)(bool);
|
||||
|
||||
using get_host_array_handler_by_index = rage::netArrayHandlerBase* (*)(CGameScriptHandlerNetComponent* component, int index);
|
||||
}
|
||||
|
@ -29,46 +29,47 @@ namespace rage
|
||||
class netSyncDataUnit_Dynamic
|
||||
{
|
||||
public:
|
||||
virtual ~netSyncDataUnit_Dynamic() = default;// 0x00
|
||||
virtual ~netSyncDataUnit_Dynamic() = default; // 0x00
|
||||
|
||||
virtual void _0x08() = 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_sync;// 0x0C
|
||||
int m_players_need_ack; // 0x08
|
||||
int m_players_need_sync; // 0x0C
|
||||
};
|
||||
|
||||
class netSyncData_Dynamic
|
||||
{
|
||||
public:
|
||||
virtual ~netSyncData_Dynamic() = default;// 0x00
|
||||
virtual ~netSyncData_Dynamic() = default; // 0x00
|
||||
|
||||
virtual rage::datBitBuffer* _0x08() = 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 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
|
||||
{
|
||||
public:
|
||||
virtual ~netArrayHandlerBase() = default;// 0x00
|
||||
virtual ~netArrayHandlerBase() = default; // 0x00
|
||||
|
||||
virtual void _0x08() = 0;
|
||||
|
||||
@ -82,152 +83,134 @@ namespace rage
|
||||
|
||||
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 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 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 _0x158() = 0;
|
||||
|
||||
// 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 _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;
|
||||
uint8_t m_pad2[244 - 104];// +8
|
||||
uint16_t m_index; // 244
|
||||
uint16_t m_count; // 246
|
||||
uint8_t m_max_elements; // 248
|
||||
uint8_t m_element_size; // 249
|
||||
uint8_t m_element_size_2; // 250
|
||||
uint8_t m_pad3[13]; // 251
|
||||
void* m_array; // 264
|
||||
|
||||
#if 0
|
||||
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
|
||||
uint8_t m_pad2[244 - 104]; // +8
|
||||
uint16_t m_index; // 244
|
||||
uint16_t m_count; // 246
|
||||
uint8_t m_max_elements; // 248
|
||||
uint8_t m_element_size; // 249
|
||||
uint8_t m_element_size_2; // 250
|
||||
uint8_t m_pad3[13]; // 251
|
||||
void* m_array; // 264
|
||||
uint8_t m_pad4[341 - (264 + 8)];
|
||||
char m_flags; // 341
|
||||
};
|
||||
|
||||
static_assert(sizeof(netArrayHandlerBase) == 272);
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(netArrayHandlerBase) == 342);
|
||||
}
|
@ -203,8 +203,6 @@ namespace big
|
||||
|
||||
PVOID m_serialize_take_off_ped_variation_task;
|
||||
|
||||
PVOID m_create_script_handler;
|
||||
|
||||
functions::encode_session_info m_encode_session_info;
|
||||
functions::decode_session_info m_decode_session_info;
|
||||
functions::decode_peer_info m_decode_peer_info;
|
||||
@ -263,6 +261,10 @@ namespace big
|
||||
|
||||
int* m_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)
|
||||
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");
|
||||
|
@ -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::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::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();
|
||||
}
|
||||
|
||||
for (auto& thread : *g_pointers->m_gta.m_script_threads)
|
||||
{
|
||||
if (thread->m_handler)
|
||||
hook_script_handler((CGameScriptHandler*)thread->m_handler);
|
||||
}
|
||||
|
||||
MH_ApplyQueued();
|
||||
|
||||
m_enabled = true;
|
||||
@ -171,7 +163,6 @@ namespace big
|
||||
delete detour_hook_helper;
|
||||
}
|
||||
m_detour_hook_helpers.clear();
|
||||
m_handler_hooks.clear();
|
||||
}
|
||||
|
||||
hooking::detour_hook_helper::~detour_hook_helper()
|
||||
@ -195,8 +186,6 @@ namespace big
|
||||
|
||||
bool hooks::run_script_threads(std::uint32_t ops_to_execute)
|
||||
{
|
||||
g_native_invoker.cache_handlers();
|
||||
|
||||
if (g_running)
|
||||
{
|
||||
g_script_mgr.tick();
|
||||
|
@ -123,10 +123,6 @@ namespace big
|
||||
|
||||
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 void queue_dependency(void* dependency);
|
||||
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)>();
|
||||
}
|
||||
|
||||
void hook_script_handler(CGameScriptHandler* handler);
|
||||
std::unordered_map<CGameScriptHandler*, std::unique_ptr<vmt_hook>> m_handler_hooks;
|
||||
|
||||
private:
|
||||
bool m_enabled{};
|
||||
minhook_keepalive m_minhook_keepalive;
|
||||
|
@ -1,12 +1,61 @@
|
||||
#include "gta/net_game_event.hpp"
|
||||
#include "hooking.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
#include "util/globals.hpp"
|
||||
#include "util/misc.hpp"
|
||||
#include "util/session.hpp"
|
||||
|
||||
#include <entities/CDynamicEntity.hpp>
|
||||
#include <script/globals/GPBD_FM.hpp>
|
||||
#include <script/globals/GlobalPlayerBD.hpp>
|
||||
|
||||
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)
|
||||
{
|
||||
switch (net_event->get_type())
|
||||
@ -21,7 +70,9 @@ namespace big
|
||||
rage::sEntityDamagedData 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;
|
||||
|
||||
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(
|
||||
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);
|
||||
victim && victim->m_entity_type == 4 && reinterpret_cast<CPed*>(victim)->m_player_info)
|
||||
if (PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,20 @@
|
||||
#include "services/player_database/player_database_service.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
#include "util/notify.hpp"
|
||||
#include "util/session.hpp"
|
||||
|
||||
#include <network/Network.hpp>
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@ -82,10 +90,9 @@ namespace big
|
||||
net_player_data->m_gamer_handle.m_rockstar_id)));
|
||||
}
|
||||
|
||||
auto id = player->m_player_id;
|
||||
bool lock_session = g.session.lock_session;
|
||||
auto id = player->m_player_id;
|
||||
|
||||
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 (plyr->get_net_data()->m_gamer_handle.m_rockstar_id != 0)
|
||||
@ -106,32 +113,30 @@ namespace big
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plyr->block_join)
|
||||
{
|
||||
if (g_player_service->get_self()->is_host())
|
||||
{
|
||||
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
|
||||
{
|
||||
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, {});
|
||||
}
|
||||
}
|
||||
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, {});
|
||||
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));
|
||||
}
|
||||
|
||||
if (is_spoofed_host_token(plyr->get_net_data()->m_host_token))
|
||||
{
|
||||
session::add_infraction(plyr, Infraction::SPOOFED_HOST_TOKEN);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "netsync/nodes/player/CPlayerAppearanceDataNode.hpp"
|
||||
#include "netsync/nodes/player/CPlayerCreationDataNode.hpp"
|
||||
#include "netsync/nodes/player/CPlayerGameStateDataNode.hpp"
|
||||
#include "netsync/nodes/player/CPlayerGamerDataNode.hpp"
|
||||
#include "netsync/nodes/proximity_migrateable/CSectorDataNode.hpp"
|
||||
#include "netsync/nodes/train/CTrainGameStateDataNode.hpp"
|
||||
#include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp"
|
||||
@ -25,6 +26,7 @@
|
||||
#include "network/netObject.hpp"
|
||||
#include "util/model_info.hpp"
|
||||
#include "util/notify.hpp"
|
||||
#include "util/session.hpp"
|
||||
#include "vehicle/CVehicleModelInfo.hpp"
|
||||
|
||||
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};
|
||||
|
||||
inline CObject* get_game_object(rage::netObject* object)
|
||||
{
|
||||
return *(CObject**)((__int64)object + 0x50);
|
||||
}
|
||||
constexpr uint32_t valid_player_models[] = {
|
||||
RAGE_JOAAT("mp_m_freemode_01"),
|
||||
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)
|
||||
{
|
||||
@ -566,9 +603,11 @@ namespace big
|
||||
{
|
||||
if (!model_info::is_model_of_type(model, eModelType::Vehicle, eModelType::Unk133))
|
||||
return true;
|
||||
|
||||
for (auto iterator : crash_vehicles)
|
||||
if (iterator == model)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -576,28 +615,81 @@ namespace big
|
||||
{
|
||||
if (!model_info::get_model(model))
|
||||
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))
|
||||
return true;
|
||||
|
||||
for (auto iterator : crash_objects)
|
||||
if (iterator == model)
|
||||
return true;
|
||||
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)
|
||||
return false;
|
||||
|
||||
constexpr size_t reasonable_limit = 150;
|
||||
size_t i = 0;
|
||||
while (object && i < reasonable_limit)
|
||||
auto target = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attached_to_net_id, false);
|
||||
|
||||
while (target)
|
||||
{
|
||||
if (object->m_net_object && object->m_net_object->m_object_id == attached_to_net_id)
|
||||
if (target == object)
|
||||
return true;
|
||||
|
||||
object = g_pointers->m_gta.m_get_entity_attached_to(object);
|
||||
i++;
|
||||
auto next = get_entity_attached_to(target->GetGameObject());
|
||||
|
||||
if (!next)
|
||||
return false;
|
||||
|
||||
if (!next->m_net_object)
|
||||
return false;
|
||||
|
||||
target = next->m_net_object;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -629,6 +721,26 @@ namespace big
|
||||
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)
|
||||
{
|
||||
if (node->IsParentNode())
|
||||
@ -641,10 +753,14 @@ namespace big
|
||||
}
|
||||
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))
|
||||
{
|
||||
if ((((CProjectBaseSyncDataNode*)node)->flags & 1) == 0)
|
||||
continue;
|
||||
|
||||
switch (node_id)
|
||||
{
|
||||
case sync_node_id("CVehicleCreationDataNode"):
|
||||
@ -681,17 +797,13 @@ namespace big
|
||||
{
|
||||
const auto attach_node = (CPhysicalAttachDataNode*)(node);
|
||||
|
||||
// TODO: Find a better method to avoid false positives
|
||||
auto model_hash = get_game_object(object) ? get_game_object(object)->m_model_info->m_hash : 0;
|
||||
if (attach_node->m_attached && attach_node->m_attached_to == object->m_object_id && (model_hash != RAGE_JOAAT("hauler2") && model_hash != RAGE_JOAAT("phantom3")))
|
||||
if (attach_node->m_attached
|
||||
&& is_attachment_infinite(object,
|
||||
attach_node->m_attached_to,
|
||||
attach_node->m_attach_bone,
|
||||
attach_node->m_other_attach_bone))
|
||||
{
|
||||
// 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");
|
||||
notify::crash_blocked(sender, "infinite physical attachment");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -715,16 +827,15 @@ namespace big
|
||||
case sync_node_id("CPedAttachDataNode"):
|
||||
{
|
||||
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");
|
||||
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;
|
||||
}
|
||||
@ -746,6 +857,7 @@ namespace big
|
||||
notify::crash_blocked(sender, "invalid player model (appearance node)");
|
||||
return true;
|
||||
}
|
||||
check_player_model(sender_plyr, player_appearance_node->m_model_hash);
|
||||
break;
|
||||
}
|
||||
case sync_node_id("CPlayerCreationDataNode"):
|
||||
@ -756,6 +868,7 @@ namespace big
|
||||
notify::crash_blocked(sender, "invalid player model (creation node)");
|
||||
return true;
|
||||
}
|
||||
check_player_model(sender_plyr, player_creation_node->m_model);
|
||||
break;
|
||||
}
|
||||
case sync_node_id("CSectorDataNode"):
|
||||
@ -771,8 +884,10 @@ namespace big
|
||||
case sync_node_id("CPlayerGameStateDataNode"):
|
||||
{
|
||||
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
|
||||
|| game_state_node->m_population_control_sphere_z == 712)
|
||||
if (game_state_node->m_is_overriding_population_control_sphere
|
||||
&& !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)");
|
||||
return true;
|
||||
@ -784,7 +899,7 @@ namespace big
|
||||
const auto train_node = (CTrainGameStateDataNode*)(node);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
@ -808,6 +923,24 @@ namespace big
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "gta_util.hpp"
|
||||
#include "hooking.hpp"
|
||||
#include "script_local.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
#include "util/misc.hpp"
|
||||
#include "util/notify.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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
@ -26,14 +26,5 @@ namespace big
|
||||
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;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,9 @@ namespace big
|
||||
|
||||
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())
|
||||
{
|
||||
rage::scrNativeHandler handler = it->second;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "hooking.hpp"
|
||||
#include "native_hooks.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "util/notify.hpp"
|
||||
#include "util/scripts.hpp"
|
||||
|
||||
namespace big
|
||||
@ -25,13 +26,10 @@ namespace big
|
||||
|
||||
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())
|
||||
{
|
||||
hook->disable();
|
||||
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
|
||||
}
|
||||
notify::crash_blocked(nullptr, "out of bounds instance id");
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
hook->disable();
|
||||
g_hooking->m_handler_hooks.erase((CGameScriptHandler*)rage::scrThread::get()->m_handler);
|
||||
}
|
||||
notify::crash_blocked(nullptr, "out of bounds instance id");
|
||||
src->set_return_value<BOOL>(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
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)));
|
||||
|
@ -71,26 +71,25 @@ namespace big
|
||||
}
|
||||
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([] {
|
||||
scripts::force_host(RAGE_JOAAT("freemode"));
|
||||
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component)
|
||||
auto hash = SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME();
|
||||
g_fiber_pool->queue_job([hash] {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
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({});
|
||||
src->set_return_value<BOOL>(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
src->set_return_value<BOOL>(NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA());
|
||||
}
|
||||
|
||||
scr_functions::set_freemode_session_active({});
|
||||
src->set_return_value<BOOL>(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -842,15 +842,6 @@ namespace big
|
||||
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
|
||||
{
|
||||
"IDC",
|
||||
@ -1223,6 +1214,15 @@ namespace big
|
||||
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
|
||||
{
|
||||
"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_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
|
||||
|
||||
|
@ -95,12 +95,6 @@ namespace big
|
||||
bool script_connection::set_script_as_networked()
|
||||
{
|
||||
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);
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "network/ChatData.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "script.hpp"
|
||||
#include "session.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));
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#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 "local_player.hpp"
|
||||
#include "math.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "outfit.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
|
||||
namespace big::ped
|
||||
{
|
||||
@ -498,14 +499,16 @@ namespace big::ped
|
||||
|
||||
inline void kill_ped(const Ped ped)
|
||||
{
|
||||
if (entity::take_control_of(ped))
|
||||
PED::APPLY_DAMAGE_TO_PED(ped, PED::GET_PED_MAX_HEALTH(ped) * 2, false, 0);
|
||||
}
|
||||
if (entity::take_control_of(ped, 0))
|
||||
ENTITY::SET_ENTITY_HEALTH(ped, 0, self::ped);
|
||||
else
|
||||
{
|
||||
auto ptr = g_pointers->m_gta.m_handle_to_ptr(ped);
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
inline void kill_ped_by_relation(Ped ped, int relation_id)
|
||||
{
|
||||
if (PED::GET_RELATIONSHIP_BETWEEN_PEDS(ped, PLAYER::PLAYER_PED_ID()) == relation_id)
|
||||
kill_ped(ped);
|
||||
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)
|
||||
@ -546,7 +549,7 @@ namespace big::ped
|
||||
int drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(ped, item.id) - 1;
|
||||
if (drawable_id_max == -1)
|
||||
continue;
|
||||
int drawable_id = range(0, drawable_id_max);
|
||||
int drawable_id = range(0, drawable_id_max);
|
||||
int texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(ped, item.id, drawable_id) - 1;
|
||||
if (texture_id_max == -1)
|
||||
continue;
|
||||
@ -568,7 +571,7 @@ namespace big::ped
|
||||
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))
|
||||
return true;
|
||||
@ -596,7 +599,8 @@ namespace big::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)
|
||||
TASK::TASK_ENTER_VEHICLE(ped, veh, 10000, (int)seat, movespeed, 8, NULL);
|
||||
else
|
||||
|
@ -265,6 +265,14 @@ namespace big
|
||||
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();
|
||||
|
||||
|
@ -115,19 +115,22 @@ namespace big
|
||||
false,
|
||||
"Interior");
|
||||
|
||||
static float new_location[3];
|
||||
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->m_navigation->get_position());
|
||||
|
||||
components::small_text("Custom TP");
|
||||
ImGui::SetNextItemWidth(400);
|
||||
ImGui::InputFloat3("##customlocation", new_location);
|
||||
components::button("TP", [] {
|
||||
teleport::teleport_player_to_coords(g_player_service->get_selected(), *reinterpret_cast<rage::fvector3*>(&new_location));
|
||||
});
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Get current"))
|
||||
if (g_player_service->get_selected()->get_ped())
|
||||
{
|
||||
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
|
||||
static float new_location[3];
|
||||
auto& current_location = *reinterpret_cast<float(*)[3]>(g_player_service->get_selected()->get_ped()->get_position());
|
||||
|
||||
components::small_text("Custom TP");
|
||||
ImGui::SetNextItemWidth(400);
|
||||
ImGui::InputFloat3("##customlocation", new_location);
|
||||
components::button("TP", [] {
|
||||
teleport::teleport_player_to_coords(g_player_service->get_selected(), *reinterpret_cast<rage::fvector3*>(&new_location));
|
||||
});
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Get current"))
|
||||
{
|
||||
std::copy(std::begin(current_location), std::end(current_location), std::begin(new_location));
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
|
@ -23,7 +23,7 @@ namespace big
|
||||
player_icons += FONT_ICON_HOST;
|
||||
if (plyr->is_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;
|
||||
|
||||
const auto player_iconsc = player_icons.c_str();
|
||||
@ -53,9 +53,11 @@ namespace big
|
||||
g_gui_service->set_selected(tabs::PLAYER);
|
||||
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())
|
||||
{
|
||||
|
@ -14,7 +14,6 @@ namespace big
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Peds");
|
||||
// Nearby Ped Actions
|
||||
|
||||
components::button<ImVec2(110, 0), ImVec4(0.70196f, 0.3333f, 0.00392f, 1.f)>("Kill", [] {
|
||||
for (auto peds : entity::get_entities(false, true))
|
||||
@ -26,10 +25,14 @@ namespace big
|
||||
ImGui::SameLine();
|
||||
|
||||
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))
|
||||
ped::kill_ped_by_relation(peds, 4 || 5);
|
||||
if (!PED::IS_PED_A_PLAYER(ped))
|
||||
{
|
||||
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();
|
||||
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;
|
||||
int failed = 0;
|
||||
|
||||
for (auto ent : list)
|
||||
{
|
||||
if (ent == self::ped)
|
||||
if (PED::IS_PED_A_PLAYER(ent))
|
||||
continue;
|
||||
|
||||
if (ENTITY::DOES_ENTITY_EXIST(ent))
|
||||
@ -122,8 +126,6 @@ namespace big
|
||||
entity::delete_entity(ent);
|
||||
}
|
||||
|
||||
script::get_current()->yield(5ms);
|
||||
|
||||
if (ENTITY::DOES_ENTITY_EXIST(ent))
|
||||
failed++;
|
||||
else
|
||||
@ -131,7 +133,7 @@ namespace big
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
|
Reference in New Issue
Block a user