using System; using System.Numerics; using System.Threading.Tasks; using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Windowing; using Dalamud.Plugin; using Dalamud.Plugin.Services; using LLib.GameData; using LLib.ImGui; using Questionable.Controller; using Questionable.Controller.GameUi; using Questionable.Data; using Questionable.Windows.QuestComponents; namespace Questionable.Windows; internal sealed class QuestWindow : ThemedWindow, IPersistableWindowConfig { private static readonly Version PluginVersion = typeof(QuestionablePlugin).Assembly.GetName().Version; private const string TestingSuffix = ""; private readonly IDalamudPluginInterface _pluginInterface; private readonly QuestController _questController; private readonly IObjectTable _objectTable; private readonly IClientState _clientState; private readonly Configuration _configuration; private readonly TerritoryData _territoryData; private readonly ActiveQuestComponent _activeQuestComponent; private readonly ARealmRebornComponent _aRealmRebornComponent; private readonly CreationUtilsComponent _creationUtilsComponent; private readonly EventInfoComponent _eventInfoComponent; private readonly NavigationBarComponent _navigationBarComponent; private readonly QuickAccessButtonsComponent _quickAccessButtonsComponent; private readonly RemainingTasksComponent _remainingTasksComponent; private readonly ManualPriorityComponent _manualPriorityComponent; private readonly SavedPresetsComponent _savedPresetsComponent; private readonly IFramework _framework; private readonly InteractionUiController _interactionUiController; private readonly TitleBarButton _minimizeButton; private int _selectedTab; private int _queueSubTab; public WindowConfig WindowConfig => _configuration.DebugWindowConfig; public bool IsMinimized { get; set; } public bool IsReloading { get; private set; } public QuestWindow(IDalamudPluginInterface pluginInterface, QuestController questController, IObjectTable objectTable, IClientState clientState, Configuration configuration, TerritoryData territoryData, ActiveQuestComponent activeQuestComponent, ARealmRebornComponent aRealmRebornComponent, EventInfoComponent eventInfoComponent, CreationUtilsComponent creationUtilsComponent, NavigationBarComponent navigationBarComponent, QuickAccessButtonsComponent quickAccessButtonsComponent, RemainingTasksComponent remainingTasksComponent, ManualPriorityComponent manualPriorityComponent, SavedPresetsComponent savedPresetsComponent, IFramework framework, InteractionUiController interactionUiController, ConfigWindow configWindow) : base("Questionable v" + PluginVersion.ToString(3) + "###Questionable", ImGuiWindowFlags.AlwaysAutoResize) { QuestWindow questWindow = this; _pluginInterface = pluginInterface; _questController = questController; _objectTable = objectTable; _clientState = clientState; _configuration = configuration; _territoryData = territoryData; _activeQuestComponent = activeQuestComponent; _aRealmRebornComponent = aRealmRebornComponent; _eventInfoComponent = eventInfoComponent; _creationUtilsComponent = creationUtilsComponent; _navigationBarComponent = navigationBarComponent; _quickAccessButtonsComponent = quickAccessButtonsComponent; _remainingTasksComponent = remainingTasksComponent; _manualPriorityComponent = manualPriorityComponent; _savedPresetsComponent = savedPresetsComponent; _framework = framework; _interactionUiController = interactionUiController; base.SizeConstraints = new WindowSizeConstraints { MinimumSize = new Vector2(350f, 30f), MaximumSize = new Vector2(350f, 4000f) }; base.RespectCloseHotkey = false; base.AllowClickthrough = false; _minimizeButton = new TitleBarButton { Icon = FontAwesomeIcon.Minus, Priority = int.MinValue, IconOffset = new Vector2(1.5f, 1f), Click = delegate { questWindow.IsMinimized = !questWindow.IsMinimized; questWindow._minimizeButton.Icon = (questWindow.IsMinimized ? FontAwesomeIcon.WindowMaximize : FontAwesomeIcon.Minus); }, AvailableClickthrough = true }; base.TitleBarButtons.Insert(0, _minimizeButton); base.TitleBarButtons.Add(new TitleBarButton { Icon = FontAwesomeIcon.Sun, IconOffset = new Vector2(1.5f, 1f), Click = delegate { configWindow.IsOpenAndUncollapsed = true; }, Priority = int.MinValue, ShowTooltip = delegate { ImGui.BeginTooltip(); ImGui.Text("Open Configuration"); ImGui.EndTooltip(); } }); _activeQuestComponent.OpenQueueTab += SwitchToQueueTab; _quickAccessButtonsComponent.Reload += OnReload; _questController.IsQuestWindowOpenFunction = () => questWindow.IsOpen; } public void SaveWindowConfig() { _pluginInterface.SavePluginConfig(_configuration); } public override void PreOpenCheck() { if (_questController.IsRunning) { base.IsOpen = true; base.Flags |= ImGuiWindowFlags.NoCollapse; base.ShowCloseButton = false; } else { base.Flags &= ~ImGuiWindowFlags.NoCollapse; base.ShowCloseButton = true; } } public override bool DrawConditions() { if (!_configuration.IsPluginSetupComplete()) { return false; } if (!_clientState.IsLoggedIn || _objectTable.LocalPlayer == null || _clientState.IsPvPExcludingDen) { return false; } if (_configuration.General.HideInAllInstances && !_configuration.Advanced.ShowWindowInInstances && _territoryData.IsDutyInstance(_clientState.TerritoryType)) { return false; } return true; } public override void DrawContent() { try { EClassJob valueOrDefault = ((EClassJob?)(_objectTable[0] as ICharacter)?.ClassJob.RowId).GetValueOrDefault(); if (valueOrDefault.IsLimitedJob()) { UiThemeUtils.WrappedTextColored(ImGuiColors.DalamudYellow, valueOrDefault.ToFriendlyString() + " is a limited job. Some quests may be unavailable."); ImGui.Separator(); } if (IsMinimized) { _activeQuestComponent.Draw(isMinimized: true); return; } _selectedTab = UiThemeUtils.DrawTabBar("Quest", "Queue", _selectedTab); if (_selectedTab == 0) { DrawQuestTab(); } else { DrawQueueTab(); } } catch (Exception ex) { UiThemeUtils.WrappedTextColored(ImGuiColors.DalamudRed, ex.ToString()); } } private void DrawQuestTab() { _activeQuestComponent.Draw(isMinimized: false); UiThemeUtils.SectionSpacing(); if (_aRealmRebornComponent.ShouldDraw) { _aRealmRebornComponent.Draw(); UiThemeUtils.SectionSpacing(); } if (_eventInfoComponent.ShouldDraw) { _eventInfoComponent.Draw(); UiThemeUtils.SectionSpacing(); } if (_remainingTasksComponent.Draw()) { UiThemeUtils.SectionSpacing(); } _quickAccessButtonsComponent.IsReloading = IsReloading; _quickAccessButtonsComponent.Draw(); UiThemeUtils.SectionSpacing(); _navigationBarComponent.Draw(); } private void DrawQueueTab() { Vector2 cursorPos = ImGui.GetCursorPos(); float x = ImGui.GetContentRegionAvail().X; ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); windowDrawList.ChannelsSplit(2); windowDrawList.ChannelsSetCurrent(1); ImGui.SetCursorPos(cursorPos + new Vector2(6f, 6f)); if (UiThemeUtils.PillButton("Manual", _queueSubTab == 0)) { _queueSubTab = 0; } ImGui.SameLine(); if (UiThemeUtils.PillButton("Saved", _queueSubTab == 1)) { _queueSubTab = 1; } Vector2 cursorPos2 = ImGui.GetCursorPos(); windowDrawList.ChannelsSetCurrent(0); ImGui.SetCursorPos(cursorPos); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImGui.SetCursorPos(new Vector2(cursorPos.X, cursorPos2.Y + 6f - ImGui.GetStyle().ItemSpacing.Y)); Vector2 cursorScreenPos2 = ImGui.GetCursorScreenPos(); windowDrawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + x, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(UiThemeUtils.CardBackgroundColor), 6f); windowDrawList.AddRect(cursorScreenPos, new Vector2(cursorScreenPos.X + x, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(UiThemeUtils.CardBorderColor), 6f, ImDrawFlags.None, 1f); windowDrawList.ChannelsMerge(); ImGui.SetCursorPos(new Vector2(cursorPos.X, cursorPos2.Y + 6f)); UiThemeUtils.SectionSpacing(); switch (_queueSubTab) { case 0: _manualPriorityComponent.DrawCompact(); break; case 1: _savedPresetsComponent.Draw(); break; } } public void SwitchToQueueTab() { _selectedTab = 1; } private void OnReload(object? sender, EventArgs e) { Reload(); } internal void Reload() { if (IsReloading) { return; } IsReloading = true; Task.Run(delegate { try { _questController.Reload(); } finally { IsReloading = false; } _framework.RunOnTick(delegate { _interactionUiController.HandleCurrentDialogueChoices(); }, TimeSpan.FromMilliseconds(200L)); }); } }