diff --git a/src/backend/looped/hud/hud_transition_state.cpp b/src/backend/looped/hud/hud_transition_state.cpp index 5524f7fe..461a6b05 100644 --- a/src/backend/looped/hud/hud_transition_state.cpp +++ b/src/backend/looped/hud/hud_transition_state.cpp @@ -82,11 +82,10 @@ namespace big "Spawn Into Personal Vehicle" }; - auto transition_state = script_global(1574993); eTransitionState last_state = eTransitionState::TRANSITION_STATE_EMPTY; void looped::hud_transition_state() { - const auto state = *transition_state.as(); + const auto state = *scr_globals::transition_state.as(); if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0) return; diff --git a/src/core/scr_globals.hpp b/src/core/scr_globals.hpp index df2bd415..53199a31 100644 --- a/src/core/scr_globals.hpp +++ b/src/core/scr_globals.hpp @@ -32,6 +32,7 @@ namespace big::scr_globals static inline script_global mission_creator_exited(1574530); static inline script_global in_multiplayer(78558); // g_bInMultiplayer + static inline script_global transition_state(1574993); static inline script_global vehicle_global = script_global(1586468); static inline script_global mechanic_global = script_global(2793044); diff --git a/src/function_types.hpp b/src/function_types.hpp index c40a8b04..5feeb9f3 100644 --- a/src/function_types.hpp +++ b/src/function_types.hpp @@ -4,6 +4,7 @@ class CMsgJoinResponse; class NetworkGameFilterMatchmakingComponent; +class sCloudFile; namespace rage { @@ -15,6 +16,11 @@ namespace rage class CDynamicEntity; } +namespace datafile_commands +{ + class SveFileObject; +} + namespace big::functions { using run_script_threads = bool(*)(std::uint32_t ops_to_execute); @@ -102,4 +108,11 @@ namespace big::functions 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 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); + + using load_cloud_file = void(*)(sCloudFile** out_cloud_file, char* buffer, int size, const char* reason); + using set_as_active_cloud_file = void(*)(datafile_commands::SveFileObject* object, sCloudFile** file); + using save_json_data = char*(*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason); } diff --git a/src/gta/tls_context.hpp b/src/gta/tls_context.hpp index e37eb5c9..961f19a7 100644 --- a/src/gta/tls_context.hpp +++ b/src/gta/tls_context.hpp @@ -7,9 +7,9 @@ namespace rage class tlsContext { public: - char m_padding1[0xC8]; // 0x00 - sysMemAllocator* m_allocator; // 0xC8 - char m_padding2[0x778]; // 0xD0 + char m_padding1[0xB8]; // 0x00 + sysMemAllocator* m_allocator; // 0xB8 + char m_padding2[0x788]; // 0xD0 scrThread* m_script_thread; // 0x848 bool m_is_script_thread_active; // 0x850 diff --git a/src/native_hooks/all_scripts.hpp b/src/native_hooks/all_scripts.hpp index 44b3dc03..6141c806 100644 --- a/src/native_hooks/all_scripts.hpp +++ b/src/native_hooks/all_scripts.hpp @@ -21,22 +21,6 @@ namespace big src->set_return_value(return_value); } - void NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA(rage::scrNativeCallContext* src) - { - if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g->session.force_script_host) - { - g_fiber_pool->queue_job([] - { - scripts::force_host(RAGE_JOAAT("freemode")); - if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component) - script->m_net_component->block_host_migration(true); - }); - } - - *scr_globals::gsbd.as() = 4; - src->set_return_value(TRUE); - } - void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src) { if (rage::scrThread::get() && rage::scrThread::get()->m_handler) diff --git a/src/native_hooks/freemode.hpp b/src/native_hooks/freemode.hpp index 537a9522..4fcc4573 100644 --- a/src/native_hooks/freemode.hpp +++ b/src/native_hooks/freemode.hpp @@ -41,5 +41,21 @@ namespace big if ((!g->m_mission_creator_thread) || src->get_arg(0) != HUD::GET_MAIN_PLAYER_BLIP_ID()) HUD::SET_BLIP_DISPLAY(src->get_arg(0), src->get_arg(1)); }; + + void NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA(rage::scrNativeCallContext* src) + { + if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g->session.force_script_host) + { + g_fiber_pool->queue_job([] + { + scripts::force_host(RAGE_JOAAT("freemode")); + if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component) + script->m_net_component->block_host_migration(true); + }); + } + + *scr_globals::gsbd.as() = 4; + src->set_return_value(TRUE); + } } } \ No newline at end of file diff --git a/src/native_hooks/native_hooks.cpp b/src/native_hooks/native_hooks.cpp index ec5818b1..6520532b 100644 --- a/src/native_hooks/native_hooks.cpp +++ b/src/native_hooks/native_hooks.cpp @@ -104,9 +104,9 @@ namespace big native_hooks::native_hooks() { add_native_detour(0x812595A0644CE1DE, all_scripts::IS_DLC_PRESENT); - add_native_detour(0x5D10B3795F3FC886, all_scripts::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA); add_native_detour(0x1CA59E306ECB80A5, all_scripts::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT); add_native_detour(0xD1110739EEADB592, all_scripts::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT); + 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); @@ -116,9 +116,12 @@ namespace big add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE); add_native_detour(RAGE_JOAAT("freemode"), 0x231C8F89D0539D8F, freemode::SET_BIGMAP_ACTIVE); add_native_detour(RAGE_JOAAT("freemode"), 0x9029B2F3DA924928, freemode::SET_BLIP_DISPLAY); + add_native_detour(RAGE_JOAAT("freemode"), 0x5D10B3795F3FC886, freemode::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA); + add_native_detour(RAGE_JOAAT("fmmc_launcher"), 0x5D10B3795F3FC886, freemode::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA); add_native_detour(RAGE_JOAAT("shop_controller"), 0xDC38CC1E35B6A5D7, shop_controller::SET_WARNING_MESSAGE_WITH_HEADER); add_native_detour(RAGE_JOAAT("maintransition"), 0x6F3D4ED9BEE4E61D, network::NETWORK_SESSION_HOST); add_native_detour(RAGE_JOAAT("am_launcher"), 0xB8BA7F44DF1575E1, am_launcher::START_NEW_SCRIPT_WITH_ARGS); + add_native_detour(RAGE_JOAAT("am_launcher"), 0x5D10B3795F3FC886, freemode::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA); add_native_detour(RAGE_JOAAT("fm_race_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH); add_native_detour(RAGE_JOAAT("fm_capture_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH); diff --git a/src/pointers.cpp b/src/pointers.cpp index 52e9e10f..7f701513 100644 --- a/src/pointers.cpp +++ b/src/pointers.cpp @@ -672,12 +672,60 @@ namespace big m_invalid_decal_crash = ptr.add(1).rip().as(); }); + // Encode Session Info + main_batch.add("ESI", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 20 57 48 81", [this](memory::handle ptr) + { + m_encode_session_info = ptr.as(); + }); + + // Decode Session Info + main_batch.add("DSI", "48 89 5C 24 08 48 89 6C 24 10 56 57 41 56 48 81 EC C0", [this](memory::handle ptr) + { + m_decode_session_info = ptr.as(); + }); + + // Can Start Session Joining Check + main_batch.add("CSSJC", "77 DB ? ? ? ? ? ? ? 74 09", [this](memory::handle ptr) + { + memory::byte_patch::make(ptr.as(), std::to_array({ 0x90, 0x90 }))->apply(); // join faster + }); + + // Can Start Joining Joining Check + main_batch.add("CSJJC", "74 16 48 8B 0B E8 ? ? ? ? 84 C0", [this](memory::handle ptr) + { + memory::byte_patch::make(ptr.as(), 0xEB)->apply(); // join faster + }); + // NTQVM Caller main_batch.add("NTQVMC", "66 0F 6F 0D ? ? ? ? 66 0F 6F 05 ? ? ? ? 66 0F 66 C4", [this](memory::handle ptr) { memory::byte_patch::make(ptr.add(4).rip().sub(32).as(), (uint64_t)&hooks::nt_query_virtual_memory)->apply(); }); + // Main File Object + main_batch.add("MFO", "48 8D 05 ? ? ? ? 48 8D 1C D0 EB 03", [this](memory::handle ptr) + { + m_main_file_object = ptr.add(3).rip().as(); + }); + + // Load Cloud File + main_batch.add("LCF", "48 89 5C 24 08 48 89 74 24 10 57 48 83 EC 40 48 8B F2 48 8B D9 41 8B D0", [this](memory::handle ptr) + { + m_load_cloud_file = ptr.as(); + }); + + // Set As Active Cloud File + main_batch.add("SAACF", "48 83 EC 28 45 33 C0 4C 39", [this](memory::handle ptr) + { + m_set_as_active_cloud_file = ptr.as(); + }); + + // Save JSON Data + main_batch.add("SJD", "48 89 5C 24 08 57 48 83 EC 30 33 DB 48 8B FA 48", [this](memory::handle ptr) + { + m_save_json_data = ptr.as(); + }); + auto mem_region = memory::module("GTA5.exe"); main_batch.run(mem_region); diff --git a/src/pointers.hpp b/src/pointers.hpp index 8c0493a5..e224cb93 100644 --- a/src/pointers.hpp +++ b/src/pointers.hpp @@ -204,6 +204,14 @@ namespace big PVOID m_write_bitbuffer_gamer_handle; PVOID m_read_bitbuffer_gamer_handle; + + functions::encode_session_info m_encode_session_info; + functions::decode_session_info m_decode_session_info; + + datafile_commands::SveFileObject* m_main_file_object; + functions::load_cloud_file m_load_cloud_file; + functions::set_as_active_cloud_file m_set_as_active_cloud_file; + functions::save_json_data m_save_json_data; }; inline pointers* g_pointers{}; diff --git a/src/script_function.cpp b/src/script_function.cpp index 30b232ee..d521f74c 100644 --- a/src/script_function.cpp +++ b/src/script_function.cpp @@ -60,6 +60,24 @@ namespace big tls_ctx->m_is_script_thread_active = og_thread != nullptr; } + void script_function::static_call(std::initializer_list args) + { + populate_ip(); + + rage::scrThread* thread = (rage::scrThread*)new uint8_t[sizeof(rage::scrThread)]; + memcpy(thread, rage::scrThread::get(), sizeof(rage::scrThread)); + + void* stack = new uint64_t[25000]; + thread->m_stack = stack; + thread->m_context.m_stack_size = 25000; + thread->m_context.m_stack_pointer = 1; + + 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 + } + void script_function::operator()(std::initializer_list args) { populate_ip(); diff --git a/src/script_function.hpp b/src/script_function.hpp index a8200b73..ec115da3 100644 --- a/src/script_function.hpp +++ b/src/script_function.hpp @@ -17,6 +17,10 @@ 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); + + // for pure functions that do not need access to thread stack + void static_call(std::initializer_list args); + void operator()(std::initializer_list args); }; @@ -25,5 +29,8 @@ namespace big static inline script_function join_ceo("JC", RAGE_JOAAT("freemode"), "2D 04 1D 00 00 5D", 0); static inline script_function dance_loop("DL", RAGE_JOAAT("am_mp_nightclub"), "2D 00 14 00 00 4F ? ? 47 ? ? 5D ? ? ? 56", 0); static inline script_function init_nightclub_script("INS", RAGE_JOAAT("am_mp_nightclub"), "2D 00 11 00 00 4F", 0); + + 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); } } \ No newline at end of file diff --git a/src/services/creator_storage/creator_storage_service.cpp b/src/services/creator_storage/creator_storage_service.cpp new file mode 100644 index 00000000..bc48e05c --- /dev/null +++ b/src/services/creator_storage/creator_storage_service.cpp @@ -0,0 +1,91 @@ +#include "gta/joaat.hpp" +#include "creator_storage_service.hpp" +#include "pointers.hpp" +#include "gta/tls_context.hpp" +#include "natives.hpp" +#include "gta/sysMemAllocator.hpp" +#include "script.hpp" +#include "script_function.hpp" + +namespace big +{ + std::vector creator_storage_service::list_files() + { + std::vector file_paths; + + const auto file_path = check_jobs_folder(); + for (const auto& directory_entry : std::filesystem::directory_iterator(file_path.get_path())) + if (directory_entry.path().extension() == ".json") + file_paths.push_back(directory_entry.path().filename().generic_string()); + + return file_paths; + } + + void creator_storage_service::create_file(std::string file) + { + std::ofstream(check_jobs_folder().get_file(file).get_path()); + } + + void creator_storage_service::save_file(std::string_view filename) + { + std::ofstream file(check_jobs_folder().get_file(filename).get_path()); + + while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(RAGE_JOAAT("fm_race_creator"))) + { + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("fm_race_creator")); + script::get_current()->yield(); + } + + char* storage = new char[0x50000]; + scr_functions::save_to_datafile.static_call({ (uint64_t)storage }); + delete[] storage; + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("fm_race_creator")); + + auto buffer = g_pointers->m_save_json_data(g_pointers->m_main_file_object, nullptr, "to save it to a file I guess?"); + + if (!buffer) + { + g_notification_service->push_error("Save Job", "Cannot obtain JSON data"); + return; + } + + file << buffer; + file.close(); + + rage::tlsContext::get()->m_allocator->Free(buffer); + } + + void creator_storage_service::load_file(std::string_view file_name) + { + const auto file = check_jobs_folder().get_file(file_name); + + std::ifstream file_stream(file.get_path()); + std::string buffer(std::istreambuf_iterator{file_stream}, {}); + + if (DATAFILE::DATAFILE_GET_FILE_DICT(0) != nullptr) + DATAFILE::DATAFILE_DELETE(0); + + sCloudFile* cloud_file = nullptr; + g_pointers->m_load_cloud_file(&cloud_file, buffer.data(), buffer.length(), "to load it from a file I guess?"); + g_pointers->m_set_as_active_cloud_file(g_pointers->m_main_file_object, &cloud_file); + + while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(RAGE_JOAAT("fm_race_creator"))) + { + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("fm_race_creator")); + script::get_current()->yield(); + } + + scr_functions::load_from_datafile.static_call({ 1, true, false, 0 }); + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("fm_race_creator")); + file_stream.close(); + } + + big::folder creator_storage_service::check_jobs_folder() + { + const auto folder = g_file_manager->get_project_folder("./jobs"); + + return folder; + } +} diff --git a/src/services/creator_storage/creator_storage_service.hpp b/src/services/creator_storage/creator_storage_service.hpp new file mode 100644 index 00000000..b9abf44a --- /dev/null +++ b/src/services/creator_storage/creator_storage_service.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "natives.hpp" + +namespace big +{ + class creator_storage_service + { + public: + static std::vector list_files(); + + static void create_file(std::string name); + static void load_file(std::string_view file_name); + static void save_file(std::string_view file_name); + + private: + static big::folder check_jobs_folder(); + }; +} \ No newline at end of file diff --git a/src/services/gui/gui_service.hpp b/src/services/gui/gui_service.hpp index 92517355..318b0214 100644 --- a/src/services/gui/gui_service.hpp +++ b/src/services/gui/gui_service.hpp @@ -26,6 +26,7 @@ namespace big WORLD, SPAWN_PED, TIME_AND_WEATHER, + CREATOR, NETWORK, SESSION, @@ -76,6 +77,7 @@ namespace big { tabs::WORLD, { "World", nullptr, { { tabs::SPAWN_PED, { "Spawn Ped", view::spawn_ped }}, { tabs::TIME_AND_WEATHER, { "Time And Weather", view::time_and_weather }}, + { tabs::CREATOR, { "Creator", view::creator }} }}}, {tabs::NETWORK, { "Network", nullptr, { { tabs::SPOOFING, { "Spoofing", view::spoofing }}, diff --git a/src/util/scripts.hpp b/src/util/scripts.hpp index 5df7e9cb..21923241 100644 --- a/src/util/scripts.hpp +++ b/src/util/scripts.hpp @@ -210,7 +210,7 @@ incorrect: return; } - if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(51000) == 0) + if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(54000) == 0) { g_notification_service->push_warning("Creator", "No free stacks for MISSION stack size"); } @@ -226,7 +226,7 @@ incorrect: *scr_globals::mission_creator_exited.as() = false; *scr_globals::mission_creator_radar_follows_camera.as() = true; - if (SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(hash, 51000)) + if (SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(hash, 54000)) { g->m_mission_creator_thread = gta_util::find_script_thread(hash); } diff --git a/src/util/toxic.hpp b/src/util/toxic.hpp index bdee015a..56383c2f 100644 --- a/src/util/toxic.hpp +++ b/src/util/toxic.hpp @@ -32,6 +32,30 @@ namespace big::toxic blame_explode_coord(to_blame, coords, explosion_type, damage, is_audible, is_invisible, camera_shake); } + inline void ceo_kick(player_ptr target) + { + auto leader = *scr_globals::gpbd_fm_3.at(target->id(), scr_globals::size::gpbd_fm_3).at(10).as(); + + if (leader == -1) + g_notification_service->push_warning("CEO Kick", "Player is not in a CEO/MC"); + else if (leader == target->id()) + { + g_notification_service->push_error("CEO Kick", "Cannot kick leader of CEO/MC anymore"); + } + else + { + // use a more private method to remove associate + const size_t arg_count = 3; + int64_t args[arg_count] = { + (int64_t)eRemoteEvent::MarkPlayerAsBeast, + (int64_t)self::id, + leader + }; + + g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id()); + } + } + inline void send_player_to_island(player_ptr target) { const size_t arg_count = 2; @@ -168,14 +192,14 @@ namespace big::toxic if (wanted_level > 0) { - *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as() = id; - *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as() = wanted_level; + *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(214).as() = id; + *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(215).as() = wanted_level; for (int i = 0; PLAYER::GET_PLAYER_WANTED_LEVEL(id) < wanted_level && i < 3600; i++) script::get_current()->yield(1ms); - *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as() = -1; // reset to prevent wanted from being constantly set - *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as() = -1; + *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(214).as() = -1; // reset to prevent wanted from being constantly set + *scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(215).as() = -1; } } diff --git a/src/views/network/view_session.cpp b/src/views/network/view_session.cpp index 7fc6d536..f460c7e7 100644 --- a/src/views/network/view_session.cpp +++ b/src/views/network/view_session.cpp @@ -8,6 +8,7 @@ #include "util/toxic.hpp" #include "core/data/apartment_names.hpp" #include "core/data/warehouse_names.hpp" +#include namespace big { @@ -20,6 +21,22 @@ namespace big session::join_by_rockstar_id(rid); }); + static char base64[500]{}; + ImGui::InputText("Session Info", base64, sizeof(base64)); + components::button("Join Session Info", [] + { + rage::rlSessionInfo info; + g_pointers->m_decode_session_info(&info, base64, nullptr); + session::join_session(info); + }); + ImGui::SameLine(); + components::button("Copy Current Session Info", [] + { + char buf[0x100]; + g_pointers->m_encode_session_info(>a_util::get_network()->m_game_session.m_rline_session.m_session_info, buf, 0x7D, nullptr); + ImGui::SetClipboardText(buf); + }); + components::sub_title("Session Switcher"); if (ImGui::ListBoxHeader("###session_switch")) { @@ -163,6 +180,14 @@ namespace big ImGui::SameLine(); components::button("Remove All Weapons", [] { g_player_service->iterate([](auto& plyr) { toxic::remove_all_weapons(plyr.second); }); }); + components::button("CEO Kick", [] { + g_player_service->iterate([](auto& plyr) + { + if (*scr_globals::gpbd_fm_3.at(plyr.second->id(), scr_globals::size::gpbd_fm_3).at(10).as() != -1) + toxic::ceo_kick(plyr.second); + }); + }); + components::small_text("Teleports"); if (ImGui::BeginCombo("##apartment", apartment_names[g->session.send_to_apartment_idx])) @@ -262,10 +287,10 @@ namespace big ImGui::SameLine(); ImGui::BeginGroup(); - components::button("One-On-One Deathmatch", [] { scripts::start_launcher_script(187); }); + components::button("One-On-One Deathmatch", [] { scripts::start_launcher_script(197); }); components::button("Impromptu Race", [] { scripts::start_launcher_script(16); }); - components::button("Flight School", [] { scripts::start_launcher_script(186); }); - components::button("Golf", [] { scripts::start_launcher_script(183); }); + components::button("Flight School", [] { scripts::start_launcher_script(196); }); + components::button("Golf", [] { scripts::start_launcher_script(193); }); components::button("Tutorial", [] { scripts::start_launcher_script(20); }); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Only works on joining players"); @@ -274,11 +299,11 @@ namespace big ImGui::SameLine(); ImGui::BeginGroup(); - components::button("Gunslinger", [] { scripts::start_launcher_script(201); }); - components::button("Space Monkey", [] { scripts::start_launcher_script(206); }); - components::button("Wizard", [] { scripts::start_launcher_script(202); }); - components::button("QUB3D", [] { scripts::start_launcher_script(207); }); - components::button("Camhedz", [] { scripts::start_launcher_script(208); }); + components::button("Gunslinger", [] { scripts::start_launcher_script(211); }); + components::button("Space Monkey", [] { scripts::start_launcher_script(216); }); + components::button("Wizard", [] { scripts::start_launcher_script(212); }); + components::button("QUB3D", [] { scripts::start_launcher_script(217); }); + components::button("Camhedz", [] { scripts::start_launcher_script(218); }); ImGui::EndGroup(); ImGui::Checkbox("Disable Pedestrians", &g->session.disable_peds); diff --git a/src/views/network/view_session_browser.cpp b/src/views/network/view_session_browser.cpp index f0e8fbd3..88cda7fb 100644 --- a/src/views/network/view_session_browser.cpp +++ b/src/views/network/view_session_browser.cpp @@ -16,6 +16,7 @@ namespace big { static char name_buf[32]; static char search[64]; + static char session_info[255]; ImGui::SetNextItemWidth(300.f); @@ -31,6 +32,7 @@ namespace big if (components::selectable(std::to_string(g_matchmaking_service->get_found_sessions()[i].info.m_session_token), i == selected_session_idx)) { selected_session_idx = i; + g_pointers->m_encode_session_info(&g_matchmaking_service->get_found_sessions()[i].info, session_info, 0x7D, nullptr); } } } @@ -57,12 +59,17 @@ namespace big auto& data = session.info.m_net_player_data; ImGui::Text("Host Rockstar ID: %d", data.m_gamer_handle.m_rockstar_id); + components::button("Copy Session Info", [] + { + ImGui::SetClipboardText(session_info); + }); + ImGui::SameLine(); components::button("Join", [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."); + g_notification_service->push_error("Join Session", "Player switch in progress, wait a bit."); return; } diff --git a/src/views/players/player/player_toxic.cpp b/src/views/players/player/player_toxic.cpp index c1adecac..7d8f596a 100644 --- a/src/views/players/player/player_toxic.cpp +++ b/src/views/players/player/player_toxic.cpp @@ -15,12 +15,13 @@ namespace big toxic::kill_player(g_player_service->get_selected(), g_player_service->get_self()); }); + components::button("CEO Kick", [] { toxic::ceo_kick(g_player_service->get_selected()); }); + components::button("Kick From Vehicle", [] { toxic::kick_player_from_vehicle(g_player_service->get_selected()); }); ImGui::SameLine(); components::button("Ragdoll Player", [] { toxic::ragdoll_player(g_player_service->get_selected()); }); components::button("Kick From Interior", [] { toxic::kick_player_from_interior(g_player_service->get_selected()); }); - ImGui::SameLine(); components::button("Turn Into Beast", [] { toxic::turn_player_into_beast(g_player_service->get_selected()); }); static int wanted_level; diff --git a/src/views/self/view_self.cpp b/src/views/self/view_self.cpp index 797c5e6b..01459100 100644 --- a/src/views/self/view_self.cpp +++ b/src/views/self/view_self.cpp @@ -214,14 +214,6 @@ namespace big ImGui::EndGroup(); - components::sub_title("Launch Creator"); - ImGui::BeginGroup(); - components::button("Race", [] { scripts::start_creator_script(RAGE_JOAAT("fm_race_creator")); }); ImGui::SameLine(); - components::button("Capture", [] { scripts::start_creator_script(RAGE_JOAAT("fm_capture_creator")); }); ImGui::SameLine(); - components::button("Deathmatch", [] { scripts::start_creator_script(RAGE_JOAAT("fm_deathmatch_creator")); }); ImGui::SameLine(); - components::button("LTS", [] { scripts::start_creator_script(RAGE_JOAAT("fm_lts_creator")); }); - ImGui::EndGroup(); - g->self.proof_mask = 0; if (g->self.god_mode) { diff --git a/src/views/view.hpp b/src/views/view.hpp index 6be48d74..c249fe64 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -46,6 +46,7 @@ namespace big static void weapons(); static void context_menu(); static void gta_data(); + static void creator(); static void player_info(); static void player_troll(); diff --git a/src/views/world/view_creator.cpp b/src/views/world/view_creator.cpp new file mode 100644 index 00000000..9318123d --- /dev/null +++ b/src/views/world/view_creator.cpp @@ -0,0 +1,85 @@ +#include "fiber_pool.hpp" +#include "script.hpp" +#include "views/view.hpp" +#include "services/creator_storage/creator_storage_service.hpp" +#include "util/scripts.hpp" + +static bool cached_creator_files = false; +static std::vector creator_files; + +namespace big +{ + void view::creator() + { + static std::string selected_creator_file = ""; + if (!cached_creator_files) + { + creator_files = creator_storage_service::list_files(); + cached_creator_files = true; + } + + ImGui::PushItemWidth(250); + components::sub_title("Saved Jobs"); + + if (ImGui::ListBoxHeader("##empty", ImVec2(200, 200))) + { + for (const auto& pair : creator_files) + { + if (ImGui::Selectable(pair.c_str(), selected_creator_file == pair)) + selected_creator_file = pair; + } + + ImGui::ListBoxFooter(); + } + + ImGui::SameLine(); + + ImGui::BeginGroup(); + + if (!selected_creator_file.empty()) + { + components::button("Save To File", [] + { + creator_storage_service::save_file(selected_creator_file); + }); + + ImGui::SameLine(); + + components::button("Load From File", [] + { + creator_storage_service::load_file(selected_creator_file); + }); + } + + static char job_file_name_input[50]{}; + + ImGui::PushItemWidth(250); + components::input_text_with_hint( + "Job Name", + "Ex: My Cool Job", + job_file_name_input, IM_ARRAYSIZE(job_file_name_input)); + + components::button("Create Job File", [] + { + cached_creator_files = false; + creator_storage_service::create_file(std::string(job_file_name_input) + ".json"); + }); + + ImGui::SameLine(); + + components::button("Refresh", [] + { + cached_creator_files = false; + }); + + ImGui::EndGroup(); + + components::sub_title("Launch Creator"); + ImGui::BeginGroup(); + components::button("Race", [] { scripts::start_creator_script(RAGE_JOAAT("fm_race_creator")); }); ImGui::SameLine(); + components::button("Capture", [] { scripts::start_creator_script(RAGE_JOAAT("fm_capture_creator")); }); ImGui::SameLine(); + components::button("Deathmatch", [] { scripts::start_creator_script(RAGE_JOAAT("fm_deathmatch_creator")); }); ImGui::SameLine(); + components::button("LTS", [] { scripts::start_creator_script(RAGE_JOAAT("fm_lts_creator")); }); + ImGui::EndGroup(); + } +}