Save creator jobs and bug fixes (#713)

* feat(Session): Session info serialization
* feat(Creator): Save and load jobs to file
* fix(Creator): Actually load the job
* fix(Creator): Try to fix loading
* fix(ScriptFunction): Fix memory corruption due to low stack size
* fix(Creator): Fix "No translation."
* fix(NativeHooks): Fix softlock when loading Cayo Perico
* chore(Toxic): Remove net time test for now
This commit is contained in:
maybegreat48 2022-12-17 14:47:01 +00:00 committed by GitHub
parent 7da9427128
commit 792d765ffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 389 additions and 46 deletions

View File

@ -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<eTransitionState*>();
const auto state = *scr_globals::transition_state.as<eTransitionState*>();
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
return;

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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<int*>() = 4;
src->set_return_value<BOOL>(TRUE);
}
void NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(rage::scrNativeCallContext* src)
{
if (rage::scrThread::get() && rage::scrThread::get()->m_handler)

View File

@ -41,5 +41,21 @@ namespace big
if ((!g->m_mission_creator_thread) || src->get_arg<Blip>(0) != HUD::GET_MAIN_PLAYER_BLIP_ID())
HUD::SET_BLIP_DISPLAY(src->get_arg<Blip>(0), src->get_arg<BOOL>(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<int*>() = 4;
src->set_return_value<BOOL>(TRUE);
}
}
}

View File

@ -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);

View File

@ -672,12 +672,60 @@ namespace big
m_invalid_decal_crash = ptr.add(1).rip().as<PVOID>();
});
// 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<functions::encode_session_info>();
});
// 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<functions::decode_session_info>();
});
// Can Start Session Joining Check
main_batch.add("CSSJC", "77 DB ? ? ? ? ? ? ? 74 09", [this](memory::handle ptr)
{
memory::byte_patch::make(ptr.as<void*>(), 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<uint8_t*>(), 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*>(), (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<datafile_commands::SveFileObject*>();
});
// 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<functions::load_cloud_file>();
});
// 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<functions::set_as_active_cloud_file>();
});
// 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<functions::save_json_data>();
});
auto mem_region = memory::module("GTA5.exe");
main_batch.run(mem_region);

View File

@ -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{};

View File

@ -60,6 +60,24 @@ namespace big
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
}
void script_function::static_call(std::initializer_list<std::uint64_t> 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<std::uint64_t> args)
{
populate_ip();

View File

@ -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<std::uint64_t> args);
// for pure functions that do not need access to thread stack
void static_call(std::initializer_list<std::uint64_t> args);
void operator()(std::initializer_list<std::uint64_t> 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);
}
}

View File

@ -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<std::string> creator_storage_service::list_files()
{
std::vector<std::string> 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<char>{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;
}
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "natives.hpp"
namespace big
{
class creator_storage_service
{
public:
static std::vector<std::string> 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();
};
}

View File

@ -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 }},

View File

@ -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<bool*>() = false;
*scr_globals::mission_creator_radar_follows_camera.as<bool*>() = 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);
}

View File

@ -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<int*>();
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<Player*>() = id;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = wanted_level;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(214).as<Player*>() = id;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(215).as<int*>() = 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<Player*>() = -1; // reset to prevent wanted from being constantly set
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = -1;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(214).as<Player*>() = -1; // reset to prevent wanted from being constantly set
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(215).as<int*>() = -1;
}
}

View File

@ -8,6 +8,7 @@
#include "util/toxic.hpp"
#include "core/data/apartment_names.hpp"
#include "core/data/warehouse_names.hpp"
#include <network/Network.hpp>
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(&gta_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<int*>() != -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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();

View File

@ -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<std::string> 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();
}
}