punish v6.8.18.0
This commit is contained in:
commit
cfb4dea47e
316 changed files with 554088 additions and 0 deletions
64
Questionable/Questionable.Windows/ConfigWindow.cs
Normal file
64
Questionable/Questionable.Windows/ConfigWindow.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Plugin;
|
||||
using LLib.ImGui;
|
||||
using Questionable.Windows.ConfigComponents;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
|
||||
{
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private readonly GeneralConfigComponent _generalConfigComponent;
|
||||
|
||||
private readonly PluginConfigComponent _pluginConfigComponent;
|
||||
|
||||
private readonly DutyConfigComponent _dutyConfigComponent;
|
||||
|
||||
private readonly SinglePlayerDutyConfigComponent _singlePlayerDutyConfigComponent;
|
||||
|
||||
private readonly StopConditionComponent _stopConditionComponent;
|
||||
|
||||
private readonly NotificationConfigComponent _notificationConfigComponent;
|
||||
|
||||
private readonly DebugConfigComponent _debugConfigComponent;
|
||||
|
||||
private readonly Configuration _configuration;
|
||||
|
||||
public WindowConfig WindowConfig => _configuration.ConfigWindowConfig;
|
||||
|
||||
public ConfigWindow(IDalamudPluginInterface pluginInterface, GeneralConfigComponent generalConfigComponent, PluginConfigComponent pluginConfigComponent, DutyConfigComponent dutyConfigComponent, SinglePlayerDutyConfigComponent singlePlayerDutyConfigComponent, StopConditionComponent stopConditionComponent, NotificationConfigComponent notificationConfigComponent, DebugConfigComponent debugConfigComponent, Configuration configuration)
|
||||
: base("Config - Questionable###QuestionableConfig", ImGuiWindowFlags.AlwaysAutoResize)
|
||||
{
|
||||
_pluginInterface = pluginInterface;
|
||||
_generalConfigComponent = generalConfigComponent;
|
||||
_pluginConfigComponent = pluginConfigComponent;
|
||||
_dutyConfigComponent = dutyConfigComponent;
|
||||
_singlePlayerDutyConfigComponent = singlePlayerDutyConfigComponent;
|
||||
_stopConditionComponent = stopConditionComponent;
|
||||
_notificationConfigComponent = notificationConfigComponent;
|
||||
_debugConfigComponent = debugConfigComponent;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabBar("QuestionableConfigTabs");
|
||||
if (!(!endObject))
|
||||
{
|
||||
_generalConfigComponent.DrawTab();
|
||||
_pluginConfigComponent.DrawTab();
|
||||
_dutyConfigComponent.DrawTab();
|
||||
_singlePlayerDutyConfigComponent.DrawTab();
|
||||
_stopConditionComponent.DrawTab();
|
||||
_notificationConfigComponent.DrawTab();
|
||||
_debugConfigComponent.DrawTab();
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveWindowConfig()
|
||||
{
|
||||
_pluginInterface.SavePluginConfig(_configuration);
|
||||
}
|
||||
}
|
230
Questionable/Questionable.Windows/DebugOverlay.cs
Normal file
230
Questionable/Questionable.Windows/DebugOverlay.cs
Normal file
|
@ -0,0 +1,230 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Game.ClientState.Conditions;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Common;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class DebugOverlay : Window
|
||||
{
|
||||
private readonly QuestController _questController;
|
||||
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly IGameGui _gameGui;
|
||||
|
||||
private readonly IClientState _clientState;
|
||||
|
||||
private readonly ICondition _condition;
|
||||
|
||||
private readonly AetheryteData _aetheryteData;
|
||||
|
||||
private readonly IObjectTable _objectTable;
|
||||
|
||||
private readonly CombatController _combatController;
|
||||
|
||||
private readonly Configuration _configuration;
|
||||
|
||||
public ElementId? HighlightedQuest { get; set; }
|
||||
|
||||
public DebugOverlay(QuestController questController, QuestRegistry questRegistry, IGameGui gameGui, IClientState clientState, ICondition condition, AetheryteData aetheryteData, IObjectTable objectTable, CombatController combatController, Configuration configuration)
|
||||
: base("Questionable Debug Overlay###QuestionableDebugOverlay", ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoSavedSettings, forceMainWindow: true)
|
||||
{
|
||||
_questController = questController;
|
||||
_questRegistry = questRegistry;
|
||||
_gameGui = gameGui;
|
||||
_clientState = clientState;
|
||||
_condition = condition;
|
||||
_aetheryteData = aetheryteData;
|
||||
_objectTable = objectTable;
|
||||
_combatController = combatController;
|
||||
_configuration = configuration;
|
||||
base.Position = Vector2.Zero;
|
||||
base.PositionCondition = ImGuiCond.Always;
|
||||
base.Size = ImGui.GetIO().DisplaySize;
|
||||
base.SizeCondition = ImGuiCond.Always;
|
||||
base.IsOpen = true;
|
||||
base.ShowCloseButton = false;
|
||||
base.RespectCloseHotkey = false;
|
||||
}
|
||||
|
||||
public override bool DrawConditions()
|
||||
{
|
||||
return _configuration.Advanced.DebugOverlay;
|
||||
}
|
||||
|
||||
public override void PreDraw()
|
||||
{
|
||||
base.Size = ImGui.GetIO().DisplaySize;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (_condition[ConditionFlag.OccupiedInCutSceneEvent])
|
||||
{
|
||||
return;
|
||||
}
|
||||
IClientState clientState = _clientState;
|
||||
if (clientState != null && clientState.IsLoggedIn && clientState.LocalPlayer != null && !clientState.IsPvPExcludingDen && _questController.IsQuestWindowOpen)
|
||||
{
|
||||
DrawCurrentQuest();
|
||||
DrawHighlightedQuest();
|
||||
if (_configuration.Advanced.CombatDataOverlay)
|
||||
{
|
||||
DrawCombatTargets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCurrentQuest()
|
||||
{
|
||||
QuestController.QuestProgress currentQuest = _questController.CurrentQuest;
|
||||
if (currentQuest == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QuestSequence questSequence = currentQuest.Quest.FindSequence(currentQuest.Sequence);
|
||||
if (questSequence == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = currentQuest.Step; i <= questSequence.Steps.Count; i++)
|
||||
{
|
||||
QuestStep questStep = questSequence.FindStep(i);
|
||||
if (questStep != null && TryGetPosition(questStep, out var position))
|
||||
{
|
||||
DrawStep(i.ToString(CultureInfo.InvariantCulture), questStep, position.Value, (Vector3.Distance(_clientState.LocalPlayer.Position, position.Value) < questStep.CalculateActualStopDistance()) ? 4278255360u : 4278190335u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawHighlightedQuest()
|
||||
{
|
||||
if (HighlightedQuest == null || !_questRegistry.TryGetQuest(HighlightedQuest, out Quest quest))
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (QuestSequence item in quest.Root.QuestSequence)
|
||||
{
|
||||
for (int i = 0; i < item.Steps.Count; i++)
|
||||
{
|
||||
QuestStep questStep = item.FindStep(i);
|
||||
if (questStep != null && TryGetPosition(questStep, out var position))
|
||||
{
|
||||
DrawStep($"{quest.Id} / {item.Sequence} / {i}", questStep, position.Value, uint.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawStep(string counter, QuestStep step, Vector3 position, uint color)
|
||||
{
|
||||
if (!step.Disabled && step.TerritoryId == _clientState.TerritoryType && _gameGui.WorldToScreen(position, out var screenPos))
|
||||
{
|
||||
ImGui.GetWindowDrawList().AddCircleFilled(screenPos, 3f, color);
|
||||
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
|
||||
Vector2 pos = screenPos + new Vector2(10f, -8f);
|
||||
ImU8String text = new ImU8String(7, 5);
|
||||
text.AppendFormatted(counter);
|
||||
text.AppendLiteral(": ");
|
||||
text.AppendFormatted(step.InteractionType);
|
||||
text.AppendLiteral("\n");
|
||||
text.AppendFormatted(position.ToString("G", CultureInfo.InvariantCulture));
|
||||
text.AppendLiteral(" [");
|
||||
text.AppendFormatted((position - _clientState.LocalPlayer.Position).Length(), "N2");
|
||||
text.AppendLiteral("]\n");
|
||||
text.AppendFormatted(step.Comment);
|
||||
windowDrawList.AddText(pos, color, text);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCombatTargets()
|
||||
{
|
||||
if (!_combatController.IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (IGameObject item3 in _objectTable.Skip(1))
|
||||
{
|
||||
if (item3 is IBattleNpc && _gameGui.WorldToScreen(item3.Position, out var screenPos))
|
||||
{
|
||||
(int Priority, string Reason) killPriority = _combatController.GetKillPriority(item3);
|
||||
int item = killPriority.Priority;
|
||||
string item2 = killPriority.Reason;
|
||||
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
|
||||
Vector2 pos = screenPos + new Vector2(10f, -8f);
|
||||
int col = ((item > 0) ? (-16711936) : (-1));
|
||||
ImU8String text = new ImU8String(12, 7);
|
||||
text.AppendFormatted(item3.Name);
|
||||
text.AppendLiteral("/");
|
||||
text.AppendFormatted(item3.GameObjectId, "X");
|
||||
text.AppendLiteral(", ");
|
||||
text.AppendFormatted(item3.DataId);
|
||||
text.AppendLiteral(", ");
|
||||
text.AppendFormatted(item);
|
||||
text.AppendLiteral(" - ");
|
||||
text.AppendFormatted(item2);
|
||||
text.AppendLiteral(", ");
|
||||
text.AppendFormatted(Vector3.Distance(item3.Position, _clientState.LocalPlayer.Position), "N2");
|
||||
text.AppendLiteral(", ");
|
||||
text.AppendFormatted(item3.IsTargetable);
|
||||
windowDrawList.AddText(pos, (uint)col, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetPosition(QuestStep step, [NotNullWhen(true)] out Vector3? position)
|
||||
{
|
||||
if (step.Position.HasValue)
|
||||
{
|
||||
position = step.Position;
|
||||
return true;
|
||||
}
|
||||
EAetheryteLocation valueOrDefault = default(EAetheryteLocation);
|
||||
bool flag;
|
||||
if (step != null)
|
||||
{
|
||||
EInteractionType interactionType = step.InteractionType;
|
||||
if ((uint)(interactionType - 4) <= 1u)
|
||||
{
|
||||
EAetheryteLocation? aetheryte = step.Aetheryte;
|
||||
if (aetheryte.HasValue)
|
||||
{
|
||||
valueOrDefault = aetheryte.GetValueOrDefault();
|
||||
flag = true;
|
||||
goto IL_004e;
|
||||
}
|
||||
}
|
||||
}
|
||||
flag = false;
|
||||
goto IL_004e;
|
||||
IL_004e:
|
||||
if (flag)
|
||||
{
|
||||
position = _aetheryteData.Locations[valueOrDefault];
|
||||
return true;
|
||||
}
|
||||
if (step != null && step.InteractionType == EInteractionType.AttuneAethernetShard)
|
||||
{
|
||||
EAetheryteLocation? aetheryte = step.AethernetShard;
|
||||
if (aetheryte.HasValue)
|
||||
{
|
||||
EAetheryteLocation valueOrDefault2 = aetheryte.GetValueOrDefault();
|
||||
position = _aetheryteData.Locations[valueOrDefault2];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
position = null;
|
||||
return false;
|
||||
}
|
||||
}
|
80
Questionable/Questionable.Windows/JournalProgressWindow.cs
Normal file
80
Questionable/Questionable.Windows/JournalProgressWindow.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin.Services;
|
||||
using LLib.ImGui;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Windows.JournalComponents;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class JournalProgressWindow : LWindow, IDisposable
|
||||
{
|
||||
private readonly QuestJournalComponent _questJournalComponent;
|
||||
|
||||
private readonly AlliedSocietyJournalComponent _alliedSocietyJournalComponent;
|
||||
|
||||
private readonly QuestRewardComponent _questRewardComponent;
|
||||
|
||||
private readonly GatheringJournalComponent _gatheringJournalComponent;
|
||||
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly IClientState _clientState;
|
||||
|
||||
public JournalProgressWindow(QuestJournalComponent questJournalComponent, QuestRewardComponent questRewardComponent, AlliedSocietyJournalComponent alliedSocietyJournalComponent, GatheringJournalComponent gatheringJournalComponent, QuestRegistry questRegistry, IClientState clientState)
|
||||
: base("Journal Progress###QuestionableJournalProgress")
|
||||
{
|
||||
_questJournalComponent = questJournalComponent;
|
||||
_alliedSocietyJournalComponent = alliedSocietyJournalComponent;
|
||||
_questRewardComponent = questRewardComponent;
|
||||
_gatheringJournalComponent = gatheringJournalComponent;
|
||||
_questRegistry = questRegistry;
|
||||
_clientState = clientState;
|
||||
_clientState.Login += _questJournalComponent.RefreshCounts;
|
||||
_clientState.Login += _gatheringJournalComponent.RefreshCounts;
|
||||
_clientState.Logout += _questJournalComponent.ClearCounts;
|
||||
_clientState.Logout += _gatheringJournalComponent.ClearCounts;
|
||||
_questRegistry.Reloaded += OnQuestsReloaded;
|
||||
base.SizeConstraints = new WindowSizeConstraints
|
||||
{
|
||||
MinimumSize = new Vector2(700f, 500f)
|
||||
};
|
||||
}
|
||||
|
||||
private void OnQuestsReloaded(object? sender, EventArgs e)
|
||||
{
|
||||
_questJournalComponent.RefreshCounts();
|
||||
_gatheringJournalComponent.RefreshCounts();
|
||||
}
|
||||
|
||||
public override void OnOpen()
|
||||
{
|
||||
_questJournalComponent.UpdateFilter();
|
||||
_questJournalComponent.RefreshCounts();
|
||||
_gatheringJournalComponent.UpdateFilter();
|
||||
_gatheringJournalComponent.RefreshCounts();
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabBar("Journal");
|
||||
if (!(!endObject))
|
||||
{
|
||||
_questJournalComponent.DrawQuests();
|
||||
_alliedSocietyJournalComponent.DrawAlliedSocietyQuests();
|
||||
_questRewardComponent.DrawItemRewards();
|
||||
_gatheringJournalComponent.DrawGatheringItems();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_questRegistry.Reloaded -= OnQuestsReloaded;
|
||||
_clientState.Logout -= _gatheringJournalComponent.ClearCounts;
|
||||
_clientState.Logout -= _questJournalComponent.ClearCounts;
|
||||
_clientState.Login -= _gatheringJournalComponent.RefreshCounts;
|
||||
_clientState.Login -= _questJournalComponent.RefreshCounts;
|
||||
}
|
||||
}
|
74
Questionable/Questionable.Windows/OneTimeSetupWindow.cs
Normal file
74
Questionable/Questionable.Windows/OneTimeSetupWindow.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Plugin;
|
||||
using LLib.ImGui;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Windows.ConfigComponents;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class OneTimeSetupWindow : LWindow
|
||||
{
|
||||
private readonly PluginConfigComponent _pluginConfigComponent;
|
||||
|
||||
private readonly Configuration _configuration;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private readonly ILogger<OneTimeSetupWindow> _logger;
|
||||
|
||||
public OneTimeSetupWindow(PluginConfigComponent pluginConfigComponent, Configuration configuration, IDalamudPluginInterface pluginInterface, ILogger<OneTimeSetupWindow> logger)
|
||||
: base("Questionable Setup###QuestionableOneTimeSetup", ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings, forceMainWindow: true)
|
||||
{
|
||||
_pluginConfigComponent = pluginConfigComponent;
|
||||
_configuration = configuration;
|
||||
_pluginInterface = pluginInterface;
|
||||
_logger = logger;
|
||||
base.RespectCloseHotkey = false;
|
||||
base.ShowCloseButton = false;
|
||||
base.AllowPinning = false;
|
||||
base.AllowClickthrough = false;
|
||||
base.IsOpen = !_configuration.IsPluginSetupComplete();
|
||||
_logger.LogInformation("One-time setup needed: {IsOpen}", base.IsOpen);
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
_pluginConfigComponent.Draw(out var allRequiredInstalled);
|
||||
ImGui.Spacing();
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
if (allRequiredInstalled)
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.ParsedGreen))
|
||||
{
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Finish Setup"))
|
||||
{
|
||||
_logger.LogInformation("Marking setup as complete");
|
||||
_configuration.MarkPluginSetupComplete();
|
||||
_pluginInterface.SavePluginConfig(_configuration);
|
||||
base.IsOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.Disabled())
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed))
|
||||
{
|
||||
ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Missing required plugins");
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Times, "Close window & don't enable Questionable"))
|
||||
{
|
||||
_logger.LogWarning("Closing window without all required plugins installed");
|
||||
base.IsOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
270
Questionable/Questionable.Windows/PriorityWindow.cs
Normal file
270
Questionable/Questionable.Windows/PriorityWindow.cs
Normal file
|
@ -0,0 +1,270 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
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 LLib.ImGui;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Functions;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
using Questionable.Windows.QuestComponents;
|
||||
using Questionable.Windows.Utils;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class PriorityWindow : LWindow
|
||||
{
|
||||
private const string ClipboardPrefix = "qst:priority:";
|
||||
|
||||
private const string LegacyClipboardPrefix = "qst:v1:";
|
||||
|
||||
private const char ClipboardSeparator = ';';
|
||||
|
||||
private readonly QuestController _questController;
|
||||
|
||||
private readonly QuestFunctions _questFunctions;
|
||||
|
||||
private readonly QuestSelector _questSelector;
|
||||
|
||||
private readonly QuestTooltipComponent _questTooltipComponent;
|
||||
|
||||
private readonly UiUtils _uiUtils;
|
||||
|
||||
private readonly IChatGui _chatGui;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private ElementId? _draggedItem;
|
||||
|
||||
public PriorityWindow(QuestController questController, QuestFunctions questFunctions, QuestSelector questSelector, QuestTooltipComponent questTooltipComponent, UiUtils uiUtils, IChatGui chatGui, IDalamudPluginInterface pluginInterface)
|
||||
: base("Quest Priority###QuestionableQuestPriority")
|
||||
{
|
||||
PriorityWindow priorityWindow = this;
|
||||
_questController = questController;
|
||||
_questFunctions = questFunctions;
|
||||
_questSelector = questSelector;
|
||||
_questTooltipComponent = questTooltipComponent;
|
||||
_uiUtils = uiUtils;
|
||||
_chatGui = chatGui;
|
||||
_pluginInterface = pluginInterface;
|
||||
_questSelector.SuggestionPredicate = (Quest quest) => !quest.Info.IsMainScenarioQuest && !questFunctions.IsQuestUnobtainable(quest.Id) && questController.ManualPriorityQuests.All((Quest x) => x.Id != quest.Id);
|
||||
_questSelector.DefaultPredicate = (Quest quest) => questFunctions.IsQuestAccepted(quest.Id);
|
||||
_questSelector.QuestSelected = delegate(Quest quest)
|
||||
{
|
||||
priorityWindow._questController.ManualPriorityQuests.Add(quest);
|
||||
};
|
||||
base.Size = new Vector2(400f, 400f);
|
||||
base.SizeCondition = ImGuiCond.Once;
|
||||
base.SizeConstraints = new WindowSizeConstraints
|
||||
{
|
||||
MinimumSize = new Vector2(400f, 400f),
|
||||
MaximumSize = new Vector2(400f, 999f)
|
||||
};
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
ImGui.Text("Quests to do first:");
|
||||
_questSelector.DrawSelection();
|
||||
DrawQuestList();
|
||||
List<ElementId> list = ParseClipboardItems();
|
||||
ImGui.BeginDisabled(list.Count == 0);
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import from Clipboard"))
|
||||
{
|
||||
ImportFromClipboard(list);
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginDisabled(_questController.ManualPriorityQuests.Count == 0);
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Upload, "Export to Clipboard"))
|
||||
{
|
||||
ExportToClipboard();
|
||||
}
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Check, "Remove finished Quests"))
|
||||
{
|
||||
_questController.ManualPriorityQuests.RemoveAll((Quest q) => _questFunctions.IsQuestComplete(q.Id));
|
||||
}
|
||||
ImGui.SameLine();
|
||||
using (ImRaii.Disabled(!ImGui.IsKeyDown(ImGuiKey.ModCtrl)))
|
||||
{
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Trash, "Clear All"))
|
||||
{
|
||||
_questController.ClearQuestPriority();
|
||||
}
|
||||
}
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
{
|
||||
ImGui.SetTooltip("Hold CTRL to enable this button.");
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
ImGui.Spacing();
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
ImGui.TextWrapped("If you have an active MSQ quest, Questionable will generally try to do:");
|
||||
ImGui.BulletText("'Priority' quests: class quests, ARR primals, ARR raids");
|
||||
ImGui.BulletText("Supported quests in your 'To-Do list'\n(quests from your Journal that are always on-screen)");
|
||||
ImGui.BulletText("MSQ quest (if available, unless it is marked as 'ignored'\nin your Journal)");
|
||||
ImGui.TextWrapped("If you don't have any active MSQ quest, it will always try to pick up the next quest in the MSQ first.");
|
||||
}
|
||||
|
||||
private void DrawQuestList()
|
||||
{
|
||||
List<Quest> manualPriorityQuests = _questController.ManualPriorityQuests;
|
||||
Quest quest = null;
|
||||
Quest quest2 = null;
|
||||
int index = 0;
|
||||
float x = ImGui.GetContentRegionAvail().X;
|
||||
List<(Vector2, Vector2)> list = new List<(Vector2, Vector2)>();
|
||||
for (int i = 0; i < manualPriorityQuests.Count; i++)
|
||||
{
|
||||
Vector2 item = ImGui.GetCursorScreenPos() + new Vector2(0f, (0f - ImGui.GetStyle().ItemSpacing.Y) / 2f);
|
||||
Quest quest3 = manualPriorityQuests[i];
|
||||
ImU8String id = new ImU8String(5, 1);
|
||||
id.AppendLiteral("Quest");
|
||||
id.AppendFormatted(quest3.Id);
|
||||
using (ImRaii.PushId(id))
|
||||
{
|
||||
(Vector4, FontAwesomeIcon, string) questStyle = _uiUtils.GetQuestStyle(quest3.Id);
|
||||
bool flag;
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextColored(in questStyle.Item1, questStyle.Item2.ToIconString());
|
||||
flag = ImGui.IsItemHovered();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.Text(quest3.Info.Name);
|
||||
flag |= ImGui.IsItemHovered();
|
||||
if (flag)
|
||||
{
|
||||
_questTooltipComponent.Draw(quest3.Info);
|
||||
}
|
||||
if (manualPriorityQuests.Count > 1)
|
||||
{
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X + ImGui.GetStyle().WindowPadding.X - ImGui.CalcTextSize(FontAwesomeIcon.ArrowsUpDown.ToIconString()).X - ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X - ImGui.GetStyle().FramePadding.X * 4f - ImGui.GetStyle().ItemSpacing.X);
|
||||
}
|
||||
if (_draggedItem == quest3.Id)
|
||||
{
|
||||
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown, ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.ButtonActive)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown);
|
||||
}
|
||||
if (_draggedItem == null && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||
{
|
||||
_draggedItem = quest3.Id;
|
||||
}
|
||||
ImGui.SameLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X + ImGui.GetStyle().WindowPadding.X - ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X - ImGui.GetStyle().FramePadding.X * 2f);
|
||||
}
|
||||
}
|
||||
if (ImGuiComponents.IconButton($"##Remove{i}", FontAwesomeIcon.Times))
|
||||
{
|
||||
quest = quest3;
|
||||
}
|
||||
}
|
||||
Vector2 item2 = new Vector2(item.X + x, ImGui.GetCursorScreenPos().Y - ImGui.GetStyle().ItemSpacing.Y + 2f);
|
||||
list.Add((item, item2));
|
||||
}
|
||||
if (!ImGui.IsMouseDragging(ImGuiMouseButton.Left))
|
||||
{
|
||||
_draggedItem = null;
|
||||
}
|
||||
else if (_draggedItem != null)
|
||||
{
|
||||
Quest item3 = manualPriorityQuests.Single((Quest quest4) => quest4.Id == _draggedItem);
|
||||
int num = manualPriorityQuests.IndexOf(item3);
|
||||
var (pMin, pMax) = list[num];
|
||||
ImGui.GetWindowDrawList().AddRect(pMin, pMax, ImGui.GetColorU32(ImGuiColors.DalamudGrey), 3f, ImDrawFlags.RoundCornersAll);
|
||||
int num2 = list.FindIndex(((Vector2 TopLeft, Vector2 BottomRight) tuple2) => ImGui.IsMouseHoveringRect(tuple2.TopLeft, tuple2.BottomRight, clip: true));
|
||||
if (num2 >= 0 && num != num2)
|
||||
{
|
||||
quest2 = manualPriorityQuests.Single((Quest quest4) => quest4.Id == _draggedItem);
|
||||
index = num2;
|
||||
}
|
||||
}
|
||||
if (quest != null)
|
||||
{
|
||||
manualPriorityQuests.Remove(quest);
|
||||
}
|
||||
if (quest2 != null)
|
||||
{
|
||||
manualPriorityQuests.Remove(quest2);
|
||||
manualPriorityQuests.Insert(index, quest2);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ElementId> ParseClipboardItems()
|
||||
{
|
||||
return DecodeQuestPriority(ImGui.GetClipboardText().Trim());
|
||||
}
|
||||
|
||||
public static List<ElementId> DecodeQuestPriority(string clipboardText)
|
||||
{
|
||||
List<ElementId> list = new List<ElementId>();
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(clipboardText))
|
||||
{
|
||||
string text = null;
|
||||
if (clipboardText.StartsWith("qst:priority:", StringComparison.InvariantCulture))
|
||||
{
|
||||
text = "qst:priority:";
|
||||
}
|
||||
else if (clipboardText.StartsWith("qst:v1:", StringComparison.InvariantCulture))
|
||||
{
|
||||
text = "qst:v1:";
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
clipboardText = clipboardText.Substring(text.Length);
|
||||
string[] array = Encoding.UTF8.GetString(Convert.FromBase64String(clipboardText)).Split(';');
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
ElementId item = ElementId.FromString(array[i]);
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public string EncodeQuestPriority()
|
||||
{
|
||||
return "qst:priority:" + Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Join(';', _questController.ManualPriorityQuests.Select((Quest x) => x.Id.ToString()))));
|
||||
}
|
||||
|
||||
private void ExportToClipboard()
|
||||
{
|
||||
ImGui.SetClipboardText(EncodeQuestPriority());
|
||||
_chatGui.Print("Copied quests to clipboard.", "Questionable", 576);
|
||||
}
|
||||
|
||||
private void ImportFromClipboard(List<ElementId> questElements)
|
||||
{
|
||||
_questController.ImportQuestPriority(questElements);
|
||||
}
|
||||
}
|
263
Questionable/Questionable.Windows/QuestSelectionWindow.cs
Normal file
263
Questionable/Questionable.Windows/QuestSelectionWindow.cs
Normal file
|
@ -0,0 +1,263 @@
|
|||
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<IQuestInfo> _quests = new List<IQuestInfo>();
|
||||
|
||||
private List<IQuestInfo> _offeredQuests = new List<IQuestInfo>();
|
||||
|
||||
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 dataId = gameObject.DataId;
|
||||
string value = gameObject.Name.ToString();
|
||||
base.WindowName = $"Quests starting with {value} [{dataId}]{"###QuestionableQuestSelection"}";
|
||||
_quests = _questData.GetAllByIssuerDataId(dataId);
|
||||
if (_gameGui.TryGetAddonByName<AddonSelectIconString>("SelectIconString", out var addonPtr))
|
||||
{
|
||||
List<string?> answers = InteractionUiController.GetChoices(addonPtr);
|
||||
_offeredQuests = _quests.Where((IQuestInfo x) => answers.Any((string y) => GameFunctions.GameStringEquals(x.Name, y))).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
_offeredQuests = new List<IQuestInfo>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_quests = new List<IQuestInfo>();
|
||||
_offeredQuests = new List<IQuestInfo>();
|
||||
}
|
||||
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<IQuestInfo>();
|
||||
base.IsOpenAndUncollapsed = true;
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
{
|
||||
_quests = new List<IQuestInfo>();
|
||||
_offeredQuests = new List<IQuestInfo>();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
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);
|
||||
_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");
|
||||
}
|
||||
}
|
95
Questionable/Questionable.Windows/QuestValidationWindow.cs
Normal file
95
Questionable/Questionable.Windows/QuestValidationWindow.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
using System.Globalization;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin;
|
||||
using FFXIVClientStructs.FFXIV.Common.Math;
|
||||
using LLib.ImGui;
|
||||
using Questionable.Data;
|
||||
using Questionable.Validation;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class QuestValidationWindow : LWindow
|
||||
{
|
||||
private readonly QuestValidator _questValidator;
|
||||
|
||||
private readonly QuestData _questData;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
public QuestValidationWindow(QuestValidator questValidator, QuestData questData, IDalamudPluginInterface pluginInterface)
|
||||
: base("Quest Validation###QuestionableValidator")
|
||||
{
|
||||
_questValidator = questValidator;
|
||||
_questData = questData;
|
||||
_pluginInterface = pluginInterface;
|
||||
base.Size = new Vector2(600f, 200f);
|
||||
base.SizeCondition = ImGuiCond.Once;
|
||||
base.SizeConstraints = new WindowSizeConstraints
|
||||
{
|
||||
MinimumSize = new Vector2(600f, 200f)
|
||||
};
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.Table("QuestSelection", 5, ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY);
|
||||
if (!endObject)
|
||||
{
|
||||
ImGui.Text("Not table");
|
||||
return;
|
||||
}
|
||||
ImGui.TableSetupColumn("Quest", ImGuiTableColumnFlags.WidthFixed, 50f);
|
||||
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, 200f);
|
||||
ImGui.TableSetupColumn("Seq", ImGuiTableColumnFlags.WidthFixed, 30f);
|
||||
ImGui.TableSetupColumn("Step", ImGuiTableColumnFlags.WidthFixed, 30f);
|
||||
ImGui.TableSetupColumn("Issue", ImGuiTableColumnFlags.None, 200f);
|
||||
ImGui.TableHeadersRow();
|
||||
foreach (ValidationIssue issue in _questValidator.Issues)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
if (ImGui.TableNextColumn())
|
||||
{
|
||||
ImGui.TextUnformatted(issue.ElementId?.ToString() ?? string.Empty);
|
||||
}
|
||||
if (ImGui.TableNextColumn())
|
||||
{
|
||||
ImGui.TextUnformatted((issue.ElementId != null) ? _questData.GetQuestInfo(issue.ElementId).Name : issue.AlliedSociety.ToString());
|
||||
}
|
||||
if (ImGui.TableNextColumn())
|
||||
{
|
||||
ImGui.TextUnformatted(issue.Sequence?.ToString(CultureInfo.InvariantCulture) ?? string.Empty);
|
||||
}
|
||||
if (ImGui.TableNextColumn())
|
||||
{
|
||||
ImGui.TextUnformatted(issue.Step?.ToString(CultureInfo.InvariantCulture) ?? string.Empty);
|
||||
}
|
||||
if (!ImGui.TableNextColumn())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
if (issue.Severity == EIssueSeverity.Error)
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed))
|
||||
{
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.ExclamationTriangle.ToIconString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.ParsedBlue))
|
||||
{
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(issue.Description);
|
||||
}
|
||||
}
|
||||
}
|
191
Questionable/Questionable.Windows/QuestWindow.cs
Normal file
191
Questionable/Questionable.Windows/QuestWindow.cs
Normal file
|
@ -0,0 +1,191 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using LLib.ImGui;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Controller.GameUi;
|
||||
using Questionable.Data;
|
||||
using Questionable.Windows.QuestComponents;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
|
||||
{
|
||||
private static readonly Version PluginVersion = typeof(QuestionablePlugin).Assembly.GetName().Version;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private readonly QuestController _questController;
|
||||
|
||||
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 QuickAccessButtonsComponent _quickAccessButtonsComponent;
|
||||
|
||||
private readonly RemainingTasksComponent _remainingTasksComponent;
|
||||
|
||||
private readonly IFramework _framework;
|
||||
|
||||
private readonly InteractionUiController _interactionUiController;
|
||||
|
||||
private readonly TitleBarButton _minimizeButton;
|
||||
|
||||
public WindowConfig WindowConfig => _configuration.DebugWindowConfig;
|
||||
|
||||
public bool IsMinimized { get; set; }
|
||||
|
||||
public QuestWindow(IDalamudPluginInterface pluginInterface, QuestController questController, IClientState clientState, Configuration configuration, TerritoryData territoryData, ActiveQuestComponent activeQuestComponent, ARealmRebornComponent aRealmRebornComponent, EventInfoComponent eventInfoComponent, CreationUtilsComponent creationUtilsComponent, QuickAccessButtonsComponent quickAccessButtonsComponent, RemainingTasksComponent remainingTasksComponent, IFramework framework, InteractionUiController interactionUiController, ConfigWindow configWindow)
|
||||
: base("Questionable v" + PluginVersion.ToString(4) + "###Questionable", ImGuiWindowFlags.AlwaysAutoResize)
|
||||
{
|
||||
QuestWindow questWindow = this;
|
||||
_pluginInterface = pluginInterface;
|
||||
_questController = questController;
|
||||
_clientState = clientState;
|
||||
_configuration = configuration;
|
||||
_territoryData = territoryData;
|
||||
_activeQuestComponent = activeQuestComponent;
|
||||
_aRealmRebornComponent = aRealmRebornComponent;
|
||||
_eventInfoComponent = eventInfoComponent;
|
||||
_creationUtilsComponent = creationUtilsComponent;
|
||||
_quickAccessButtonsComponent = quickAccessButtonsComponent;
|
||||
_remainingTasksComponent = remainingTasksComponent;
|
||||
_framework = framework;
|
||||
_interactionUiController = interactionUiController;
|
||||
base.SizeConstraints = new WindowSizeConstraints
|
||||
{
|
||||
MinimumSize = new Vector2(240f, 30f),
|
||||
MaximumSize = default(Vector2)
|
||||
};
|
||||
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.Cog,
|
||||
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.Reload += OnReload;
|
||||
_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 || _clientState.LocalPlayer == null || _clientState.IsPvPExcludingDen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_configuration.General.HideInAllInstances && _territoryData.IsDutyInstance(_clientState.TerritoryType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void DrawContent()
|
||||
{
|
||||
try
|
||||
{
|
||||
_activeQuestComponent.Draw(IsMinimized);
|
||||
if (!IsMinimized)
|
||||
{
|
||||
ImGui.Separator();
|
||||
if (_aRealmRebornComponent.ShouldDraw)
|
||||
{
|
||||
_aRealmRebornComponent.Draw();
|
||||
ImGui.Separator();
|
||||
}
|
||||
if (_eventInfoComponent.ShouldDraw)
|
||||
{
|
||||
_eventInfoComponent.Draw();
|
||||
ImGui.Separator();
|
||||
}
|
||||
_creationUtilsComponent.Draw();
|
||||
ImGui.Separator();
|
||||
_quickAccessButtonsComponent.Draw();
|
||||
_remainingTasksComponent.Draw();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReload(object? sender, EventArgs e)
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
|
||||
internal void Reload()
|
||||
{
|
||||
_questController.Reload();
|
||||
_framework.RunOnTick(delegate
|
||||
{
|
||||
_interactionUiController.HandleCurrentDialogueChoices();
|
||||
}, TimeSpan.FromMilliseconds(200L, 0L));
|
||||
}
|
||||
}
|
94
Questionable/Questionable.Windows/UiUtils.cs
Normal file
94
Questionable/Questionable.Windows/UiUtils.cs
Normal file
|
@ -0,0 +1,94 @@
|
|||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Plugin;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
using Questionable.Functions;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Windows;
|
||||
|
||||
internal sealed class UiUtils
|
||||
{
|
||||
private readonly QuestFunctions _questFunctions;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
public UiUtils(QuestFunctions questFunctions, IDalamudPluginInterface pluginInterface)
|
||||
{
|
||||
_questFunctions = questFunctions;
|
||||
_pluginInterface = pluginInterface;
|
||||
}
|
||||
|
||||
public (Vector4 Color, FontAwesomeIcon Icon, string Status) GetQuestStyle(ElementId elementId)
|
||||
{
|
||||
if (_questFunctions.IsQuestAccepted(elementId))
|
||||
{
|
||||
return (Color: ImGuiColors.DalamudYellow, Icon: FontAwesomeIcon.PersonWalkingArrowRight, Status: "Active");
|
||||
}
|
||||
if (elementId is QuestId questId && _questFunctions.IsDailyAlliedSocietyQuestAndAvailableToday(questId))
|
||||
{
|
||||
if (!_questFunctions.IsReadyToAcceptQuest(questId))
|
||||
{
|
||||
return (Color: ImGuiColors.ParsedGreen, Icon: FontAwesomeIcon.Check, Status: "Complete");
|
||||
}
|
||||
if (_questFunctions.IsQuestComplete(questId))
|
||||
{
|
||||
return (Color: ImGuiColors.ParsedBlue, Icon: FontAwesomeIcon.Running, Status: "Available (Complete)");
|
||||
}
|
||||
return (Color: ImGuiColors.DalamudYellow, Icon: FontAwesomeIcon.Running, Status: "Available");
|
||||
}
|
||||
if (_questFunctions.IsQuestAcceptedOrComplete(elementId))
|
||||
{
|
||||
return (Color: ImGuiColors.ParsedGreen, Icon: FontAwesomeIcon.Check, Status: "Complete");
|
||||
}
|
||||
if (_questFunctions.IsQuestUnobtainable(elementId))
|
||||
{
|
||||
return (Color: ImGuiColors.DalamudGrey, Icon: FontAwesomeIcon.Minus, Status: "Unobtainable");
|
||||
}
|
||||
if (_questFunctions.IsQuestLocked(elementId))
|
||||
{
|
||||
return (Color: ImGuiColors.DalamudRed, Icon: FontAwesomeIcon.Times, Status: "Locked");
|
||||
}
|
||||
return (Color: ImGuiColors.DalamudYellow, Icon: FontAwesomeIcon.Running, Status: "Available");
|
||||
}
|
||||
|
||||
public static (Vector4 color, FontAwesomeIcon icon) GetInstanceStyle(ushort instanceId)
|
||||
{
|
||||
if (UIState.IsInstanceContentCompleted(instanceId))
|
||||
{
|
||||
return (color: ImGuiColors.ParsedGreen, icon: FontAwesomeIcon.Check);
|
||||
}
|
||||
if (UIState.IsInstanceContentUnlocked(instanceId))
|
||||
{
|
||||
return (color: ImGuiColors.DalamudYellow, icon: FontAwesomeIcon.Running);
|
||||
}
|
||||
return (color: ImGuiColors.DalamudRed, icon: FontAwesomeIcon.Times);
|
||||
}
|
||||
|
||||
public bool ChecklistItem(string text, Vector4 color, FontAwesomeIcon icon, float extraPadding = 0f)
|
||||
{
|
||||
if (extraPadding > 0f)
|
||||
{
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + extraPadding);
|
||||
}
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
ImGui.TextColored(in color, icon.ToIconString());
|
||||
}
|
||||
bool num = ImGui.IsItemHovered();
|
||||
ImGui.SameLine();
|
||||
if (extraPadding > 0f)
|
||||
{
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + extraPadding);
|
||||
}
|
||||
ImGui.TextUnformatted(text);
|
||||
return num | ImGui.IsItemHovered();
|
||||
}
|
||||
|
||||
public bool ChecklistItem(string text, bool complete, Vector4? colorOverride = null)
|
||||
{
|
||||
return ChecklistItem(text, colorOverride ?? (complete ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed), complete ? FontAwesomeIcon.Check : FontAwesomeIcon.Times);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue