using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using Dalamud.Plugin; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.UI; using LLib.GameUI; using LLib.ImGui; using Questionable.Controller; using Questionable.Controller.GameUi; using Questionable.Data; using Questionable.Functions; using Questionable.Model; using Questionable.Model.Questing; using Questionable.Windows.QuestComponents; namespace Questionable.Windows; internal sealed class QuestSelectionWindow : LWindow { private const string WindowId = "###QuestionableQuestSelection"; private readonly QuestData _questData; private readonly IGameGui _gameGui; private readonly IChatGui _chatGui; private readonly QuestFunctions _questFunctions; private readonly QuestController _questController; private readonly QuestRegistry _questRegistry; private readonly IDalamudPluginInterface _pluginInterface; private readonly TerritoryData _territoryData; private readonly IClientState _clientState; private readonly UiUtils _uiUtils; private readonly QuestTooltipComponent _questTooltipComponent; private List _quests = new List(); private List _offeredQuests = new List(); private bool _onlyAvailableQuests = true; public QuestSelectionWindow(QuestData questData, IGameGui gameGui, IChatGui chatGui, QuestFunctions questFunctions, QuestController questController, QuestRegistry questRegistry, IDalamudPluginInterface pluginInterface, TerritoryData territoryData, IClientState clientState, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent) : base("Quest Selection###QuestionableQuestSelection") { _questData = questData; _gameGui = gameGui; _chatGui = chatGui; _questFunctions = questFunctions; _questController = questController; _questRegistry = questRegistry; _pluginInterface = pluginInterface; _territoryData = territoryData; _clientState = clientState; _uiUtils = uiUtils; _questTooltipComponent = questTooltipComponent; base.Size = new Vector2(500f, 200f); base.SizeCondition = ImGuiCond.Once; base.SizeConstraints = new WindowSizeConstraints { MinimumSize = new Vector2(500f, 200f) }; } public unsafe void OpenForTarget(IGameObject? gameObject) { if (gameObject != null) { uint baseId = gameObject.BaseId; string value = gameObject.Name.ToString(); base.WindowName = $"Quests starting with {value} [{baseId}]{"###QuestionableQuestSelection"}"; _quests = _questData.GetAllByIssuerDataId(baseId); if (_gameGui.TryGetAddonByName("SelectIconString", out var addonPtr)) { List answers = InteractionUiController.GetChoices(addonPtr); _offeredQuests = _quests.Where((IQuestInfo x) => answers.Any((string y) => GameFunctions.GameStringEquals(x.Name, y))).ToList(); } else { _offeredQuests = new List(); } } else { _quests = new List(); _offeredQuests = new List(); } base.IsOpenAndUncollapsed = _quests.Count > 0; } public unsafe void OpenForCurrentZone() { ushort territoryId = _clientState.TerritoryType; string nameAndId = _territoryData.GetNameAndId(territoryId); base.WindowName = "Quests starting in " + nameAndId + "###QuestionableQuestSelection"; _quests = (from x in _questRegistry.AllQuests where x.FindSequence(0)?.FindStep(0)?.TerritoryId == territoryId select _questData.GetQuestInfo(x.Id)).ToList(); foreach (ref MarkerInfo unacceptedQuestMarker in Map.Instance()->UnacceptedQuestMarkers) { MarkerInfo current = unacceptedQuestMarker; QuestId questId = QuestId.FromRowId(current.ObjectiveId); if (_quests.All((IQuestInfo q) => q.QuestId != questId)) { _quests.Add(_questData.GetQuestInfo(questId)); } } _offeredQuests = new List(); base.IsOpenAndUncollapsed = true; } public override void OnClose() { _quests = new List(); _offeredQuests = new List(); } public override void DrawContent() { if (_offeredQuests.Count != 0) { ImGui.Checkbox("Only show quests currently offered", ref _onlyAvailableQuests); } using ImRaii.IEndObject endObject = ImRaii.Table("QuestSelection", 4, ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY); if (!endObject) { ImGui.Text("Not table"); return; } float x; using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push()) { x = ImGui.CalcTextSize(FontAwesomeIcon.Copy.ToIconString()).X; } ImGui.PushFont(UiBuilder.IconFont); float initWidthOrWeight = ImGui.CalcTextSize(FontAwesomeIcon.Copy.ToIconString()).X + ImGui.CalcTextSize(FontAwesomeIcon.Copy.ToIconString()).X + ImGui.CalcTextSize(FontAwesomeIcon.Copy.ToIconString()).X + 6f * ImGui.GetStyle().FramePadding.X + 2f * ImGui.GetStyle().ItemSpacing.X; ImGui.PopFont(); ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed, 50f * ImGui.GetIO().FontGlobalScale); ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, x); ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.None, 200f); ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.WidthFixed, initWidthOrWeight); ImGui.TableHeadersRow(); foreach (IQuestInfo item in (_offeredQuests.Count != 0 && _onlyAvailableQuests) ? _offeredQuests : _quests) { ImGui.TableNextRow(); string text = item.QuestId.ToString(); Quest quest; bool flag = _questRegistry.TryGetQuest(item.QuestId, out quest); if (ImGui.TableNextColumn()) { ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(text); } if (ImGui.TableNextColumn()) { ImGui.AlignTextToFramePadding(); var (col, icon, _) = _uiUtils.GetQuestStyle(item.QuestId); using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push()) { if (flag) { ImGui.TextColored(in col, icon.ToIconString()); } else { ImGui.TextColored(ImGuiColors.DalamudGrey, icon.ToIconString()); } } if (ImGui.IsItemHovered()) { _questTooltipComponent.Draw(item); } } if (ImGui.TableNextColumn()) { ImGui.AlignTextToFramePadding(); if (quest != null && quest.Root.Disabled) { using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push()) { ImGui.TextColored(ImGuiColors.DalamudOrange, FontAwesomeIcon.Ban.ToIconString()); ImGui.SameLine(); } } ImGui.TextUnformatted(item.Name); } if (!ImGui.TableNextColumn()) { continue; } using (ImRaii.PushId(text)) { bool num = ImGuiComponents.IconButton(FontAwesomeIcon.Copy); if (ImGui.IsItemHovered()) { ImGui.SetTooltip("Copy as file name"); } if (num) { CopyToClipboard(item, suffix: true); } else if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { CopyToClipboard(item, suffix: false); } ImGui.SameLine(); if (quest == null) { continue; } EInteractionType? eInteractionType = quest.FindSequence(0)?.LastStep()?.InteractionType; if (!eInteractionType.HasValue || eInteractionType != EInteractionType.AcceptQuest || !_questFunctions.IsReadyToAcceptQuest(item.QuestId)) { continue; } ImGui.BeginDisabled(_questController.NextQuest != null || _questController.SimulatedQuest != null); bool num2 = ImGuiComponents.IconButton(FontAwesomeIcon.Play); if (ImGui.IsItemHovered()) { ImGui.SetTooltip("Start as next quest"); } if (num2) { _questController.SetNextQuest(quest); if (!_questController.ManualPriorityQuests.Contains(quest)) { _questController.ManualPriorityQuests.Insert(0, quest); } _questController.Start("QuestSelectionWindow"); } ImGui.SameLine(); bool num3 = ImGuiComponents.IconButton(FontAwesomeIcon.AngleDoubleRight); if (ImGui.IsItemHovered()) { ImGui.SetTooltip("Set as next quest"); } if (num3) { _questController.SetNextQuest(quest); } ImGui.EndDisabled(); } } } private void CopyToClipboard(IQuestInfo quest, bool suffix) { string text = $"{quest.QuestId}_{quest.SimplifiedName}{(suffix ? ".json" : "")}"; ImGui.SetClipboardText(text); _chatGui.Print("Copied '" + text + "' to clipboard"); } }