From e5a33e2b323e7b00f8e050f1f5302eeb79c1cb6b Mon Sep 17 00:00:00 2001 From: DayibBaba <79384354+DayibBaba@users.noreply.github.com> Date: Fri, 30 Jun 2023 20:36:45 +0200 Subject: [PATCH] Custom location system (#1567) --- src/backend/backend.cpp | 4 ++ src/util/teleport.hpp | 91 ++++++++++++++++++++++++++ src/views/self/view_teleport.cpp | 86 ++++++++++++++++++++++++ src/views/world/view_squad_spawner.cpp | 2 + 4 files changed, 183 insertions(+) diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp index 653f2608..c8656621 100644 --- a/src/backend/backend.cpp +++ b/src/backend/backend.cpp @@ -11,6 +11,8 @@ #include "services/tunables/tunables_service.hpp" #include "services/vehicle/vehicle_control_service.hpp" #include "thread_pool.hpp" +#include "util/teleport.hpp" +#include "services/squad_spawner/squad_spawner.hpp" namespace big @@ -21,6 +23,8 @@ namespace big command->refresh(); register_script_patches(); + teleport::fetch_saved_locations(); + g_squad_spawner_service.fetch_squads(); while (g_running) { diff --git a/src/util/teleport.hpp b/src/util/teleport.hpp index e8dcebc3..58161892 100644 --- a/src/util/teleport.hpp +++ b/src/util/teleport.hpp @@ -8,6 +8,97 @@ namespace big::teleport { + struct telelocation + { + std::string name; + float x, y, z; + }; + + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(telelocation, name, x, y, z); + + inline std::map> all_saved_locations; + + inline std::filesystem::path get_telelocations_file_path() + { + return g_file_manager->get_project_file("telelocations.json").get_path(); + } + + inline bool fetch_saved_locations() + { + all_saved_locations.clear(); + + auto path = get_telelocations_file_path(); + std::ifstream file(path, std::ios::binary); + + try + { + if (!file.is_open()) + return false; + + nlohmann::json j; + file >> j; + all_saved_locations = j.get>>(); + + return true; + } + catch (const std::exception& e) + { + LOG(WARNING) << "Failed fetching saved locations: " << e.what() << '\n'; + return false; + } + + return false; + } + + inline bool save_new_location(const std::string& category, telelocation t) + { + const auto& pair = all_saved_locations.insert({category, {t}}); + if (!pair.second) + { + pair.first->second.push_back(t); + } + + auto path = get_telelocations_file_path(); + + std::ofstream file_out(path, std::ofstream::trunc | std::ofstream::binary); + if (!file_out.is_open()) + return false; + + nlohmann::json j = all_saved_locations; + file_out << j.dump(4); + file_out.close(); + + return true; + } + + inline bool delete_saved_location(const std::string& category, const std::string& location_name) + { + auto path = get_telelocations_file_path(); + + const auto& it = all_saved_locations.find(category); + if (it == all_saved_locations.end()) + return false; + + std::erase_if(it->second, [location_name](telelocation t) { + return t.name == location_name; + }); + + if (!it->second.size()) + { + all_saved_locations.erase(category); + } + + std::ofstream file_out(path, std::ofstream::trunc | std::ofstream::binary); + if (!file_out.is_open()) + return false; + + nlohmann::json j = all_saved_locations; + file_out << j.dump(4); + file_out.close(); + + return true; + } + inline bool teleport_player_to_coords(player_ptr player, Vector3 coords) { Entity ent; diff --git a/src/views/self/view_teleport.cpp b/src/views/self/view_teleport.cpp index f77c7bb7..da271b01 100644 --- a/src/views/self/view_teleport.cpp +++ b/src/views/self/view_teleport.cpp @@ -141,5 +141,91 @@ namespace big ImGui::Text(std::vformat("IPL_POSITION"_T, std::make_format_args(selected_ipl.location.x, selected_ipl.location.y, selected_ipl.location.z)) .data()); + + ImGui::SeparatorText("Custom Locations"); + + ImGui::BeginGroup(); + static std::string new_location_name; + static std::string category = "Default"; + static teleport::telelocation deletion_telelocation; + + if (!std::string(deletion_telelocation.name).empty()) + ImGui::OpenPopup("##deletelocation"); + + if (ImGui::BeginPopupModal("##deletelocation")) + { + ImGui::Text("Are you sure you want to delete %s?", deletion_telelocation.name); + + if (ImGui::Button("Yes")) + { + teleport::delete_saved_location(category, deletion_telelocation.name); + deletion_telelocation.name = ""; + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("No")) + { + deletion_telelocation.name = ""; + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + + ImGui::PushItemWidth(300); + components::input_text_with_hint("Category", "Category", &category); + components::input_text_with_hint("Location name", "New location", &new_location_name); + ImGui::PopItemWidth(); + + components::button("Save current location", [] { + teleport::save_new_location(category, {new_location_name, self::pos.x, self::pos.y, self::pos.z}); + }); + + ImGui::BeginGroup(); + components::small_text("Categories"); + if (ImGui::BeginListBox("##categories", ImVec2(250, 150))) + { + for (auto& l : teleport::all_saved_locations | std::ranges::views::keys) + { + if (ImGui::Selectable(l.data(), l == category)) + { + category = l; + } + } + ImGui::EndListBox(); + } + ImGui::EndGroup(); + ImGui::SameLine(); + ImGui::BeginGroup(); + components::small_text("Locations"); + if (ImGui::BeginListBox("##telelocations", ImVec2(250, 150))) + { + if (teleport::all_saved_locations.find(category) != teleport::all_saved_locations.end()) + { + for (const auto& l : teleport::all_saved_locations.at(category)) + { + if (ImGui::Selectable(l.name.data())) + { + if (GetAsyncKeyState(VK_SHIFT) & 0x8000) + { + deletion_telelocation = l; + } + else + g_fiber_pool->queue_job([l] { + teleport::teleport_player_to_coords(g_player_service->get_self(), {l.x, l.y, l.z}); + }); + } + } + } + + ImGui::EndListBox(); + } + + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Shift click to delete"); + + ImGui::EndGroup(); + + ImGui::EndGroup(); } } diff --git a/src/views/world/view_squad_spawner.cpp b/src/views/world/view_squad_spawner.cpp index 5ec21629..b073786a 100644 --- a/src/views/world/view_squad_spawner.cpp +++ b/src/views/world/view_squad_spawner.cpp @@ -103,6 +103,8 @@ namespace big } ImGui::EndCombo(); } + if(ImGui::IsItemHovered()) + ImGui::SetTooltip("Shift click to delete"); ImGui::SeparatorText("Squad Details");