diff --git a/tf2_bot_detector/ConsoleLog/ConsoleLines.cpp b/tf2_bot_detector/ConsoleLog/ConsoleLines.cpp index a8de307c..20e0f806 100644 --- a/tf2_bot_detector/ConsoleLog/ConsoleLines.cpp +++ b/tf2_bot_detector/ConsoleLog/ConsoleLines.cpp @@ -163,9 +163,20 @@ void ChatConsoleLine::Print(const PrintArgs& args) const ImGuiDesktop::ScopeGuards::ID id(this); ImGui::BeginGroup(); - ProcessChatMessage(*this, args.m_Settings.m_Theme, - [](const ImVec4& color, const std::string_view& msg) { ImGui::TextFmt(color, msg); }, - [] { ImGui::SameLine(); }); + ProcessChatMessage( + *this, + args.m_Settings.m_Theme, + [](const ImVec4& color, const std::string_view& msg) { + // TODO: selectable text? + //ImGuiDesktop::TextColor scope(color); + //auto message = mh::fmtstr<3073>(msg); + //std::string str = message.str(); + //ImGui::InputText("", &str, ImGuiInputTextFlags_ReadOnly); + + ImGui::TextFmt(color, msg); + }, + [] { ImGui::SameLine(); } + ); ImGui::EndGroup(); const bool isHovered = ImGui::IsItemHovered(); @@ -175,6 +186,7 @@ void ChatConsoleLine::Print(const PrintArgs& args) const if (ImGui::MenuItem("Copy")) { std::string fullText; + ImGui::Selectable("test"); ProcessChatMessage(*this, args.m_Settings.m_Theme, [&](const ImVec4&, const std::string_view& msg) @@ -188,6 +200,31 @@ void ChatConsoleLine::Print(const PrintArgs& args) const ImGui::SetClipboardText(fullText.c_str()); } + + // not copypasted from scoreboard, fiy + if (ImGui::BeginMenu("Mark")) + { + std::string mark_reason; + + IModeratorLogic* modLogic = &args.m_MainWindow.GetModLogic(); + + ImGui::InputTextWithHint("", "Reason", &mark_reason, ImGuiInputTextFlags_CallbackAlways); + for (int i = 0; i < (int)PlayerAttribute::COUNT; i++) + { + const auto attr = PlayerAttribute(i); + const bool existingMarked = (bool)modLogic->HasPlayerAttributes(m_PlayerSteamID, attr, AttributePersistence::Saved); + + if (ImGui::MenuItem(mh::fmtstr<512>("{:v}", mh::enum_fmt(attr)).c_str(), nullptr, existingMarked)) + { + if (modLogic->SetPlayerAttribute(m_PlayerSteamID, m_PlayerName, attr, AttributePersistence::Saved, !existingMarked, mark_reason)) + Log("Manually marked {}{} {:v}", m_PlayerName, (existingMarked ? " NOT" : ""), mh::enum_fmt(attr)); + } + } + + ImGui::EndMenu(); + } + + ImGui::TextFmt(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), m_PlayerSteamID.str()); } else if (isHovered) { diff --git a/tf2_bot_detector/ModeratorLogic.cpp b/tf2_bot_detector/ModeratorLogic.cpp index 7e3a844b..076b7eee 100644 --- a/tf2_bot_detector/ModeratorLogic.cpp +++ b/tf2_bot_detector/ModeratorLogic.cpp @@ -55,6 +55,7 @@ namespace bool InitiateVotekick(const IPlayer& player, KickReason reason, const PlayerMarks* marks = nullptr) override; bool SetPlayerAttribute(const IPlayer& id, PlayerAttribute markType, AttributePersistence persistence, bool set = true, std::string proof = "") override; + bool SetPlayerAttribute(const SteamID& id, std::string name, PlayerAttribute markType, AttributePersistence persistence, bool set = true, std::string proof = "") override; std::optional TryGetMyTeam() const; TeamShareResult GetTeamShareResult(const SteamID& id) const override; @@ -857,10 +858,15 @@ void ModeratorLogic::ProcessPlayerActions() } bool ModeratorLogic::SetPlayerAttribute(const IPlayer& player, PlayerAttribute attribute, AttributePersistence persistence, bool set, std::string proof) +{ + return SetPlayerAttribute(player.GetSteamID(), player.GetNameUnsafe(), attribute, persistence, set, proof); +} + +bool ModeratorLogic::SetPlayerAttribute(const SteamID& player, std::string name, PlayerAttribute attribute, AttributePersistence persistence, bool set, std::string proof) { bool attributeChanged = false; - m_PlayerList.ModifyPlayer(player.GetSteamID(), [&](PlayerListData& data) + m_PlayerList.ModifyPlayer(player, [&](PlayerListData& data) { PlayerAttributesList& attribs = [&]() -> PlayerAttributesList& { @@ -883,7 +889,7 @@ bool ModeratorLogic::SetPlayerAttribute(const IPlayer& player, PlayerAttribute a data.m_LastSeen->m_Time = m_World->GetCurrentTime(); - if (const auto& name = player.GetNameUnsafe(); !name.empty()) + if (!name.empty()) data.m_LastSeen->m_PlayerName = name; if (proof != "" && !data.proofExists(proof)) { diff --git a/tf2_bot_detector/ModeratorLogic.h b/tf2_bot_detector/ModeratorLogic.h index 0533a3ed..1620e038 100644 --- a/tf2_bot_detector/ModeratorLogic.h +++ b/tf2_bot_detector/ModeratorLogic.h @@ -53,7 +53,9 @@ namespace tf2_bot_detector virtual PlayerMarks GetPlayerAttributes(const SteamID& id) const = 0; virtual PlayerMarks HasPlayerAttributes(const SteamID& id, const PlayerAttributesList& attributes, AttributePersistence persistence = AttributePersistence::Any) const = 0; - virtual bool SetPlayerAttribute(const IPlayer& player, PlayerAttribute markType, AttributePersistence persistence, bool set = true, std::string reason = "") = 0; + + virtual bool SetPlayerAttribute(const IPlayer& id, PlayerAttribute markType, AttributePersistence persistence, bool set = true, std::string proof = "") = 0; + virtual bool SetPlayerAttribute(const SteamID& id, std::string name, PlayerAttribute markType, AttributePersistence persistence, bool set = true, std::string proof = "") = 0; virtual TeamShareResult GetTeamShareResult(const SteamID& id) const = 0; diff --git a/tf2_bot_detector/UI/MainWindow.cpp b/tf2_bot_detector/UI/MainWindow.cpp index 1b4ed7f7..7770c927 100644 --- a/tf2_bot_detector/UI/MainWindow.cpp +++ b/tf2_bot_detector/UI/MainWindow.cpp @@ -687,6 +687,12 @@ void MainWindow::OnDrawMenuBar() { ImGui::Separator(); + if (ImGui::MenuItem("FakeState")) + { + // TODO: fake a in-game state so i dont have to launch tf2 every time i want to debug this + // though i don't think i have the effort to do this tbf + } + if (ImGui::MenuItem("Crash")) { struct Test diff --git a/tf2_bot_detector/UI/MainWindow.h b/tf2_bot_detector/UI/MainWindow.h index 51d1deda..59167fa7 100644 --- a/tf2_bot_detector/UI/MainWindow.h +++ b/tf2_bot_detector/UI/MainWindow.h @@ -193,6 +193,7 @@ namespace tf2_bot_detector }; std::optional m_MainState; + public: IModeratorLogic& GetModLogic() { return *m_MainState.value().m_ModeratorLogic; } const IModeratorLogic& GetModLogic() const { return *m_MainState.value().m_ModeratorLogic; } SponsorsList& GetSponsorsList() { return m_MainState.value().m_SponsorsList; }