From d4d504dca2c3f4b456ff7ce7a71fdea422d0ad40 Mon Sep 17 00:00:00 2001 From: Andreas Maerten <24669514+Yimura@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:54:25 +0100 Subject: [PATCH] feat: Add menu onboarding to YimMenu (#2492) --- .../commands/system/external_console.cpp | 17 ++++ src/core/settings.cpp | 11 --- src/core/settings.hpp | 7 +- src/gta_pointers.hpp | 4 +- src/gui.cpp | 44 ++++++++-- src/logger/logger.cpp | 74 ++++++----------- src/logger/logger.hpp | 44 +++++----- src/main.cpp | 18 ++-- src/views/core/view_onboarding.cpp | 83 +++++++++++++++++++ src/views/debug/view_debug_misc.cpp | 2 + src/views/view.hpp | 5 +- 11 files changed, 205 insertions(+), 104 deletions(-) create mode 100644 src/backend/commands/system/external_console.cpp create mode 100644 src/views/core/view_onboarding.cpp diff --git a/src/backend/commands/system/external_console.cpp b/src/backend/commands/system/external_console.cpp new file mode 100644 index 00000000..6a2c42cb --- /dev/null +++ b/src/backend/commands/system/external_console.cpp @@ -0,0 +1,17 @@ +#include "backend/bool_command.hpp" + +namespace big +{ + class external_console : bool_command + { + using bool_command::bool_command; + + virtual void refresh() override + { + g_log.toggle_external_console(m_toggle); + } + }; + + external_console + g_external_console("external_console", "BACKEND_EXTERNAL_CONSOLE", "BACKEND_EXTERNAL_CONSOLE_DESC", g.debug.external_console); +} diff --git a/src/core/settings.cpp b/src/core/settings.cpp index e1424fd1..40d457d4 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -8,17 +8,6 @@ namespace big { m_save_file = save_file; load(); - - g_thread_pool->push([this] { - while (!g_running) - std::this_thread::yield(); - - while (g_running) - { - std::this_thread::sleep_for(100ms); - attempt_save(); - } - }); } void menu_settings::attempt_save() diff --git a/src/core/settings.hpp b/src/core/settings.hpp index a68aa87a..44f7f9f6 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -122,9 +122,11 @@ namespace big int thread_id = 0; std::int16_t syncing_object_id = -1; } fuzzer{}; + + bool external_console = true; bool window_hook = false; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(debug, logs, window_hook) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(debug, logs, external_console, window_hook) } debug{}; struct tunables @@ -453,6 +455,7 @@ namespace big struct settings { + bool onboarding_complete = false; bool dev_dlc = false; struct hotkeys @@ -489,7 +492,7 @@ namespace big NLOHMANN_DEFINE_TYPE_INTRUSIVE(hotkeys, editing_menu_toggle, menu_toggle, teleport_waypoint, teleport_objective, teleport_selected, teleport_pv, noclip, vehicle_flymode, bringvehicle, invis, heal, fill_inventory, skip_cutscene, freecam, superrun, passive, superjump, beastjump, invisveh, localinvisveh, fill_ammo, fast_quit, cmd_excecutor, repairpv, open_vehicle_controller, clear_wanted, random_ped_components) } hotkeys{}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(settings, hotkeys, dev_dlc) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(settings, hotkeys, dev_dlc, onboarding_complete) } settings{}; struct spawn_vehicle diff --git a/src/gta_pointers.hpp b/src/gta_pointers.hpp index 147f40a7..050470e1 100644 --- a/src/gta_pointers.hpp +++ b/src/gta_pointers.hpp @@ -363,8 +363,8 @@ namespace big functions::get_ped_seat m_get_ped_seat; functions::received_clone_remove m_received_clone_remove; - - CWeaponInfoManager* m_weapon_info_manager; + + CWeaponInfoManager* m_weapon_info_manager; }; #pragma pack(pop) static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); diff --git a/src/gui.cpp b/src/gui.cpp index 7849be49..49704672 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -10,19 +10,49 @@ namespace big { + /** + * @brief The later an entry comes in this enum to higher up it comes in the z-index. + */ + enum eRenderPriority + { + // low priority + ESP, + CONTEXT_MENU, + + // medium priority + MENU = 0x1000, + VEHICLE_CONTROL, + + // high priority + INFO_OVERLAY = 0x2000, + CMD_EXECUTOR, + + GTA_DATA_CACHE = 0x3000, + ONBOARDING, + + // should remain in a league of its own + NOTIFICATIONS = 0x4000, + }; + gui::gui() : m_is_open(false), m_override_mouse(false) { - g_renderer.add_dx_callback(view::gta_data, -1); - g_renderer.add_dx_callback(view::notifications, -2); - g_renderer.add_dx_callback(view::overlay, -3); - g_renderer.add_dx_callback(view::cmd_executor, -4); + g_renderer.add_dx_callback(view::notifications, eRenderPriority::NOTIFICATIONS); + g_renderer.add_dx_callback(view::onboarding, eRenderPriority::ONBOARDING); + g_renderer.add_dx_callback(view::gta_data, eRenderPriority::GTA_DATA_CACHE); + g_renderer.add_dx_callback(view::cmd_executor, eRenderPriority::CMD_EXECUTOR); + g_renderer.add_dx_callback(view::overlay, eRenderPriority::INFO_OVERLAY); + + g_renderer.add_dx_callback(view::vehicle_control, eRenderPriority::VEHICLE_CONTROL); + g_renderer.add_dx_callback(esp::draw, eRenderPriority::ESP); // TODO: move to ESP service + g_renderer.add_dx_callback(view::context_menu, eRenderPriority::CONTEXT_MENU); + g_renderer.add_dx_callback( [this] { dx_on_tick(); }, - -5); + eRenderPriority::MENU); g_renderer.add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { wndproc(hwnd, msg, wparam, lparam); @@ -34,10 +64,6 @@ namespace big } }); - g_renderer.add_dx_callback(view::vehicle_control, 3); - 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/logger/logger.cpp b/src/logger/logger.cpp index 67200f08..b30652e9 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -1,5 +1,5 @@ -#pragma once #include "logger.hpp" + #include "util/is_proton.hpp" namespace big @@ -12,34 +12,39 @@ namespace big return system_clock::to_time_t(sctp); } - logger::logger(std::string_view console_title, file file, bool attach_console) : - m_attach_console(attach_console), - m_did_console_exist(false), - m_console_logger(&logger::format_console), - m_console_title(console_title), - m_original_console_mode(0), - m_console_handle(nullptr), - m_file(file) + void logger::initialize(const std::string_view console_title, file file, bool attach_console) { + m_console_title = console_title; + m_file = file; if (is_proton()) { LOG(VERBOSE) << "Using simple logger."; m_console_logger = &logger::format_console_simple; } - initialize(); + toggle_external_console(attach_console); + create_backup(); + m_file_out.open(m_file.get_path(), std::ios_base::out | std::ios_base::trunc); - g_log = this; + Logger::Init(); + Logger::AddSink([this](LogMessagePtr msg) { + (this->*m_console_logger)(std::move(msg)); + }); + Logger::AddSink([this](LogMessagePtr msg) { + format_file(std::move(msg)); + }); } - logger::~logger() + void logger::destroy() { - g_log = nullptr; + Logger::Destroy(); + m_file_out.close(); + toggle_external_console(false); } - void logger::initialize() + void logger::toggle_external_console(bool toggle) { - if (m_attach_console) + if (toggle) { if (m_did_console_exist = ::AttachConsole(GetCurrentProcessId()); !m_did_console_exist) AllocConsole(); @@ -60,28 +65,17 @@ namespace big SetConsoleMode(m_console_handle, console_mode); } + + m_console_out.open("CONOUT$", std::ios_base::out | std::ios_base::app); + + return; } - create_backup(); - open_outstreams(); - - Logger::Init(); - Logger::AddSink([this](LogMessagePtr msg) { - (this->*m_console_logger)(std::move(msg)); - }); - Logger::AddSink([this](LogMessagePtr msg) { - format_file(std::move(msg)); - }); - } - - void logger::destroy() - { - Logger::Destroy(); - close_outstreams(); + m_console_out.close(); if (m_did_console_exist) SetConsoleMode(m_console_handle, m_original_console_mode); - if (!m_did_console_exist && m_attach_console) + if (!m_did_console_exist) FreeConsole(); } @@ -104,22 +98,6 @@ namespace big } } - void logger::open_outstreams() - { - if (m_attach_console) - m_console_out.open("CONOUT$", std::ios_base::out | std::ios_base::app); - - m_file_out.open(m_file.get_path(), std::ios_base::out | std::ios_base::trunc); - } - - void logger::close_outstreams() - { - if (m_attach_console) - m_console_out.close(); - - m_file_out.close(); - } - const LogColor get_color(const eLogLevel level) { switch (level) diff --git a/src/logger/logger.hpp b/src/logger/logger.hpp index 772f1baf..647ae01b 100644 --- a/src/logger/logger.hpp +++ b/src/logger/logger.hpp @@ -25,38 +25,38 @@ namespace big class logger final { - public: - logger(std::string_view console_title, file file, bool attach_console = true); - virtual ~logger(); - - void initialize(); - void destroy(); - private: - void create_backup(); + bool m_attach_console = true; + bool m_did_console_exist = false; - void open_outstreams(); - void close_outstreams(); - - void format_console(const LogMessagePtr msg); - void format_console_simple(const LogMessagePtr msg); - void format_file(const LogMessagePtr msg); - - private: - bool m_attach_console; - bool m_did_console_exist; - - void (logger::*m_console_logger)(const LogMessagePtr msg); + void (logger::*m_console_logger)(const LogMessagePtr msg) = &logger::format_console; std::string_view m_console_title; - DWORD m_original_console_mode; + DWORD m_original_console_mode = 0; HANDLE m_console_handle; std::ofstream m_console_out; std::ofstream m_file_out; file m_file; + + public: + logger() = default; + virtual ~logger() = default; + + void initialize(const std::string_view console_title, file file, bool attach_console = true); + void destroy(); + + void toggle_external_console(bool toggle); + + private: + void create_backup(); + + void format_console(const LogMessagePtr msg); + void format_console_simple(const LogMessagePtr msg); + void format_file(const LogMessagePtr msg); + }; - inline logger* g_log = nullptr; + inline logger g_log{}; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c9633de6..c57bc289 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -142,6 +142,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) 0, [](PVOID) -> DWORD { auto handler = exception_handler(); + std::srand(std::chrono::system_clock::now().time_since_epoch().count()); while (!FindWindow("grcWindow", nullptr)) std::this_thread::sleep_for(100ms); @@ -150,11 +151,10 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) base_dir /= "YimMenu"; g_file_manager.init(base_dir); - auto logger_instance = std::make_unique("YimMenu", g_file_manager.get_project_file("./cout.log")); + g.init(g_file_manager.get_project_file("./settings.json")); + LOG(INFO) << "Settings Loaded."; - EnableMenuItem(GetSystemMenu(GetConsoleWindow(), 0), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); - - std::srand(std::chrono::system_clock::now().time_since_epoch().count()); + g_log.initialize("YimMenu", g_file_manager.get_project_file("./cout.log"), g.debug.external_console); LOG(INFO) << "Yim's Menu Initializing"; LOGF(INFO, "Git Info\n\tBranch:\t{}\n\tHash:\t{}\n\tDate:\t{}", version::GIT_BRANCH, version::GIT_SHA1, version::GIT_DATE); @@ -179,9 +179,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto thread_pool_instance = std::make_unique(); LOG(INFO) << "Thread pool initialized."; - g.init(g_file_manager.get_project_file("./settings.json")); - LOG(INFO) << "Settings Loaded."; - auto pointers_instance = std::make_unique(); LOG(INFO) << "Pointers initialized."; @@ -266,7 +263,11 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) g_running = true; while (g_running) + { + g.attempt_save(); + std::this_thread::sleep_for(500ms); + } g_script_mgr.remove_all_scripts(); LOG(INFO) << "Scripts unregistered."; @@ -340,8 +341,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) LOG(INFO) << "Thread pool uninitialized."; LOG(INFO) << "Farewell!"; - logger_instance->destroy(); - logger_instance.reset(); + g_log.destroy(); CloseHandle(g_main_thread); FreeLibraryAndExitThread(g_hmodule, 0); diff --git a/src/views/core/view_onboarding.cpp b/src/views/core/view_onboarding.cpp new file mode 100644 index 00000000..5fdc9be0 --- /dev/null +++ b/src/views/core/view_onboarding.cpp @@ -0,0 +1,83 @@ +#include "gui.hpp" +#include "pointers.hpp" +#include "views/view.hpp" +#include "widgets/imgui_hotkey.hpp" + +namespace big +{ + void select_language() + { + ImGui::SeparatorText("ONBOARDING_SET_LANGUAGE"_T.data()); + + const auto& language_entries = g_translation_service.available_translations(); + const auto& current_pack = g_translation_service.current_language_pack(); + if (language_entries.contains(current_pack) + && ImGui::BeginCombo("VIEW_SETTINGS_MENU_LANGUAGE"_T.data(), language_entries.at(current_pack).name.c_str())) + { + for (auto& i : language_entries) + { + if (ImGui::Selectable(i.second.name.c_str(), i.first == current_pack)) + g_translation_service.select_language_pack(i.first); + + if (i.first == current_pack) + { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + } + + void select_menu_open_key() + { + ImGui::SeparatorText("ONBOARDING_SET_MENU_OPEN_KEY"_T.data()); + if (ImGui::Hotkey("VIEW_HOTKEY_SETTINGS_MENU_TOGGLE"_T.data(), &g.settings.hotkeys.menu_toggle)) + { + g_notification_service->push("ONBOARDING_NOTIFICATION_TITLE"_T.data(), "ONBOARDING_NOTIFICATION_OPEN_KEY"_T.data()); + } + } + + void developer_console() + { + ImGui::SeparatorText("ONBOARDING_ENABLE_DEVELOPER_CONSOLE"_T.data()); + components::command_checkbox<"external_console">(); + } + + void view::onboarding() + { + static bool onboarding_open = false; + if (g.settings.onboarding_complete) + { + return; + } + + if (!onboarding_open) + { + g_gui->toggle(true); + ImGui::OpenPopup("ONBOARDING_WELCOME_TITLE"_T.data()); + onboarding_open = true; + } + + const auto window_size = ImVec2{600, 400}; + const auto window_position = ImVec2{(*g_pointers->m_gta.m_resolution_x - window_size.x) / 2, + (*g_pointers->m_gta.m_resolution_y - window_size.y) / 2}; + + ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); + ImGui::SetNextWindowPos(window_position, ImGuiCond_Always); + + if (ImGui::BeginPopupModal("ONBOARDING_WELCOME_TITLE"_T.data())) + { + select_language(); + select_menu_open_key(); + developer_console(); + + if (ImGui::Button("CLOSE"_T.data())) + { + g.settings.onboarding_complete = true; + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + } +} diff --git a/src/views/debug/view_debug_misc.cpp b/src/views/debug/view_debug_misc.cpp index 8f546dde..e3f50a3b 100644 --- a/src/views/debug/view_debug_misc.cpp +++ b/src/views/debug/view_debug_misc.cpp @@ -18,6 +18,8 @@ namespace big { if (ImGui::BeginTabItem("DEBUG_TAB_MISC"_T.data())) { + components::command_checkbox<"external_console">(); + components::command_checkbox<"windowhook">("VIEW_DEBUG_MISC_DISABLE_GTA_WINDOW_HOOK"_T); ImGui::Text(std::format("{}: {}/{}", "VIEW_DEBUG_MISC_FIBER_POOL_USAGE"_T, g_fiber_pool->get_used_fibers(), g_fiber_pool->get_total_fibers()).c_str()); diff --git a/src/views/view.hpp b/src/views/view.hpp index 2b0e33d5..43e486b1 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -77,12 +77,15 @@ namespace big static void lua_scripts(); static void vfx(); + static void onboarding(); + + static void cmd_executor(); + static void player_info(); static void player_teleport(); static void player_kick(); static void player_toxic(); static void player_misc(); - static void cmd_executor(); static void player_vehicle(); }; }