diff --git a/resource/common/locale/English.toml b/resource/common/locale/English.toml index 46df4a5..df24536 100644 --- a/resource/common/locale/English.toml +++ b/resource/common/locale/English.toml @@ -405,6 +405,9 @@ Wasted = "Wasted!" AddLocation = "Add location" Coordinates = "Coordinates" CustomLocationRemoveOnly = "You can only remove custom location" +CustomMapSize = "Custom map size" +CustomMapSizeHint = "Custom game map size for quick teleport. Only needed for Total Conversion mods (SAxVCxLC)" +Height = "Height" InsertCoord = "Insert coordinates" InvalidCoord = "Invalid coordinates" InvalidLocation = "Invalid location" @@ -420,6 +423,7 @@ TargetBlipText = "Target blip not found. You need to place it on the map first" TeleportCenter = "Teleport to center" TeleportMarker = "Teleport to marker" TeleportToCoord = "Teleport to coordinates" +Width = "Width" [Updater] Failed = "Failed to check for updates" diff --git a/src/datastore.h b/src/datastore.h index 9313698..eb4ae99 100644 --- a/src/datastore.h +++ b/src/datastore.h @@ -22,21 +22,41 @@ public: DataStore(const char* fileName, bool isPathPredefined = false) noexcept; // Returns data from store structure - std::string Get(const char* key, const char* defaultVal) noexcept + std::string Get(const char* key, const char* defaultVal, bool writeOnNone = false) noexcept { if (pTable) { - return (*pTable).at_path(key).value_or(defaultVal); + std::optional option = pTable->at_path(key).value(); + + if (option.has_value()) + { + return option.value(); + } + } + + if (writeOnNone) + { + Set(key, std::string(defaultVal)); } return defaultVal; } template - T Get(const char* key, const T& defaultVal) noexcept + T Get(const char* key, const T& defaultVal, bool writeOnNone = false) noexcept { if (pTable) { - return (*pTable).at_path(key).value_or(defaultVal); + std::optional option = pTable->at_path(key).value(); + + if (option.has_value()) + { + return option.value(); + } + } + + if (writeOnNone) + { + Set(key, defaultVal); } return defaultVal; } diff --git a/src/menu.cpp b/src/menu.cpp index f1f2a6d..299bd3f 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -86,7 +86,8 @@ void Menu::ShowPage() ImGui::Spacing(); ImGui::Spacing(); ImGui::SameLine(); - if (ImGui::Combo(TEXT("Menu.Position"), (int*)&Overlay::m_nSelectedPos, "Custom\0Top left\0Top right\0Bottom left\0Bottom right\0")) + if (ImGui::Combo(TEXT("Menu.Position"), reinterpret_cast(&Overlay::m_nSelectedPos), + "Custom\0Top left\0Top right\0Bottom left\0Bottom right\0")) { gConfig.Set("Overlay.SelectedPosition", static_cast(Overlay::m_nSelectedPos)); } @@ -129,13 +130,13 @@ void Menu::ShowPage() gConfig.Set("Overlay.ShowLocationName", Overlay::m_bLocName); } + ImGui::NextColumn(); + if (ImGui::Checkbox(TEXT("Menu.ShowModelInfo"), &Overlay::m_bModelInfo)) { gConfig.Set("Overlay.ShowModelInfo", Overlay::m_bModelInfo); } - ImGui::NextColumn(); - if (ImGui::Checkbox(TEXT("Menu.ShowPedTasks"), &Overlay::m_bPedTasks)) { gConfig.Set("Overlay.ShowPedTasks", Overlay::m_bPedTasks); diff --git a/src/overlay.cpp b/src/overlay.cpp index fef9fa7..53545f8 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -23,7 +23,7 @@ void Overlay::Init() m_bMemUsage = gConfig.Get("Overlay.ShowMemoryUsage", false); m_bVehHealth = gConfig.Get("Overlay.ShowVehicleHealth", false); m_bVehSpeed = gConfig.Get("Overlay.ShowVehicleSpeed", false); - m_nSelectedPos = (DisplayPos)gConfig.Get("Overlay.SelectedPosition", (int)DisplayPos::BOTTOM_RIGHT); + m_nSelectedPos = (eDisplayPos)gConfig.Get("Overlay.SelectedPosition", (int)eDisplayPos::BottomRight); m_fPos.x = gConfig.Get("Overlay.PosX", 0); m_fPos.y = gConfig.Get("Overlay.PosY", 0); m_fTextCol[0] = gConfig.Get("Overlay.TextColor.Red", 1.0f); @@ -154,6 +154,7 @@ void Overlay::ProcessPedTasks() for (size_t i = 0; i != TASK_SECONDARY_MAX; ++i) { CTask *pTask = pPed->m_pIntelligence->m_TaskMgr.m_aSecondaryTasks[i]; + if (pTask) { const char *name = taskNames[pTask->GetId()]; @@ -379,7 +380,7 @@ void Overlay::ProcessInfoBox() ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; - if (m_nSelectedPos == DisplayPos::CUSTOM) + if (m_nSelectedPos == eDisplayPos::Custom) { if (m_fPos.x != NULL && m_fPos.y != NULL) { @@ -393,25 +394,25 @@ void Overlay::ProcessInfoBox() window_flags |= ImGuiWindowFlags_NoMove; ImVec2 pos, pivot; - if (m_nSelectedPos == DisplayPos::TOP_LEFT) + if (m_nSelectedPos == eDisplayPos::TopLeft) { pos = ImVec2(offset, offset); pivot = ImVec2(0.0f, 0.0f); } - if (m_nSelectedPos == DisplayPos::TOP_RIGHT) + if (m_nSelectedPos == eDisplayPos::TopRight) { pos = ImVec2(io.DisplaySize.x - offset, offset); pivot = ImVec2(1.0f, 0.0f); } - if (m_nSelectedPos == DisplayPos::BOTTOM_LEFT) + if (m_nSelectedPos == eDisplayPos::BottomLeft) { pos = ImVec2(offset, io.DisplaySize.y - offset); pivot = ImVec2(0.0f, 1.0f); } - if (m_nSelectedPos == DisplayPos::BOTTOM_RIGHT) + if (m_nSelectedPos == eDisplayPos::BottomRight) { pos = ImVec2(io.DisplaySize.x - offset, io.DisplaySize.y - offset); pivot = ImVec2(1.0f, 1.0f); diff --git a/src/overlay.h b/src/overlay.h index c7b40fc..e82e5fc 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -11,13 +11,13 @@ class Overlay { private: - enum DisplayPos + enum class eDisplayPos { - CUSTOM, - TOP_LEFT, - TOP_RIGHT, - BOTTOM_LEFT, - BOTTOM_RIGHT + Custom, + TopLeft, + TopRight, + BottomLeft, + BottomRight }; static inline std::vector m_EntityList; static inline const float m_fMaxDistance = 50.0f; @@ -53,7 +53,7 @@ public: static inline bool m_bVehHealth; static inline bool m_bVehSpeed; static inline float m_fTextCol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - static inline DisplayPos m_nSelectedPos = DisplayPos::BOTTOM_RIGHT; + static inline eDisplayPos m_nSelectedPos = eDisplayPos::BottomRight; Overlay() = delete; Overlay(Overlay&) = delete; diff --git a/src/teleport.cpp b/src/teleport.cpp index 1a73a84..4655bf4 100644 --- a/src/teleport.cpp +++ b/src/teleport.cpp @@ -38,6 +38,8 @@ void Teleport::Init() { m_bTeleportMarker = gConfig.Get("Features.TeleportMarker", false); m_bQuickTeleport = gConfig.Get("Features.QuickTeleport", false); + m_fMapSize.x = gConfig.Get("Game.MapSizeX", 6000.0f); + m_fMapSize.y = gConfig.Get("Game.MapSizeY", 6000.0f); Events::processScriptsEvent += [] { @@ -110,8 +112,8 @@ void Teleport::Init() pos.y -= size/2; // Convert image space to map space - pos.x = pos.x / size * 6000; - pos.y = pos.y / size * 6000; + pos.x = pos.x / size * m_fMapSize.x; + pos.y = pos.y / size * m_fMapSize.y; pos.y *= -1; WarpPlayer(CVector(pos.x, pos.y, 0.0f)); @@ -325,7 +327,34 @@ void Teleport::ShowPage() { WarpPlayer(CVector(0, 0, 23)); } -#endif +#endif + ImGui::Dummy(ImVec2(0, 20)); + + if (m_bQuickTeleport) + { + if (ImGui::CollapsingHeader(TEXT("Teleport.CustomMapSize"))) + { + ImGui::TextWrapped(TEXT("Teleport.CustomMapSizeHint")); + ImGui::Spacing(); + if (Widget::InputFloat(TEXT("Teleport.Width"), &m_fMapSize.x, 1.0f, 0.0f, 9999999)) + { + gConfig.Set("Game.MapSizeX", m_fMapSize.x); + } + if (Widget::InputFloat(TEXT("Teleport.Height"), &m_fMapSize.y, 1.0f, 0.0f, 9999999)) + { + gConfig.Set("Game.MapSizeY", m_fMapSize.y); + } + ImGui::Spacing(); + if (ImGui::Button(TEXT("Game.ResetDefault"), Widget::CalcSize())) + { + m_fMapSize = {6000.0f, 6000.0f}; + gConfig.Set("Game.MapSizeX", m_fMapSize.x); + gConfig.Set("Game.MapSizeY", m_fMapSize.y); + } + ImGui::Spacing(); + ImGui::Separator(); + } + } ImGui::EndChild(); } ImGui::EndTabItem(); diff --git a/src/teleport.h b/src/teleport.h index 8bb0521..a2e8e8d 100644 --- a/src/teleport.h +++ b/src/teleport.h @@ -15,6 +15,7 @@ private: static inline bool m_bTeleportMarker; static inline char m_nInputBuffer[INPUT_BUFFER_SIZE]; static inline char m_nLocationBuffer[INPUT_BUFFER_SIZE]; + static inline ImVec2 m_fMapSize; struct TPMarker { diff --git a/src/widget.cpp b/src/widget.cpp index 3a7c917..723a123 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -634,6 +634,43 @@ bool Widget::CheckboxBits(const char* label, uint flag, const char* hint) return rtn; } +bool Widget::InputFloat(const char* label, float *val, float change, float min, float max) +{ + bool state = false; + ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth() / 2.0f); + if (ImGui::InputFloat(std::format("##{}", label).c_str(), val)) + { + if (min != max) + { + *val = (*val < min) ? min : *val; + *val = (*val > max) ? max : *val; + } + state = true; + } + ImGui::SameLine(0.0, 4.0); + int size = ImGui::GetFrameHeight(); + if (ImGui::Button(std::format("-##{}", label).c_str(), ImVec2(size, size))) + { + if (min != max && (*val - change) > min) + { + *val -= change; + } + state = true; + } + ImGui::SameLine(0.0, 4.0); + if (ImGui::Button(std::format("+##{}", label).c_str(), ImVec2(size, size))) + { + if (min != max && (*val + change) < max) + { + *val += change; + } + state = true; + } + ImGui::SameLine(0.0, 4.0); + ImGui::LabelText(label, "%s", label); + return state; +} + void Widget::EditAddr(const char* label, uint address, float min, float def, float max, float mul, float change) { if (ImGui::CollapsingHeader(label)) @@ -665,37 +702,10 @@ void Widget::EditAddr(const char* label, uint address, float min, float def, flo int size = ImGui::GetFrameHeight(); - if (ImGui::InputFloat(("##" + std::string(label)).c_str(), &val)) + if (InputFloat(std::format("Set##{}", label).c_str(), &val, change, min, max)) { - if (val < min) - { - val = min; - } - - if (val > max) - { - val = max; - } patch::SetFloat(address, val / mul); } - - ImGui::SameLine(0.0, 4.0); - if (ImGui::Button("-", ImVec2(size, size)) && (val - change) > min) - { - val -= change; - if (val < min) - patch::SetFloat(address, val / mul); - } - ImGui::SameLine(0.0, 4.0); - if (ImGui::Button("+", ImVec2(size, size)) && (val + change) < max) - { - val += change; - patch::SetFloat(address, val / mul); - } - ImGui::SameLine(0.0, 4.0); - ImGui::Text("Set"); - - ImGui::Spacing(); if (ImGui::Button(("Minimum##" + std::string(label)).c_str(), CalcSize(items))) diff --git a/src/widget.h b/src/widget.h index bd3485a..fa68120 100644 --- a/src/widget.h +++ b/src/widget.h @@ -64,6 +64,9 @@ public: // ImGui::TextFilter with hint support static void Filter(const char* label, ImGuiTextFilter& filter, const char* hint); + // Input Float widget with increment & decrement buttons + static bool InputFloat(const char* label, float *val, float change = 1.0f, float min = -1.0f, float max = -1.0f); + // Draws ResourceStore images in the interface static void ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, ArgCallbackRtnBool verifyFunc = nullptr);