diff --git a/src/hooks/gui/swap_chain_present.cpp b/src/hooks/gui/swap_chain_present.cpp index 8220d6a4..c44f2779 100644 --- a/src/hooks/gui/swap_chain_present.cpp +++ b/src/hooks/gui/swap_chain_present.cpp @@ -1,22 +1,16 @@ -#include "hooking.hpp" -#include "renderer.hpp" -#include "script.hpp" - -namespace big -{ - HRESULT hooks::swapchain_present(IDXGISwapChain* this_, UINT sync_interval, UINT flags) - { - TRY_CLAUSE - { - if (g_running) - { - g_renderer->on_present(); - } - - return g_hooking->m_swapchain_hook.get_original(swapchain_present_index)(this_, sync_interval, flags); - } - EXCEPT_CLAUSE - - return NULL; - } -} +#include "hooking.hpp" +#include "renderer.hpp" +#include "script.hpp" + +namespace big +{ + HRESULT hooks::swapchain_present(IDXGISwapChain* this_, UINT sync_interval, UINT flags) + { + if (g_running) + { + g_renderer->on_present(); + } + + return g_hooking->m_swapchain_hook.get_original(swapchain_present_index)(this_, sync_interval, flags); + } +} \ No newline at end of file diff --git a/src/hooks/gui/swap_chain_resizebuffers.cpp b/src/hooks/gui/swap_chain_resizebuffers.cpp index 1105310d..6f0ea2ab 100644 --- a/src/hooks/gui/swap_chain_resizebuffers.cpp +++ b/src/hooks/gui/swap_chain_resizebuffers.cpp @@ -1,31 +1,25 @@ -#include "hooking.hpp" -#include "renderer.hpp" -#include "script.hpp" - -namespace big -{ - HRESULT hooks::swapchain_resizebuffers(IDXGISwapChain* this_, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swapchain_flags) - { - TRY_CLAUSE - { - if (g_running) - { - g_renderer->pre_reset(); - - const auto result = g_hooking->m_swapchain_hook.get_original(swapchain_resizebuffers_index)(this_, buffer_count, width, height, new_format, swapchain_flags); - - if (SUCCEEDED(result)) - { - g_renderer->post_reset(); - } - - return result; - } - - return g_hooking->m_swapchain_hook.get_original(swapchain_resizebuffers_index)(this_, buffer_count, width, height, new_format, swapchain_flags); - } - EXCEPT_CLAUSE - - return NULL; - } -} +#include "hooking.hpp" +#include "renderer.hpp" +#include "script.hpp" + +namespace big +{ + HRESULT hooks::swapchain_resizebuffers(IDXGISwapChain* this_, UINT buffer_count, UINT width, UINT height, DXGI_FORMAT new_format, UINT swapchain_flags) + { + if (g_running) + { + g_renderer->pre_reset(); + + const auto result = g_hooking->m_swapchain_hook.get_original(swapchain_resizebuffers_index)(this_, buffer_count, width, height, new_format, swapchain_flags); + + if (SUCCEEDED(result)) + { + g_renderer->post_reset(); + } + + return result; + } + + return g_hooking->m_swapchain_hook.get_original(swapchain_resizebuffers_index)(this_, buffer_count, width, height, new_format, swapchain_flags); + } +} diff --git a/src/hooks/gui/wndproc.cpp b/src/hooks/gui/wndproc.cpp index e788e6cd..52583365 100644 --- a/src/hooks/gui/wndproc.cpp +++ b/src/hooks/gui/wndproc.cpp @@ -1,22 +1,16 @@ -#include "hooking.hpp" -#include "renderer.hpp" -#include "script.hpp" - -namespace big -{ - LRESULT hooks::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) - { - TRY_CLAUSE - { - if (g_running) - { - g_renderer->wndproc(hwnd, msg, wparam, lparam); - } - - return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam); - } - EXCEPT_CLAUSE - - return NULL; - } -} +#include "hooking.hpp" +#include "renderer.hpp" +#include "script.hpp" + +namespace big +{ + LRESULT hooks::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + if (g_running) + { + g_renderer->wndproc(hwnd, msg, wparam, lparam); + } + + return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam); + } +} diff --git a/src/hooks/player_management/assign_physical_index.cpp b/src/hooks/player_management/assign_physical_index.cpp index 610dbdde..537a325c 100644 --- a/src/hooks/player_management/assign_physical_index.cpp +++ b/src/hooks/player_management/assign_physical_index.cpp @@ -51,8 +51,8 @@ namespace big auto found = std::find(admin_rids.begin(), admin_rids.end(), net_player_data->m_gamer_handle.m_rockstar_id); if (found != admin_rids.end()) { - g_notification_service->push_warning("Potential Admin Found!", - std::format("{} has been detected as admin", net_player_data->m_name)); + g_notification_service->push_warning("POTENTIAL_ADMIN_FOUND"_T.data(), + std::vformat("PLAYER_DETECTED_AS_ADMIN"_T, std::make_format_args(net_player_data->m_name))); LOG(WARNING) << net_player_data->m_name << " (" << net_player_data->m_gamer_handle.m_rockstar_id << ") has been detected as admin"; auto id = player->m_player_id; if (auto plyr = g_player_service->get_by_id(id)) diff --git a/src/logger/exception_handler.cpp b/src/logger/exception_handler.cpp index a827727f..c5f30733 100644 --- a/src/logger/exception_handler.cpp +++ b/src/logger/exception_handler.cpp @@ -1,37 +1,39 @@ -#include "exception_handler.hpp" - -#include "stack_trace.hpp" - -#include - -namespace big -{ - exception_handler::exception_handler() - { - m_exception_handler = AddVectoredExceptionHandler(1, &vectored_exception_handler); - } - - exception_handler::~exception_handler() - { - RemoveVectoredExceptionHandler(m_exception_handler); - } - - inline static stack_trace trace; - LONG vectored_exception_handler(EXCEPTION_POINTERS* exception_info) - { - const auto exception_code = exception_info->ExceptionRecord->ExceptionCode; - if (exception_code == EXCEPTION_BREAKPOINT || exception_code == DBG_PRINTEXCEPTION_C || exception_code == DBG_PRINTEXCEPTION_WIDE_C) - return EXCEPTION_CONTINUE_SEARCH; - - trace.new_stack_trace(exception_info); - LOG(FATAL) << trace; - - ZyanU64 opcode_address = exception_info->ContextRecord->Rip; - ZydisDisassembledInstruction instruction; - ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64, opcode_address, reinterpret_cast(opcode_address), 32, &instruction); - - exception_info->ContextRecord->Rip += instruction.info.length; - - return EXCEPTION_CONTINUE_EXECUTION; - } +#include "exception_handler.hpp" + +#include "stack_trace.hpp" + +#include + +namespace big +{ + exception_handler::exception_handler() + { + SetErrorMode(0); + SetUnhandledExceptionFilter(&vectored_exception_handler); + } + + exception_handler::~exception_handler() + { + // passing NULL / 0 will make it go back to normal exception handling + SetUnhandledExceptionFilter(0); + } + + inline static stack_trace trace; + LONG vectored_exception_handler(EXCEPTION_POINTERS* exception_info) + { + const auto exception_code = exception_info->ExceptionRecord->ExceptionCode; + if (exception_code == EXCEPTION_BREAKPOINT || exception_code == DBG_PRINTEXCEPTION_C || exception_code == DBG_PRINTEXCEPTION_WIDE_C) + return EXCEPTION_CONTINUE_SEARCH; + + trace.new_stack_trace(exception_info); + LOG(FATAL) << trace; + + ZyanU64 opcode_address = exception_info->ContextRecord->Rip; + ZydisDisassembledInstruction instruction; + ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64, opcode_address, reinterpret_cast(opcode_address), 32, &instruction); + + exception_info->ContextRecord->Rip += instruction.info.length; + + return EXCEPTION_CONTINUE_EXECUTION; + } } \ No newline at end of file diff --git a/src/native_hooks/freemode.hpp b/src/native_hooks/freemode.hpp index 504ba92a..c3f5ab48 100644 --- a/src/native_hooks/freemode.hpp +++ b/src/native_hooks/freemode.hpp @@ -18,11 +18,6 @@ namespace big src->set_return_value(STATS::STAT_GET_INT(src->get_arg(0), src->get_arg(1), src->get_arg(2))); } - inline void NETWORK_BAIL(rage::scrNativeCallContext* src) - { - LOG(INFO) << "NETWORK_BAIL prevented"; - } - inline void IS_PLAYER_PLAYING(rage::scrNativeCallContext* src) { // block undead OTR diff --git a/src/native_hooks/native_hooks.cpp b/src/native_hooks/native_hooks.cpp index 3dfa311c..3ed27ada 100644 --- a/src/native_hooks/native_hooks.cpp +++ b/src/native_hooks/native_hooks.cpp @@ -121,7 +121,6 @@ namespace big add_native_detour(RAGE_JOAAT("carmod_shop"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS); add_native_detour(RAGE_JOAAT("freemode"), 0x767FBC2AC802EF3D, freemode::STAT_GET_INT); - 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); add_native_detour(RAGE_JOAAT("freemode"), 0x231C8F89D0539D8F, freemode::SET_BIGMAP_ACTIVE); diff --git a/src/script.cpp b/src/script.cpp index ddc6880e..d78908e3 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1,120 +1,100 @@ -#pragma once -#include "script.hpp" - -#include "common.hpp" - -namespace big -{ - void script::script_exception_handler(PEXCEPTION_POINTERS exp) - { - HMODULE mod{}; - DWORD64 offset{}; - char buffer[MAX_PATH]{}; - if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)exp->ExceptionRecord->ExceptionAddress, &mod) == TRUE && mod != nullptr) - { - offset = ((DWORD64)exp->ExceptionRecord->ExceptionAddress - (DWORD64)mod); - GetModuleFileNameA(mod, buffer, MAX_PATH - 1); - } - LOG(FATAL) << "Exception Code: " << HEX_TO_UPPER(exp->ExceptionRecord->ExceptionCode) << " Exception Offset: " << HEX_TO_UPPER(offset) << " Fault Module Name: " << buffer; - } - - script::script(const func_t func, const std::string_view name, const bool toggleable, const std::optional stack_size) : - script(func, stack_size) - { - m_name = name; - m_toggleable = toggleable; - } - - script::script(const func_t func, const std::optional stack_size) : - m_enabled(true), - m_toggleable(false), - m_script_fiber(nullptr), - m_main_fiber(nullptr), - m_func(func) - { - m_script_fiber = CreateFiber( - stack_size.has_value() ? stack_size.value() : 0, - [](void* param) { - auto this_script = static_cast(param); - this_script->fiber_func(); - }, - this); - } - - script::~script() - { - if (m_script_fiber) - DeleteFiber(m_script_fiber); - } - - const char* script::name() const - { - return m_name.data(); - } - - bool script::is_enabled() const - { - return m_enabled; - } - - void script::set_enabled(const bool toggle) - { - if (m_toggleable) - m_enabled = toggle; - } - - bool* script::toggle_ptr() - { - return &m_enabled; - } - - bool script::is_toggleable() const - { - return m_toggleable; - } - - void script::tick() - { - m_main_fiber = GetCurrentFiber(); - if (!m_wake_time.has_value() || m_wake_time.value() <= std::chrono::high_resolution_clock::now()) - { - SwitchToFiber(m_script_fiber); - } - } - - void script::yield(std::optional time) - { - if (time.has_value()) - { - m_wake_time = std::chrono::high_resolution_clock::now() + time.value(); - } - else - { - m_wake_time = std::nullopt; - } - - SwitchToFiber(m_main_fiber); - } - - script* script::get_current() - { - return static_cast(GetFiberData()); - } - - void script::fiber_func() - { - TRY_CLAUSE - { - m_func(); - } - EXCEPT_CLAUSE - []() { - LOG(INFO) << "Script finished!"; - }(); - - while (true) - { - yield(); - } - } +#pragma once +#include "script.hpp" + +#include "common.hpp" + +namespace big +{ + script::script(const func_t func, const std::string_view name, const bool toggleable, const std::optional stack_size) : + script(func, stack_size) + { + m_name = name; + m_toggleable = toggleable; + } + + script::script(const func_t func, const std::optional stack_size) : + m_enabled(true), + m_toggleable(false), + m_script_fiber(nullptr), + m_main_fiber(nullptr), + m_func(func) + { + m_script_fiber = CreateFiber( + stack_size.has_value() ? stack_size.value() : 0, + [](void* param) { + auto this_script = static_cast(param); + this_script->fiber_func(); + }, + this); + } + + script::~script() + { + if (m_script_fiber) + DeleteFiber(m_script_fiber); + } + + const char* script::name() const + { + return m_name.data(); + } + + bool script::is_enabled() const + { + return m_enabled; + } + + void script::set_enabled(const bool toggle) + { + if (m_toggleable) + m_enabled = toggle; + } + + bool* script::toggle_ptr() + { + return &m_enabled; + } + + bool script::is_toggleable() const + { + return m_toggleable; + } + + void script::tick() + { + m_main_fiber = GetCurrentFiber(); + if (!m_wake_time.has_value() || m_wake_time.value() <= std::chrono::high_resolution_clock::now()) + { + SwitchToFiber(m_script_fiber); + } + } + + void script::yield(std::optional time) + { + if (time.has_value()) + { + m_wake_time = std::chrono::high_resolution_clock::now() + time.value(); + } + else + { + m_wake_time = std::nullopt; + } + + SwitchToFiber(m_main_fiber); + } + + script* script::get_current() + { + return static_cast(GetFiberData()); + } + + void script::fiber_func() + { + m_func(); + + while (true) + { + yield(); + } + } } \ No newline at end of file diff --git a/src/script.hpp b/src/script.hpp index 31339be3..53548301 100644 --- a/src/script.hpp +++ b/src/script.hpp @@ -1,54 +1,40 @@ -#pragma once -#include "common.hpp" - -namespace big -{ - class script - { - std::string_view m_name; - bool m_enabled; - bool m_toggleable; - - public: - using func_t = void (*)(); - - public: - explicit script(const func_t func, const std::string_view name, const bool toggleable = true, const std::optional stack_size = std::nullopt); - explicit script(const func_t func, const std::optional stack_size = std::nullopt); - ~script(); - - [[nodiscard]] const char* name() const; - [[nodiscard]] bool is_enabled() const; - void set_enabled(const bool toggle); - [[nodiscard]] bool* toggle_ptr(); - - [[nodiscard]] bool is_toggleable() const; - - void tick(); - void yield(std::optional time = std::nullopt); - static script* get_current(); - static void script_exception_handler(PEXCEPTION_POINTERS exp); - - private: - void fiber_func(); - - private: - void* m_script_fiber; - void* m_main_fiber; - func_t m_func; - std::optional m_wake_time; - }; - - -#define TRY_CLAUSE __try -#define EXCEPT_CLAUSE \ - __except (script::script_exception_handler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) \ - { \ - } -#define QUEUE_JOB_BEGIN_CLAUSE(...) g_fiber_pool->queue_job([__VA_ARGS__] { __try -#define QUEUE_JOB_END_CLAUSE \ - __except (script::script_exception_handler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) \ - { \ - } \ - }); +#pragma once +#include "common.hpp" + +namespace big +{ + class script + { + std::string_view m_name; + bool m_enabled; + bool m_toggleable; + + public: + using func_t = void (*)(); + + public: + explicit script(const func_t func, const std::string_view name, const bool toggleable = true, const std::optional stack_size = std::nullopt); + explicit script(const func_t func, const std::optional stack_size = std::nullopt); + ~script(); + + [[nodiscard]] const char* name() const; + [[nodiscard]] bool is_enabled() const; + void set_enabled(const bool toggle); + [[nodiscard]] bool* toggle_ptr(); + + [[nodiscard]] bool is_toggleable() const; + + void tick(); + void yield(std::optional time = std::nullopt); + static script* get_current(); + + private: + void fiber_func(); + + private: + void* m_script_fiber; + void* m_main_fiber; + func_t m_func; + std::optional m_wake_time; + }; } \ No newline at end of file diff --git a/src/services/gui/gui_service.hpp b/src/services/gui/gui_service.hpp index a64cfff5..fe7f2af8 100644 --- a/src/services/gui/gui_service.hpp +++ b/src/services/gui/gui_service.hpp @@ -11,6 +11,8 @@ namespace big WEAPONS, TELEPORT, MOBILE, + OUTFIT_EDITOR, + OUTFIT_SLOTS, VEHICLE, HANDLING, @@ -26,10 +28,8 @@ namespace big WORLD, SPAWN_PED, - TIME_AND_WEATHER, CREATOR, TRAIN, - WATER, BLACKHOLE, MODEL_SWAPPER, NEARBY, @@ -41,13 +41,12 @@ namespace big SPOOFING, PLAYER_DATABASE, SESSION_BROWSER, + STAT_EDITOR, SETTINGS, - OUTFIT_EDITOR, - OUTFIT_SLOTS, - STAT_EDITOR, CONTEXT_MENU_SETTINGS, ESP_SETTINGS, + GTA_CACHE_SETTINGS, GUI_SETTINGS, HOTKEY_SETTINGS, REACTION_SETTINGS, @@ -80,6 +79,8 @@ namespace big {tabs::WEAPONS, {"GUI_TAB_WEAPONS", view::weapons}}, {tabs::MOBILE, {"GUI_TAB_MOBILE", view::mobile}}, {tabs::TELEPORT, {"GUI_TAB_TELEPORT", view::teleport}}, + {tabs::OUTFIT_EDITOR, {"GUI_TAB_OUTFIT_EDITOR", view::outfit_editor}}, + {tabs::OUTFIT_SLOTS, {"GUI_TAB_OUTFIT_SLOTS", view::outfit_slots}}, }, }, }, @@ -112,17 +113,15 @@ namespace big tabs::WORLD, { "GUI_TAB_WORLD", - nullptr, + view::world, { {tabs::SPAWN_PED, {"GUI_TAB_SPAWN_PED", view::spawn_ped}}, - {tabs::TIME_AND_WEATHER, {"GUI_TAB_TIME_N_WEATHER", view::time_and_weather}}, {tabs::CREATOR, {"GUI_TAB_CREATOR", view::creator}}, {tabs::TRAIN, {"GUI_TAB_TRAIN", view::train}}, - {tabs::WATER, {"GUI_TAB_WATER", view::water}}, {tabs::BLACKHOLE, {"GUI_TAB_BLACKHOLE", view::blackhole}}, {tabs::MODEL_SWAPPER, {"GUI_TAB_MODEL_SWAPPER", view::model_swapper}}, {tabs::NEARBY, {"GUI_TAB_NEARBY", view::nearby}}, - {tabs::ORBITAL_DRONE, {"Orbital Drone", view::orbital_drone}}, + {tabs::ORBITAL_DRONE, {"GUI_TAB_ORBITAL_DRONE", view::orbital_drone}}, }, }, }, @@ -137,6 +136,7 @@ namespace big {tabs::MISSIONS, {"GUI_TAB_MISSIONS", view::missions}}, {tabs::PLAYER_DATABASE, {"GUI_TAB_PLAYER_DB", view::player_database}}, {tabs::SESSION_BROWSER, {"GUI_TAB_SESSION_BROWSER", view::session_browser}}, + {tabs::STAT_EDITOR, {"GUI_TAB_STAT_EDITOR", view::stat_editor}}, }, }, }, @@ -146,11 +146,9 @@ namespace big "GUI_TAB_SETTINGS", view::settings, { - {tabs::OUTFIT_EDITOR, {"GUI_TAB_OUTFIT_EDITOR", view::outfit_editor}}, - {tabs::OUTFIT_SLOTS, {"GUI_TAB_OUTFIT_SLOTS", view::outfit_slots}}, - {tabs::STAT_EDITOR, {"GUI_TAB_STAT_EDITOR", view::stat_editor}}, {tabs::CONTEXT_MENU_SETTINGS, {"GUI_TAB_CONTEXT_MENU", view::context_menu_settings}}, {tabs::ESP_SETTINGS, {"GUI_TAB_ESP", view::esp_settings}}, + {tabs::GTA_CACHE_SETTINGS, {"GTA Cache", view::gta_cache}}, {tabs::GUI_SETTINGS, {"GUI_TAB_GUI", view::gui_settings}}, {tabs::HOTKEY_SETTINGS, {"GUI_TAB_HOTKEYS", view::hotkey_settings}}, {tabs::REACTION_SETTINGS, {"GUI_TAB_REACTIONS", view::reaction_settings}}, diff --git a/src/services/translation_service/translation_service.cpp b/src/services/translation_service/translation_service.cpp index 44e2f3a3..151a9d36 100644 --- a/src/services/translation_service/translation_service.cpp +++ b/src/services/translation_service/translation_service.cpp @@ -1,213 +1,213 @@ -#include "translation_service.hpp" - -#include "file_manager.hpp" -#include "thread_pool.hpp" - -#include - -namespace big -{ - translation_service::translation_service() : - m_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master") - { - } - - void translation_service::init() - { - m_translation_directory = std::make_unique(g_file_manager->get_project_folder("./translations").get_path()); - - bool loaded_remote_index = false; - for (size_t i = 0; i < 5 && !loaded_remote_index; i++) - { - if (i) - LOG(WARNING) << "Failed to download remote index, trying again... (" << i << ")"; - loaded_remote_index = download_index(); - } - - if (load_local_index()) - { - if (!loaded_remote_index) - { - LOG(WARNING) << "Failed to load remote index, attempting to use fallback."; - use_fallback_remote(); - } - else if (m_local_index.version < m_remote_index.version) - { - LOG(INFO) << "Languages outdated, downloading new translations."; - - update_language_packs(); - m_local_index.version = m_remote_index.version; - } - load_translations(); - - return; - } - - if (!loaded_remote_index) - { - LOG(WARNING) << "Failed to load remote index, unable to load translations."; - return; - } - - LOG(INFO) << "Downloading translations..."; - - m_local_index.fallback_default_language = m_remote_index.default_lang; - m_local_index.selected_language = m_remote_index.default_lang; - m_local_index.version = m_remote_index.version; - - load_translations(); - } - - std::string_view translation_service::get_translation(const std::string_view translation_key) const - { - return get_translation(rage::joaat(translation_key)); - } - - - std::string_view translation_service::get_translation(const rage::joaat_t translation_key) const - { - if (auto it = m_translations.find(translation_key); it != m_translations.end()) - return it->second.c_str(); - - return {0, 0}; - } - - std::map& translation_service::available_translations() - { - return m_remote_index.translations; - } - - const std::string& translation_service::current_language_pack() - { - return m_local_index.selected_language; - } - - void translation_service::select_language_pack(const std::string& pack_id) - { - g_thread_pool->push([this, &pack_id] { - m_local_index.selected_language = pack_id; - load_translations(); - }); - } - - void translation_service::load_translations() - { - m_translations.clear(); - - // load default lang first to make sure there are fallback keys if another language pack doesn't have a certain key - auto j = load_translation(m_remote_index.default_lang); - for (auto& [key, value] : j.items()) - { - m_translations.insert({rage::joaat(key), value.get()}); - } - - // Don't load selected language if it's the same as default - if (m_local_index.selected_language != m_remote_index.default_lang) - { - auto j = load_translation(m_local_index.selected_language); - for (auto& [key, value] : j.items()) - { - m_translations[rage::joaat(key)] = value; - } - } - - save_local_index(); - } - - nlohmann::json translation_service::load_translation(const std::string_view pack_id) - { - auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id)); - if (!file.exists()) - { - LOG(INFO) << "Translations for '" << pack_id << "' does not exist, downloading from " << m_url; - if (!download_language_pack(pack_id)) - { - LOG(WARNING) << "Failed to download language pack, can't recover..."; - return {}; - } - // make a copy available - m_local_index.fallback_languages[pack_id.data()] = m_remote_index.translations[pack_id.data()]; - } - return nlohmann::json::parse(std::ifstream(file.get_path(), std::ios::binary)); - } - - bool translation_service::download_language_pack(const std::string_view pack_id) - { - if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end()) - { - cpr::Response response = cpr::Get(cpr::Url{m_url + "/" + it->second.file}); - - if (response.status_code == 200) - { - auto json = nlohmann::json::parse(response.text); - auto lang_file = m_translation_directory->get_file("./" + it->second.file); - - auto out_file = std::ofstream(lang_file.get_path(), std::ios::binary | std::ios::trunc); - out_file << json.dump(4); - out_file.close(); - - return true; - } - } - return false; - } - - void translation_service::update_language_packs() - { - for (auto item : std::filesystem::directory_iterator(m_translation_directory->get_path())) - { - const auto path = item.path(); - const auto stem = path.stem().string(); - if (stem == "index" || item.path().extension() != ".json") - continue; - - if (!download_language_pack(stem)) - { - LOG(WARNING) << "Failed to update '" << stem << "' language pack"; - } - } - } - - bool translation_service::download_index() - { - cpr::Response response = cpr::Get(cpr::Url{m_url + "/index.json"}); - - if (response.status_code == 200) - { - m_remote_index = nlohmann::json::parse(response.text); - - return true; - } - return false; - } - - bool translation_service::load_local_index() - { - const auto local_index = m_translation_directory->get_file("./index.json"); - if (local_index.exists()) - { - const auto path = local_index.get_path(); - m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary)); - - return true; - } - return false; - } - - void translation_service::save_local_index() - { - nlohmann::json j = m_local_index; - - const auto local_index = m_translation_directory->get_file("./index.json"); - - auto os = std::ofstream(local_index.get_path(), std::ios::binary | std::ios::trunc); - os << j.dump(4); - os.close(); - } - - void translation_service::use_fallback_remote() - { - m_remote_index.default_lang = m_local_index.fallback_default_language; - m_remote_index.translations = m_local_index.fallback_languages; - } -} +#include "translation_service.hpp" + +#include "file_manager.hpp" +#include "thread_pool.hpp" + +#include + +namespace big +{ + translation_service::translation_service() : + m_url("https://cdn.jsdelivr.net/gh/YimMenu/Translations@master") + { + } + + void translation_service::init() + { + m_translation_directory = std::make_unique(g_file_manager->get_project_folder("./translations").get_path()); + + bool loaded_remote_index = false; + for (size_t i = 0; i < 5 && !loaded_remote_index; i++) + { + if (i) + LOG(WARNING) << "Failed to download remote index, trying again... (" << i << ")"; + loaded_remote_index = download_index(); + } + + if (load_local_index()) + { + if (!loaded_remote_index) + { + LOG(WARNING) << "Failed to load remote index, attempting to use fallback."; + use_fallback_remote(); + } + else if (m_local_index.version < m_remote_index.version) + { + LOG(INFO) << "Languages outdated, downloading new translations."; + + update_language_packs(); + m_local_index.version = m_remote_index.version; + } + load_translations(); + + return; + } + + if (!loaded_remote_index) + { + LOG(WARNING) << "Failed to load remote index, unable to load translations."; + return; + } + + LOG(INFO) << "Downloading translations..."; + + m_local_index.fallback_default_language = m_remote_index.default_lang; + m_local_index.selected_language = m_remote_index.default_lang; + m_local_index.version = m_remote_index.version; + + load_translations(); + } + + std::string_view translation_service::get_translation(const std::string_view translation_key) const + { + return get_translation(rage::joaat(translation_key)); + } + + + std::string_view translation_service::get_translation(const rage::joaat_t translation_key) const + { + if (auto it = m_translations.find(translation_key); it != m_translations.end()) + return it->second.c_str(); + + return {0, 0}; + } + + std::map& translation_service::available_translations() + { + return m_remote_index.translations; + } + + const std::string& translation_service::current_language_pack() + { + return m_local_index.selected_language; + } + + void translation_service::select_language_pack(const std::string& pack_id) + { + g_thread_pool->push([this, &pack_id] { + m_local_index.selected_language = pack_id; + load_translations(); + }); + } + + void translation_service::update_language_packs() + { + for (auto item : std::filesystem::directory_iterator(m_translation_directory->get_path())) + { + const auto path = item.path(); + const auto stem = path.stem().string(); + if (stem == "index" || item.path().extension() != ".json") + continue; + + if (!download_language_pack(stem)) + { + LOG(WARNING) << "Failed to update '" << stem << "' language pack"; + } + } + } + + void translation_service::load_translations() + { + m_translations.clear(); + + // load default lang first to make sure there are fallback keys if another language pack doesn't have a certain key + auto j = load_translation(m_remote_index.default_lang); + for (auto& [key, value] : j.items()) + { + m_translations.insert({rage::joaat(key), value.get()}); + } + + // Don't load selected language if it's the same as default + if (m_local_index.selected_language != m_remote_index.default_lang) + { + auto j = load_translation(m_local_index.selected_language); + for (auto& [key, value] : j.items()) + { + m_translations[rage::joaat(key)] = value; + } + } + + save_local_index(); + } + + nlohmann::json translation_service::load_translation(const std::string_view pack_id) + { + auto file = m_translation_directory->get_file(std::format("./{}.json", pack_id)); + if (!file.exists()) + { + LOG(INFO) << "Translations for '" << pack_id << "' does not exist, downloading from " << m_url; + if (!download_language_pack(pack_id)) + { + LOG(WARNING) << "Failed to download language pack, can't recover..."; + return {}; + } + // make a copy available + m_local_index.fallback_languages[pack_id.data()] = m_remote_index.translations[pack_id.data()]; + } + return nlohmann::json::parse(std::ifstream(file.get_path(), std::ios::binary)); + } + + bool translation_service::download_language_pack(const std::string_view pack_id) + { + if (auto it = m_remote_index.translations.find(pack_id.data()); it != m_remote_index.translations.end()) + { + cpr::Response response = cpr::Get(cpr::Url{m_url + "/" + it->second.file}); + + if (response.status_code == 200) + { + auto json = nlohmann::json::parse(response.text); + auto lang_file = m_translation_directory->get_file("./" + it->second.file); + + auto out_file = std::ofstream(lang_file.get_path(), std::ios::binary | std::ios::trunc); + out_file << json.dump(4); + out_file.close(); + + return true; + } + } + return false; + } + + bool translation_service::download_index() + { + cpr::Response response = cpr::Get(cpr::Url{m_url + "/index.json"}); + + if (response.status_code == 200) + { + m_remote_index = nlohmann::json::parse(response.text); + + return true; + } + return false; + } + + bool translation_service::load_local_index() + { + const auto local_index = m_translation_directory->get_file("./index.json"); + if (local_index.exists()) + { + const auto path = local_index.get_path(); + m_local_index = nlohmann::json::parse(std::ifstream(path, std::ios::binary)); + + return true; + } + return false; + } + + void translation_service::save_local_index() + { + nlohmann::json j = m_local_index; + + const auto local_index = m_translation_directory->get_file("./index.json"); + + auto os = std::ofstream(local_index.get_path(), std::ios::binary | std::ios::trunc); + os << j.dump(4); + os.close(); + } + + void translation_service::use_fallback_remote() + { + m_remote_index.default_lang = m_local_index.fallback_default_language; + m_remote_index.translations = m_local_index.fallback_languages; + } +} diff --git a/src/services/translation_service/translation_service.hpp b/src/services/translation_service/translation_service.hpp index c3f372fa..99aec211 100644 --- a/src/services/translation_service/translation_service.hpp +++ b/src/services/translation_service/translation_service.hpp @@ -1,87 +1,87 @@ -#pragma once -#include "file_manager/folder.hpp" -#include "gta/joaat.hpp" -#include "local_index.hpp" -#include "remote_index.hpp" - -namespace big -{ - using translation_map = std::unordered_map; - - class translation_service - { - public: - translation_service(); - virtual ~translation_service() = default; - translation_service(const translation_service&) = delete; - translation_service(translation_service&&) noexcept = delete; - translation_service& operator=(const translation_service&) = delete; - translation_service& operator=(translation_service&&) noexcept = delete; - - void init(); - - std::string_view get_translation(const std::string_view translation_key) const; - std::string_view get_translation(const rage::joaat_t translation_key) const; - - std::map& available_translations(); - const std::string& current_language_pack(); - void select_language_pack(const std::string& pack_id); - - private: - void load_translations(); - nlohmann::json load_translation(const std::string_view pack_id); - - bool download_language_pack(const std::string_view pack_id); - void update_language_packs(); - - /** - * @brief Downloads the remote index to compare with our local index - * - * @return true - * @return false - */ - bool download_index(); - bool load_local_index(); - void save_local_index(); - /** - * @brief Attempts to load the remote from the local index fallback - */ - void use_fallback_remote(); - - private: - const std::string m_url; - std::unique_ptr m_translation_directory; - local_index m_local_index; - remote_index m_remote_index; - - translation_map m_translations; - }; - - inline auto g_translation_service = translation_service(); - - template - struct TranslationLiteral - { - rage::joaat_t m_hash; - char m_key[N]{}; - - consteval TranslationLiteral(char const (&pp)[N]) - { - std::ranges::copy(pp, m_key); - m_hash = rage::joaat(pp); - }; - - const std::string_view translation() const - { - if (const auto translation = g_translation_service.get_translation(m_hash); translation.length()) - return translation; - return m_key; - } - }; - - template - constexpr auto operator"" _T() - { - return T.translation(); - } +#pragma once +#include "file_manager/folder.hpp" +#include "gta/joaat.hpp" +#include "local_index.hpp" +#include "remote_index.hpp" + +namespace big +{ + using translation_map = std::unordered_map; + + class translation_service + { + public: + translation_service(); + virtual ~translation_service() = default; + translation_service(const translation_service&) = delete; + translation_service(translation_service&&) noexcept = delete; + translation_service& operator=(const translation_service&) = delete; + translation_service& operator=(translation_service&&) noexcept = delete; + + void init(); + + std::string_view get_translation(const std::string_view translation_key) const; + std::string_view get_translation(const rage::joaat_t translation_key) const; + + std::map& available_translations(); + const std::string& current_language_pack(); + void select_language_pack(const std::string& pack_id); + void update_language_packs(); + + private: + void load_translations(); + nlohmann::json load_translation(const std::string_view pack_id); + + bool download_language_pack(const std::string_view pack_id); + + /** + * @brief Downloads the remote index to compare with our local index + * + * @return true + * @return false + */ + bool download_index(); + bool load_local_index(); + void save_local_index(); + /** + * @brief Attempts to load the remote from the local index fallback + */ + void use_fallback_remote(); + + private: + const std::string m_url; + std::unique_ptr m_translation_directory; + local_index m_local_index; + remote_index m_remote_index; + + translation_map m_translations; + }; + + inline auto g_translation_service = translation_service(); + + template + struct TranslationLiteral + { + rage::joaat_t m_hash; + char m_key[N]{}; + + consteval TranslationLiteral(char const (&pp)[N]) + { + std::ranges::copy(pp, m_key); + m_hash = rage::joaat(pp); + }; + + const std::string_view translation() const + { + if (const auto translation = g_translation_service.get_translation(m_hash); translation.length()) + return translation; + return m_key; + } + }; + + template + constexpr auto operator"" _T() + { + return T.translation(); + } } \ No newline at end of file diff --git a/src/services/vehicle/vehicle_control_service.cpp b/src/services/vehicle/vehicle_control_service.cpp index b5b80b8d..e98a8480 100644 --- a/src/services/vehicle/vehicle_control_service.cpp +++ b/src/services/vehicle/vehicle_control_service.cpp @@ -187,7 +187,7 @@ namespace big 4.f, 5.f); //LOG(INFO) << "Navmesh probably failed, issiuing regular task "; - g_notification_service->push_warning("Vehicle controller", "Your vehicle could not assess an accurate path, it will try something else"); + g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_TRY_ALT_PATHFINDING"_T.data()); script::get_current()->yield(500ms); } @@ -331,12 +331,12 @@ namespace big if (vehicle_control::find_suitable_destination_near_player(destination, heading)) { //LOG(INFO) << "Suitable destination found"; - g_notification_service->push_warning("Vehicle controller", "Found a nice spot, your vehicle is on its way"); + g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_FOUND_LOCATION"_T.data()); } else { //LOG(INFO) << "Couldn't find suitable destionation, defaulting to offset of player\nThis might go wrong"; - g_notification_service->push_warning("Vehicle controller", "Couldn't locate an accurate spot, your vehicle is on its way regardless"); + g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_FORCE_PATHFINDING"_T.data()); destination = behind_pos; } @@ -359,7 +359,7 @@ namespace big else { //LOG(INFO) << "Navmesh load failed"; - g_notification_service->push_error("Nav mesh", "Failed loading the navmesh"); + g_notification_service->push_error("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_NAVMESH_FAILURE"_T.data()); m_driver_performing_task = false; } } diff --git a/src/views/settings/view_outfit_editor.cpp b/src/views/self/view_outfit_editor.cpp similarity index 96% rename from src/views/settings/view_outfit_editor.cpp rename to src/views/self/view_outfit_editor.cpp index 02285422..1bec730b 100644 --- a/src/views/settings/view_outfit_editor.cpp +++ b/src/views/self/view_outfit_editor.cpp @@ -1,251 +1,251 @@ -#include "natives.hpp" -#include "pointers.hpp" -#include "util/outfit.hpp" -#include "util/ped.hpp" -#include "views/view.hpp" - -namespace big -{ - void view::outfit_editor() - { - static outfit::components_t components; - static outfit::props_t props; - - g_fiber_pool->queue_job([] { - for (auto& item : components.items) - { - item.drawable_id = PED::GET_PED_DRAWABLE_VARIATION(self::ped, item.id); - item.drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; - - item.texture_id = PED::GET_PED_TEXTURE_VARIATION(self::ped, item.id); - item.texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; - } - - for (auto& item : props.items) - { - item.drawable_id = PED::GET_PED_PROP_INDEX(self::ped, item.id, 1); - item.drawable_id_max = PED::GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; - - item.texture_id = PED::GET_PED_PROP_TEXTURE_INDEX(self::ped, item.id); - item.texture_id_max = PED::GET_NUMBER_OF_PED_PROP_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; - } - }); - - components::button("OUTFIT_RANDOM_COMPONENT"_T, [] { - ped::set_ped_random_component_variation(self::ped); - }); - ImGui::SameLine(); - - components::button("OUTFIT_DEFAULT_COMPONENT"_T, [] { - PED::SET_PED_DEFAULT_COMPONENT_VARIATION(self::ped); - }); - ImGui::SameLine(); - - components::button("OUTFIT_RANDOM_PROPS"_T, [] { - PED::SET_PED_RANDOM_PROPS(self::ped); - }); - ImGui::SameLine(); - - components::button("OUTFIT_CLEAR_PROPS"_T, [] { - PED::CLEAR_ALL_PED_PROPS(self::ped, 1); - }); - ImGui::SameLine(); - - components::button("EXPORT_TO_CLIPBOARD"_T, [] { - std::stringstream ss; - for (auto& item : components.items) - ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; - for (auto& item : props.items) - ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; - ImGui::SetClipboardText(ss.str().c_str()); - g_notification_service->push("OUTFIT"_T.data(), "EXPORT_TO_CLIPBOARD"_T.data()); - }); - ImGui::SameLine(); - - components::button("IMPORT_FROM_CLIPBOARD"_T, [] { - std::stringstream ss(ImGui::GetClipboardText()); - for (auto& item : components.items) - { - int id = 0; - int drawable_id = 0; - int texture_id = 0; - ss >> id; - ss >> drawable_id; - ss >> texture_id; - PED::SET_PED_COMPONENT_VARIATION(self::ped, id, drawable_id, texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, id)); - } - for (auto& item : props.items) - { - int id = 0; - int drawable_id = 0; - int texture_id = 0; - ss >> id; - ss >> drawable_id; - ss >> texture_id; - if (drawable_id == -1) - PED::CLEAR_PED_PROP(self::ped, id, 1); - else - PED::SET_PED_PROP_INDEX(self::ped, id, drawable_id, texture_id, TRUE, 1); - } - }); - - ImGui::BeginGroup(); - for (auto& item : components.items) - { - ImGui::SetNextItemWidth(60); - if (ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), &item.drawable_id, 0)) - { - g_fiber_pool->queue_job([item] { - PED::SET_PED_COMPONENT_VARIATION(self::ped, item.id, item.drawable_id, 0, PED::GET_PED_PALETTE_VARIATION(self::ped, item.id)); - }); - } - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : components.items) - { - ImGui::SetNextItemWidth(60); - if (ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), &item.texture_id, 0)) - { - g_fiber_pool->queue_job([item] { - PED::SET_PED_COMPONENT_VARIATION(self::ped, item.id, item.drawable_id, item.texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, item.id)); - }); - } - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : props.items) - { - ImGui::SetNextItemWidth(60); - if (ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), &item.drawable_id, 0)) - { - g_fiber_pool->queue_job([item] { - if (item.drawable_id == -1) - PED::CLEAR_PED_PROP(self::ped, item.id, 1); - else - PED::SET_PED_PROP_INDEX(self::ped, item.id, item.drawable_id, 0, TRUE, 1); - }); - } - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : props.items) - { - ImGui::SetNextItemWidth(60); - if (ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), &item.texture_id, 0)) - { - g_fiber_pool->queue_job([item] { - PED::SET_PED_PROP_INDEX(self::ped, item.id, item.drawable_id, item.texture_id, TRUE, 1); - }); - } - } - ImGui::EndGroup(); - - ImGui::Separator(); - - static char outfit_name[MAX_PATH] = {}; - static folder saved_outfit_path = g_file_manager->get_project_folder("saved_outfits"); - std::vector saved_outfits; - for (const auto& directory_entry : std::filesystem::directory_iterator(saved_outfit_path.get_path())) - saved_outfits.push_back(directory_entry.path().filename().generic_string()); - static int selected_index = -1; - - ImGui::SetNextItemWidth(300); - - ImGui::InputText("##outfit_name", outfit_name, sizeof(outfit_name)); - ImGui::SameLine(); - - components::button("OUTFIT_SAVE_CURRENT"_T, [] { - nlohmann::json j; - nlohmann::json j_components; - nlohmann::json j_props; - - for (auto& item : components.items) - { - nlohmann::json tmp; - tmp["drawable_id"] = item.drawable_id; - tmp["texture_id"] = item.texture_id; - j_components[std::to_string(item.id)] = tmp; - } - - for (auto& item : props.items) - { - nlohmann::json tmp; - tmp["drawable_id"] = item.drawable_id; - tmp["texture_id"] = item.texture_id; - j_props[std::to_string(item.id)] = tmp; - } - - j["components"] = j_components; - j["props"] = j_props; - - size_t index = 0; - std::string str = outfit_name; - while (saved_outfit_path.get_file(str + ".json").exists()) - str = std::format("{}({})", outfit_name, ++index); - - std::ofstream o(saved_outfit_path.get_file(str + ".json").get_path()); - o << std::setw(4) << j << std::endl; - }); - ImGui::SameLine(); - - components::button("OUTFIT_APPLY_SELECTED"_T, [saved_outfits] { - if (selected_index >= 0 && selected_index < saved_outfits.size()) - { - std::ifstream i(saved_outfit_path.get_file(saved_outfits[selected_index]).get_path()); - nlohmann::json j; - i >> j; - - for (auto& item : j["components"].items()) - { - std::stringstream ss(item.key()); - int id = 0; - ss >> id; - int drawable_id = item.value()["drawable_id"]; - int texture_id = item.value()["texture_id"]; - PED::SET_PED_COMPONENT_VARIATION(self::ped, id, drawable_id, texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, id)); - } - - for (auto& item : j["props"].items()) - { - std::stringstream ss(item.key()); - int id = 0; - ss >> id; - int drawable_id = item.value()["drawable_id"]; - int texture_id = item.value()["texture_id"]; - if (drawable_id == -1) - PED::CLEAR_PED_PROP(self::ped, id, 1); - else - PED::SET_PED_PROP_INDEX(self::ped, id, drawable_id, texture_id, TRUE, 1); - } - } - }); - ImGui::SameLine(); - - components::button("OUTFIT_DELETE_SELECTED"_T, [saved_outfits] { - if (selected_index >= 0 && selected_index < saved_outfits.size()) - { - std::filesystem::remove(saved_outfit_path.get_file(saved_outfits[selected_index]).get_path()); - if (selected_index == saved_outfits.size() - 1) - --selected_index; - } - }); - - if (ImGui::BeginListBox("##outfit_editor_list_box", ImVec2(300, 0))) - { - for (size_t i = 0; i < saved_outfits.size(); i++) - if (ImGui::Selectable(saved_outfits[i].c_str(), selected_index == i)) - selected_index = i; - ImGui::EndListBox(); - } - } +#include "natives.hpp" +#include "pointers.hpp" +#include "util/outfit.hpp" +#include "util/ped.hpp" +#include "views/view.hpp" + +namespace big +{ + void view::outfit_editor() + { + static outfit::components_t components; + static outfit::props_t props; + + g_fiber_pool->queue_job([] { + for (auto& item : components.items) + { + item.drawable_id = PED::GET_PED_DRAWABLE_VARIATION(self::ped, item.id); + item.drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; + + item.texture_id = PED::GET_PED_TEXTURE_VARIATION(self::ped, item.id); + item.texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; + } + + for (auto& item : props.items) + { + item.drawable_id = PED::GET_PED_PROP_INDEX(self::ped, item.id, 1); + item.drawable_id_max = PED::GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; + + item.texture_id = PED::GET_PED_PROP_TEXTURE_INDEX(self::ped, item.id); + item.texture_id_max = PED::GET_NUMBER_OF_PED_PROP_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; + } + }); + + components::button("OUTFIT_RANDOM_COMPONENT"_T, [] { + ped::set_ped_random_component_variation(self::ped); + }); + ImGui::SameLine(); + + components::button("OUTFIT_DEFAULT_COMPONENT"_T, [] { + PED::SET_PED_DEFAULT_COMPONENT_VARIATION(self::ped); + }); + ImGui::SameLine(); + + components::button("OUTFIT_RANDOM_PROPS"_T, [] { + PED::SET_PED_RANDOM_PROPS(self::ped); + }); + ImGui::SameLine(); + + components::button("OUTFIT_CLEAR_PROPS"_T, [] { + PED::CLEAR_ALL_PED_PROPS(self::ped, 1); + }); + ImGui::SameLine(); + + components::button("EXPORT_TO_CLIPBOARD"_T, [] { + std::stringstream ss; + for (auto& item : components.items) + ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; + for (auto& item : props.items) + ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; + ImGui::SetClipboardText(ss.str().c_str()); + g_notification_service->push("OUTFIT"_T.data(), "EXPORT_TO_CLIPBOARD"_T.data()); + }); + ImGui::SameLine(); + + components::button("IMPORT_FROM_CLIPBOARD"_T, [] { + std::stringstream ss(ImGui::GetClipboardText()); + for (auto& item : components.items) + { + int id = 0; + int drawable_id = 0; + int texture_id = 0; + ss >> id; + ss >> drawable_id; + ss >> texture_id; + PED::SET_PED_COMPONENT_VARIATION(self::ped, id, drawable_id, texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, id)); + } + for (auto& item : props.items) + { + int id = 0; + int drawable_id = 0; + int texture_id = 0; + ss >> id; + ss >> drawable_id; + ss >> texture_id; + if (drawable_id == -1) + PED::CLEAR_PED_PROP(self::ped, id, 1); + else + PED::SET_PED_PROP_INDEX(self::ped, id, drawable_id, texture_id, TRUE, 1); + } + }); + + ImGui::BeginGroup(); + for (auto& item : components.items) + { + ImGui::SetNextItemWidth(60); + if (ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), &item.drawable_id, 0)) + { + g_fiber_pool->queue_job([item] { + PED::SET_PED_COMPONENT_VARIATION(self::ped, item.id, item.drawable_id, 0, PED::GET_PED_PALETTE_VARIATION(self::ped, item.id)); + }); + } + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : components.items) + { + ImGui::SetNextItemWidth(60); + if (ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), &item.texture_id, 0)) + { + g_fiber_pool->queue_job([item] { + PED::SET_PED_COMPONENT_VARIATION(self::ped, item.id, item.drawable_id, item.texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, item.id)); + }); + } + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : props.items) + { + ImGui::SetNextItemWidth(60); + if (ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), &item.drawable_id, 0)) + { + g_fiber_pool->queue_job([item] { + if (item.drawable_id == -1) + PED::CLEAR_PED_PROP(self::ped, item.id, 1); + else + PED::SET_PED_PROP_INDEX(self::ped, item.id, item.drawable_id, 0, TRUE, 1); + }); + } + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : props.items) + { + ImGui::SetNextItemWidth(60); + if (ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), &item.texture_id, 0)) + { + g_fiber_pool->queue_job([item] { + PED::SET_PED_PROP_INDEX(self::ped, item.id, item.drawable_id, item.texture_id, TRUE, 1); + }); + } + } + ImGui::EndGroup(); + + ImGui::Separator(); + + static char outfit_name[MAX_PATH] = {}; + static folder saved_outfit_path = g_file_manager->get_project_folder("saved_outfits"); + std::vector saved_outfits; + for (const auto& directory_entry : std::filesystem::directory_iterator(saved_outfit_path.get_path())) + saved_outfits.push_back(directory_entry.path().filename().generic_string()); + static int selected_index = -1; + + ImGui::SetNextItemWidth(300); + + ImGui::InputText("##outfit_name", outfit_name, sizeof(outfit_name)); + ImGui::SameLine(); + + components::button("OUTFIT_SAVE_CURRENT"_T, [] { + nlohmann::json j; + nlohmann::json j_components; + nlohmann::json j_props; + + for (auto& item : components.items) + { + nlohmann::json tmp; + tmp["drawable_id"] = item.drawable_id; + tmp["texture_id"] = item.texture_id; + j_components[std::to_string(item.id)] = tmp; + } + + for (auto& item : props.items) + { + nlohmann::json tmp; + tmp["drawable_id"] = item.drawable_id; + tmp["texture_id"] = item.texture_id; + j_props[std::to_string(item.id)] = tmp; + } + + j["components"] = j_components; + j["props"] = j_props; + + size_t index = 0; + std::string str = outfit_name; + while (saved_outfit_path.get_file(str + ".json").exists()) + str = std::format("{}({})", outfit_name, ++index); + + std::ofstream o(saved_outfit_path.get_file(str + ".json").get_path()); + o << std::setw(4) << j << std::endl; + }); + ImGui::SameLine(); + + components::button("OUTFIT_APPLY_SELECTED"_T, [saved_outfits] { + if (selected_index >= 0 && selected_index < saved_outfits.size()) + { + std::ifstream i(saved_outfit_path.get_file(saved_outfits[selected_index]).get_path()); + nlohmann::json j; + i >> j; + + for (auto& item : j["components"].items()) + { + std::stringstream ss(item.key()); + int id = 0; + ss >> id; + int drawable_id = item.value()["drawable_id"]; + int texture_id = item.value()["texture_id"]; + PED::SET_PED_COMPONENT_VARIATION(self::ped, id, drawable_id, texture_id, PED::GET_PED_PALETTE_VARIATION(self::ped, id)); + } + + for (auto& item : j["props"].items()) + { + std::stringstream ss(item.key()); + int id = 0; + ss >> id; + int drawable_id = item.value()["drawable_id"]; + int texture_id = item.value()["texture_id"]; + if (drawable_id == -1) + PED::CLEAR_PED_PROP(self::ped, id, 1); + else + PED::SET_PED_PROP_INDEX(self::ped, id, drawable_id, texture_id, TRUE, 1); + } + } + }); + ImGui::SameLine(); + + components::button("OUTFIT_DELETE_SELECTED"_T, [saved_outfits] { + if (selected_index >= 0 && selected_index < saved_outfits.size()) + { + std::filesystem::remove(saved_outfit_path.get_file(saved_outfits[selected_index]).get_path()); + if (selected_index == saved_outfits.size() - 1) + --selected_index; + } + }); + + if (ImGui::BeginListBox("##outfit_editor_list_box", ImVec2(300, 0))) + { + for (size_t i = 0; i < saved_outfits.size(); i++) + if (ImGui::Selectable(saved_outfits[i].c_str(), selected_index == i)) + selected_index = i; + ImGui::EndListBox(); + } + } } \ No newline at end of file diff --git a/src/views/settings/view_outfit_slots.cpp b/src/views/self/view_outfit_slots.cpp similarity index 96% rename from src/views/settings/view_outfit_slots.cpp rename to src/views/self/view_outfit_slots.cpp index 6ec899a2..de3ac4c1 100644 --- a/src/views/settings/view_outfit_slots.cpp +++ b/src/views/self/view_outfit_slots.cpp @@ -1,124 +1,124 @@ -#include "natives.hpp" -#include "pointers.hpp" -#include "util/outfit.hpp" -#include "views/view.hpp" - -namespace big -{ - void view::outfit_slots() - { - if (*g_pointers->m_script_globals) - { - static int slot = 0; - ImGui::SetNextItemWidth(160); - if (ImGui::InputInt("OUTFIT_SLOT"_T.data(), &slot)) - { - if (slot < 0) - slot = 19; - if (slot > 19) - slot = 0; - } - - ImGui::SetNextItemWidth(300); - ImGui::InputText("OUTFIT_NAME"_T.data(), outfit::get_slot_name_address(slot), 16); - - static outfit::components_t components; - static outfit::props_t props; - - g_fiber_pool->queue_job([] { - for (auto& item : components.items) - { - item.drawable_id = *outfit::get_component_drawable_id_address(slot, item.id); - item.drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; - - item.texture_id = *outfit::get_component_texture_id_address(slot, item.id); - item.texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; - } - - for (auto& item : props.items) - { - item.drawable_id = *outfit::get_prop_drawable_id_address(slot, item.id); - item.drawable_id_max = PED::GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; - - item.texture_id = *outfit::get_prop_texture_id_address(slot, item.id); - item.texture_id_max = PED::GET_NUMBER_OF_PED_PROP_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; - } - }); - - components::button("EXPORT_TO_CLIPBOARD"_T, [] { - std::stringstream ss; - for (auto& item : components.items) - ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; - for (auto& item : props.items) - ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; - ImGui::SetClipboardText(ss.str().c_str()); - g_notification_service->push("OUTFIT"_T.data(), "EXPORT_TO_CLIPBOARD"_T.data()); - }); - ImGui::SameLine(); - - components::button("IMPORT_FROM_CLIPBOARD"_T, [] { - std::stringstream ss(ImGui::GetClipboardText()); - for (auto& item : components.items) - { - int id = 0; - int drawable_id = 0; - int texture_id = 0; - ss >> id; - ss >> drawable_id; - ss >> texture_id; - *outfit::get_component_drawable_id_address(slot, id) = drawable_id; - *outfit::get_component_texture_id_address(slot, id) = texture_id; - } - for (auto& item : props.items) - { - int id = 0; - int drawable_id = 0; - int texture_id = 0; - ss >> id; - ss >> drawable_id; - ss >> texture_id; - *outfit::get_prop_drawable_id_address(slot, id) = drawable_id; - *outfit::get_prop_texture_id_address(slot, id) = texture_id; - } - }); - - ImGui::BeginGroup(); - for (auto& item : components.items) - { - ImGui::SetNextItemWidth(60); - ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), outfit::get_component_drawable_id_address(slot, item.id), 0); - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : components.items) - { - ImGui::SetNextItemWidth(60); - ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), outfit::get_component_texture_id_address(slot, item.id), 0); - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : props.items) - { - ImGui::SetNextItemWidth(60); - ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), outfit::get_prop_drawable_id_address(slot, item.id), 0); - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - for (auto& item : props.items) - { - ImGui::SetNextItemWidth(60); - ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), outfit::get_prop_texture_id_address(slot, item.id), 0); - } - ImGui::EndGroup(); - } - } +#include "natives.hpp" +#include "pointers.hpp" +#include "util/outfit.hpp" +#include "views/view.hpp" + +namespace big +{ + void view::outfit_slots() + { + if (*g_pointers->m_script_globals) + { + static int slot = 0; + ImGui::SetNextItemWidth(160); + if (ImGui::InputInt("OUTFIT_SLOT"_T.data(), &slot)) + { + if (slot < 0) + slot = 19; + if (slot > 19) + slot = 0; + } + + ImGui::SetNextItemWidth(300); + ImGui::InputText("OUTFIT_NAME"_T.data(), outfit::get_slot_name_address(slot), 16); + + static outfit::components_t components; + static outfit::props_t props; + + g_fiber_pool->queue_job([] { + for (auto& item : components.items) + { + item.drawable_id = *outfit::get_component_drawable_id_address(slot, item.id); + item.drawable_id_max = PED::GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; + + item.texture_id = *outfit::get_component_texture_id_address(slot, item.id); + item.texture_id_max = PED::GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; + } + + for (auto& item : props.items) + { + item.drawable_id = *outfit::get_prop_drawable_id_address(slot, item.id); + item.drawable_id_max = PED::GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(self::ped, item.id) - 1; + + item.texture_id = *outfit::get_prop_texture_id_address(slot, item.id); + item.texture_id_max = PED::GET_NUMBER_OF_PED_PROP_TEXTURE_VARIATIONS(self::ped, item.id, item.drawable_id) - 1; + } + }); + + components::button("EXPORT_TO_CLIPBOARD"_T, [] { + std::stringstream ss; + for (auto& item : components.items) + ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; + for (auto& item : props.items) + ss << item.id << " " << item.drawable_id << " " << item.texture_id << " "; + ImGui::SetClipboardText(ss.str().c_str()); + g_notification_service->push("OUTFIT"_T.data(), "EXPORT_TO_CLIPBOARD"_T.data()); + }); + ImGui::SameLine(); + + components::button("IMPORT_FROM_CLIPBOARD"_T, [] { + std::stringstream ss(ImGui::GetClipboardText()); + for (auto& item : components.items) + { + int id = 0; + int drawable_id = 0; + int texture_id = 0; + ss >> id; + ss >> drawable_id; + ss >> texture_id; + *outfit::get_component_drawable_id_address(slot, id) = drawable_id; + *outfit::get_component_texture_id_address(slot, id) = texture_id; + } + for (auto& item : props.items) + { + int id = 0; + int drawable_id = 0; + int texture_id = 0; + ss >> id; + ss >> drawable_id; + ss >> texture_id; + *outfit::get_prop_drawable_id_address(slot, id) = drawable_id; + *outfit::get_prop_texture_id_address(slot, id) = texture_id; + } + }); + + ImGui::BeginGroup(); + for (auto& item : components.items) + { + ImGui::SetNextItemWidth(60); + ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), outfit::get_component_drawable_id_address(slot, item.id), 0); + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : components.items) + { + ImGui::SetNextItemWidth(60); + ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), outfit::get_component_texture_id_address(slot, item.id), 0); + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : props.items) + { + ImGui::SetNextItemWidth(60); + ImGui::InputInt(std::format("{} [0,{}]", item.label, item.drawable_id_max).c_str(), outfit::get_prop_drawable_id_address(slot, item.id), 0); + } + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + for (auto& item : props.items) + { + ImGui::SetNextItemWidth(60); + ImGui::InputInt(std::format("{} {} [0,{}]", item.label, "OUTFIT_TEX"_T, item.texture_id_max).c_str(), outfit::get_prop_texture_id_address(slot, item.id), 0); + } + ImGui::EndGroup(); + } + } } \ No newline at end of file diff --git a/src/views/settings/view_gta_cache.cpp b/src/views/settings/view_gta_cache.cpp new file mode 100644 index 00000000..a7695527 --- /dev/null +++ b/src/views/settings/view_gta_cache.cpp @@ -0,0 +1,33 @@ +#include "natives.hpp" +#include "pointers.hpp" +#include "script.hpp" +#include "services/gta_data/gta_data_service.hpp" +#include "thread_pool.hpp" +#include "views/view.hpp" + +namespace big +{ + void view::gta_cache() + { + auto ped_count = g_gta_data_service->peds().size(); + auto veh_count = g_gta_data_service->vehicles().size(); + auto wep_count = g_gta_data_service->weapons().size(); + + components::sub_title("GTA cache stats:"); + ImGui::Text("Peds Cached: %d\nVehicles Cached: %d\nWeapons Cached: %d", ped_count, veh_count, wep_count); + + if (components::button("Rebuild Cache in Online")) + { + g_gta_data_service->set_state(eGtaDataUpdateState::NEEDS_UPDATE); + + if (!*g_pointers->m_is_session_started) + { + g_gta_data_service->update_in_online(); + } + else + { + g_gta_data_service->update_now(); + } + } + } +} diff --git a/src/views/settings/view_translation_settings.cpp b/src/views/settings/view_translation_settings.cpp index e5d4bcbd..9f8da874 100644 --- a/src/views/settings/view_translation_settings.cpp +++ b/src/views/settings/view_translation_settings.cpp @@ -1,26 +1,38 @@ -#include "views/view.hpp" - -namespace big -{ - void view::translation_settings() - { - const auto& language_entries = g_translation_service.available_translations(); - const auto current_pack = g_translation_service.current_language_pack(); - - ImGui::Text("SETTINGS_LANGUAGES"_T.data()); - if (ImGui::BeginCombo("##combo-languages", 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(); - } - } -} +#include "thread_pool.hpp" +#include "views/view.hpp" + + +namespace big +{ + void view::translation_settings() + { + const auto& language_entries = g_translation_service.available_translations(); + const auto current_pack = g_translation_service.current_language_pack(); + + ImGui::Text("SETTINGS_LANGUAGES"_T.data()); + if (ImGui::BeginCombo("##combo-languages", 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(); + } + + if (components::button("Force Update Languages")) + { + g_thread_pool->push([] + { + g_translation_service.update_language_packs(); + + g_notification_service->push("Translations", "Finished updating translations."); + }); + } + } +} diff --git a/src/views/view.hpp b/src/views/view.hpp index 08d1e373..6dc1b437 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -57,10 +57,11 @@ namespace big static void gta_data(); static void creator(); static void train(); - static void water(); static void blackhole(); static void model_swapper(); static void nearby(); + static void world(); + static void gta_cache(); static void player_info(); static void player_troll(); diff --git a/src/views/view_vehicle_control.cpp b/src/views/view_vehicle_control.cpp index 1bcd61d8..32a122dc 100644 --- a/src/views/view_vehicle_control.cpp +++ b/src/views/view_vehicle_control.cpp @@ -37,7 +37,7 @@ namespace big ImGui::BeginGroup(); ImGui::SetNextItemWidth(200); - if (ImGui::BeginCombo("##alldoorslock", "All doors")) + if (ImGui::BeginCombo("##alldoorslock", "VEHICLE_CONTROLLER_ALL_DOORS"_T.data())) { for (int lockindex = 0; lockindex < MAX_VEHICLE_LOCK_STATES; lockindex++) { @@ -52,7 +52,7 @@ namespace big } ImGui::SameLine(); - if (ImGui::Button("Open all")) + if (components::button("OPEN_ALL_DOORS"_T)) { g_fiber_pool->queue_job([=] { g_vehicle_control_service.operate_door(eDoorId::VEH_EXT_DOOR_INVALID_ID, true); @@ -60,7 +60,7 @@ namespace big } ImGui::SameLine(); - if (ImGui::Button("Close all")) + if (components::button("CLOSE_ALL_DOORS"_T)) { g_fiber_pool->queue_job([=] { g_vehicle_control_service.operate_door(eDoorId::VEH_EXT_DOOR_INVALID_ID, false); @@ -75,6 +75,7 @@ namespace big for (int i = 0; i < MAX_VEHICLE_DOORS; i++) { + ImGui::PushID(i); if (!g_vehicle_control_service.m_controlled_vehicle.doors[i].valid) continue; ImGui::SetNextItemWidth(200); @@ -94,15 +95,15 @@ namespace big ImGui::SameLine(300); - std::string buttonlabel = g_vehicle_control_service.m_controlled_vehicle.doors[i].open ? "Close" : "Open"; - buttonlabel.append("##").append(std::to_string(i)); - if (ImGui::Button(buttonlabel.data())) + const auto button_label = g_vehicle_control_service.m_controlled_vehicle.doors[i].open ? "CLOSE"_T : "OPEN"_T; + if (components::button(button_label)) { g_fiber_pool->queue_job([=] { g_vehicle_control_service.operate_door((eDoorId)i, !g_vehicle_control_service.m_controlled_vehicle.doors[i].open); }); } + ImGui::PopID(); } @@ -118,21 +119,21 @@ namespace big "Rear", }; - if (ImGui::Button("Toggle lights")) + if (components::button("VEHICLE_CONTROLLER_TOGGLE_LIGHTS"_T)) { g_fiber_pool->queue_job([=] { g_vehicle_control_service.operate_lights(!g_vehicle_control_service.m_controlled_vehicle.headlights, false); }); } ImGui::SameLine(); - if (ImGui::Button("Toggle High beams")) + if (components::button("VEHICLE_CONTROLLER_TOGGLE_HIGH_BEAMS"_T)) { g_fiber_pool->queue_job([=] { g_vehicle_control_service.operate_lights(g_vehicle_control_service.m_controlled_vehicle.headlights, !g_vehicle_control_service.m_controlled_vehicle.highbeams); }); } - if (ImGui::Button("Interior lights on")) + if (components::button("VEHICLE_CONTROLLER_INTERIOR_LIGHTS_ON"_T)) { g_fiber_pool->queue_job([=] { if (g.window.vehicle_control.operation_animation) @@ -141,7 +142,7 @@ namespace big }); } ImGui::SameLine(); - if (ImGui::Button("Interior lights off")) + if (components::button("VEHICLE_CONTROLLER_INTERIOR_LIGHTS_OFF"_T)) { g_fiber_pool->queue_job([=] { if (g.window.vehicle_control.operation_animation) @@ -150,7 +151,7 @@ namespace big }); } - ImGui::Text("Neon lights"); + ImGui::Text("VEHICLE_CONTROLLER_NEON_LIGHTS"_T.data()); ImGui::Separator(); for (int i = 0; i < 4; i++) @@ -180,18 +181,18 @@ namespace big static int movespeed = 1; - if (ImGui::RadioButton("Walk", movespeed == 1)) + if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_WALKING"_T.data(), movespeed == 1)) movespeed = 1; ImGui::SameLine(); - if (ImGui::RadioButton("Run", movespeed == 2)) + if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_RUNNING"_T.data(), movespeed == 2)) movespeed = 2; ImGui::SameLine(); - if (ImGui::RadioButton("Sprint", movespeed == 3)) + if (ImGui::RadioButton("VEHICLE_CONTROLLER_ENTER_VEHICLE_SPEED_SPRINTING"_T.data(), movespeed == 3)) movespeed = 3; for (int i = 0; i < 6; i++) { - if (ImGui::Button(seatnames[i])) + if (components::button(seatnames[i])) { g_fiber_pool->queue_job([=] { if (g.window.vehicle_control.operation_animation) @@ -214,7 +215,7 @@ namespace big if (g_vehicle_control_service.m_controlled_vehicle.isconvertible) { - if (ImGui::Button(g_vehicle_control_service.m_controlled_vehicle.convertibelstate ? "Raise" : "Lower")) + if (components::button(g_vehicle_control_service.m_controlled_vehicle.convertibelstate ? "Raise" : "Lower")) { g_fiber_pool->queue_job([=] { if (g.window.vehicle_control.operation_animation) diff --git a/src/views/world/view_orbital_drone.cpp b/src/views/world/view_orbital_drone.cpp index 51a685ec..899cbb38 100644 --- a/src/views/world/view_orbital_drone.cpp +++ b/src/views/world/view_orbital_drone.cpp @@ -10,22 +10,21 @@ namespace big { ImGui::Separator(); ImGui::BeginGroup(); - ImGui::Text("press 'Look behind' (C/R3 by default) to activate\npress WASD buttons or Left thumbstick to navigate\nUse scroll wheel/Mouse or Right thumbstick to zoom\npress E/Q or L1/R1 to modify speed\npress 'Jump' (Space/X/Square by default) to lock on an entity\npress 'Fire' (Mouse button 1/Right trigger by default) to Obliterate\npress Enter or A/X by default to teleport to target"); + ImGui::Text("ORBITAL_DRONE_USAGE_DESCR"_T.data()); ImGui::EndGroup(); ImGui::Separator(); ImGui::BeginGroup(); - ImGui::Checkbox("Detect player on lock", &g.world.orbital_drone.detect_player); + ImGui::Checkbox("ORBITAL_DRONE_AUTO_LOCK_ON_PLAYER"_T.data(), &g.world.orbital_drone.detect_player); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("if enabled, changes the selected player to the one it detects upon locking on an entity"); - ImGui::Text("All explosions will be blamed on the selected player, defaulting to the local player"); + ImGui::TextWrapped("ORBITAL_DRONE_AUTO_LOCK_ON_PLAYER_TOOLTIP"_T.data()); ImGui::EndTooltip(); } - ImGui::Text("Adjust fast modifier"); + ImGui::Text("ORBITAL_DRONE_HIGH_SPEED_MULTIPLIER"_T.data()); ImGui::SliderFloat("##fastspeed", &g.world.orbital_drone.nav_ovverride_fast, 1.f, 10.f); - ImGui::Text("Adjust slow modifier"); + ImGui::Text("ORBITAL_DRONE_LOW_SPEED_MULTIPLIER"_T.data()); ImGui::SliderFloat("##slowspeed", &g.world.orbital_drone.nav_ovverride_slow, 0.f, 1.f); ImGui::EndGroup(); } diff --git a/src/views/world/view_time_and_weather.cpp b/src/views/world/view_time_and_weather.cpp index af568e50..8d3b76f7 100644 --- a/src/views/world/view_time_and_weather.cpp +++ b/src/views/world/view_time_and_weather.cpp @@ -1,41 +1,41 @@ -#include "fiber_pool.hpp" -#include "util/session.hpp" -#include "views/view.hpp" - -namespace big -{ - void view::time_and_weather() - { - if (ImGui::TreeNode("LOCAL_TIME"_T.data())) - { - ImGui::Checkbox("OVERRIDE_TIME"_T.data(), &g.session.override_time); - - if (g.session.override_time) - { - ImGui::SliderInt("HOUR"_T.data(), &g.session.custom_time.hour, 0, 23); - ImGui::SliderInt("MINUTE"_T.data(), &g.session.custom_time.minute, 0, 59); - ImGui::SliderInt("SECOND"_T.data(), &g.session.custom_time.second, 0, 59); - } - - ImGui::TreePop(); - } - - if (ImGui::TreeNode("LOCAL_WEATHER"_T.data())) - { - components::button("CLEAR_OVERRIDE"_T, [] { - MISC::CLEAR_OVERRIDE_WEATHER(); - }); - - if (ImGui::ListBox("##weather-listbox", &g.session.local_weather, session::weathers, 15)) - { - g_fiber_pool->queue_job([] { - session::local_weather(); - }); - - ImGui::ListBoxFooter(); - } - - ImGui::TreePop(); - } - } -} +#include "fiber_pool.hpp" +#include "util/session.hpp" +#include "views/view.hpp" + +namespace big +{ + void view::time_and_weather() + { + if (ImGui::TreeNode("LOCAL_TIME"_T.data())) + { + ImGui::Checkbox("OVERRIDE_TIME"_T.data(), &g.session.override_time); + + if (g.session.override_time) + { + ImGui::SliderInt("HOUR"_T.data(), &g.session.custom_time.hour, 0, 23); + ImGui::SliderInt("MINUTE"_T.data(), &g.session.custom_time.minute, 0, 59); + ImGui::SliderInt("SECOND"_T.data(), &g.session.custom_time.second, 0, 59); + } + + ImGui::TreePop(); + } + + if (ImGui::TreeNode("LOCAL_WEATHER"_T.data())) + { + components::button("CLEAR_OVERRIDE"_T, [] { + MISC::CLEAR_OVERRIDE_WEATHER(); + }); + + if (ImGui::ListBox("##weather-listbox", &g.session.local_weather, session::weathers, 15)) + { + g_fiber_pool->queue_job([] { + session::local_weather(); + }); + + ImGui::ListBoxFooter(); + } + + ImGui::TreePop(); + } + } +} diff --git a/src/views/world/view_water.cpp b/src/views/world/view_water.cpp deleted file mode 100644 index 22107675..00000000 --- a/src/views/world/view_water.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "fiber_pool.hpp" -#include "views/view.hpp" - -namespace big -{ - void view::water() - { - components::command_checkbox<"partwater">(); - } -} \ No newline at end of file diff --git a/src/views/world/view_world.cpp b/src/views/world/view_world.cpp new file mode 100644 index 00000000..122546bb --- /dev/null +++ b/src/views/world/view_world.cpp @@ -0,0 +1,19 @@ +#include "views/view.hpp" + +namespace big +{ + void view::world() + { + components::sub_title("GUI_TAB_TIME_N_WEATHER"_T); + { + view::time_and_weather(); + } + + ImGui::Separator(); + + components::sub_title("GUI_TAB_WATER"_T); + { + components::command_checkbox<"partwater">(); + } + } +} \ No newline at end of file