From f09b1cbda32c24a183d6ec1b567a3676236713da Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Wed, 12 Jul 2023 17:03:29 +0000 Subject: [PATCH] General improvements (#1693) * remove(replay): remove replay interface * fix(context_menu): better console controls * feat(protections): improve protections * feat(protections): actually fix parachute crash * feat(protections): kick rejoin * feat(context_menu): more context menu stuff --- .../commands/player/kick/breakup_kick.cpp | 39 +------ .../looped/vehicle/unlimited_weapons.cpp | 12 +-- src/backend/script_patches.hpp | 5 + src/core/data/infractions.hpp | 2 +- src/core/settings.hpp | 33 +++--- src/gta/enums.hpp | 11 ++ src/gta/net_object_mgr.hpp | 13 ++- src/gta/pools.hpp | 20 ++-- src/gta/replay.hpp | 94 ---------------- src/gta_pointers.hpp | 3 +- src/hooking.cpp | 2 + src/hooking.hpp | 3 + src/hooks/info/get_network_event_data.cpp | 18 +++- src/hooks/protections/can_apply_data.cpp | 101 ++++++++++++++---- src/hooks/protections/receive_net_message.cpp | 34 ++++-- .../protections/script_event_handler.cpp | 56 +++++++--- .../send_non_physical_player_data.cpp | 25 +++++ .../serialize_take_off_ped_variation_task.cpp | 24 ++++- src/native_hooks/carmod_shop.hpp | 9 ++ src/native_hooks/native_hooks.cpp | 1 + src/pointers.cpp | 18 ++-- src/pointers.hpp | 1 - src/script_function.hpp | 2 + .../context_menu/context_menu_service.cpp | 39 +++++-- .../context_menu/context_menu_service.hpp | 41 +++++-- src/services/orbital_drone/orbital_drone.cpp | 18 +--- src/services/players/player.hpp | 2 + src/services/vehicle/xml_vehicles_service.cpp | 29 +++-- src/util/entity.hpp | 3 +- src/util/math.hpp | 5 + src/util/notify.hpp | 12 ++- src/util/session.hpp | 44 ++++++-- src/views/core/view_overlay.cpp | 25 ++--- src/views/network/view_network.cpp | 3 +- .../settings/view_protection_settings.cpp | 1 + src/views/settings/view_reaction_settings.cpp | 7 ++ 36 files changed, 458 insertions(+), 297 deletions(-) delete mode 100644 src/gta/replay.hpp create mode 100644 src/hooks/protections/send_non_physical_player_data.cpp diff --git a/src/backend/commands/player/kick/breakup_kick.cpp b/src/backend/commands/player/kick/breakup_kick.cpp index f0281a52..495a85bf 100644 --- a/src/backend/commands/player/kick/breakup_kick.cpp +++ b/src/backend/commands/player/kick/breakup_kick.cpp @@ -20,7 +20,7 @@ namespace big virtual void execute(player_ptr player, const std::vector& _args, const std::shared_ptr ctx) { - if (!g_player_service->get_self()->is_host()) + if (!g_player_service->get_self()->is_host() || !player->get_net_data()) return; rage::snMsgRemoveGamersFromSessionCmd cmd{}; @@ -31,42 +31,7 @@ namespace big if (g.session.show_cheating_message) cmd.m_unk = 19; - if (gta_util::get_network()->m_game_session.is_host()) - { - g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd); - } - else if (player->is_host()) - { - for (auto& [_, plyr] : g_player_service->players()) - { - if (plyr->id() != player->id()) - g_pointers->m_gta.m_send_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr, - g_pointers->m_gta.m_get_connection_peer(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr, - plyr->get_session_player()->m_player_data.m_peer_id_2), - gta_util::get_network()->m_game_session_ptr->m_connection_identifier, - &cmd, - 0x1000000); - } - - g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd); - } - else - { - for (auto& [_, plyr] : g_player_service->players()) - { - if (plyr->is_host()) - { - g_pointers->m_gta.m_send_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr, - g_pointers->m_gta.m_get_connection_peer(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr, - plyr->get_session_player()->m_player_data.m_peer_id_2), - gta_util::get_network()->m_game_session_ptr->m_connection_identifier, - &cmd, - 0x1000000); - - break; - } - } - } + g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd); } }; diff --git a/src/backend/looped/vehicle/unlimited_weapons.cpp b/src/backend/looped/vehicle/unlimited_weapons.cpp index 3e25092d..b4f471c4 100644 --- a/src/backend/looped/vehicle/unlimited_weapons.cpp +++ b/src/backend/looped/vehicle/unlimited_weapons.cpp @@ -3,14 +3,6 @@ namespace big { - class veh_unlimited_weapons : looped_command - { - using looped_command::looped_command; - - virtual void on_tick() override - { - - } - }; - veh_unlimited_weapons g_veh_unlimited_weapons("vehallweapons", "Allow Weapons In Vehicle", "Allows you to use all weapons in vehicle", g.vehicle.unlimited_weapons); + bool_command g_veh_unlimited_weapons("vehallweapons", "Allow Weapons In Vehicle", "Allows you to use all weapons in vehicle", + g.vehicle.unlimited_weapons); } diff --git a/src/backend/script_patches.hpp b/src/backend/script_patches.hpp index 118e2743..bd6baaa7 100644 --- a/src/backend/script_patches.hpp +++ b/src/backend/script_patches.hpp @@ -36,6 +36,11 @@ namespace big 0, {0x2B, 0x2B, 0x2B, 0x00, 0x55}, &g.self.invisibility}); + g_script_patcher_service->add_patch({RAGE_JOAAT("freemode"), + "2D 01 03 00 00 38 00 71 72 5D ? ? ? 06 56 ? ? 71 2E ? ? 2C ? ? ? 71", + 5, + {0x72, 0x2E, 0x01, 0x01}, + &g.session.unhide_players_from_player_list}); g_script_patcher_service->add_patch( {RAGE_JOAAT("carmod_shop"), "2D 01 0A 00 00 4F ? ? 40 ? 41 ? 39 03", 5, {0x2E, 0x01, 0x00}, &g.vehicle.ls_customs}); // disable camera diff --git a/src/core/data/infractions.hpp b/src/core/data/infractions.hpp index bb90ea71..4b51cedf 100644 --- a/src/core/data/infractions.hpp +++ b/src/core/data/infractions.hpp @@ -19,7 +19,7 @@ namespace big ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, SPOOFED_DATA, SPOOFED_HOST_TOKEN, - INVALID_PLAYER_MODEL + INVALID_PLAYER_MODEL, }; inline std::unordered_map infraction_desc = { diff --git a/src/core/settings.hpp b/src/core/settings.hpp index 8cd3bf40..ae65a9fa 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -187,8 +187,9 @@ namespace big reaction rotate_cam{"Rotate Cam", "Blocked Rotate Cam from %s", "%s tried to mess with my camera!"}; reaction send_to_cutscene{"Send To Cutscene", "Blocked Send To Cutscene from %s", "%s tried to force me into a cutscene!"}; reaction send_to_location{"Send To Location", "Blocked Send To Location from %s", "%s tried to send me to Cayo Perico!"}; + reaction send_to_interior{"Send To Interior", "Blocked Send To Interior from %s", "%s tried to send me to an interior!"}; reaction sound_spam{"Sound Spam", "Blocked Sound Spam from %s", "%s tried to spam annoying sounds at me!"}; - reaction spectate_notification{"Spectate", "Blocked Spectate from %s", "Blocked Spectate from %s"}; + reaction spectate_notification{"Spectate Notification", "Blocked Spectate Notification from %s", "Blocked Spectate Notification from %s"}; reaction give_collectible{"Give Collectible", "Blocked Give Collectible from %s", "%s tried to give me a collectible!"}; reaction transaction_error{"Transaction Error", "Blocked Transaction Error from %s", "%s tried to show me a transaction error!"}; reaction tse_freeze{"TSE Freeze", "Blocked TSE Freeze from %s", "%s tried to softlock my game!"}; @@ -211,10 +212,12 @@ namespace big reaction modder_detection{"Modder Detection", "%s is detected as a modder by the anticheat", "%s is detected as a modder by the anticheat"}; reaction request_control_event{"Request Control Event", "Blocked Request Control Event from %s", "%s tried to mess with my vehicle!"}; reaction report{"Report", "Blocked Report from %s", "%s tried to report me!"}; + reaction spectate{"Spectate", "%s is spectating you", "%s is spectating me!"}; + interloper_reaction spectate_others{"Spectate Others", "%s is spectating %s!", "%s is spectating %s!", false, false}; reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, gamer_instruction_kick) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, gamer_instruction_kick, send_to_interior, spectate, spectate_others) } reactions{}; struct player @@ -263,8 +266,9 @@ namespace big bool rid_join = false; bool receive_pickup = false; bool admin_check = true; + bool kick_rejoin = true; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, receive_pickup, admin_check) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, receive_pickup, admin_check, kick_rejoin) } protections{}; struct self @@ -343,16 +347,17 @@ namespace big struct session { - bool log_chat_messages = false; - bool log_text_messages = false; - bool decloak_players = false; - bool force_session_host = false; - bool force_script_host = false; - bool player_magnet_enabled = false; - int player_magnet_count = 32; - bool is_team = false; - bool join_in_sctv_slots = false; - bool lock_session = false; + bool log_chat_messages = false; + bool log_text_messages = false; + bool decloak_players = false; + bool unhide_players_from_player_list = true; + bool force_session_host = false; + bool force_script_host = false; + bool player_magnet_enabled = false; + int player_magnet_count = 32; + bool is_team = false; + bool join_in_sctv_slots = false; + bool lock_session = false; const char chat_command_prefix = '/'; const char chat_output_prefix = '>'; @@ -392,7 +397,7 @@ namespace big bool fast_join = false; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, 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) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, 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, unhide_players_from_player_list) } session{}; struct settings diff --git a/src/gta/enums.hpp b/src/gta/enums.hpp index 6cccc613..074186ae 100644 --- a/src/gta/enums.hpp +++ b/src/gta/enums.hpp @@ -509,6 +509,17 @@ enum class eNetworkEvents : uint16_t NETWORK_CHECK_CATALOG_CRC }; +enum class KickReason : std::uint8_t +{ + VOTED_OUT, + PEER_COMPLAINTS, + CONNECTION_ERROR, + NAT_TYPE, + SCADMIN, + SCADMIN_BLACKLIST, + NUM_REASONS +}; + enum class ScriptEntityChangeType { BlockingOfNonTemporaryEvents, diff --git a/src/gta/net_object_mgr.hpp b/src/gta/net_object_mgr.hpp index c5c4edde..056ad82e 100644 --- a/src/gta/net_object_mgr.hpp +++ b/src/gta/net_object_mgr.hpp @@ -2,7 +2,6 @@ #include "../pointers.hpp" #include "enums.hpp" #include "node_list.hpp" -#include "replay.hpp" class CNetGamePlayer; @@ -11,10 +10,10 @@ namespace rage class CPlayerSyncTree { public: - char pad_0000[8]; //0x0000 - netObject* player_object;//0x0008 - char pad_0010[256]; //0x0010 - }; //Size: 0x0110 + char pad_0000[8]; //0x0000 + netObject* player_object; //0x0008 + char pad_0010[256]; //0x0010 + }; //Size: 0x0110 class CNetworkSyncDataULBase { @@ -60,12 +59,12 @@ namespace rage uint8_t ownerId; uint8_t nextOwnerId; uint8_t isRemote; - uint8_t wantsToDelete : 1;// netobj+76 + uint8_t wantsToDelete : 1; // netobj+76 uint8_t unk1 : 1; uint8_t shouldNotBeDeleted : 1; uint8_t pad_4Dh[3]; uint8_t pad_50h[32]; - uint32_t creationAckedPlayers;// netobj+112 + uint32_t creationAckedPlayers; // netobj+112 uint32_t m64; uint32_t m68; uint32_t m6C; diff --git a/src/gta/pools.hpp b/src/gta/pools.hpp index 16f117e9..a4abd402 100644 --- a/src/gta/pools.hpp +++ b/src/gta/pools.hpp @@ -56,7 +56,7 @@ public: std::vector arr; for (auto entity : *static_cast(this)) { - if(entity) + if (entity) arr.push_back(big::g_pointers->m_gta.m_ptr_to_handle(entity)); } @@ -98,10 +98,12 @@ public: class GenericPool : public PoolUtils { public: - UINT64 m_pool_address; - BYTE* m_bit_array; - UINT32 m_size; - UINT32 m_item_size; + UINT64 m_pool_address; // 0x0 + BYTE* m_bit_array; // 0x8 + UINT32 m_size; // 0x10 + UINT32 m_item_size; // 0x14 + UINT32 m_pad[2]; // 0x18 + UINT32 m_item_count; // 0x20 inline bool is_valid(UINT32 i) { @@ -113,10 +115,16 @@ public: return mask(i) & (m_pool_address + i * m_item_size); } + inline int get_item_count() + { + return (4 * m_item_count) >> 2; + } + private: inline long long mask(UINT32 i) { long long num1 = m_bit_array[i] & 0x80; return ~((num1 | -num1) >> 63); } -}; \ No newline at end of file +}; +static_assert(offsetof(GenericPool, GenericPool::m_item_count) == 0x20); \ No newline at end of file diff --git a/src/gta/replay.hpp b/src/gta/replay.hpp deleted file mode 100644 index 54856509..00000000 --- a/src/gta/replay.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "base/CObject.hpp" -#include "common.hpp" -#include "fwddec.hpp" - -#pragma pack(push, 4) -namespace rage -{ - template - class CEntityEntry - { - public: - T* m_entity_ptr; //0x0000 - int32_t m_handle; //0x0008 - char pad_000C[4]; //0x000C - }; //Size: 0x0010 - static_assert(sizeof(CEntityEntry) == 0x10, "CEntityHandle is not properly sized"); - - class CObjectEntry : public CEntityEntry - { - }; - - class CPedEntry : public CEntityEntry - { - }; - - class CVehicleEntry : public CEntityEntry - { - }; //Size: 0x8FC0 - - class CObjectInterface - { - public: - char pad_0000[344]; //0x0000 - std::array* m_object_list; //0x0158 - int32_t m_max_objects; //0x0160 - char pad_0164[4]; //0x0164 - int32_t m_cur_objects; //0x0168 - - CObject* get_object(const int& index) - { - if (index < m_max_objects) - return (*m_object_list)[index].m_entity_ptr; - return nullptr; - } - }; //Size: 0x016C - - class CPedInterface - { - public: - char pad_0000[256]; //0x0000 - std::array* m_ped_list; //0x0100 - int32_t m_max_peds; //0x0108 - char pad_010C[4]; //0x010C - int32_t m_cur_peds; //0x0110 - - CPed* get_ped(const int& index) - { - if (index < m_max_peds) - return (*m_ped_list)[index].m_entity_ptr; - return nullptr; - } - }; //Size: 0x0114 - - class CVehicleInterface - { - public: - char pad_0000[384]; //0x0000 - std::array* m_vehicle_list; //0x0180 - int32_t m_max_vehicles; //0x0188 - char pad_018C[4]; //0x018C - int32_t m_cur_vehicles; //0x0190 - - CVehicle* get_vehicle(const int& index) - { - if (index < m_max_vehicles) - return (*m_vehicle_list)[index].m_entity_ptr; - return nullptr; - } - }; //Size: 0x0194 - - - class CReplayInterface - { - public: - char pad_0000[16]; //0x0000 - class CVehicleInterface* m_vehicle_interface; //0x0010 - class CPedInterface* m_ped_interface; //0x0018 - char pad_0020[8]; //0x0020 - class CObjectInterface* m_object_interface; //0x0028 - }; //Size: 0x0030 -} -#pragma pack(pop) \ No newline at end of file diff --git a/src/gta_pointers.hpp b/src/gta_pointers.hpp index 422f8df1..424e7d10 100644 --- a/src/gta_pointers.hpp +++ b/src/gta_pointers.hpp @@ -56,7 +56,6 @@ namespace big CPedFactory** m_ped_factory{}; CNetworkPlayerMgr** m_network_player_mgr{}; CNetworkObjectMgr** m_network_object_mgr{}; - rage::CReplayInterface** m_replay_interface{}; functions::ptr_to_handle m_ptr_to_handle{}; functions::handle_to_ptr m_handle_to_ptr{}; @@ -271,6 +270,8 @@ namespace big PVOID m_error_message_box{}; functions::get_title_caption_error_message_box m_get_title_caption_error_message_box{}; + + PVOID m_send_non_physical_player_data; }; #pragma pack(pop) static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); diff --git a/src/hooking.cpp b/src/hooking.cpp index b556e303..efc0bad2 100644 --- a/src/hooking.cpp +++ b/src/hooking.cpp @@ -114,6 +114,8 @@ namespace big detour_hook_helper::add("E0MBH", g_pointers->m_gta.m_error_message_box); + detour_hook_helper::add("SNPPD", g_pointers->m_gta.m_send_non_physical_player_data); + g_hooking = this; } diff --git a/src/hooking.hpp b/src/hooking.hpp index 0f7c8d20..48efa4dc 100644 --- a/src/hooking.hpp +++ b/src/hooking.hpp @@ -30,6 +30,7 @@ class CPlayerAppearanceDataNode; class CFoundDevice; class IDirectSoundCapture; class CVehicleProximityMigrationDataNode; +class CNonPhysicalPlayerData; namespace rage { @@ -151,6 +152,8 @@ namespace big static int netfilter_handle_message(__int64 filter, char* message, int flags); static void log_error_message_box(rage::joaat_t joaated_error_code, char a2); + + static void send_non_physical_player_data(CNetGamePlayer* player, __int64 message, int flags, void* a4, CNetGamePlayer* a5); }; class minhook_keepalive diff --git a/src/hooks/info/get_network_event_data.cpp b/src/hooks/info/get_network_event_data.cpp index eee1d115..6408229f 100644 --- a/src/hooks/info/get_network_event_data.cpp +++ b/src/hooks/info/get_network_event_data.cpp @@ -21,9 +21,6 @@ namespace big 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()->Entries[player->id()].IsInvisible) return true; @@ -62,7 +59,17 @@ namespace big { case rage::eEventNetworkType::CEventNetworkRemovedFromSessionDueToComplaints: { - g_notification_service->push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data()); + if (g.protections.kick_rejoin && !NETWORK::NETWORK_IS_ACTIVITY_SESSION() && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0 && !STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS()) + { + g_fiber_pool->queue_job([] { + session::join_session(gta_util::get_network()->m_last_joined_session.m_session_info); + }); + g_notification_service->push_warning("KICKED"_T.data(), "You have been desync kicked. Rejoining previous session..."); + } + else + { + g_notification_service->push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data()); + } break; } case rage::eEventNetworkType::CEventNetworkEntityDamage: @@ -101,6 +108,9 @@ namespace big if (NETWORK::NETWORK_IS_ACTIVITY_SESSION()) break; + if (!NETWORK::NETWORK_ARE_PLAYERS_IN_SAME_TUTORIAL_SESSION(self::id, player->id())) + break; + if (globals::get_interior_from_player(player->id()) != 0) break; diff --git a/src/hooks/protections/can_apply_data.cpp b/src/hooks/protections/can_apply_data.cpp index 6891502e..7c58282a 100644 --- a/src/hooks/protections/can_apply_data.cpp +++ b/src/hooks/protections/can_apply_data.cpp @@ -723,22 +723,9 @@ namespace big inline bool is_sane_override_pos(float x, float y, float z) { - if (isnan(x) || isnan(y) || isnan(z)) - return false; + bool crash = (char)(fmaxf(0.0, (x + 149.0) - -8192.0) / 75.0) == 255 || (char)(fmaxf(0.0, (y + 149.0) - -8192.0) / 75.0) == 255; - 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; + return !crash; } bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object) @@ -807,6 +794,22 @@ namespace big return true; } + if (attach_node->m_attached && object && object->m_object_type == (int16_t)eNetObjType::NET_OBJ_TYPE_TRAILER) + { + if (auto net_obj = + g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attach_node->m_attached_to, false)) + { + if (auto entity = net_obj->GetGameObject()) + { + if (entity->m_entity_type != 3) + { + notify::crash_blocked(sender, "invalid attachment"); + return true; + } + } + } + } + break; } case sync_node_id("CPedCreationDataNode"): @@ -887,11 +890,72 @@ namespace big 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)) + game_state_node->m_population_control_sphere_z) + && gta_util::get_network()->m_game_session_ptr->is_host()) { notify::crash_blocked(sender, "invalid sector position (player game state node)"); return true; } + + if (sender_plyr) + { + if (game_state_node->m_is_spectating) + { + if (!sender_plyr->get_ped()) + break; + + if (sender_plyr->get_ped()->m_health <= 0.0f) // you spectate the player that killed you + break; + + auto net_obj = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, + game_state_node->m_spectating_net_id, + false); + + if (!net_obj) + break; + + auto entity = net_obj->GetGameObject(); + + if (!entity || entity->m_entity_type != 4) + break; + + auto player_info = ((CPed*)entity)->m_player_info; + + if (!player_info) + break; + + player_ptr target = nullptr; + + if (g_local_player && (CPed*)entity == g_local_player) + { + target = g_player_service->get_self(); + } + else + { + for (auto p : g_player_service->players()) + if (p.second->get_player_info() == player_info) + target = p.second; + } + + if (!target || !target->is_valid()) + break; + + if (target->id() != sender_plyr->spectating_player) + { + if (target->id() == self::id) + g.reactions.spectate.process(sender_plyr); + else + g.reactions.spectate_others.process(sender_plyr, target); + + sender_plyr->spectating_player = target->id(); + } + } + else + { + sender_plyr->spectating_player = -1; + } + } + break; } case sync_node_id("CTrainGameStateDataNode"): @@ -899,7 +963,8 @@ 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 bounds train track index"); + //notify::crash_blocked(sender, "out of bounds train track index"); + //LOG(INFO) << train_node->m_track_id; return true; } break; @@ -958,4 +1023,4 @@ namespace big return g_hooking->get_original()(tree, object); } -} +} \ No newline at end of file diff --git a/src/hooks/protections/receive_net_message.cpp b/src/hooks/protections/receive_net_message.cpp index 13ee9106..ee6c4741 100644 --- a/src/hooks/protections/receive_net_message.cpp +++ b/src/hooks/protections/receive_net_message.cpp @@ -177,16 +177,6 @@ namespace big } return true; } - case rage::eNetMessage::MsgRequestObjectIds: - { - if (player->block_join) - { - g_notification_service->push("BLOCK_JOIN"_T.data(), - std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(player->get_name()))); - return true; - } - break; - } case rage::eNetMessage::MsgScriptHostRequest: { CGameScriptId script; @@ -216,7 +206,7 @@ namespace big } case rage::eNetMessage::MsgTransitionGamerInstruction: { - // this kick is still a thing + // it doesn't work but a certain p2c uses it if (is_kick_instruction(buffer)) { g.reactions.gamer_instruction_kick.process(player); @@ -224,6 +214,28 @@ namespace big } break; } + case rage::eNetMessage::MsgKickPlayer: + { + KickReason reason = buffer.Read(3); + + if (!player->is_host()) + return true; + + if (reason == KickReason::VOTED_OUT) + { + g_notification_service->push_warning("Protections", "You have been kicked by the host"); + return true; + } + + break; + } + } + } + else + { + switch (msgType) + { + case rage::eNetMessage::MsgScriptMigrateHost: return true; } } diff --git a/src/hooks/protections/script_event_handler.cpp b/src/hooks/protections/script_event_handler.cpp index d84cad31..2b2c71f3 100644 --- a/src/hooks/protections/script_event_handler.cpp +++ b/src/hooks/protections/script_event_handler.cpp @@ -4,6 +4,7 @@ #include "gta_util.hpp" #include "hooking.hpp" #include "lua/lua_manager.hpp" +#include "util/math.hpp" #include "util/session.hpp" #include @@ -51,6 +52,11 @@ namespace big return false; } + inline bool is_player_our_boss(Player sender) + { + return sender == scr_globals::gpbd_fm_3.as()->Entries[self::id].BossGoon.Boss; + } + bool hooks::scripted_game_event(CScriptedGameEvent* scripted_game_event, CNetGamePlayer* player) { const auto args = scripted_game_event->m_args; @@ -156,10 +162,16 @@ namespace big } break; case eRemoteEvent::MCTeleport: - if (g.protections.script_events.mc_teleport && args[3] <= 32) + if (g.protections.script_events.mc_teleport && args[3] <= 32 && !is_player_our_boss(plyr->id())) { - g.reactions.mc_teleport.process(plyr); - return true; + for (int i = 0; i < 32; i++) + { + if (args[4 + i] == NETWORK::NETWORK_HASH_FROM_PLAYER_HANDLE(self::id)) + { + g.reactions.mc_teleport.process(plyr); + return true; + } + } } else if (args[3] > 32) { @@ -175,16 +187,14 @@ namespace big } break; case eRemoteEvent::RemoteOffradar: - if (g.protections.script_events.remote_off_radar - && player->m_player_id != scr_globals::gpbd_fm_3.as()->Entries[self::id].BossGoon.Boss) + if (g.protections.script_events.remote_off_radar && !is_player_our_boss(plyr->id()) && !is_player_driver_of_local_vehicle(plyr->id())) { g.reactions.remote_off_radar.process(plyr); return true; } break; case eRemoteEvent::TSECommand: - if (g.protections.script_events.rotate_cam && static_cast(args[2]) == eRemoteEvent::TSECommandRotateCam - && !gta_util::get_network()->m_is_activity_session) + if (g.protections.script_events.rotate_cam && static_cast(args[2]) == eRemoteEvent::TSECommandRotateCam && !NETWORK::NETWORK_IS_ACTIVITY_SESSION()) { g.reactions.rotate_cam.process(plyr); return true; @@ -198,8 +208,7 @@ namespace big } break; case eRemoteEvent::SendToCutscene: - if (g.protections.script_events.send_to_cutscene - && player->m_player_id != scr_globals::gpbd_fm_3.as()->Entries[self::id].BossGoon.Boss) + if (g.protections.script_events.send_to_cutscene && !is_player_our_boss(plyr->id())) { g.reactions.send_to_cutscene.process(plyr); return true; @@ -207,6 +216,9 @@ namespace big break; case eRemoteEvent::SendToLocation: { + if (is_player_our_boss(plyr->id())) + break; + bool known_location = false; if (args[2] == 0 && args[3] == 0) @@ -242,11 +254,9 @@ namespace big } case eRemoteEvent::SoundSpam: { - auto plyr = g_player_service->get_by_id(player->m_player_id); - if (g.protections.script_events.sound_spam && (!plyr || plyr->m_invites_rate_limit.process())) { - if (plyr && plyr->m_invites_rate_limit.exceeded_last_process()) + if (plyr->m_invites_rate_limit.exceeded_last_process()) g.reactions.sound_spam.process(plyr); return true; } @@ -275,8 +285,7 @@ namespace big } break; case eRemoteEvent::NetworkBail: - if (auto plyr = g_player_service->get_by_id(player->m_player_id)) - session::add_infraction(plyr, Infraction::TRIED_KICK_PLAYER); + session::add_infraction(plyr, Infraction::TRIED_KICK_PLAYER); g.reactions.network_bail.process(plyr); return true; case eRemoteEvent::TeleportToWarehouse: @@ -341,6 +350,25 @@ namespace big g.reactions.null_function_kick.process(plyr); return true; } + + if (NETWORK::NETWORK_IS_ACTIVITY_SESSION()) + break; + + if (!g_local_player) + break; + + if (is_player_our_boss(plyr->id())) + break; + + if (is_player_driver_of_local_vehicle(plyr->id())) + break; + + if (!plyr->get_ped() || math::distance_between_vectors(*plyr->get_ped()->get_position(), *g_local_player->get_position()) > 75.0f) + { + g.reactions.send_to_interior.process(plyr); + return true; + } + break; } case eRemoteEvent::DestroyPersonalVehicle: g.reactions.destroy_personal_vehicle.process(plyr); return true; diff --git a/src/hooks/protections/send_non_physical_player_data.cpp b/src/hooks/protections/send_non_physical_player_data.cpp new file mode 100644 index 00000000..534709c2 --- /dev/null +++ b/src/hooks/protections/send_non_physical_player_data.cpp @@ -0,0 +1,25 @@ +#include "hooking.hpp" +#include "services/players/player_service.hpp" + +#include +#include + +namespace big +{ + void hooks::send_non_physical_player_data(CNetGamePlayer* player, __int64 message, int flags, void* a4, CNetGamePlayer* a5) + { + auto plyr = g_player_service->get_by_id(player->m_player_id); + auto data = *(CNonPhysicalPlayerData**)(message + 0x10); + int old_bubble_id = data->m_bubble_id; + + if (plyr && plyr->block_join) + { + data->m_bubble_id = 10; + g_notification_service->push("BLOCK_JOIN"_T.data(), std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(plyr->get_name()))); + } + + g_hooking->get_original()(player, message, flags, a4, a5); + + data->m_bubble_id = old_bubble_id; + } +} \ No newline at end of file diff --git a/src/hooks/protections/serialize_take_off_ped_variation_task.cpp b/src/hooks/protections/serialize_take_off_ped_variation_task.cpp index 559301e3..70e1382b 100644 --- a/src/hooks/protections/serialize_take_off_ped_variation_task.cpp +++ b/src/hooks/protections/serialize_take_off_ped_variation_task.cpp @@ -5,12 +5,32 @@ namespace big { + constexpr uint32_t valid_parachute_models[] = { + RAGE_JOAAT("p_parachute_s"), + RAGE_JOAAT("vw_p_para_bag_vine_s"), + RAGE_JOAAT("reh_p_para_bag_reh_s_01a"), + RAGE_JOAAT("xm_prop_x17_scuba_tank"), + RAGE_JOAAT("lts_p_para_bag_pilot2_s"), + RAGE_JOAAT("lts_p_para_bag_lts_s"), + RAGE_JOAAT("p_para_bag_tr_s_01a"), + RAGE_JOAAT("p_para_bag_xmas_s"), + }; + + bool is_valid_parachute_model(rage::joaat_t hash) + { + for (auto& model : valid_parachute_models) + if (model == hash) + return true; + + return false; + } + void hooks::serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer) { g_hooking->get_original()(info, serializer); - if (info->m_prop_hash != 0 && info->m_variation_component == 5 && info->m_prop_hash != RAGE_JOAAT("p_parachute_s")) + if (!is_valid_parachute_model(info->m_prop_hash)) { - // notify::crash_blocked(g.m_syncing_player, "invalid parachute"); false positives + notify::crash_blocked(g.m_syncing_player, "invalid parachute"); info->m_prop_hash = 0; } } diff --git a/src/native_hooks/carmod_shop.hpp b/src/native_hooks/carmod_shop.hpp index 68636c17..a2c30c15 100644 --- a/src/native_hooks/carmod_shop.hpp +++ b/src/native_hooks/carmod_shop.hpp @@ -53,6 +53,15 @@ namespace big } } + inline void STAT_SET_INT(rage::scrNativeCallContext* src) + { + const auto hash = src->get_arg(0); + if (hash == RAGE_JOAAT("SP0_TOTAL_CASH") || hash == RAGE_JOAAT("SP1_TOTAL_CASH") || hash == RAGE_JOAAT("SP2_TOTAL_CASH")) + return; + + src->set_return_value(STATS::STAT_SET_INT(hash, src->get_arg(1), src->get_arg(2))); + } + inline void SET_ENTITY_COORDS(rage::scrNativeCallContext* src) { if (!g.vehicle.ls_customs) diff --git a/src/native_hooks/native_hooks.cpp b/src/native_hooks/native_hooks.cpp index 157aab68..53a8dac3 100644 --- a/src/native_hooks/native_hooks.cpp +++ b/src/native_hooks/native_hooks.cpp @@ -125,6 +125,7 @@ namespace big add_native_detour(RAGE_JOAAT("carmod_shop"), 0x8E2530AA8ADA980E, carmod_shop::SET_ENTITY_HEADING); add_native_detour(RAGE_JOAAT("carmod_shop"), 0x34E710FF01247C5A, carmod_shop::SET_VEHICLE_LIGHTS); add_native_detour(RAGE_JOAAT("carmod_shop"), 0x767FBC2AC802EF3D, carmod_shop::STAT_GET_INT); + add_native_detour(RAGE_JOAAT("carmod_shop"), 0xB3271D7AB655B441, carmod_shop::STAT_SET_INT); add_native_detour(RAGE_JOAAT("carmod_shop"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS); add_native_detour(RAGE_JOAAT("freemode"), 0x2C83A9DA6BFFC4F9, freemode::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH); diff --git a/src/pointers.cpp b/src/pointers.cpp index 1cf6deb8..9bedf7f6 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -297,15 +297,6 @@ namespace big g_pointers->m_gta.m_write_player_game_state_data_node = ptr.as(); } }, - // Replay Interface - { - "RI", - "0F B7 44 24 ? 66 89 44 4E", - [](memory::handle ptr) - { - g_pointers->m_gta.m_replay_interface = ptr.add(0x1F).rip().as(); - } - }, // Ptr To Handle { "PTH", @@ -1217,6 +1208,15 @@ namespace big g_pointers->m_gta.m_get_host_array_handler_by_index = ptr.as(); } }, + // Send Non Physical Player Data + { + "SNPPD", + "E8 ? ? ? ? 4C 8B 0F 44 0F B7 85 A0 01 00 00", + [](memory::handle ptr) + { + g_pointers->m_gta.m_send_non_physical_player_data = ptr.add(1).rip().as(); + } + }, // Max Wanted Level { "MWL", diff --git a/src/pointers.hpp b/src/pointers.hpp index a96aaf6d..8d7a226b 100644 --- a/src/pointers.hpp +++ b/src/pointers.hpp @@ -2,7 +2,6 @@ #include "base/HashTable.hpp" #include "function_types.hpp" #include "gta/fwddec.hpp" -#include "gta/replay.hpp" #include "gta_pointers.hpp" #include "memory/batch.hpp" #include "memory/byte_patch.hpp" diff --git a/src/script_function.hpp b/src/script_function.hpp index b54cd3b2..91360fb6 100644 --- a/src/script_function.hpp +++ b/src/script_function.hpp @@ -37,5 +37,7 @@ namespace big static inline script_function modshop_loop("ML", RAGE_JOAAT("carmod_shop"), "2D 00 07 00 00 71 51", 0); static inline script_function setup_modshop("SM", RAGE_JOAAT("carmod_shop"), "2D 04 12 00 00 38 00 51", 0); + + static inline script_function reset_session_data("RSD", RAGE_JOAAT("pausemenu_multiplayer"), "2D 02 7D 00 00", 0); } } \ No newline at end of file diff --git a/src/services/context_menu/context_menu_service.cpp b/src/services/context_menu/context_menu_service.cpp index ed478860..bbc5b5fb 100644 --- a/src/services/context_menu/context_menu_service.cpp +++ b/src/services/context_menu/context_menu_service.cpp @@ -1,12 +1,13 @@ #include "context_menu_service.hpp" #include "fiber_pool.hpp" -#include "gta/replay.hpp" #include "gui.hpp" #include "natives.hpp" #include "pointers.hpp" #include "util/misc.hpp" +#include + namespace big { context_menu_service::context_menu_service() @@ -228,11 +229,11 @@ namespace big ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON, ControllerInputs::INPUT_SELECT_NEXT_WEAPON, ControllerInputs::INPUT_SELECT_PREV_WEAPON, - ControllerInputs::INPUT_WEAPON_WHEEL_NEXT, - ControllerInputs::INPUT_WEAPON_WHEEL_PREV, ControllerInputs::INPUT_ATTACK, + ControllerInputs::INPUT_ATTACK2, ControllerInputs::INPUT_SPECIAL_ABILITY, ControllerInputs::INPUT_VEH_MOUSE_CONTROL_OVERRIDE, + ControllerInputs::INPUT_SNIPER_ZOOM, }; void context_menu_service::disable_control_action_loop() @@ -248,11 +249,13 @@ namespace big { while (g_running) { - if (g_gui->is_open()) + if (g_gui->is_open() || HUD::IS_PAUSE_MENU_ACTIVE() + || (*g_pointers->m_gta.m_chat_data && (*g_pointers->m_gta.m_chat_data)->m_chat_open)) { script::get_current()->yield(); continue; } + if (!g.context_menu.enabled) { g_context_menu_service->enabled = false; @@ -261,9 +264,19 @@ namespace big continue; } - if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_VEH_DUCK)) + if (PAD::IS_USING_KEYBOARD_AND_MOUSE(0)) { - g_context_menu_service->enabled = !g_context_menu_service->enabled; + if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_VEH_DUCK)) + { + g_context_menu_service->enabled = !g_context_menu_service->enabled; + } + } + else + { + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_AIM) && PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_FRONTEND_Y)) + { + g_context_menu_service->enabled = !g_context_menu_service->enabled; + } } if (g_context_menu_service->enabled) @@ -279,12 +292,20 @@ namespace big continue; } - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_NEXT)) + ControllerInputs next_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_WEAPON_WHEEL_NEXT : ControllerInputs::INPUT_SCRIPT_PAD_DOWN; + ControllerInputs prev_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_WEAPON_WHEEL_PREV : ControllerInputs::INPUT_SCRIPT_PAD_UP; + ControllerInputs execute_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_ATTACK : ControllerInputs::INPUT_FRONTEND_ACCEPT; + + PAD::DISABLE_CONTROL_ACTION(0, static_cast(next_key), true); + PAD::DISABLE_CONTROL_ACTION(0, static_cast(prev_key), true); + PAD::DISABLE_CONTROL_ACTION(0, static_cast(execute_key), true); + + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)next_key)) cm->current_option = cm->options.size() <= cm->current_option + 1 ? 0 : cm->current_option + 1; - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_PREV)) + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)prev_key)) cm->current_option = 0 > cm->current_option - 1 ? static_cast(cm->options.size()) - 1 : cm->current_option - 1; - if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK) || PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_SPECIAL_ABILITY)) + if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)execute_key)) { if (!g_context_menu_service->m_pointer) { diff --git a/src/services/context_menu/context_menu_service.hpp b/src/services/context_menu/context_menu_service.hpp index 5a2d8458..29916354 100644 --- a/src/services/context_menu/context_menu_service.hpp +++ b/src/services/context_menu/context_menu_service.hpp @@ -85,7 +85,7 @@ namespace big else g_notification_service->push_warning("Toxic", "Failed to take control of vehicle."); }}, - {"HALT", + {"HALT", [this] { if (entity::take_control_of(m_handle)) { @@ -137,18 +137,22 @@ namespace big for (auto& [_, weapon] : g_gta_data_service->weapons()) WEAPON::REMOVE_WEAPON_FROM_PED(m_handle, weapon.m_hash); }}, + {"KILL", + [this] { + ped::kill_ped(m_handle); + }}, {"RAGDOLL", [this] { PED::SET_PED_TO_RAGDOLL(m_handle, 2000, 2000, 0, 0, 0, 0); }}, {"DANCE", [this] { - ped::ped_play_animation(m_handle, "mini@strip_club@private_dance@part1", "priv_dance_p1"); + ped::ped_play_animation(m_handle, "mini@strip_club@private_dance@part1", "priv_dance_p1", 3.5f, -4.0f, -1, 1); }}, {"RECRUIT", [this] { TASK::CLEAR_PED_TASKS(m_handle); PED::SET_PED_AS_GROUP_MEMBER(m_handle, PED::GET_PED_GROUP_INDEX(self::ped)); - PED::SET_PED_RELATIONSHIP_GROUP_HASH(m_handle, PED::GET_PED_RELATIONSHIP_GROUP_HASH(self::ped)); + PED::SET_PED_RELATIONSHIP_GROUP_HASH(m_handle, PED::GET_PED_RELATIONSHIP_GROUP_HASH(self::ped)); PED::SET_PED_NEVER_LEAVES_GROUP(m_handle, true); PED::SET_CAN_ATTACK_FRIENDLY(m_handle, 0, 1); PED::SET_PED_COMBAT_ABILITY(m_handle, 2); @@ -158,7 +162,7 @@ namespace big PED::SET_PED_COMBAT_ATTRIBUTES(m_handle, 13, true); PED::SET_PED_CONFIG_FLAG(m_handle, 394, true); PED::SET_PED_CONFIG_FLAG(m_handle, 400, true); - PED::SET_PED_CONFIG_FLAG(m_handle, 134, true); + PED::SET_PED_CONFIG_FLAG(m_handle, 134, true); WEAPON::GIVE_WEAPON_TO_PED(m_handle, RAGE_JOAAT("weapon_microsmg"), 9999, false, false); WEAPON::GIVE_WEAPON_TO_PED(m_handle, RAGE_JOAAT("weapon_carbinerifle"), 9999, false, true); TASK::TASK_COMBAT_HATED_TARGETS_AROUND_PED(self::ped, 100, 67108864); @@ -177,19 +181,19 @@ namespace big [this] { ped::steal_identity(m_handle); }}, - {"BREAKUP KICK", - [this] { - static player_command* command = dynamic_cast(command::get(rage::consteval_joaat("breakup"))); - command->call(ped::get_player_from_ped(m_handle), {}); - }}, {"KICK", [this] { static player_command* command = dynamic_cast(command::get(rage::consteval_joaat("nfkick"))); static player_command* command1 = dynamic_cast(command::get(rage::consteval_joaat("shkick"))); static player_command* command2 = dynamic_cast(command::get(rage::consteval_joaat("endkick"))); + static player_command* command3 = dynamic_cast(command::get(rage::consteval_joaat("desync"))); + static player_command* command4 = dynamic_cast(command::get(rage::consteval_joaat("breakup"))); command->call(ped::get_player_from_ped(m_handle), {}); command1->call(ped::get_player_from_ped(m_handle), {}); command2->call(ped::get_player_from_ped(m_handle), {}); + command3->call(ped::get_player_from_ped(m_handle), {}); + script::get_current()->yield(500ms); + command4->call(ped::get_player_from_ped(m_handle), {}); }}, {"DISARM", [this] { @@ -218,6 +222,25 @@ namespace big [this] { teleport::tp_on_top(m_handle, true); }}, + {"BRING", + [this] { + rage::fvector3 pos = *g_local_player->m_navigation->get_position(); + + if (PED::IS_PED_A_PLAYER(m_handle)) + { + if (auto plyr = g_player_service->get_by_id(NETWORK::NETWORK_GET_PLAYER_INDEX_FROM_PED(m_handle))) + { + teleport::teleport_player_to_coords(plyr, {pos.x, pos.y, pos.z}); + } + } + else + { + if (entity::take_control_of(m_handle)) + { + ENTITY::SET_ENTITY_COORDS(m_handle, pos.x, pos.y, pos.z, false, false, false, false); + } + } + }}, {"ENFLAME", [this] { Vector3 pos = ENTITY::GET_ENTITY_COORDS(m_handle, TRUE); diff --git a/src/services/orbital_drone/orbital_drone.cpp b/src/services/orbital_drone/orbital_drone.cpp index 7fb92bbe..ebb723df 100644 --- a/src/services/orbital_drone/orbital_drone.cpp +++ b/src/services/orbital_drone/orbital_drone.cpp @@ -378,21 +378,9 @@ namespace big Vector3 campos = CAM::GET_CAM_COORD(m_cam); Vector3 entpos = ENTITY::GET_ENTITY_COORDS(entity::get_entity_closest_to_middle_of_screen(), 0); - if (*g_pointers->m_gta.m_is_session_started && g_player_service->get_selected()->is_valid() - && ENTITY::DOES_ENTITY_EXIST(g_pointers->m_gta.m_ptr_to_handle(g_player_service->get_selected()->get_ped()))) - { - toxic::blame_explode_coord(g_player_service->get_selected(), m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); - - if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10) - toxic::blame_explode_coord(g_player_service->get_selected(), entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); - } - else - { - toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); - if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10) - toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); - } - + toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); + if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10) + toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); if (!STREAMING::HAS_NAMED_PTFX_ASSET_LOADED("scr_xm_orbital")) { diff --git a/src/services/players/player.hpp b/src/services/players/player.hpp index e5c0b3df..1e9ecc7f 100644 --- a/src/services/players/player.hpp +++ b/src/services/players/player.hpp @@ -85,6 +85,8 @@ namespace big bool block_explosions = false; + int spectating_player = -1; + protected: bool equals(const CNetGamePlayer* net_game_player) const; diff --git a/src/services/vehicle/xml_vehicles_service.cpp b/src/services/vehicle/xml_vehicles_service.cpp index 57476ec8..03f9fbd7 100644 --- a/src/services/vehicle/xml_vehicles_service.cpp +++ b/src/services/vehicle/xml_vehicles_service.cpp @@ -41,7 +41,7 @@ namespace big } catch (const std::exception& e) { - LOG(WARNING) << "Failed fetching xml vehicles: " << e.what() << std::endl; + LOG(WARNING) << "Failed fetching XML vehicles: " << e.what() << std::endl; } } @@ -213,6 +213,7 @@ namespace big ENTITY::SET_ENTITY_VISIBLE(vehicle_handle, vehicle_node.child("IsVisible").text().as_bool(), false); ENTITY::SET_ENTITY_INVINCIBLE(vehicle_handle, vehicle_node.child("IsInvincible").text().as_bool()); + ENTITY::SET_ENTITY_ALPHA(vehicle_handle, vehicle_node.child("OpacityLevel").text().as_int(), false); ENTITY::SET_ENTITY_PROOFS(vehicle_handle, vehicle_node.child("IsBulletProof").text().as_bool(), vehicle_node.child("IsFireProof").text().as_bool(), @@ -255,19 +256,35 @@ namespace big attachment_handle = vehicle_attachment(attachment_item, entity_model, position, rotation, offset, vehicle_handle, bone); else if (type == 3) attachment_handle = object_attachment(attachment_item, entity_model, position, rotation, offset, vehicle_handle, bone); - - if(!attachment_item.child("PtfxLopAsset").text().empty()) + + if (!attachment_item.child("PtfxLopAsset").text().empty()) { const char* asset = const_cast(attachment_item.child("PtfxLopAsset").text().as_string()); STREAMING::REQUEST_NAMED_PTFX_ASSET(asset); for (int i = 0; i < 35 && !STREAMING::HAS_NAMED_PTFX_ASSET_LOADED(asset); i++) STREAMING::REQUEST_NAMED_PTFX_ASSET(asset), script::get_current()->yield(); - - if(STREAMING::HAS_NAMED_PTFX_ASSET_LOADED(asset)) + + if (STREAMING::HAS_NAMED_PTFX_ASSET_LOADED(asset)) { GRAPHICS::USE_PARTICLE_FX_ASSET(asset); - GRAPHICS::START_NETWORKED_PARTICLE_FX_LOOPED_ON_ENTITY(const_cast(attachment_item.child("PtfxLopEffect").text().as_string()), attachment_handle, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1); + GRAPHICS::START_NETWORKED_PARTICLE_FX_LOOPED_ON_ENTITY( + const_cast(attachment_item.child("PtfxLopEffect").text().as_string()), + attachment_handle, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 1); STREAMING::REMOVE_NAMED_PTFX_ASSET(asset); } } diff --git a/src/util/entity.hpp b/src/util/entity.hpp index 59924499..6cb96d49 100644 --- a/src/util/entity.hpp +++ b/src/util/entity.hpp @@ -1,6 +1,5 @@ #pragma once #include "gta/joaat.hpp" -#include "gta/replay.hpp" #include "gta_util.hpp" #include "math.hpp" #include "natives.hpp" @@ -121,7 +120,7 @@ namespace big::entity { for (auto ped : pools::get_all_peds()) { - if(ped == g_local_player) + if (ped == g_local_player) continue; target_entities.push_back(g_pointers->m_gta.m_ptr_to_handle(ped)); diff --git a/src/util/math.hpp b/src/util/math.hpp index 9824d335..f7c7ac95 100644 --- a/src/util/math.hpp +++ b/src/util/math.hpp @@ -14,6 +14,11 @@ namespace big::math return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2)); } + inline float distance_between_vectors(rage::fvector3 a, rage::fvector3 b) + { + return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2)); + } + inline Vector3 rotation_to_direction(Vector3 rotation) { float x = deg_to_rad(rotation.x); diff --git a/src/util/notify.hpp b/src/util/notify.hpp index 044b6df0..b90bf77c 100644 --- a/src/util/notify.hpp +++ b/src/util/notify.hpp @@ -22,13 +22,17 @@ namespace big::notify { if (player) { - g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name())); - LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " (" - << (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")"; + if (g.reactions.crash.notify) + g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name())); + + if (g.reactions.crash.log) + LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " (" + << (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")"; } else { - g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash)); + if (g.reactions.crash.notify) + g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash)); } } diff --git a/src/util/session.hpp b/src/util/session.hpp index f6885075..d9a73172 100644 --- a/src/util/session.hpp +++ b/src/util/session.hpp @@ -8,6 +8,7 @@ #include "pointers.hpp" #include "rage/rlSessionByGamerTaskResult.hpp" #include "script.hpp" +#include "script_function.hpp" #include "script_global.hpp" #include "services/api/api_service.hpp" #include "services/player_database/player_database_service.hpp" @@ -36,24 +37,41 @@ namespace big::session inline bool join_type(eSessionType session) { - if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS()) - { - g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit."); + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("pausemenu_multiplayer")); - return false; - } - - *script_global(2695915).as() = (session == eSessionType::SC_TV ? 1 : 0); // If SC TV Then Enable Spectator Mode + while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(RAGE_JOAAT("pausemenu_multiplayer"))) + script::get_current()->yield(); + + *script_global(2695915).as() = (session == eSessionType::SC_TV ? 1 : 0); // If SCTV then enable spectator mode if (session == eSessionType::LEAVE_ONLINE) *script_global(1574589).at(2).as() = -1; else - *script_global(1575020).as() = (int)session; + { + *script_global(1574589).at(2).as() = 0; + *script_global(1575020).as() = (int)session; + } *script_global(1574589).as() = 1; - script::get_current()->yield(200ms); - *script_global(1574589).as() = 0; + if (*g_pointers->m_gta.m_is_session_started && session != eSessionType::LEAVE_ONLINE) + { + *scr_globals::transition_state.as() = eTransitionState::TRANSITION_STATE_LOOK_TO_JOIN_ANOTHER_SESSION_FM; + } + + scr_functions::reset_session_data({true, true}); + *script_global(32284).as() = 0; + *script_global(1574934).as() = 1; + *script_global(1574995).as() = 32; + + if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0) + { + *script_global(2694534).as() = 1; + script::get_current()->yield(200ms); + *script_global(1574589).as() = 0; + } + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("pausemenu_multiplayer")); return true; } @@ -77,6 +95,12 @@ namespace big::session inline void join_session(const rage::rlSessionInfo& info) { + if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS()) + { + g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit."); + return; + } + g.session.join_queued = true; g.session.info = info; session::join_type({eSessionType::NEW_PUBLIC}); diff --git a/src/views/core/view_overlay.cpp b/src/views/core/view_overlay.cpp index d6ab28fa..562abfa9 100644 --- a/src/views/core/view_overlay.cpp +++ b/src/views/core/view_overlay.cpp @@ -1,3 +1,4 @@ +#include "gta/pools.hpp" #include "gta_util.hpp" #include "gui.hpp" #include "pointers.hpp" @@ -77,28 +78,28 @@ namespace big ImGui::Text("Pos: %.2f, %.2f, %.2f", pos.x, pos.y, pos.z); } - // can't easily get used item count using pools, so keeping replay interface for now - if (auto replay_interface = *g_pointers->m_gta.m_replay_interface; g.window.ingame_overlay.show_replay_interface) + if (g.window.ingame_overlay.show_replay_interface) { - if (replay_interface->m_ped_interface || replay_interface->m_vehicle_interface || replay_interface->m_object_interface) + if (*g_pointers->m_gta.m_ped_pool || (*g_pointers->m_gta.m_vehicle_pool && **g_pointers->m_gta.m_vehicle_pool) + || *g_pointers->m_gta.m_prop_pool) ImGui::Separator(); - if (replay_interface->m_ped_interface) + if (*g_pointers->m_gta.m_ped_pool) ImGui::Text(std::format("Ped Pool: {}/{}", - replay_interface->m_ped_interface->m_cur_peds, - replay_interface->m_ped_interface->m_max_peds) + (*g_pointers->m_gta.m_ped_pool)->get_item_count(), + (*g_pointers->m_gta.m_ped_pool)->m_size) .c_str()); - if (replay_interface->m_vehicle_interface) + if (*g_pointers->m_gta.m_vehicle_pool && **g_pointers->m_gta.m_vehicle_pool) ImGui::Text(std::format("Vehicle Pool: {}/{}", - replay_interface->m_vehicle_interface->m_cur_vehicles, - replay_interface->m_vehicle_interface->m_max_vehicles) + (**g_pointers->m_gta.m_vehicle_pool)->m_item_count, + (**g_pointers->m_gta.m_vehicle_pool)->m_size) .c_str()); - if (replay_interface->m_object_interface) + if (*g_pointers->m_gta.m_prop_pool) ImGui::Text(std::format("Object Pool: {}/{}", - replay_interface->m_object_interface->m_cur_objects, - replay_interface->m_object_interface->m_max_objects) + (*g_pointers->m_gta.m_prop_pool)->get_item_count(), + (*g_pointers->m_gta.m_prop_pool)->m_size) .c_str()); } diff --git a/src/views/network/view_network.cpp b/src/views/network/view_network.cpp index 98a1cb80..baaf54c9 100644 --- a/src/views/network/view_network.cpp +++ b/src/views/network/view_network.cpp @@ -120,7 +120,8 @@ namespace big ImGui::EndDisabled(); - components::script_patch_checkbox("REVEAL_OTR_PLAYERS"_T, &g.session.decloak_players); + components::script_patch_checkbox("REVEAL_OTR_PLAYERS"_T, &g.session.decloak_players, "Reveals players that are off the radar"); + components::script_patch_checkbox("Reveal Hidden Players", &g.session.unhide_players_from_player_list, "Reveals players that have hidden themselves from the player list"); ImGui::EndListBox(); } diff --git a/src/views/settings/view_protection_settings.cpp b/src/views/settings/view_protection_settings.cpp index 2fdb38e8..29cd1262 100644 --- a/src/views/settings/view_protection_settings.cpp +++ b/src/views/settings/view_protection_settings.cpp @@ -45,6 +45,7 @@ namespace big if (ImGui::IsItemHovered()) ImGui::SetTooltip("This prevents the collection of pickups such as unwanted money bags\nNote: Normal pickups are also no longer possible to collect with this enabled"); ImGui::Checkbox("ADMIN_CHECK"_T.data(), &g.protections.admin_check); + ImGui::Checkbox("Kick Rejoin", &g.protections.kick_rejoin); ImGui::EndGroup(); } diff --git a/src/views/settings/view_reaction_settings.cpp b/src/views/settings/view_reaction_settings.cpp index 84bc07b8..2b4ce1fd 100644 --- a/src/views/settings/view_reaction_settings.cpp +++ b/src/views/settings/view_reaction_settings.cpp @@ -14,6 +14,7 @@ namespace big void draw_reaction(reaction& reaction) { + ImGui::PushID(&reaction); if (ImGui::TreeNode(reaction.m_event_name)) { ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat); @@ -25,11 +26,13 @@ namespace big ImGui::Checkbox("REACTION_KICK_PLAYER"_T.data(), &reaction.kick); ImGui::TreePop(); } + ImGui::PopID(); } // TODO code duplication void draw_interloper_reaction(interloper_reaction& reaction) { + ImGui::PushID(&reaction); if (ImGui::TreeNode(reaction.m_event_name)) { ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat); @@ -51,6 +54,7 @@ namespace big ImGui::TreePop(); } + ImGui::PopID(); } void view::reaction_settings() @@ -77,6 +81,7 @@ namespace big draw_reaction(g.reactions.rotate_cam); draw_reaction(g.reactions.send_to_cutscene); draw_reaction(g.reactions.send_to_location); + draw_reaction(g.reactions.send_to_interior); draw_reaction(g.reactions.sound_spam); draw_reaction(g.reactions.spectate_notification); draw_reaction(g.reactions.start_activity); @@ -98,6 +103,8 @@ namespace big draw_reaction(g.reactions.report); draw_reaction(g.reactions.report_cash_spawn); draw_reaction(g.reactions.request_control_event); + draw_reaction(g.reactions.spectate); + draw_interloper_reaction(g.reactions.spectate_others); ImGui::Separator(); draw_reaction(g.reactions.gamer_instruction_kick);