From 632faefb1ad9006cce2269b0b454d8f233529993 Mon Sep 17 00:00:00 2001 From: Deji Date: Sun, 15 Sep 2024 23:38:47 +0100 Subject: [PATCH] Add in-game overlay --- src/Config.h | 16 ++++++++ src/Stealthometer.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++ src/Stealthometer.h | 3 ++ 3 files changed, 107 insertions(+) diff --git a/src/Config.h b/src/Config.h index c527a06..50f4bf3 100644 --- a/src/Config.h +++ b/src/Config.h @@ -2,11 +2,23 @@ #include #include +enum class DockMode +{ + None, + TopLeft, + TopRight, + BottomLeft, + BottomRight, +}; + struct ConfigData { bool externalWindow = true; bool externalWindowDark = true; bool externalWindowOnTop = false; + bool inGameOverlay = false; + bool inGameOverlayDetailed = false; + DockMode overlayDockMode = DockMode::None; bool liveSplitEnabled = false; std::string liveSplitIP = "127.0.0.1"; uint16_t liveSplitPort = 16834; @@ -22,6 +34,8 @@ class Config data.externalWindow = plugin.GetSettingBool("general", "external_window", data.externalWindow); data.externalWindowDark = plugin.GetSettingBool("general", "external_window_dark", data.externalWindowDark); data.externalWindowOnTop = plugin.GetSettingBool("general", "external_window_on_top", data.externalWindowOnTop); + data.inGameOverlay = plugin.GetSettingBool("general", "overlay", data.inGameOverlay); + data.inGameOverlayDetailed = plugin.GetSettingBool("general", "overlay_detailed", data.inGameOverlayDetailed); data.liveSplitEnabled = plugin.GetSettingBool("livesplit", "enabled", data.liveSplitEnabled); data.liveSplitIP = plugin.GetSetting("livesplit", "ip", data.liveSplitIP); data.liveSplitPort = plugin.GetSettingInt("livesplit", "port", data.liveSplitPort); @@ -36,6 +50,8 @@ class Config plugin.SetSettingBool("general", "external_window", data.externalWindow); plugin.SetSettingBool("general", "external_window_dark", data.externalWindowDark); plugin.SetSettingBool("general", "external_window_on_top", data.externalWindowOnTop); + plugin.SetSettingBool("general", "overlay", data.inGameOverlay); + plugin.SetSettingBool("general", "overlay_detailed", data.inGameOverlayDetailed); plugin.SetSettingBool("livesplit", "enabled", data.liveSplitEnabled); plugin.SetSetting("livesplit", "ip", data.liveSplitIP); plugin.SetSettingInt("livesplit", "port", data.liveSplitPort); diff --git a/src/Stealthometer.cpp b/src/Stealthometer.cpp index 1444a33..7910939 100644 --- a/src/Stealthometer.cpp +++ b/src/Stealthometer.cpp @@ -28,6 +28,8 @@ #include "json.hpp" #include "FixMinMax.h" +using namespace std::string_literals; + #pragma comment(lib, "Ws2_32.lib") CMRC_DECLARE(stealthometer); @@ -274,11 +276,23 @@ auto Stealthometer::DrawSettingsUI(bool focused) -> void { config.Save(); } + if (ImGui::Button("Overlay")) { + cfg.inGameOverlay = true; + config.Save(); + } + ImGui::SameLine(); + if (ImGui::Checkbox("Detailed", &cfg.inGameOverlayDetailed)) { + if (cfg.inGameOverlayDetailed) this->window.create(hInstance); + else this->window.destroy(); + config.Save(); + } + if (ImGui::Button("LiveSplit")) this->liveSplitWindowOpen = true; if (ImGui::Button("Kill Stats")) this->killsWindowOpen = true; ImGui::SameLine(); if (ImGui::Button("KO Stats")) this->pacifiesWindowOpen = true; + ImGui::SameLine(); if (ImGui::Button("Misc Stats")) this->miscWindowOpen = true; ImGui::PopFont(); @@ -288,6 +302,79 @@ auto Stealthometer::DrawSettingsUI(bool focused) -> void { ImGui::PopFont(); } +auto Stealthometer::DrawOverlayUI(bool focused) -> void +{ + auto& cfg = config.Get(); + if (!cfg.inGameOverlay) return; + + auto viewportSize = ImGui::GetMainViewport()->Size; + auto flags = static_cast(ImGuiWindowFlags_AlwaysAutoResize); + + if (cfg.overlayDockMode != DockMode::None || !focused) + flags |= ImGuiWindowFlags_NoTitleBar; + + switch (cfg.overlayDockMode) { + case DockMode::TopLeft: + ImGui::SetNextWindowPos({0, 0}); + break; + case DockMode::TopRight: + ImGui::SetNextWindowPos({viewportSize.x - this->overlaySize.x, 0}); + break; + case DockMode::BottomLeft: + ImGui::SetNextWindowPos({0, viewportSize.y - this->overlaySize.y}); + break; + case DockMode::BottomRight: + ImGui::SetNextWindowPos({viewportSize.x - this->overlaySize.x, viewportSize.y - this->overlaySize.y}); + break; + } + + ImGui::PushFont(SDK()->GetImGuiBlackFont()); + if (ImGui::Begin(ICON_MD_PIE_CHART " STATUS", &cfg.inGameOverlay, flags)) { + this->overlaySize = ImGui::GetWindowSize(); + + ImGui::PushFont(SDK()->GetImGuiBoldFont()); + + if (this->displayStats.silentAssassin == SilentAssassinStatus::OK) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255)); + ImGui::Text("Silent Assassin"); + ImGui::PopStyleColor(); + } + else if (this->displayStats.silentAssassin == SilentAssassinStatus::RedeemableCamera) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(217, 109, 0, 255)); + ImGui::Text("Cams"); + ImGui::PopStyleColor(); + } + else if (this->displayStats.silentAssassin == SilentAssassinStatus::RedeemableTarget) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(217, 109, 0, 255)); + ImGui::Text("Target"); + ImGui::PopStyleColor(); + } + else if (this->displayStats.silentAssassin == SilentAssassinStatus::RedeemableCameraAndTarget) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(217, 109, 0, 255)); + ImGui::Text("Cams | Target"); + ImGui::PopStyleColor(); + } + else { + std::string str; + + if (this->displayStats.spotted > 0) + str += "Spotted"; + if (this->displayStats.bodiesFound > 0) + str += (str.empty() ? ""s : " | "s) + "Body Found"s; + if (this->displayStats.civilianKills > 0 || this->displayStats.guardKills > 0) + str += (str.empty() ? ""s : " | "s) + "Non-Target Kill"s; + + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); + ImGui::Text(str.c_str()); + ImGui::PopStyleColor(); + } + + ImGui::PopFont(); + } + ImGui::End(); + ImGui::PopFont(); +} + auto Stealthometer::DrawLiveSplitUI(bool focused) -> void { if (!this->liveSplitWindowOpen) return; @@ -481,6 +568,7 @@ auto Stealthometer::DrawExpandedStatsUI(bool focused) -> void { auto Stealthometer::OnDrawUI(bool focused) -> void { this->DrawExpandedStatsUI(focused); this->DrawLiveSplitUI(focused); + this->DrawOverlayUI(focused); if (!this->statVisibleUI) return; diff --git a/src/Stealthometer.h b/src/Stealthometer.h index 01b870c..ee1c305 100644 --- a/src/Stealthometer.h +++ b/src/Stealthometer.h @@ -51,6 +51,7 @@ class Stealthometer : public IPluginInterface auto DrawSettingsUI(bool focused) -> void; auto DrawExpandedStatsUI(bool focused) -> void; auto DrawLiveSplitUI(bool focused) -> void; + auto DrawOverlayUI(bool focused) -> void; auto IsContractEnded() const -> bool; auto IsRepoIdTargetNPC(const std::string& id) const -> bool; auto GetRepoEntry(const std::string& id) -> const nlohmann::json*; @@ -92,9 +93,11 @@ class Stealthometer : public IPluginInterface bool externalWindowOnTop = false; bool showAllStats = false; bool liveSplitWindowOpen = false; + bool inGameOverlayOpen = false; bool killsWindowOpen = false; bool pacifiesWindowOpen = false; bool miscWindowOpen = false; + ImVec2 overlaySize = {}; bool loadRemovalActive = false; bool isLoadingScreenCheckHasBeenTrue = false;