diff --git a/scripts/gtav-classes.cmake b/scripts/gtav-classes.cmake index 5ebb60ee..3524390d 100644 --- a/scripts/gtav-classes.cmake +++ b/scripts/gtav-classes.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare( gtav_classes GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git - GIT_TAG f71748dd1dfac7b1c678e0e8b87d2739bde314b6 + GIT_TAG 56aeddea31d677efa0e5c4f84b4f353d420a8502 GIT_PROGRESS TRUE CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/src/backend/commands/player/kick/lost_connection_kick.cpp b/src/backend/commands/player/kick/lost_connection_kick.cpp deleted file mode 100644 index f115eff8..00000000 --- a/src/backend/commands/player/kick/lost_connection_kick.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "backend/player_command.hpp" -#include "core/scr_globals.hpp" -#include "gta_util.hpp" -#include "natives.hpp" -#include "packet.hpp" -#include "pointers.hpp" - -#include - -namespace big -{ - class lost_connection_kick : player_command - { - using player_command::player_command; - - void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf) - { - buf.Write(*reinterpret_cast(&hnd.m_platform), 8); - if (*reinterpret_cast(&hnd.m_platform) == 3) - { - buf.WriteInt64(*(int64_t*)&hnd.m_rockstar_id, 64); - buf.Write(hnd.unk_0009, 8); - } - } - - virtual CommandAccessLevel get_access_level() - { - return CommandAccessLevel::TOXIC; - } - - virtual void execute(player_ptr player, const std::vector& _args, const std::shared_ptr ctx) - { - if (gta_util::get_network()->m_game_session_ptr->is_host()) - { - g_notification_service->push_error("Kick", "Cannot use the lost connection kick while host"); - return; - } - - packet msg{}; - msg.write_message(rage::eNetMessage::MsgLostConnectionToHost); - msg.write(gta_util::get_network()->m_game_session_ptr->m_rline_session.m_session_id, 64); - gamer_handle_serialize(player->get_net_data()->m_gamer_handle, msg); - for (auto& [_, plyr] : g_player_service->players()) - { - if (plyr->is_host()) - { - msg.send(plyr->get_session_player()->m_msg_id); - break; - } - } - } - }; - - lost_connection_kick g_lost_connection_kick("lckick", "Lost Connection Kick", "Can only be detected or blocked by the host. Does not work when you are the host, use Host Kick instead", 0); -} \ No newline at end of file diff --git a/src/backend/commands/player/troll/bring.cpp b/src/backend/commands/player/troll/bring.cpp index b501e78d..45fce699 100644 --- a/src/backend/commands/player/troll/bring.cpp +++ b/src/backend/commands/player/troll/bring.cpp @@ -15,5 +15,5 @@ namespace big } }; - bring g_bring("bring", "Bring", "Teleports the player to you if they are in a vehicle", 0); + bring g_bring("bring", "Bring", "Teleports the player to you", 0, false); } \ No newline at end of file diff --git a/src/backend/commands/teleport/teleport_to_last_vehicle.cpp b/src/backend/commands/teleport/teleport_to_last_vehicle.cpp index 717a3e87..0e8a5476 100644 --- a/src/backend/commands/teleport/teleport_to_last_vehicle.cpp +++ b/src/backend/commands/teleport/teleport_to_last_vehicle.cpp @@ -1,7 +1,6 @@ #include "backend/command.hpp" #include "natives.hpp" -#include "util/mobile.hpp" -#include "util/vehicle.hpp" +#include "util/teleport.hpp" namespace big { diff --git a/src/backend/commands/teleport/teleport_to_personal_vehicle.cpp b/src/backend/commands/teleport/teleport_to_personal_vehicle.cpp index c1680b79..bef51e01 100644 --- a/src/backend/commands/teleport/teleport_to_personal_vehicle.cpp +++ b/src/backend/commands/teleport/teleport_to_personal_vehicle.cpp @@ -1,7 +1,7 @@ #include "backend/command.hpp" #include "natives.hpp" #include "util/mobile.hpp" -#include "util/vehicle.hpp" +#include "util/teleport.hpp" namespace big { diff --git a/src/backend/looped/system/voice_chat_audio.cpp b/src/backend/looped/system/voice_chat_audio.cpp new file mode 100644 index 00000000..889bf9e4 --- /dev/null +++ b/src/backend/looped/system/voice_chat_audio.cpp @@ -0,0 +1,30 @@ +#include "backend/looped_command.hpp" +#include "natives.hpp" +#include "pointers.hpp" + +namespace big +{ + class voice_chat_audio : looped_command + { + using looped_command::looped_command; + + virtual void on_enable() override + { + *g_pointers->m_refresh_audio_input = true; + } + + virtual void on_tick() override + { + NETWORK::NETWORK_OVERRIDE_SEND_RESTRICTIONS_ALL(true); + } + + virtual void on_disable() override + { + *g_pointers->m_refresh_audio_input = true; + NETWORK::NETWORK_OVERRIDE_SEND_RESTRICTIONS_ALL(false); + } + }; + + voice_chat_audio g_voice_chat_audio("vcaudio", "Play Audio Through Voice Chat", "Plays the audio.wav file in the project folder through voice chat. The wave file must be encoded with a mono 16 bit 16kHz PCM format. You have to reset voice chat settings whenever you load the menu for the sound to play", + g.spoofing.voice_chat_audio); +} diff --git a/src/backend/looped/vehicle/ls_customs.cpp b/src/backend/looped/vehicle/ls_customs.cpp index bdff9b41..8e1f61df 100644 --- a/src/backend/looped/vehicle/ls_customs.cpp +++ b/src/backend/looped/vehicle/ls_customs.cpp @@ -1,70 +1,101 @@ #include "backend/looped/looped.hpp" +#include "gta/enums.hpp" #include "gta_util.hpp" +#include "script_function.hpp" #include "script_local.hpp" +#include "services/script_patcher/script_patcher_service.hpp" #include "util/math.hpp" #include "util/scripts.hpp" namespace big { - static bool state = false; - static bool busy = false; - - constexpr auto CARMOD_SHOP_STRUCT = 730; // move_m@generic_idles@std -- one function below -- first local - constexpr auto CARMOD_SHOP_CUTSCENE = 2208;// "carmod_fam1" -- first boolean local below it + static bool bLastLsCustoms = false; + static bool bModshopReady = false; void looped::vehicle_ls_customs() { - if (busy) - return; - busy = true; - - constexpr int hash = RAGE_JOAAT("carmod_shop"); - if (g.vehicle.ls_customs && g.vehicle.ls_customs == state) + if (g.vehicle.ls_customs && g.vehicle.ls_customs != bLastLsCustoms) { - if (auto carmod_shop_thread = gta_util::find_script_thread(hash); - carmod_shop_thread && *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(11).as() != 4) - { - g.vehicle.ls_customs = false; - - *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).as() = 1;// cleanup - } - } - - if (g.vehicle.ls_customs && g.vehicle.ls_customs != state) - { - Vehicle veh = self::veh; - if (!ENTITY::DOES_ENTITY_EXIST(veh) || ENTITY::IS_ENTITY_DEAD(veh, false)) - { - busy = false; - g.vehicle.ls_customs = false; - - g_notification_service->push_warning("LS Customs", "You aren't in a vehicle."); - - return; - } - - scripts::request_script(hash); - if (scripts::wait_till_loaded(hash)) - { - int args[] = {45, 0, 9}; - scripts::start_script_with_args(hash, args, 3, 3600); - - scripts::wait_till_running(hash); - } - - if (scripts::is_running(hash)) - { - if (auto carmod_shop_thread = gta_util::find_script_thread(hash); carmod_shop_thread) + g_fiber_pool->queue_job([] { + scripts::request_script(RAGE_JOAAT("carmod_shop")); + if (scripts::wait_till_loaded(RAGE_JOAAT("carmod_shop"))) { - *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(409).as() = veh;// "HIDDEN_RADIO_09_HIPHOP_OLD" - *script_local(carmod_shop_thread, CARMOD_SHOP_CUTSCENE).as() = false;// skips cutscene that's invisible + HUD::REQUEST_ADDITIONAL_TEXT("MOD_MNU", 9); - *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(11).as() = 4; + while (!HUD::HAS_THIS_ADDITIONAL_TEXT_LOADED("MOD_MNU", 9)) + script::get_current()->yield(); + + GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("CommonMenu", false); + GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("MPShopSale", false); + GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("ShopUI_Title_Los_Santos_Car_Meet", false); + + // clang-format off + while (!GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("CommonMenu") + || !GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("MPShopSale") + || !GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("ShopUI_Title_Los_Santos_Car_Meet")) + script::get_current()->yield(); + // clang-format on + + auto id = SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("carmod_shop"), 5050); + if (!id) + return; + + g.m_modshop_thread = gta_util::find_script_thread_by_id(id); + if (!g.m_modshop_thread) + return; + + g.m_modshop_thread->m_context.m_state = rage::eThreadState::unk_3; + scr_functions::modshop_loop.populate_ip(); + scr_functions::setup_modshop.populate_ip(); + + g_script_patcher_service->update(); + + scr_functions::setup_modshop.call_latent(g.m_modshop_thread, gta_util::find_script_program(RAGE_JOAAT("carmod_shop")), {45, 0, 18, 0}, bModshopReady); + *script_local(g.m_modshop_thread->m_stack, 730).at(446).as() = 2; + *script_local(g.m_modshop_thread->m_stack, 2237).as() = ControllerInputs::INPUT_FRONTEND_LT; } - } + }); + bLastLsCustoms = true; + } + else if (!g.vehicle.ls_customs && g.vehicle.ls_customs != bLastLsCustoms) + { + if (g.m_modshop_thread) + g.m_modshop_thread->kill(); + + GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("CommonMenu"); + GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPShopSale"); + GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("ShopUI_Title_Los_Santos_Car_Meet"); + + g.m_modshop_thread = nullptr; + bLastLsCustoms = false; + bModshopReady = false; + g_script_patcher_service->update(); } - busy = false; - state = g.vehicle.ls_customs; + if (self::veh == 0 || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) > 0 || (!g.m_modshop_thread && bModshopReady)) + { + g.vehicle.ls_customs = false; + return; + } + + if (g.vehicle.ls_customs && g.m_modshop_thread) + { + PAD::DISABLE_CONTROL_ACTION(0, (int)ControllerInputs::INPUT_VEH_CIN_CAM, true); + + if (*script_local(g.m_modshop_thread->m_stack, 2466).as() && PAD::IS_CONTROL_JUST_PRESSED(2, (int)ControllerInputs::INPUT_FRONTEND_ACCEPT)) + g.vehicle.ls_customs = false; + } + + if (g.vehicle.ls_customs && bModshopReady && g.m_modshop_thread && g.m_modshop_thread->m_stack) + { + *script_local(g.m_modshop_thread->m_stack, 2418).as() = false; + *script_local(g.m_modshop_thread->m_stack, 730).at(638).as() = -1; + *script_local(g.m_modshop_thread->m_stack, 730).at(409).as() = self::veh; + + if (*script_local(g.m_modshop_thread->m_stack, 730).at(446).as() == 0) + *script_local(g.m_modshop_thread->m_stack, 730).at(446).as() = 2; + + scr_functions::modshop_loop.call(g.m_modshop_thread, gta_util::find_script_program(RAGE_JOAAT("carmod_shop")), {}); + } } } \ No newline at end of file diff --git a/src/backend/looped/weapons/repair_gun.cpp b/src/backend/looped/weapons/repair_gun.cpp index 0854d4d2..2551de35 100644 --- a/src/backend/looped/weapons/repair_gun.cpp +++ b/src/backend/looped/weapons/repair_gun.cpp @@ -1,5 +1,6 @@ #include "backend/looped/looped.hpp" #include "core/enums.hpp" +#include "gta/enums.hpp" #include "util/entity.hpp" #include "util/vehicle.hpp" diff --git a/src/backend/looped/weapons/vehicle_gun.cpp b/src/backend/looped/weapons/vehicle_gun.cpp index b28f4057..b3bbc819 100644 --- a/src/backend/looped/weapons/vehicle_gun.cpp +++ b/src/backend/looped/weapons/vehicle_gun.cpp @@ -1,5 +1,6 @@ #include "backend/looped/looped.hpp" #include "core/enums.hpp" +#include "gta/enums.hpp" #include "gui.hpp" #include "util/math.hpp" #include "util/vehicle.hpp" diff --git a/src/backend/script_patches.hpp b/src/backend/script_patches.hpp index f2691016..674004c9 100644 --- a/src/backend/script_patches.hpp +++ b/src/backend/script_patches.hpp @@ -44,6 +44,19 @@ namespace big {0x2B, 0x2B, 0x2B, 0x00, 0x55}, &g.self.invisibility}); + 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 + g_script_patcher_service->add_patch( + {RAGE_JOAAT("carmod_shop"), "2D 02 10 00 00 2C", 5, {0x71, 0x2E, 0x02, 0x01}, &g.vehicle.ls_customs}); + g_script_patcher_service->add_patch( + {RAGE_JOAAT("carmod_shop"), "2D 00 B8 00 00", 5, {0x2E, 0x00, 0x00}, &g.vehicle.ls_customs}); + g_script_patcher_service->add_patch( + {RAGE_JOAAT("carmod_shop"), "06 1F 56 ? ? 62 ? ? ? 56", 0, {0x2B, 0x2B, 0x55}, &g.vehicle.ls_customs});// buy mods for free in SP + g_script_patcher_service->add_patch( + {RAGE_JOAAT("carmod_shop"), "2D 03 16 00 00 5D", 5, {0x72, 0x2E, 0x03, 0x01}, &g.vehicle.ls_customs});// allow all vehicles + g_script_patcher_service->add_patch( + {RAGE_JOAAT("carmod_shop"), "2D 03 07 00 00 71 38 02", 5, {0x72, 0x2E, 0x03, 0x01}, &g.vehicle.ls_customs});// allow all vehicles 2 + for (auto& entry : *g_pointers->m_script_program_table) { if (entry.m_program) diff --git a/src/core/globals.hpp b/src/core/globals.hpp index 941525bf..cdb60e15 100644 --- a/src/core/globals.hpp +++ b/src/core/globals.hpp @@ -53,8 +53,9 @@ namespace big int m_remote_controller_vehicle = -1; int m_remote_controlled_vehicle = -1; - int m_mod_net_id = -1; - int m_test_net_id = -1; + std::uint16_t m_tp_veh_net_id; + std::uint16_t m_tp_player_net_id; + rage::fvector3 m_tp_position; rage::scrThread* m_hunt_the_beast_thread = nullptr; @@ -63,6 +64,10 @@ namespace big rage::scrThread* m_mission_creator_thread = nullptr; + rage::scrThread* m_modshop_thread = nullptr; + + bool in_script_vm = false; + struct debug { struct logs @@ -79,7 +84,7 @@ namespace big bool filter_player = true; std::int8_t player_id = -1; - bool block_all = false;//should not save + bool block_all = false; //should not save NLOHMANN_DEFINE_TYPE_INTRUSIVE(script_event, logs, filter_player, player_id) } script_event{}; @@ -145,7 +150,7 @@ namespace big reaction fake_deposit{"Fake Deposit", "Blocked Fake Deposit from %s", "%s tried to show me a fake money notification!"}; reaction force_mission{"Force Mission", "Blocked Force Mission from %s", "%s tried to force me into a mission!"}; reaction force_teleport{"Force Teleport", "Blocked Force Teleport from %s", "%s tried to teleport me!"}; - reaction gta_banner{"GTA Banner", "Blocked GTA Banner from %s", "Blocked GTA Banner from %s"};// please don't enable this + reaction gta_banner{"GTA Banner", "Blocked GTA Banner from %s", "Blocked GTA Banner from %s"}; // please don't enable this reaction kick_from_interior{"Kick From Interior", "Blocked Kick From Interior from %s", "%s tried to kick me from my interior!"}; reaction mc_teleport{"MC Teleport", "Blocked MC Teleport from %s", "%s tried to teleport me!"}; reaction network_bail{"Network Bail", "Blocked Network Bail from %s", "%s tried to kick me out!"}; @@ -179,7 +184,7 @@ namespace big 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!"}; - interloper_reaction breakup_others{"Breakup Kicks On Other Players", "%s is trying to breakup kick %s!", "%s is trying to breakup kick %s!", true, true};// blockable only when host but we have no way to specify that atm + interloper_reaction breakup_others{"Breakup Kicks On Other Players", "%s is trying to breakup kick %s!", "%s is trying to breakup kick %s!", true, true}; // blockable only when host but we have no way to specify that atm reaction lost_connection_kick{"Lost Connection Kick", "Blocked Lost Connection Kick from %s", "%s tried to kick me out!"}; reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"}; interloper_reaction lost_connection_kick_others{"Lost Connection Kick On Other Players", "%s is trying to lost connection kick %s!", "%s is trying to lost connection kick %s!", true, false}; @@ -225,7 +230,7 @@ namespace big bool desync_kick = false; bool rid_join = false; - bool lessen_breakups = false;// disabled by default due to anticheat concerns + bool lessen_breakups = false; // disabled by default due to anticheat concerns bool receive_pickup = false; NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, lessen_breakups, desync_kick, receive_pickup) @@ -478,7 +483,7 @@ namespace big bool hide_from_player_list = false; bool spoof_blip = false; - int blip_type = 0;// actual blip type + 1 + int blip_type = 0; // actual blip type + 1 bool spoof_rank = false; int rank = 1; @@ -512,7 +517,9 @@ namespace big bool spoof_session_player_count = false; int session_player_count = 25; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing, hide_from_player_list, spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_crew_data, crew_tag, rockstar_crew, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language, session_language, spoof_session_player_count, session_player_count, spoof_blip, blip_type, spoof_rank, rank, spoof_job_points, job_points, spoof_bad_sport, badsport_type, spoof_kd_ratio, kd_ratio, spoof_player_model, player_model) + bool voice_chat_audio = false; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing, hide_from_player_list, spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_crew_data, crew_tag, rockstar_crew, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language, session_language, spoof_session_player_count, session_player_count, voice_chat_audio) } spoofing{}; struct vehicle @@ -564,36 +571,30 @@ namespace big uint32_t proof_mask = 0; AutoDriveDestination auto_drive_destination = AutoDriveDestination::STOPPED; - AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING; - float auto_drive_speed = 1; - bool auto_turn_signals = false; - eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT; - bool drive_on_water = false; - bool horn_boost = false; - bool instant_brake = false; - bool block_homing = true; - bool ls_customs = false; // don't save this to disk - bool seatbelt = false; - bool turn_signals = false; - bool vehicle_jump = false; - bool keep_vehicle_repaired = false; - bool no_water_collision = false; - bool disable_engine_auto_start = false; - bool change_engine_state_immediately = false; - bool vehinvisibility = false; - bool localveh_visibility = false; - bool localped_visibility = true; - bool keep_on_ground = false; - bool no_collision = false; - bool unlimited_weapons = false; + AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING; + float auto_drive_speed = 1; + bool auto_turn_signals = false; + eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT; + bool drive_on_water = false; + bool horn_boost = false; + bool instant_brake = false; + bool block_homing = true; + bool ls_customs = false; // don't save this to disk + bool seatbelt = false; + bool turn_signals = false; + bool vehicle_jump = false; + bool keep_vehicle_repaired = false; + bool no_water_collision = false; + bool disable_engine_auto_start = false; + bool change_engine_state_immediately = false; + bool vehinvisibility = false; + bool localveh_visibility = false; + bool localped_visibility = true; + bool keep_on_ground = false; + bool no_collision = false; + bool unlimited_weapons = false; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, - speedo_meter, fly, rainbow_paint, speed_unit, god_mode, - proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, - auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, - drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, - keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, - vehinvisibility, localveh_visibility, localped_visibility, keep_on_ground, no_collision, unlimited_weapons) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, vehinvisibility, localveh_visibility, localped_visibility, keep_on_ground, no_collision, unlimited_weapons) } vehicle{}; struct weapons @@ -634,7 +635,7 @@ namespace big bool on_npc = false; float fov = 90.f; float distance = 200.f; - std::uint32_t selected_bone = 0x796E;// Default to head + std::uint32_t selected_bone = 0x796E; // Default to head NLOHMANN_DEFINE_TYPE_INTRUSIVE(aimbot, enable, smoothing, smoothing_speed, fov, selected_bone) } aimbot{}; diff --git a/src/fiber_pool.cpp b/src/fiber_pool.cpp index b03af067..5fdc6d6d 100644 --- a/src/fiber_pool.cpp +++ b/src/fiber_pool.cpp @@ -6,7 +6,8 @@ namespace big { - fiber_pool::fiber_pool(std::size_t num_fibers) + fiber_pool::fiber_pool(std::size_t num_fibers) : + m_num_fibers(num_fibers) { for (std::size_t i = 0; i < num_fibers; ++i) { @@ -51,4 +52,22 @@ namespace big script::get_current()->yield(); } } + + int fiber_pool::get_total_fibers() + { + return m_num_fibers; + } + + int fiber_pool::get_used_fibers() + { + return m_jobs.size(); + } + + void fiber_pool::reset() + { + std::lock_guard lock(m_mutex); + + while (!m_jobs.empty()) + m_jobs.pop(); + } } \ No newline at end of file diff --git a/src/fiber_pool.hpp b/src/fiber_pool.hpp index 6dd33669..abbc86c4 100644 --- a/src/fiber_pool.hpp +++ b/src/fiber_pool.hpp @@ -14,9 +14,15 @@ namespace big void fiber_tick(); static void fiber_func(); + int get_total_fibers(); + int get_used_fibers(); + + void reset(); + private: std::recursive_mutex m_mutex; std::stack> m_jobs; + int m_num_fibers; }; inline fiber_pool* g_fiber_pool{}; diff --git a/src/function_types.hpp b/src/function_types.hpp index e8beb07d..6b82a6a5 100644 --- a/src/function_types.hpp +++ b/src/function_types.hpp @@ -21,6 +21,7 @@ namespace rage class snConnectToPeerTaskResult; class rlScHandle; class rlQueryPresenceAttributesContext; + enum class eThreadState : uint32_t; } namespace datafile_commands @@ -91,9 +92,9 @@ namespace big::functions using fipackfile_unmount = bool (*)(const char* mount_point); using start_get_session_by_gamer_handle = bool (*)(int profile_index, rage::rlGamerHandle* handles, int count, rage::rlSessionByGamerTaskResult* result, int unk, bool* success, rage::rlTaskStatus* state); - using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state); - using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state); - using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); + using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state); + using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state); + using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); using generate_uuid = bool (*)(std::uint64_t* uuid); @@ -108,14 +109,14 @@ namespace big::functions using send_chat_message = bool (*)(int64_t* send_chat_ptr, rage::rlGamerInfo* gamer_info, char* message, bool is_team); using send_network_damage = void (*)(CEntity* source, CEntity* target, rage::fvector3* position, int hit_component, bool override_default_damage, int weapon_type, float override_damage, int tire_index, int suspension_index, int flags, std::uint32_t action_result_hash, std::int16_t action_result_id, int action_unk, bool hit_weapon, bool hit_weapon_ammo_attachment, bool silenced, bool unk, rage::fvector3* impact_direction); - using request_ragdoll = void (*)(uint16_t object_id); - using request_control = void (*)(rage::netObject* net_object); + using request_ragdoll = void (*)(uint16_t object_id); + using request_control = void (*)(rage::netObject* net_object); - using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_id); + using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_id); using send_remove_gamer_cmd = void (*)(rage::netConnectionManager* net_connection_mgr, rage::netConnectionPeer* player, int connection_id, rage::snMsgRemoveGamersFromSessionCmd* cmd, int flags); using handle_remove_gamer_cmd = void* (*)(rage::snSession* session, rage::snPlayer* origin, rage::snMsgRemoveGamersFromSessionCmd* cmd); - using script_vm = int (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx); + using script_vm = rage::eThreadState (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx); using encode_session_info = bool (*)(rage::rlSessionInfo* info, char* buffer, int buffer_size, int* bytes_written); using decode_session_info = bool (*)(rage::rlSessionInfo* out_info, char* buffer, int* bytes_read); @@ -126,11 +127,13 @@ namespace big::functions using save_json_data = char* (*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason); using sync_network_time = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, rage::netTimeSyncMsg* msg, int flags); - using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags); - using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status); + using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags); + using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status); using clear_ped_tasks_network = void (*)(CPed* ped, bool immediately); using get_next_carriage = void* (*)(void* carriage); using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity); + + using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type); } diff --git a/src/gta/sound.hpp b/src/gta/sound.hpp new file mode 100644 index 00000000..ea6ada3f --- /dev/null +++ b/src/gta/sound.hpp @@ -0,0 +1,203 @@ +#pragma once +#include "file_manager.hpp" +#include "thread_pool.hpp" + +using namespace std::chrono_literals; + +// {DCB7EF33-CD8A-4231-8051-66E3F683180B} +static const GUID g_yim_device = {0xdcb7ef33, 0xcd8a, 0x4231, {0x80, 0x51, 0x66, 0xe3, 0xf6, 0x83, 0x18, 0xb}}; + +class IDirectSoundCaptureBuffer +{ + inline int GetActualReadPos() + { + return read_position + (audio_page * 32000); + } + + virtual void QueryInterface(){}; + + virtual int AddRef() + { + return 0; + }; + + virtual int Release() + { + return 0; + } + + virtual HRESULT GetCaps(void* caps) + { + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT GetCurrentPosition(int* capture, int* read) + { + if (capture) + *capture = 0; + + if (read) + *read = read_position; + + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT GetFormat(void* out, int length, int* out_length) + { + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT GetStatus(int* status) + { + *status = 1; // DSCBSTATUS_CAPTURING + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT Initialize(void*, void*) + { + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT Lock(DWORD dwOffset, DWORD dwBytes, char** ppvAudioPtr1, LPDWORD pdwAudioBytes1, char** ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) + { + if (dwOffset > read_position && audio_page != 0) + { + dwOffset -= 32000;// fix page offset if we have to read back + } + + dwOffset += (audio_page * 32000);// add our page offset to get the actual position + + // fix artifacts after audio ends + if (dwBytes > 1280) + dwOffset = 0; + + if (dwOffset + dwBytes <= audio_size) + { + *ppvAudioPtr1 = &audio_buffer[dwOffset]; + *pdwAudioBytes1 = dwBytes; + *ppvAudioPtr2 = NULL; + *pdwAudioBytes2 = 0; + } + else + { + *ppvAudioPtr1 = &audio_buffer[dwOffset]; + *pdwAudioBytes1 = audio_size - dwOffset; + *ppvAudioPtr2 = &audio_buffer[0]; + *pdwAudioBytes2 = dwBytes - *pdwAudioBytes1; + } + + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT Start(int flags) + { + if (big::g_file_manager->get_project_file("./audio.wav").exists()) + { + std::ifstream wave_stream(big::g_file_manager->get_project_file("./audio.wav").get_path(), std::ios::in | std::ios::binary); + + // https://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html + int header_size = 0; + int data_size = 0; + wave_stream.seekg(4, std::ios_base::cur); // RIFF + wave_stream.seekg(4, std::ios_base::cur); // chunk size + wave_stream.seekg(4, std::ios_base::cur); // Wave ID + wave_stream.seekg(4, std::ios_base::cur); // ckID "fmt " + wave_stream.read((char*)&header_size, 4); // cksize "fmt " + wave_stream.seekg(header_size, std::ios_base::cur);// format + wave_stream.seekg(4, std::ios_base::cur); // ckID "data" + wave_stream.read((char*)&data_size, 4); // cksize "data" + + audio_buffer = new char[data_size]; + memset(audio_buffer, 0, data_size); + audio_size = data_size; + wave_stream.read(audio_buffer, audio_size); + wave_stream.close(); + } + else + { + audio_buffer = new char[0xFFFF]; + audio_size = 0xFFFF; + } + + running = true; + big::g_thread_pool->push([this] { + last_read = std::chrono::high_resolution_clock::now(); + + while (!big::g_running) + std::this_thread::yield(); + + while (big::g_running && running) + { + std::this_thread::yield(); + + // the buffer can only support up to 32000 bytes of data at once, so we have to page it instead + if (std::chrono::high_resolution_clock::now() - last_read >= 1ms) + { + last_read = std::chrono::high_resolution_clock::now(); + read_position += ((2 * 16000) / 1000);// F*M*Nc/1000 + + // reset page idx after audio playback completes + if (GetActualReadPos() > audio_size) + { + read_position = 0; + audio_page = 0; + } + + // use next page if we go beyond 32000 + if (read_position > 32000) + { + read_position = read_position % 32000; + audio_page++; + } + } + } + }); + + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT Stop() + { + running = false; + delete[] audio_buffer; + + return (HRESULT)0L;// DS_OK + } + + virtual HRESULT Unlock(LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) + { + return (HRESULT)0L;// DS_OK + } + + char* audio_buffer = nullptr; + int audio_size = 0; + int audio_page = 0; + int read_position = 0; + bool running = false; + std::chrono::high_resolution_clock::time_point last_read = std::chrono::high_resolution_clock::time_point(); +}; +inline IDirectSoundCaptureBuffer g_direct_sound_capture_buffer{}; + +class IDirectSoundCapture +{ + virtual void QueryInterface(){}; + + virtual int AddRef() + { + return 0; + }; + + virtual int Release() + { + return 0; + } + + virtual HRESULT CreateSoundBuffer(void* desc, IDirectSoundCaptureBuffer** buffer, void* unknown) + { + *buffer = &g_direct_sound_capture_buffer; + return (HRESULT)0L;// DS_OK + } + + // we shouldn't need the rest +}; +inline IDirectSoundCapture g_direct_sound_capture{}; \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp index 5c04dfb7..ecae4241 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -13,20 +13,20 @@ namespace big gui::gui() : m_is_open(false) { - g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing - g_renderer->add_dx_callback(view::notifications, -2); // second highest priority - g_renderer->add_dx_callback(view::overlay, -3); // 3rd highest priority + g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing + g_renderer->add_dx_callback(view::notifications, -2);// second highest priority + g_renderer->add_dx_callback(view::overlay, -3); // 3rd highest priority g_renderer->add_dx_callback( [this] { dx_on_tick(); }, - -4); // 4th highest priority + -4);// 4th highest priority g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { wndproc(hwnd, msg, wparam, lparam); }); - g_renderer->add_dx_callback(esp::draw, 2); // TODO: move to ESP service + g_renderer->add_dx_callback(esp::draw, 2);// TODO: move to ESP service g_renderer->add_dx_callback(view::context_menu, 1); dx_init(); diff --git a/src/hooking.cpp b/src/hooking.cpp index 17fed8aa..99318f9d 100644 --- a/src/hooking.cpp +++ b/src/hooking.cpp @@ -11,6 +11,7 @@ #include "script_mgr.hpp" #include +#include namespace big { @@ -113,6 +114,11 @@ namespace big detour_hook_helper::add("GMI", g_pointers->m_get_model_info); + detour_hook_helper::add("EAD", g_pointers->m_enumerate_audio_devices); + detour_hook_helper::add("DSCC", g_pointers->m_direct_sound_capture_create); + + detour_hook_helper::add("WVPMDN", g_pointers->m_write_vehicle_proximity_migration_data_node); + g_hooking = this; } diff --git a/src/hooking.hpp b/src/hooking.hpp index 13c56e31..3997cae0 100644 --- a/src/hooking.hpp +++ b/src/hooking.hpp @@ -27,6 +27,9 @@ class CPlayerCardStats; class CStatsSerializationContext; class CPlayerCreationDataNode; class CPlayerAppearanceDataNode; +class CFoundDevice; +class IDirectSoundCapture; +class CVehicleProximityMigrationDataNode; namespace rage { @@ -153,6 +156,11 @@ namespace big static void write_player_appearance_data_node(rage::netObject* player, CPlayerAppearanceDataNode* node); static CBaseModelInfo* get_model_info(rage::joaat_t hash, uint32_t* a2); + + static int enumerate_audio_devices(CFoundDevice* found_devices, int count, int flags); + static HRESULT direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown); + + static void write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node); }; class minhook_keepalive 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 0ded7ccf..559301e3 100644 --- a/src/hooks/protections/serialize_take_off_ped_variation_task.cpp +++ b/src/hooks/protections/serialize_take_off_ped_variation_task.cpp @@ -10,7 +10,7 @@ namespace big 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")) { - notify::crash_blocked(g.m_syncing_player, "invalid parachute"); + // notify::crash_blocked(g.m_syncing_player, "invalid parachute"); false positives info->m_prop_hash = 0; } } diff --git a/src/hooks/script/gta_thread_kill.cpp b/src/hooks/script/gta_thread_kill.cpp index ffcdf5ae..a44c11b4 100644 --- a/src/hooks/script/gta_thread_kill.cpp +++ b/src/hooks/script/gta_thread_kill.cpp @@ -8,7 +8,8 @@ namespace big const auto result = g_hooking->get_original()(thread); if (g.notifications.gta_thread_kill.log) - LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated."; + LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated (" << thread->m_exit_message << ")."; + if (g.notifications.gta_thread_kill.notify) g_notification_service->push("Script Thread Termination", std::format("Script Thread '{}' terminated.", thread->m_name)); @@ -22,6 +23,9 @@ namespace big if (thread == g.m_mission_creator_thread) g.m_mission_creator_thread = nullptr; + if (thread == g.m_modshop_thread) + g.m_modshop_thread = nullptr; + return result; } } diff --git a/src/hooks/script/script_vm.cpp b/src/hooks/script/script_vm.cpp index 200eeccf..c4700b68 100644 --- a/src/hooks/script/script_vm.cpp +++ b/src/hooks/script/script_vm.cpp @@ -30,6 +30,8 @@ namespace big scr_globals::globalplayer_bd.as()->Entries[self::id].CurrentShopIndex = old_shop_index; scr_globals::globalplayer_bd.as()->Entries[self::id].CayoPericoFlags = old_cayo_flags; } + + g.in_script_vm = true; } ~script_vm_guard() @@ -47,6 +49,8 @@ namespace big scr_globals::globalplayer_bd.as()->Entries[self::id].CayoPericoFlags = 1; } } + + g.in_script_vm = false; } }; diff --git a/src/hooks/toxic/write_vehicle_proximity_migration_data_node.cpp b/src/hooks/toxic/write_vehicle_proximity_migration_data_node.cpp new file mode 100644 index 00000000..4d970c9c --- /dev/null +++ b/src/hooks/toxic/write_vehicle_proximity_migration_data_node.cpp @@ -0,0 +1,24 @@ +#include "gta/net_array.hpp" +#include "hooking.hpp" +#include "script_global.hpp" +#include "script_local.hpp" + +#include + +namespace big +{ + void hooks::write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node) + { + CVehicle* vehicle = *(CVehicle**)(((__int64)veh) - 432); + + g_hooking->get_original()(veh, node); + + if (vehicle->m_net_object->m_object_id = g.m_tp_veh_net_id) + { + node->m_has_occupants[0] = true; + node->m_occupants[0] = g.m_tp_player_net_id; + node->m_override_position = true; + node->m_position = g.m_tp_position; + } + } +} \ No newline at end of file diff --git a/src/hooks/voice/direct_sound_capture_create.cpp b/src/hooks/voice/direct_sound_capture_create.cpp new file mode 100644 index 00000000..5057c861 --- /dev/null +++ b/src/hooks/voice/direct_sound_capture_create.cpp @@ -0,0 +1,18 @@ +#include "gta/sound.hpp" +#include "hooking.hpp" + +namespace big +{ + HRESULT hooks::direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown) + { + if ((*guid) == g_yim_device && g.spoofing.voice_chat_audio) + { + *sound = &g_direct_sound_capture; + return (HRESULT)0L;// DS_OK + } + else + { + return g_hooking->get_original()(guid, sound, unknown); + } + } +} diff --git a/src/hooks/voice/enumerate_audio_devices.cpp b/src/hooks/voice/enumerate_audio_devices.cpp new file mode 100644 index 00000000..ba78502c --- /dev/null +++ b/src/hooks/voice/enumerate_audio_devices.cpp @@ -0,0 +1,42 @@ +#include "gta/sound.hpp" +#include "hooking.hpp" + +class CFoundDevice +{ +public: + GUID m_guid; + char16_t m_name[64]; + int m_device_type; + int m_default_type; + int m_pad2; +}; +static_assert(sizeof(CFoundDevice) == 0x9C); + +namespace big +{ + int hooks::enumerate_audio_devices(CFoundDevice* found_devices, int count, int flags) + { + auto res = g_hooking->get_original()(found_devices, count, flags); + + if ((flags & 1) && g.spoofing.voice_chat_audio) + { + for (int i = 0; i < count; i++) + { + if (found_devices[i].m_device_type != 2 || found_devices[i].m_default_type != 2) + { + lstrcpyW((LPWSTR)found_devices[i].m_name, L"YimMenu Virtual Input Device"); + found_devices[i].m_guid = g_yim_device; + found_devices[i].m_device_type = 1; + found_devices[i].m_default_type = 1; + + if (i >= res) + res++; + + break; + } + } + } + + return res; + } +} diff --git a/src/logger/stack_trace.cpp b/src/logger/stack_trace.cpp index a70ff4bb..c977a915 100644 --- a/src/logger/stack_trace.cpp +++ b/src/logger/stack_trace.cpp @@ -1,5 +1,6 @@ #include "stack_trace.hpp" +#include "gta/script_thread.hpp" #include "memory/module.hpp" #include @@ -26,9 +27,13 @@ namespace big m_exception_info = exception_info; m_dump << exception_code_to_string(exception_info->ExceptionRecord->ExceptionCode) << '\n'; + + if (g.in_script_vm) + dump_script_info(); dump_module_info(); dump_registers(); dump_stacktrace(); + m_dump << "\n--------End of exception--------\n"; } @@ -40,11 +45,11 @@ namespace big // I'd prefer to make some sort of global instance that cache all modules once instead of doing this every time void stack_trace::dump_module_info() { - m_dump << "Dumping modules:\n"; + // modules cached already + if (m_modules.size()) + return; - // modules cached already - if (m_modules.size()) - return; + m_dump << "Dumping modules:\n"; const auto peb = reinterpret_cast(NtCurrentTeb()->ProcessEnvironmentBlock); if (!peb) @@ -138,6 +143,13 @@ namespace big } } + void stack_trace::dump_script_info() + { + m_dump << "Currently executing script: " << rage::scrThread::get()->m_name << '\n'; + m_dump << "Thread program counter (could be inaccurate): " + << m_exception_info->ContextRecord->Rdi - m_exception_info->ContextRecord->Rsi << '\n'; + } + void stack_trace::grab_stacktrace() { CONTEXT context = *m_exception_info->ContextRecord; diff --git a/src/logger/stack_trace.hpp b/src/logger/stack_trace.hpp index c4eac919..667c703a 100644 --- a/src/logger/stack_trace.hpp +++ b/src/logger/stack_trace.hpp @@ -37,6 +37,7 @@ namespace big void dump_module_info(); void dump_registers(); void dump_stacktrace(); + void dump_script_info(); void grab_stacktrace(); const module_info* get_module_by_address(uint64_t addr) const; diff --git a/src/native_hooks/all_scripts.hpp b/src/native_hooks/all_scripts.hpp index 418fc97c..91c32f4f 100644 --- a/src/native_hooks/all_scripts.hpp +++ b/src/native_hooks/all_scripts.hpp @@ -66,69 +66,68 @@ namespace big { const auto action = src->get_arg(1); - if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka - { - switch (action) - { - // case ControllerInputs::INPUT_JUMP: TODO: add as separate feature - case ControllerInputs::INPUT_ATTACK: - case ControllerInputs::INPUT_AIM: - case ControllerInputs::INPUT_DUCK: - case ControllerInputs::INPUT_SELECT_WEAPON: - case ControllerInputs::INPUT_COVER: - case ControllerInputs::INPUT_TALK: - case ControllerInputs::INPUT_DETONATE: - case ControllerInputs::INPUT_WEAPON_SPECIAL: - case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO: - case ControllerInputs::INPUT_VEH_AIM: - case ControllerInputs::INPUT_VEH_ATTACK: - case ControllerInputs::INPUT_VEH_ATTACK2: - case ControllerInputs::INPUT_VEH_HEADLIGHT: - case ControllerInputs::INPUT_VEH_NEXT_RADIO: - case ControllerInputs::INPUT_VEH_PREV_RADIO: - case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK: - case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK: - case ControllerInputs::INPUT_VEH_RADIO_WHEEL: - case ControllerInputs::INPUT_VEH_PASSENGER_AIM: - case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK: - case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON: - case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON: - case ControllerInputs::INPUT_VEH_ROOF: - case ControllerInputs::INPUT_VEH_JUMP: - case ControllerInputs::INPUT_VEH_FLY_ATTACK: - case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT: - case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY: - case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE: - case ControllerInputs::INPUT_MELEE_BLOCK: - case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED: - case ControllerInputs::INPUT_SELECT_WEAPON_MELEE: - case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN: - case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN: - case ControllerInputs::INPUT_SELECT_WEAPON_SMG: - case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE: - case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER: - case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY: - case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL: - case ControllerInputs::INPUT_ATTACK2: - case ControllerInputs::INPUT_MELEE_ATTACK1: - case ControllerInputs::INPUT_MELEE_ATTACK2: - case ControllerInputs::INPUT_VEH_GUN_LEFT: - case ControllerInputs::INPUT_VEH_GUN_RIGHT: - case ControllerInputs::INPUT_VEH_GUN_UP: - case ControllerInputs::INPUT_VEH_GUN_DOWN: - case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE: - case ControllerInputs::INPUT_VEH_MELEE_HOLD: - case ControllerInputs::INPUT_VEH_MELEE_LEFT: - case ControllerInputs::INPUT_VEH_MELEE_RIGHT: - case ControllerInputs::INPUT_VEH_CAR_JUMP: - case ControllerInputs::INPUT_VEH_ROCKET_BOOST: - case ControllerInputs::INPUT_VEH_FLY_BOOST: - case ControllerInputs::INPUT_VEH_PARACHUTE: - case ControllerInputs::INPUT_VEH_BIKE_WINGS: - case ControllerInputs::INPUT_VEH_TRANSFORM: - return; - } - } + if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka + { + switch (action) + { + // case ControllerInputs::INPUT_JUMP: TODO: add as separate feature + case ControllerInputs::INPUT_ATTACK: + case ControllerInputs::INPUT_AIM: + case ControllerInputs::INPUT_DUCK: + case ControllerInputs::INPUT_SELECT_WEAPON: + case ControllerInputs::INPUT_COVER: + case ControllerInputs::INPUT_TALK: + case ControllerInputs::INPUT_DETONATE: + case ControllerInputs::INPUT_WEAPON_SPECIAL: + case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO: + case ControllerInputs::INPUT_VEH_AIM: + case ControllerInputs::INPUT_VEH_ATTACK: + case ControllerInputs::INPUT_VEH_ATTACK2: + case ControllerInputs::INPUT_VEH_HEADLIGHT: + case ControllerInputs::INPUT_VEH_NEXT_RADIO: + case ControllerInputs::INPUT_VEH_PREV_RADIO: + case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK: + case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK: + case ControllerInputs::INPUT_VEH_RADIO_WHEEL: + case ControllerInputs::INPUT_VEH_PASSENGER_AIM: + case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK: + case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON: + case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON: + case ControllerInputs::INPUT_VEH_ROOF: + case ControllerInputs::INPUT_VEH_JUMP: + case ControllerInputs::INPUT_VEH_FLY_ATTACK: + case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT: + case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY: + case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE: + case ControllerInputs::INPUT_MELEE_BLOCK: + case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED: + case ControllerInputs::INPUT_SELECT_WEAPON_MELEE: + case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN: + case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN: + case ControllerInputs::INPUT_SELECT_WEAPON_SMG: + case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE: + case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER: + case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY: + case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL: + case ControllerInputs::INPUT_ATTACK2: + case ControllerInputs::INPUT_MELEE_ATTACK1: + case ControllerInputs::INPUT_MELEE_ATTACK2: + case ControllerInputs::INPUT_VEH_GUN_LEFT: + case ControllerInputs::INPUT_VEH_GUN_RIGHT: + case ControllerInputs::INPUT_VEH_GUN_UP: + case ControllerInputs::INPUT_VEH_GUN_DOWN: + case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE: + case ControllerInputs::INPUT_VEH_MELEE_HOLD: + case ControllerInputs::INPUT_VEH_MELEE_LEFT: + case ControllerInputs::INPUT_VEH_MELEE_RIGHT: + case ControllerInputs::INPUT_VEH_CAR_JUMP: + case ControllerInputs::INPUT_VEH_ROCKET_BOOST: + case ControllerInputs::INPUT_VEH_FLY_BOOST: + case ControllerInputs::INPUT_VEH_PARACHUTE: + case ControllerInputs::INPUT_VEH_BIKE_WINGS: + case ControllerInputs::INPUT_VEH_TRANSFORM: return; + } + } PAD::DISABLE_CONTROL_ACTION(src->get_arg(0), (int)action, src->get_arg(2)); } @@ -138,12 +137,12 @@ namespace big if (g.weapons.interior_weapon && src->get_arg(0) == false) return; - HUD::HUD_FORCE_WEAPON_WHEEL(src->get_arg(0)); - } + HUD::HUD_FORCE_WEAPON_WHEEL(src->get_arg(0)); + } - void NETWORK_CASINO_CAN_BET(rage::scrNativeCallContext* src) - { - src->set_return_value(TRUE); - } - } + void RETURN_TRUE(rage::scrNativeCallContext* src) + { + src->set_return_value(TRUE); + } + } } \ No newline at end of file diff --git a/src/native_hooks/carmod_shop.hpp b/src/native_hooks/carmod_shop.hpp index 71f6b5a0..68636c17 100644 --- a/src/native_hooks/carmod_shop.hpp +++ b/src/native_hooks/carmod_shop.hpp @@ -46,6 +46,9 @@ namespace big case RAGE_JOAAT("MP1_AWD_FMRALLYWONNAV"): case RAGE_JOAAT("MP1_AWD_FMWINSEARACE"): case RAGE_JOAAT("MP1_AWD_FMWINAIRRACE"): *out = 1; break; + case RAGE_JOAAT("SP0_TOTAL_CASH"): + case RAGE_JOAAT("SP1_TOTAL_CASH"): + case RAGE_JOAAT("SP2_TOTAL_CASH"): *out = 999999; break; default: src->set_return_value(STATS::STAT_GET_INT(hash, out, src->get_arg(2))); break; } } @@ -73,5 +76,13 @@ namespace big VEHICLE::SET_VEHICLE_LIGHTS(src->get_arg(0), src->get_arg(1)); } } + + inline void DISABLE_ALL_CONTROL_ACTIONS(rage::scrNativeCallContext* src) + { + if (!g.vehicle.ls_customs) + { + PAD::DISABLE_ALL_CONTROL_ACTIONS(src->get_arg(0)); + } + } } } \ No newline at end of file diff --git a/src/native_hooks/native_hooks.cpp b/src/native_hooks/native_hooks.cpp index 8e3b1c8e..9a721f45 100644 --- a/src/native_hooks/native_hooks.cpp +++ b/src/native_hooks/native_hooks.cpp @@ -111,12 +111,14 @@ namespace big add_native_detour(0xADF692B254977C0C, all_scripts::SET_CURRENT_PED_WEAPON); add_native_detour(0xFE99B66D079CF6BC, all_scripts::DISABLE_CONTROL_ACTION); add_native_detour(0xEB354E5376BC81A7, all_scripts::HUD_FORCE_WEAPON_WHEEL); - add_native_detour(0x158C16F5E4CF41F8, all_scripts::NETWORK_CASINO_CAN_BET);//bypass casino country restrictions + add_native_detour(0x158C16F5E4CF41F8, all_scripts::RETURN_TRUE); //bypass casino country restrictions add_native_detour(RAGE_JOAAT("carmod_shop"), 0x06843DA7060A026B, carmod_shop::SET_ENTITY_COORDS); 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"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS); + add_native_detour(RAGE_JOAAT("freemode"), 0x95914459A87EBA28, freemode::NETWORK_BAIL); add_native_detour(RAGE_JOAAT("freemode"), 0x5E9564D8246B909A, freemode::IS_PLAYER_PLAYING); add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE); diff --git a/src/pointers.cpp b/src/pointers.cpp index 5251be5e..45a8342a 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -271,9 +271,9 @@ namespace big // Received clone sync & Get sync tree for type & Get net object for player & Get sync type info & Get net object main_batch.add("RCS/GSTFT/GNOFP/GNO/GSTI", "4C 8B FA 41 0F B7 D1", [this](memory::handle ptr) { m_received_clone_sync = ptr.sub(0x1D).as(); - m_get_sync_tree_for_type = ptr.add(0x14).rip().as(); // 0F B7 CA 83 F9 07 .as() - m_get_net_object = ptr.add(0x76).rip().as(); // E8 ? ? ? ? 0F B7 53 7C .add(1).rip().as() - m_get_sync_type_info = ptr.add(0x8C).rip().as(); // 44 0F B7 C1 4C 8D 0D .as() + m_get_sync_tree_for_type = ptr.add(0x14).rip().as();// 0F B7 CA 83 F9 07 .as() + m_get_net_object = ptr.add(0x76).rip().as();// E8 ? ? ? ? 0F B7 53 7C .add(1).rip().as() + m_get_sync_type_info = ptr.add(0x8C).rip().as();// 44 0F B7 C1 4C 8D 0D .as() }); // Read Bitbuffer Into Sync Tree @@ -471,7 +471,7 @@ namespace big // Is Matchmaking Session Valid main_batch.add("IMSV", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 45 0F", [this](memory::handle ptr) { - memory::byte_patch::make(ptr.as(), std::to_array({0xB0, 0x01, 0xC3}))->apply(); // has no observable side effects + memory::byte_patch::make(ptr.as(), std::to_array({0xB0, 0x01, 0xC3}))->apply();// has no observable side effects }); // Send Network Damage @@ -624,8 +624,8 @@ namespace big // Sound Overload Detour main_batch.add("SOD", "66 45 3B C1 74 38", [this](memory::handle ptr) { - g_sound_overload_ret_addr = ptr.add(13 + 15).as(); - std::vector bytes = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90}; // far jump opcode + a nop opcode + g_sound_overload_ret_addr = ptr.add(13 + 15).as(); + std::vector bytes = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90};// far jump opcode + a nop opcode *(void**)(bytes.data() + 6) = sound_overload_detour; memory::byte_patch::make(ptr.add(13).as(), bytes)->apply(); }); @@ -711,14 +711,39 @@ namespace big m_write_player_appearance_data_node = ptr.as(); }); - // DC + // Enumerate Audio Devices + main_batch.add("EAD", "48 89 5C 24 08 48 89 7C 24 10 55 48 8B EC 48 83 EC 70 41", [this](memory::handle ptr) { + m_enumerate_audio_devices = ptr.as(); + }); + + // Direct Sound Capture Create + main_batch.add("DSCC", "E8 ? ? ? ? 33 FF 85 C0 78 C1", [this](memory::handle ptr) { + m_direct_sound_capture_create = ptr.add(1).rip().as(); + }); + + // Refresh Audio Input + main_batch.add("RAI", "40 88 3D ? ? ? ? 89 05 ? ? ? ? 40 38 3D", [this](memory::handle ptr) { + m_refresh_audio_input = ptr.add(3).rip().as(); + }); + + // Disable Collision main_batch.add("DC", "48 8B D1 49 8B CA ? ? ? ? ? 48 8B D1 49 8B CA", [this](memory::handle ptr) { m_disable_collision = memory::byte_patch::make(ptr.sub(2).as(), 0xEB).get(); }); - // AWIV + // Allow Weapons In Vehicle main_batch.add("AWIV", "49 3B C9 7C F0 ? ? C3", [this](memory::handle ptr) { - m_allow_weapons_in_vehicle = memory::byte_patch::make(ptr.add(5).as(), 0x01B0).get(); //In order for the second xref loop not to stop + m_allow_weapons_in_vehicle = memory::byte_patch::make(ptr.add(5).as(), 0x01B0).get();//In order for the second xref loop not to stop + }); + + // Write Vehicle Proximity Migration Data Node + main_batch.add("WVPMDN", "48 89 4C 24 08 55 53 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 68 4C 8B A9", [this](memory::handle ptr) { + m_write_vehicle_proximity_migration_data_node = ptr.as(); + }); + + // Migrate Object + main_batch.add("MO", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 41 8B F8 48", [this](memory::handle ptr) { + m_migrate_object = ptr.as(); }); auto mem_region = memory::module("GTA5.exe"); diff --git a/src/pointers.hpp b/src/pointers.hpp index aece77d9..949dd06d 100644 --- a/src/pointers.hpp +++ b/src/pointers.hpp @@ -161,8 +161,8 @@ namespace big functions::generate_uuid m_generate_uuid{}; std::uint64_t* m_host_token{}; - rage::rlGamerInfo* m_profile_gamer_info{}; // per profile gamer info - rage::rlGamerInfo* m_player_info_gamer_info{}; // the gamer info that is applied to CPlayerInfo + rage::rlGamerInfo* m_profile_gamer_info{}; // per profile gamer info + rage::rlGamerInfo* m_player_info_gamer_info{};// the gamer info that is applied to CPlayerInfo CCommunications** m_communications{}; PVOID m_update_presence_attribute_int; @@ -249,8 +249,15 @@ namespace big PVOID m_write_player_creation_data_node{}; PVOID m_write_player_appearance_data_node{}; + PVOID m_enumerate_audio_devices{}; + PVOID m_direct_sound_capture_create{}; + bool* m_refresh_audio_input{}; + memory::byte_patch* m_disable_collision{}; memory::byte_patch* m_allow_weapons_in_vehicle{}; + + PVOID m_write_vehicle_proximity_migration_data_node{}; + functions::migrate_object m_migrate_object{}; }; inline pointers* g_pointers{}; diff --git a/src/script_function.cpp b/src/script_function.cpp index a609858a..4d222984 100644 --- a/src/script_function.cpp +++ b/src/script_function.cpp @@ -62,6 +62,45 @@ namespace big tls_ctx->m_is_script_thread_active = og_thread != nullptr; } + void script_function::call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list args, bool& done) + { + g_fiber_pool->queue_job([this, thread, program, args, &done] { + auto stack = (uint64_t*)thread->m_stack; + + rage::eThreadState result = rage::eThreadState::idle; + + rage::scrThreadContext ctx = thread->m_context; + + for (auto& arg : args) + stack[ctx.m_stack_pointer++] = arg; + + stack[ctx.m_stack_pointer++] = 0; + ctx.m_instruction_pointer = m_ip; + ctx.m_state = rage::eThreadState::idle; + + while (result != rage::eThreadState::killed) + { + auto tls_ctx = rage::tlsContext::get(); + auto og_thread = tls_ctx->m_script_thread; + + tls_ctx->m_script_thread = thread; + tls_ctx->m_is_script_thread_active = true; + + auto old_ctx = thread->m_context; + thread->m_context = ctx; + result = g_pointers->m_script_vm(stack, g_pointers->m_script_globals, program, &thread->m_context); + thread->m_context = old_ctx; + + tls_ctx->m_script_thread = og_thread; + tls_ctx->m_is_script_thread_active = og_thread != nullptr; + + script::get_current()->yield(); + } + + done = true; + }); + } + void script_function::static_call(std::initializer_list args) { populate_ip(); @@ -77,7 +116,7 @@ namespace big call(thread, gta_util::find_script_program(m_script), args); delete[] stack; - delete[] (uint8_t*)thread; // without the cast it ends up calling the destructor which leads to some pretty funny crashes + delete[](uint8_t*) thread;// without the cast it ends up calling the destructor which leads to some pretty funny crashes } void script_function::operator()(std::initializer_list args) diff --git a/src/script_function.hpp b/src/script_function.hpp index a5b1df04..b54cd3b2 100644 --- a/src/script_function.hpp +++ b/src/script_function.hpp @@ -17,6 +17,7 @@ namespace big script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset); void populate_ip(); void call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list args); + void call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list args, bool& done); // for pure functions that do not need access to thread stack void static_call(std::initializer_list args); @@ -33,5 +34,8 @@ namespace big static inline script_function save_to_datafile("STD", RAGE_JOAAT("fm_race_creator"), "2D 01 03 00 00 71 2C", 0); static inline script_function load_from_datafile("LFD", RAGE_JOAAT("fm_race_creator"), "2D 04 0D 00 00 71 2C", 0); + + 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); } } \ No newline at end of file diff --git a/src/util/entity.hpp b/src/util/entity.hpp index 2823117f..12c176db 100644 --- a/src/util/entity.hpp +++ b/src/util/entity.hpp @@ -141,4 +141,34 @@ namespace big::entity } return target_entities; } + + inline bool load_ground_at_3dcoord(Vector3& location) + { + float groundZ; + const uint8_t attempts = 10; + + for (uint8_t i = 0; i < attempts; i++) + { + // Only request a collision after the first try failed because the location might already be loaded on first attempt. + for (uint16_t z = 0; i && z < 1000; z += 100) + { + STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, (float)z); + + script::get_current()->yield(); + } + + if (MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, 1000.f, &groundZ, false, false)) + { + location.z = groundZ + 1.f; + + return true; + } + + script::get_current()->yield(); + } + + location.z = 1000.f; + + return false; + } } \ No newline at end of file diff --git a/src/util/teleport.hpp b/src/util/teleport.hpp index 61a5438d..8447ca2d 100644 --- a/src/util/teleport.hpp +++ b/src/util/teleport.hpp @@ -2,7 +2,9 @@ #include "blip.hpp" #include "entity.hpp" #include "gta/enums.hpp" +#include "gta/net_object_mgr.hpp" #include "services/players/player_service.hpp" +#include "vehicle.hpp" namespace big::teleport { @@ -16,20 +18,49 @@ namespace big::teleport return false; } - if (!PED::IS_PED_IN_ANY_VEHICLE(ent, true)) + if (PED::IS_PED_IN_ANY_VEHICLE(ent, true)) { - g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_PLAYER_IS_NOT_IN_VEHICLE"_T.data()); - return false; + ent = PED::GET_VEHICLE_PED_IS_IN(ent, false); + + if (entity::take_control_of(ent)) + ENTITY::SET_ENTITY_COORDS(ent, coords.x, coords.y, coords.z, 0, 0, 0, 0); + else + g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data()); + + return true; } - - ent = PED::GET_VEHICLE_PED_IS_IN(ent, false); - - if (entity::take_control_of(ent)) - ENTITY::SET_ENTITY_COORDS(ent, coords.x, coords.y, coords.z, 0, 0, 0, 0); else - g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data()); + { + auto hnd = vehicle::spawn(RAGE_JOAAT("ninef"), *player->get_ped()->get_position(), 0.0f, true); + ENTITY::SET_ENTITY_VISIBLE(hnd, false, false); + ENTITY::SET_ENTITY_COLLISION(hnd, false, false); + ENTITY::FREEZE_ENTITY_POSITION(hnd, true); - return true; + g.m_tp_position = {coords.x, coords.y, coords.z}; + g.m_tp_player_net_id = player->get_ped()->m_net_object->m_object_id; + g.m_tp_veh_net_id = g_pointers->m_handle_to_ptr(hnd)->m_net_object->m_object_id; + + if ((player->is_valid() && PED::IS_PED_IN_ANY_VEHICLE(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id()), false)) + || PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id())) + g_pointers->m_clear_ped_tasks_network(player->get_ped(), true); + + for (int i = 0; i < 15; i++) + { + script::get_current()->yield(50ms); + + if (auto ptr = (rage::CDynamicEntity*)g_pointers->m_handle_to_ptr(hnd)) + { + if (auto netobj = ptr->m_net_object) + { + g_pointers->m_migrate_object(player->get_net_game_player(), netobj, 3); + } + } + } + + entity::delete_entity(hnd); + + return true; + } } inline bool bring_player(player_ptr player) @@ -37,36 +68,6 @@ namespace big::teleport return teleport_player_to_coords(player, self::pos); } - inline bool load_ground_at_3dcoord(Vector3& location) - { - float groundZ; - const uint8_t attempts = 10; - - for (uint8_t i = 0; i < attempts; i++) - { - // Only request a collision after the first try failed because the location might already be loaded on first attempt. - for (uint16_t z = 0; i && z < 1000; z += 100) - { - STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, (float)z); - - script::get_current()->yield(); - } - - if (MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, 1000.f, &groundZ, false, false)) - { - location.z = groundZ + 1.f; - - return true; - } - - script::get_current()->yield(); - } - - location.z = 1000.f; - - return false; - } - inline bool into_vehicle(Vehicle veh) { if (!ENTITY::IS_ENTITY_A_VEHICLE(veh)) @@ -90,7 +91,7 @@ namespace big::teleport } Vector3 location = ENTITY::GET_ENTITY_COORDS(veh, true); - load_ground_at_3dcoord(location); + entity::load_ground_at_3dcoord(location); Ped ped = self::ped; @@ -116,7 +117,7 @@ namespace big::teleport return false; if (sprite == (int)BlipIcons::Waypoint) - load_ground_at_3dcoord(location); + entity::load_ground_at_3dcoord(location); PED::SET_PED_COORDS_KEEP_VEHICLE(self::ped, location.x, location.y, location.z); diff --git a/src/util/vehicle.hpp b/src/util/vehicle.hpp index 97b2142c..2ef492e0 100644 --- a/src/util/vehicle.hpp +++ b/src/util/vehicle.hpp @@ -9,7 +9,6 @@ #include "script.hpp" #include "script_global.hpp" #include "services/vehicle_helper/vehicle_helper.hpp" -#include "teleport.hpp" namespace big::vehicle { @@ -66,7 +65,7 @@ namespace big::vehicle return g_notification_service->push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data()); auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true); - teleport::load_ground_at_3dcoord(vecVehicleLocation); + entity::load_ground_at_3dcoord(vecVehicleLocation); if (!entity::take_control_of(veh)) return g_notification_service->push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); diff --git a/src/views/core/view_heading.cpp b/src/views/core/view_heading.cpp index 1a06114e..56d37ab8 100644 --- a/src/views/core/view_heading.cpp +++ b/src/views/core/view_heading.cpp @@ -24,6 +24,7 @@ namespace big ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.69f, 0.29f, 0.29f, 1.00f)); if (components::nav_button("UNLOAD"_T)) { + g_fiber_pool->reset(); g_fiber_pool->queue_job([] { for (auto& command : g_looped_commands) if (command->is_enabled()) diff --git a/src/views/debug/view_debug_misc.cpp b/src/views/debug/view_debug_misc.cpp index cdf75e4c..6ab50061 100644 --- a/src/views/debug/view_debug_misc.cpp +++ b/src/views/debug/view_debug_misc.cpp @@ -15,15 +15,13 @@ namespace big { if (ImGui::BeginTabItem("DEBUG_TAB_MISC"_T.data())) { - if (components::button("MOV QWORD")) - { - *static_cast(nullptr) = 0; - uint64_t i = *static_cast(nullptr); - } + ImGui::Text("Fiber Pool Usage %d/%d", g_fiber_pool->get_used_fibers(), g_fiber_pool->get_total_fibers()); - if (components::button("MOV 0xdead")) + ImGui::SameLine(); + + if (components::button("Reset")) { - *((unsigned int*)0) = 0xDEAD; + g_fiber_pool->reset(); } if (components::button("Dump entrypoints")) diff --git a/src/views/network/view_spoofing.cpp b/src/views/network/view_spoofing.cpp index 7b34316a..a5b2a16c 100644 --- a/src/views/network/view_spoofing.cpp +++ b/src/views/network/view_spoofing.cpp @@ -11,11 +11,9 @@ namespace big { void view::spoofing() { - // requires translation + ImGui::Checkbox("HIDE_FROM_PLAYER_LIST"_T.data(), &g.spoofing.hide_from_player_list); - ImGui::Checkbox("Hide From Player List", &g.spoofing.hide_from_player_list); - - components::script_patch_checkbox("Spoof Blip Type", &g.spoofing.spoof_blip); + components::script_patch_checkbox("SPOOF_BLIP_TYPE"_T, &g.spoofing.spoof_blip); if (g.spoofing.spoof_blip) { ImGui::SameLine(); @@ -32,7 +30,7 @@ namespace big } } - ImGui::Checkbox("Spoof Rank", &g.spoofing.spoof_rank); + ImGui::Checkbox("SPOOF_RANK"_T.data(), &g.spoofing.spoof_rank); if (g.spoofing.spoof_rank) { ImGui::SameLine(); @@ -42,7 +40,7 @@ namespace big } } - ImGui::Checkbox("Spoof K/D Ratio", &g.spoofing.spoof_kd_ratio); + ImGui::Checkbox("SPOOF_KD"_T.data(), &g.spoofing.spoof_kd_ratio); if (g.spoofing.spoof_kd_ratio) { ImGui::SameLine(); @@ -52,7 +50,7 @@ namespace big } } - ImGui::Checkbox("Spoof Badsport State", &g.spoofing.spoof_bad_sport); + ImGui::Checkbox("SPOOF_BADSPORT"_T.data(), &g.spoofing.spoof_bad_sport); if (g.spoofing.spoof_bad_sport) { ImGui::SameLine(); @@ -62,14 +60,14 @@ namespace big } } - ImGui::Checkbox("Spoof Job Points", &g.spoofing.spoof_job_points); + ImGui::Checkbox("SPOOF_JOB_POINTS"_T.data(), &g.spoofing.spoof_job_points); if (g.spoofing.spoof_job_points) { ImGui::SameLine(); ImGui::InputInt("###jp", &g.spoofing.job_points); } - ImGui::Checkbox("Spoof Player Model", &g.spoofing.spoof_player_model); + ImGui::Checkbox("SPOOF_PLAYER_MODEL"_T.data(), &g.spoofing.spoof_player_model); if (g.spoofing.spoof_player_model) { static char model[32]; @@ -82,6 +80,7 @@ namespace big g.spoofing.player_model = std::string(model); } + components::command_checkbox<"vcaudio">(); components::sub_title("SPOOFING_HIDE_FEATURES"_T); ImGui::Checkbox("SPOOFING_HIDE_GOD_MODE"_T.data(), &g.spoofing.spoof_hide_god); diff --git a/src/views/players/player/player_info.cpp b/src/views/players/player/player_info.cpp index 46227bbe..0497d195 100644 --- a/src/views/players/player/player_info.cpp +++ b/src/views/players/player/player_info.cpp @@ -1,9 +1,9 @@ #include "core/data/command_access_levels.hpp" #include "core/data/language_codes.hpp" #include "core/scr_globals.hpp" +#include "natives.hpp" #include "services/player_database/player_database_service.hpp" #include "views/view.hpp" -#include "natives.hpp" #include