using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
using System.Linq;
+using Dalamud.Game.Text;
using Dalamud.Memory;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
return new(firstTrackedQuest, firstTrackedSequence, msqQuest.State);
}
- ElementId? priorityQuest = GetNextPriorityQuestsThatCanBeAccepted().FirstOrDefault();
+ ElementId? priorityQuest = GetNextPriorityQuestsThatCanBeAccepted()
+ .Where(x => x.IsAvailable)
+ .Select(x => x.QuestId)
+ .FirstOrDefault();
if (priorityQuest != null)
{
// if we have an accepted msq quest, and know of no quest of those currently in the to-do list...
return null;
}
- public List<ElementId> GetNextPriorityQuestsThatCanBeAccepted()
+ public List<PriorityQuestInfo> GetNextPriorityQuestsThatCanBeAccepted()
{
// all priority quests assume we're able to teleport to the beginning (and for e.g. class quests, the end)
// ideally without having to wait 15m for Return.
return GetPriorityQuests()
.Where(x => IsReadyToAcceptQuest(x))
- .Where(x =>
+ .Select(x =>
{
if (!_questRegistry.TryGetQuest(x, out Quest? quest))
- return false;
+ return new PriorityQuestInfo(x, "Unknown quest");
var firstStep = quest.FindSequence(0)?.FindStep(0);
if (firstStep == null)
- return false;
+ return new PriorityQuestInfo(x, "No sequence 0 with steps");
- return firstStep.IsTeleportableForPriorityQuests();
- })
- .Where(x =>
- {
- if (!_questRegistry.TryGetQuest(x, out Quest? quest))
- return false;
+ if (!firstStep.IsTeleportableForPriorityQuests())
+ return new PriorityQuestInfo(x, "Can't teleport to start");
if (gil < EstimateTeleportCosts(quest))
- return false;
-
- return quest.AllSteps().All(y =>
{
- if (y.Step.AetheryteShortcut is { } aetheryteShortcut &&
- !_aetheryteFunctions.IsAetheryteUnlocked(aetheryteShortcut))
+ return new PriorityQuestInfo(x,
+ string.Create(CultureInfo.InvariantCulture,
+ $"Not enough gil, estimated cost: {EstimateTeleportCosts(quest):N0}{SeIconChar.Gil.ToIconString()}"));
+ }
+
+ EAetheryteLocation? firstLockedAetheryte = quest.AllSteps()
+ .Select(y =>
{
- if (y.Step.SkipConditions?.AetheryteShortcutIf?.AetheryteLocked == aetheryteShortcut)
+ if (y.Step.AetheryteShortcut is { } aetheryteShortcut &&
+ !_aetheryteFunctions.IsAetheryteUnlocked(aetheryteShortcut))
{
- // _logger.LogTrace("Checking priority quest {QuestId}: aetheryte locked, but is listed as skippable", quest.Id);
+ if (y.Step.SkipConditions?.AetheryteShortcutIf?.AetheryteLocked == aetheryteShortcut)
+ {
+ // _logger.LogTrace("Checking priority quest {QuestId}: aetheryte locked, but is listed as skippable", quest.Id);
+ }
+ else
+ return aetheryteShortcut;
+ }
+
+ if (y.Step.AethernetShortcut is { } aethernetShortcut)
+ {
+ if (!_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.From))
+ return aethernetShortcut.From;
+
+ if (!_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.To))
+ return aethernetShortcut.To;
}
- else return false;
- }
- if (y.Step.AethernetShortcut is { } aethernetShortcut &&
- (!_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.From) ||
- !_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.To)))
- return false;
+ return (EAetheryteLocation?)null;
+ })
+ .FirstOrDefault(y => y != null);
+ if (firstLockedAetheryte != null)
+ return new PriorityQuestInfo(x, $"Aetheryte locked: {firstLockedAetheryte}");
- return true;
- });
+ return new PriorityQuestInfo(x);
})
.ToList();
}
Complete,
LoadingScreen,
}
+
+internal sealed record PriorityQuestInfo(ElementId QuestId, string? UnavailableReason = null)
+{
+ public bool IsAvailable => UnavailableReason == null;
+}
ImGui.Separator();
ImGui.Text("Available priority quests:");
- List<ElementId> priorityQuests = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted();
- if (priorityQuests.Count > 0)
+ List<PriorityQuestInfo> priorityQuests = _questFunctions.GetNextPriorityQuestsThatCanBeAccepted();
+ var availablePriorityQuests = priorityQuests
+ .Where(x => x.IsAvailable)
+ .Select(x => x.QuestId)
+ .ToList();
+ if (availablePriorityQuests.Count > 0)
{
- foreach (var questId in priorityQuests)
+ foreach (var questId in availablePriorityQuests)
{
if (_questRegistry.TryGetQuest(questId, out var quest))
ImGui.BulletText($"{quest.Info.Name} ({questId})");
}
else
ImGui.BulletText("(none)");
+
+ if (_configuration.Advanced.AdditionalStatusInformation)
+ {
+ var unavailablePriorityQuests = priorityQuests
+ .Where(x => !x.IsAvailable)
+ .ToList();
+ if (unavailablePriorityQuests.Count > 0)
+ {
+ ImGui.Text("Unavailable priority quests:");
+ foreach (var (questId, reason) in unavailablePriorityQuests)
+ {
+ if (_questRegistry.TryGetQuest(questId, out var quest))
+ ImGui.BulletText($"{quest.Info.Name} ({questId}) - {reason}");
+ }
+ }
+ }
}
}
}