muffin v6.13

This commit is contained in:
alydev 2025-10-09 08:30:06 +10:00
parent 0950798597
commit b08d196477
10 changed files with 1304 additions and 1038 deletions

View file

@ -5,11 +5,11 @@ using System.Runtime.Versioning;
[assembly: AssemblyCompany("GatheringPaths")] [assembly: AssemblyCompany("GatheringPaths")]
[assembly: AssemblyConfiguration("Release")] [assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("6.12.0.0")] [assembly: AssemblyFileVersion("6.13.0.0")]
[assembly: AssemblyInformationalVersion("6.12+bba82029b26f7908bb8be007c95a312e3aa9e80f")] [assembly: AssemblyInformationalVersion("6.13+1f54814b9cb724c2d6bc1cd7614ccb494d8bbd75")]
[assembly: AssemblyProduct("GatheringPaths")] [assembly: AssemblyProduct("GatheringPaths")]
[assembly: AssemblyTitle("GatheringPaths")] [assembly: AssemblyTitle("GatheringPaths")]
[assembly: TargetPlatform("Windows7.0")] [assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")] [assembly: SupportedOSPlatform("Windows7.0")]
[assembly: AssemblyVersion("6.12.0.0")] [assembly: AssemblyVersion("6.13.0.0")]
[module: RefSafetyRules(11)] [module: RefSafetyRules(11)]

View file

@ -7,12 +7,12 @@ using System.Security.Permissions;
[assembly: AssemblyCompany("LLib")] [assembly: AssemblyCompany("LLib")]
[assembly: AssemblyConfiguration("Release")] [assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("6.12.0.0")] [assembly: AssemblyFileVersion("6.13.0.0")]
[assembly: AssemblyInformationalVersion("6.12+5367edf45faba59401605531555000d1429966c1")] [assembly: AssemblyInformationalVersion("6.13+5367edf45faba59401605531555000d1429966c1")]
[assembly: AssemblyProduct("LLib")] [assembly: AssemblyProduct("LLib")]
[assembly: AssemblyTitle("LLib")] [assembly: AssemblyTitle("LLib")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WigglyMuffin/LLib.git")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WigglyMuffin/LLib.git")]
[assembly: TargetPlatform("Windows7.0")] [assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")] [assembly: SupportedOSPlatform("Windows7.0")]
[assembly: AssemblyVersion("6.12.0.0")] [assembly: AssemblyVersion("6.13.0.0")]
[module: RefSafetyRules(11)] [module: RefSafetyRules(11)]

View file

@ -5,9 +5,9 @@ using System.Runtime.Versioning;
[assembly: AssemblyCompany("QuestPaths")] [assembly: AssemblyCompany("QuestPaths")]
[assembly: AssemblyConfiguration("Release")] [assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("6.12.0.0")] [assembly: AssemblyFileVersion("6.13.0.0")]
[assembly: AssemblyInformationalVersion("6.12+bba82029b26f7908bb8be007c95a312e3aa9e80f")] [assembly: AssemblyInformationalVersion("6.13+1f54814b9cb724c2d6bc1cd7614ccb494d8bbd75")]
[assembly: AssemblyProduct("QuestPaths")] [assembly: AssemblyProduct("QuestPaths")]
[assembly: AssemblyTitle("QuestPaths")] [assembly: AssemblyTitle("QuestPaths")]
[assembly: AssemblyVersion("6.12.0.0")] [assembly: AssemblyVersion("6.13.0.0")]
[module: RefSafetyRules(11)] [module: RefSafetyRules(11)]

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,9 @@ using System.Runtime.Versioning;
[assembly: AssemblyCompany("Questionable.Model")] [assembly: AssemblyCompany("Questionable.Model")]
[assembly: AssemblyConfiguration("Release")] [assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("6.12.0.0")] [assembly: AssemblyFileVersion("6.13.0.0")]
[assembly: AssemblyInformationalVersion("6.12+bba82029b26f7908bb8be007c95a312e3aa9e80f")] [assembly: AssemblyInformationalVersion("6.13+1f54814b9cb724c2d6bc1cd7614ccb494d8bbd75")]
[assembly: AssemblyProduct("Questionable.Model")] [assembly: AssemblyProduct("Questionable.Model")]
[assembly: AssemblyTitle("Questionable.Model")] [assembly: AssemblyTitle("Questionable.Model")]
[assembly: AssemblyVersion("6.12.0.0")] [assembly: AssemblyVersion("6.13.0.0")]
[module: RefSafetyRules(11)] [module: RefSafetyRules(11)]

View file

@ -7,12 +7,12 @@ using System.Security.Permissions;
[assembly: AssemblyCompany("Questionable")] [assembly: AssemblyCompany("Questionable")]
[assembly: AssemblyConfiguration("Release")] [assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("6.12.0.0")] [assembly: AssemblyFileVersion("6.13.0.0")]
[assembly: AssemblyInformationalVersion("6.12+bba82029b26f7908bb8be007c95a312e3aa9e80f")] [assembly: AssemblyInformationalVersion("6.13+1f54814b9cb724c2d6bc1cd7614ccb494d8bbd75")]
[assembly: AssemblyProduct("Questionable")] [assembly: AssemblyProduct("Questionable")]
[assembly: AssemblyTitle("Questionable")] [assembly: AssemblyTitle("Questionable")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WigglyMuffin/Ambivalence")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/WigglyMuffin/Ambivalence")]
[assembly: TargetPlatform("Windows7.0")] [assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")] [assembly: SupportedOSPlatform("Windows7.0")]
[assembly: AssemblyVersion("6.12.0.0")] [assembly: AssemblyVersion("6.13.0.0")]
[module: RefSafetyRules(11)] [module: RefSafetyRules(11)]

View file

@ -520,6 +520,18 @@ internal sealed class QuestController : MiniTaskController<QuestController>
else if (!_questFunctions.IsQuestComplete(_startedQuest.Quest.Id)) else if (!_questFunctions.IsQuestComplete(_startedQuest.Quest.Id))
{ {
_logger.LogInformation("Quest {QuestId} was abandoned, clearing started quest", _startedQuest.Quest.Id); _logger.LogInformation("Quest {QuestId} was abandoned, clearing started quest", _startedQuest.Quest.Id);
(ElementId, byte)? tuple = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id)
select ((ElementId Id, byte))(Id: x.Id, 0)).FirstOrDefault();
if (tuple.HasValue)
{
(ElementId, byte) valueOrDefault = tuple.GetValueOrDefault();
if ((object)valueOrDefault.Item1 != null && _questRegistry.TryGetQuest(valueOrDefault.Item1, out Quest quest))
{
_logger.LogInformation("Setting priority quest {QuestId} as next quest", valueOrDefault.Item1);
SetNextQuest(quest);
}
}
_startedQuest = null; _startedQuest = null;
Stop("Quest abandoned"); Stop("Quest abandoned");
return; return;
@ -551,9 +563,8 @@ internal sealed class QuestController : MiniTaskController<QuestController>
} }
byte b; byte b;
QuestProgress questProgress; QuestProgress questProgress;
ElementId CurrentQuest; ElementId elementId;
byte Sequence; MainScenarioQuestState mainScenarioQuestState;
MainScenarioQuestState State;
if (_simulatedQuest != null) if (_simulatedQuest != null)
{ {
b = _simulatedQuest.Sequence; b = _simulatedQuest.Sequence;
@ -577,8 +588,38 @@ internal sealed class QuestController : MiniTaskController<QuestController>
ExecuteNextStep(); ExecuteNextStep();
} }
} }
else if (_startedQuest != null) else
{ {
ElementId CurrentQuest;
byte Sequence;
MainScenarioQuestState State;
if (_startedQuest == null)
{
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State);
elementId = CurrentQuest;
b = Sequence;
mainScenarioQuestState = State;
(ElementId, byte)? tuple2 = (from x in ManualPriorityQuests
where _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple2.HasValue)
{
(ElementId, byte) valueOrDefault2 = tuple2.GetValueOrDefault();
if ((object)valueOrDefault2.Item1 != null)
{
(elementId, b) = valueOrDefault2;
goto IL_0813;
}
}
Quest quest2 = ManualPriorityQuests.FirstOrDefault((Quest x) => _questFunctions.IsReadyToAcceptQuest(x.Id));
if (quest2 != null)
{
_logger.LogInformation("Setting ready priority quest {QuestId} as next quest", quest2.Id);
SetNextQuest(quest2);
return;
}
goto IL_0813;
}
questProgress = _startedQuest; questProgress = _startedQuest;
b = _startedQuest.Sequence; b = _startedQuest.Sequence;
QuestProgressInfo questProgressInfo2 = _questFunctions.GetQuestProgressInfo(_startedQuest.Quest.Id); QuestProgressInfo questProgressInfo2 = _questFunctions.GetQuestProgressInfo(_startedQuest.Quest.Id);
@ -590,117 +631,42 @@ internal sealed class QuestController : MiniTaskController<QuestController>
if (AutomationType == EAutomationType.Manual || !IsRunning) if (AutomationType == EAutomationType.Manual || !IsRunning)
{ {
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State); _questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State);
ElementId elementId = CurrentQuest; ElementId elementId2 = CurrentQuest;
byte sequence = Sequence; byte sequence = Sequence;
(ElementId, byte)? tuple = (from x in ManualPriorityQuests (ElementId, byte)? tuple4 = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id) || _questFunctions.IsQuestAccepted(x.Id) where _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault(); select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple.HasValue) if (tuple4.HasValue)
{ {
(ElementId, byte) valueOrDefault = tuple.GetValueOrDefault(); (ElementId, byte) valueOrDefault3 = tuple4.GetValueOrDefault();
if ((object)valueOrDefault.Item1 != null) if ((object)valueOrDefault3.Item1 != null)
{ {
(elementId, sequence) = valueOrDefault; (elementId2, sequence) = valueOrDefault3;
} }
} }
if (elementId != null && elementId.Value != 0 && _startedQuest.Quest.Id != elementId) if (elementId2 != null && elementId2.Value != 0 && _startedQuest.Quest.Id != elementId2)
{ {
_logger.LogInformation("Game current quest changed from {OldQuest} to {NewQuest}, updating started quest", _startedQuest.Quest.Id, elementId); _logger.LogInformation("Game current quest changed from {OldQuest} to {NewQuest}, updating started quest", _startedQuest.Quest.Id, elementId2);
if (_questRegistry.TryGetQuest(elementId, out Quest quest)) if (_questRegistry.TryGetQuest(elementId2, out Quest quest3))
{ {
_logger.LogInformation("Switching to new quest: {QuestName}", quest.Info.Name); _logger.LogInformation("Switching to new quest: {QuestName}", quest3.Info.Name);
_startedQuest = new QuestProgress(quest, sequence); _startedQuest = new QuestProgress(quest3, sequence);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest.Info.Level) if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest3.Info.Level)
{ {
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest.Info.Level); _logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest3.Info.Level);
Stop("Quest level too high"); Stop("Quest level too high");
} }
questProgress = _startedQuest; questProgress = _startedQuest;
} }
else else
{ {
_logger.LogInformation("New quest {QuestId} not found in registry", elementId); _logger.LogInformation("New quest {QuestId} not found in registry", elementId2);
} }
} }
} }
} }
else goto IL_0b43;
{ IL_0b43:
_questFunctions.GetCurrentQuest(AutomationType != EAutomationType.SingleQuestB).Deconstruct(out CurrentQuest, out Sequence, out State);
ElementId elementId2 = CurrentQuest;
b = Sequence;
MainScenarioQuestState mainScenarioQuestState = State;
(ElementId, byte)? tuple3 = (from x in ManualPriorityQuests
where _questFunctions.IsReadyToAcceptQuest(x.Id) || _questFunctions.IsQuestAccepted(x.Id)
select (Id: x.Id, _questFunctions.GetQuestProgressInfo(x.Id)?.Sequence ?? 0)).FirstOrDefault();
if (tuple3.HasValue)
{
(ElementId, byte) valueOrDefault2 = tuple3.GetValueOrDefault();
if ((object)valueOrDefault2.Item1 != null)
{
(elementId2, b) = valueOrDefault2;
}
}
if (elementId2 == null || elementId2.Value == 0)
{
if (_startedQuest != null)
{
switch (mainScenarioQuestState)
{
case MainScenarioQuestState.Unavailable:
_logger.LogWarning("MSQ information not available, doing nothing");
return;
case MainScenarioQuestState.LoadingScreen:
_logger.LogWarning("On loading screen, no MSQ - doing nothing");
return;
}
_logger.LogInformation("No current quest, resetting data [CQI: {CurrrentQuestData}], [CQ: {QuestData}], [MSQ: {MsqData}]", _questFunctions.GetCurrentQuestInternal(allowNewMsq: true), _questFunctions.GetCurrentQuest(), _questFunctions.GetMainScenarioQuest());
_startedQuest = null;
Stop("Resetting current quest");
}
questProgress = null;
}
else
{
if (_startedQuest == null || _startedQuest.Quest.Id != elementId2)
{
Quest quest2;
if (_configuration.Stop.Enabled && _startedQuest != null && _configuration.Stop.QuestsToStopAfter.Contains(_startedQuest.Quest.Id) && _questFunctions.IsQuestComplete(_startedQuest.Quest.Id))
{
ElementId id = _startedQuest.Quest.Id;
_logger.LogInformation("Reached stopping point (quest: {QuestId})", id);
_chatGui.Print("Completed quest '" + _startedQuest.Quest.Info.Name + "', which is configured as a stopping point.", "Questionable", 576);
_startedQuest = null;
Stop($"Stopping point [{id}] reached");
}
else if (_questRegistry.TryGetQuest(elementId2, out quest2))
{
_logger.LogInformation("New quest: {QuestName}", quest2.Info.Name);
_startedQuest = new QuestProgress(quest2, b);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest2.Info.Level)
{
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest2.Info.Level);
Stop("Quest level too high");
return;
}
if (AutomationType == EAutomationType.SingleQuestB)
{
_logger.LogInformation("Single quest is finished");
AutomationType = EAutomationType.Manual;
}
CheckNextTasks("Different Quest");
}
else if (_startedQuest != null)
{
_logger.LogInformation("No active quest anymore? Not sure what happened...");
_startedQuest = null;
Stop("No active Quest");
}
return;
}
questProgress = _startedQuest;
}
}
if (questProgress == null) if (questProgress == null)
{ {
DebugState = "No quest active"; DebugState = "No quest active";
@ -758,6 +724,68 @@ internal sealed class QuestController : MiniTaskController<QuestController>
{ {
DebugState = null; DebugState = null;
} }
return;
IL_0813:
if (elementId == null || elementId.Value == 0)
{
if (_startedQuest != null)
{
switch (mainScenarioQuestState)
{
case MainScenarioQuestState.Unavailable:
_logger.LogWarning("MSQ information not available, doing nothing");
return;
case MainScenarioQuestState.LoadingScreen:
_logger.LogWarning("On loading screen, no MSQ - doing nothing");
return;
}
_logger.LogInformation("No current quest, resetting data [CQI: {CurrrentQuestData}], [CQ: {QuestData}], [MSQ: {MsqData}]", _questFunctions.GetCurrentQuestInternal(allowNewMsq: true), _questFunctions.GetCurrentQuest(), _questFunctions.GetMainScenarioQuest());
_startedQuest = null;
Stop("Resetting current quest");
}
questProgress = null;
}
else
{
if (_startedQuest == null || _startedQuest.Quest.Id != elementId)
{
Quest quest4;
if (_configuration.Stop.Enabled && _startedQuest != null && _configuration.Stop.QuestsToStopAfter.Contains(_startedQuest.Quest.Id) && _questFunctions.IsQuestComplete(_startedQuest.Quest.Id))
{
ElementId id = _startedQuest.Quest.Id;
_logger.LogInformation("Reached stopping point (quest: {QuestId})", id);
_chatGui.Print("Completed quest '" + _startedQuest.Quest.Info.Name + "', which is configured as a stopping point.", "Questionable", 576);
_startedQuest = null;
Stop($"Stopping point [{id}] reached");
}
else if (_questRegistry.TryGetQuest(elementId, out quest4))
{
_logger.LogInformation("New quest: {QuestName}", quest4.Info.Name);
_startedQuest = new QuestProgress(quest4, b);
if (_clientState.LocalPlayer != null && _clientState.LocalPlayer.Level < quest4.Info.Level)
{
_logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer.Level, quest4.Info.Level);
Stop("Quest level too high");
return;
}
if (AutomationType == EAutomationType.SingleQuestB)
{
_logger.LogInformation("Single quest is finished");
AutomationType = EAutomationType.Manual;
}
CheckNextTasks("Different Quest");
}
else if (_startedQuest != null)
{
_logger.LogInformation("No active quest anymore? Not sure what happened...");
_startedQuest = null;
Stop("No active Quest");
}
return;
}
questProgress = _startedQuest;
}
goto IL_0b43;
} }
} }

View file

@ -66,7 +66,14 @@ internal sealed class PluginConfigComponent : ConfigComponent
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_uiUtils = uiUtils; _uiUtils = uiUtils;
_commandManager = commandManager; _commandManager = commandManager;
PluginInfo[] array = new PluginInfo[4]; PluginInfo[] obj = new PluginInfo[5]
{
new PluginInfo("Artisan", "Artisan", "Handles automatic crafting for quests that require\ncrafted items.", new Uri("https://github.com/PunishXIV/Artisan"), new Uri("https://puni.sh/api/plugins")),
null,
null,
null,
null
};
Uri websiteUri = new Uri("https://github.com/Jaksuhn/Automaton"); Uri websiteUri = new Uri("https://github.com/Jaksuhn/Automaton");
Uri dalamudRepositoryUri = new Uri("https://puni.sh/api/repository/croizat"); Uri dalamudRepositoryUri = new Uri("https://puni.sh/api/repository/croizat");
int num = 1; int num = 1;
@ -75,7 +82,7 @@ internal sealed class PluginConfigComponent : ConfigComponent
Span<PluginDetailInfo> span = CollectionsMarshal.AsSpan(list); Span<PluginDetailInfo> span = CollectionsMarshal.AsSpan(list);
int index = 0; int index = 0;
span[index] = new PluginDetailInfo("'Sniper no sniping' enabled", "Automatically completes sniping tasks introduced in Stormblood", () => automatonIpc.IsAutoSnipeEnabled); span[index] = new PluginDetailInfo("'Sniper no sniping' enabled", "Automatically completes sniping tasks introduced in Stormblood", () => automatonIpc.IsAutoSnipeEnabled);
array[0] = new PluginInfo("CBT (formerly known as Automaton)", "Automaton", "Automaton is a collection of automation-related tweaks.", websiteUri, dalamudRepositoryUri, "/cbt", list); obj[1] = new PluginInfo("CBT (formerly known as Automaton)", "Automaton", "Automaton is a collection of automation-related tweaks.", websiteUri, dalamudRepositoryUri, "/cbt", list);
Uri websiteUri2 = new Uri("https://github.com/PunishXIV/PandorasBox"); Uri websiteUri2 = new Uri("https://github.com/PunishXIV/PandorasBox");
Uri dalamudRepositoryUri2 = new Uri("https://puni.sh/api/plugins"); Uri dalamudRepositoryUri2 = new Uri("https://puni.sh/api/plugins");
index = 1; index = 1;
@ -84,10 +91,10 @@ internal sealed class PluginConfigComponent : ConfigComponent
span = CollectionsMarshal.AsSpan(list2); span = CollectionsMarshal.AsSpan(list2);
num = 0; num = 0;
span[num] = new PluginDetailInfo("'Auto Active Time Maneuver' enabled", "Automatically completes active time maneuvers in\nsingle player instances, trials and raids\"", () => pandorasBoxIpc.IsAutoActiveTimeManeuverEnabled); span[num] = new PluginDetailInfo("'Auto Active Time Maneuver' enabled", "Automatically completes active time maneuvers in\nsingle player instances, trials and raids\"", () => pandorasBoxIpc.IsAutoActiveTimeManeuverEnabled);
array[1] = new PluginInfo("Pandora's Box", "PandorasBox", "Pandora's Box is a collection of tweaks.", websiteUri2, dalamudRepositoryUri2, "/pandora", list2); obj[2] = new PluginInfo("Pandora's Box", "PandorasBox", "Pandora's Box is a collection of tweaks.", websiteUri2, dalamudRepositoryUri2, "/pandora", list2);
array[2] = new PluginInfo("QuestMap", "QuestMap", "Displays quest objectives and markers on the map for\nbetter navigation and tracking.", new Uri("https://github.com/rreminy/QuestMap"), null); obj[3] = new PluginInfo("QuestMap", "QuestMap", "Displays quest objectives and markers on the map for\nbetter navigation and tracking.", new Uri("https://github.com/rreminy/QuestMap"), null);
array[3] = new PluginInfo("NotificationMaster", "NotificationMaster", "Sends a configurable out-of-game notification if a quest\nrequires manual actions.", new Uri("https://github.com/NightmareXIV/NotificationMaster"), null); obj[4] = new PluginInfo("NotificationMaster", "NotificationMaster", "Sends a configurable out-of-game notification if a quest\nrequires manual actions.", new Uri("https://github.com/NightmareXIV/NotificationMaster"), null);
_recommendedPlugins = new global::_003C_003Ez__ReadOnlyArray<PluginInfo>(array); _recommendedPlugins = new global::_003C_003Ez__ReadOnlyArray<PluginInfo>(obj);
} }
public override void DrawTab() public override void DrawTab()

View file

@ -1,9 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Components; using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller; using Questionable.Controller;
using Questionable.Data;
using Questionable.Functions; using Questionable.Functions;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.Questing; using Questionable.Model.Questing;
@ -16,13 +20,25 @@ internal sealed class QuestJournalUtils
private readonly QuestFunctions _questFunctions; private readonly QuestFunctions _questFunctions;
private readonly QuestData _questData;
private readonly QuestRegistry _questRegistry;
private readonly ICommandManager _commandManager; private readonly ICommandManager _commandManager;
public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions, ICommandManager commandManager) private readonly IChatGui _chatGui;
private readonly ILogger<QuestJournalUtils> _logger;
public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions, QuestData questData, QuestRegistry questRegistry, ICommandManager commandManager, IChatGui chatGui, ILogger<QuestJournalUtils> logger)
{ {
_questController = questController; _questController = questController;
_questFunctions = questFunctions; _questFunctions = questFunctions;
_questData = questData;
_questRegistry = questRegistry;
_commandManager = commandManager; _commandManager = commandManager;
_chatGui = chatGui;
_logger = logger;
} }
public void ShowContextMenu(IQuestInfo questInfo, Quest? quest, string label) public void ShowContextMenu(IQuestInfo questInfo, Quest? quest, string label)
@ -43,7 +59,10 @@ internal sealed class QuestJournalUtils
{ {
return; return;
} }
using (ImRaii.Disabled(quest == null || (!_questFunctions.IsReadyToAcceptQuest(questInfo.QuestId) && !_questFunctions.IsQuestAccepted(questInfo.QuestId)))) bool flag = _questFunctions.IsQuestComplete(questInfo.QuestId);
bool flag2 = _questFunctions.IsQuestAccepted(questInfo.QuestId);
bool flag3 = _questFunctions.IsReadyToAcceptQuest(questInfo.QuestId);
using (ImRaii.Disabled(quest == null || flag || (!flag3 && !flag2)))
{ {
if (ImGui.MenuItem("Start as next quest")) if (ImGui.MenuItem("Start as next quest"))
{ {
@ -51,7 +70,7 @@ internal sealed class QuestJournalUtils
{ {
return; return;
} }
if (_questFunctions.IsQuestAccepted(questInfo.QuestId)) if (flag2)
{ {
QuestProgressInfo questProgressInfo = _questFunctions.GetQuestProgressInfo(questInfo.QuestId); QuestProgressInfo questProgressInfo = _questFunctions.GetQuestProgressInfo(questInfo.QuestId);
if (questProgressInfo != null) if (questProgressInfo != null)
@ -67,8 +86,32 @@ internal sealed class QuestJournalUtils
} }
} }
} }
bool flag = _commandManager.Commands.ContainsKey("/questinfo"); List<ElementId> incompletePrerequisiteQuests = GetIncompletePrerequisiteQuests(questInfo);
using (ImRaii.Disabled(!(questInfo.QuestId is QuestId) || !flag)) using (ImRaii.Disabled(incompletePrerequisiteQuests.Count == 0))
{
if (ImGui.MenuItem(incompletePrerequisiteQuests.Count switch
{
0 => "Add quest and requirements to priority",
1 => "Add 1 quest to priority",
_ => $"Add {incompletePrerequisiteQuests.Count} quests to priority",
}))
{
AddRequiredQuestsToPriority(questInfo, incompletePrerequisiteQuests);
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
if (incompletePrerequisiteQuests.Count == 0)
{
ImGui.SetTooltip("No quests to add (quest may be complete or already in priority)");
}
else
{
ImGui.SetTooltip((incompletePrerequisiteQuests.Count == 1) ? "Add this quest to the priority list" : $"Add this quest and {incompletePrerequisiteQuests.Count - 1} required quest(s) to the priority list in completion order");
}
}
bool flag4 = _commandManager.Commands.ContainsKey("/questinfo");
using (ImRaii.Disabled(!(questInfo.QuestId is QuestId) || !flag4))
{ {
if (ImGui.MenuItem("View in Quest Map")) if (ImGui.MenuItem("View in Quest Map"))
{ {
@ -77,6 +120,97 @@ internal sealed class QuestJournalUtils
} }
} }
private List<ElementId> GetIncompletePrerequisiteQuests(IQuestInfo questInfo)
{
List<ElementId> list = new List<ElementId>();
HashSet<ElementId> visited = new HashSet<ElementId>();
CollectPrerequisitesRecursive(questInfo, list, visited);
list.Reverse();
List<ElementId> list2 = (from qId in list
where !_questFunctions.IsQuestComplete(qId)
where !_questFunctions.IsQuestUnobtainable(qId)
where _questRegistry.IsKnownQuest(qId)
where !_questController.ManualPriorityQuests.Any((Quest q) => q.Id.Equals(qId))
select qId).ToList();
list2.Reverse();
if (!_questFunctions.IsQuestComplete(questInfo.QuestId) && !_questFunctions.IsQuestUnobtainable(questInfo.QuestId) && _questRegistry.IsKnownQuest(questInfo.QuestId) && !_questController.ManualPriorityQuests.Any((Quest q) => q.Id.Equals(questInfo.QuestId)))
{
list2.Add(questInfo.QuestId);
}
return list2;
}
private void CollectPrerequisitesRecursive(IQuestInfo questInfo, List<ElementId> prerequisites, HashSet<ElementId> visited)
{
if (visited.Contains(questInfo.QuestId))
{
return;
}
visited.Add(questInfo.QuestId);
if (questInfo.PreviousQuests.Count <= 0)
{
return;
}
if (questInfo.PreviousQuestJoin == EQuestJoin.All)
{
foreach (PreviousQuestInfo previousQuest in questInfo.PreviousQuests)
{
if (_questData.TryGetQuestInfo(previousQuest.QuestId, out IQuestInfo questInfo2))
{
CollectPrerequisitesRecursive(questInfo2, prerequisites, visited);
if (!prerequisites.Contains(previousQuest.QuestId))
{
prerequisites.Add(previousQuest.QuestId);
}
}
}
return;
}
if (questInfo.PreviousQuestJoin != EQuestJoin.AtLeastOne)
{
return;
}
foreach (PreviousQuestInfo previousQuest2 in questInfo.PreviousQuests)
{
if (_questFunctions.IsQuestComplete(previousQuest2.QuestId))
{
continue;
}
if (_questData.TryGetQuestInfo(previousQuest2.QuestId, out IQuestInfo questInfo3))
{
CollectPrerequisitesRecursive(questInfo3, prerequisites, visited);
if (!prerequisites.Contains(previousQuest2.QuestId))
{
prerequisites.Add(previousQuest2.QuestId);
}
}
break;
}
}
private void AddRequiredQuestsToPriority(IQuestInfo questInfo, List<ElementId> prerequisiteQuests)
{
int num = 0;
foreach (ElementId prerequisiteQuest in prerequisiteQuests)
{
if (_questController.AddQuestPriority(prerequisiteQuest))
{
num++;
}
}
if (num > 0)
{
string text = ((num == 1) ? "quest" : "quests");
_logger.LogInformation("Added {Count} {QuestWord} for '{QuestName}' to priority list", num, text, questInfo.Name);
_chatGui.Print($"Added {num} {text} to priority list.", "Questionable", 576);
}
else
{
_logger.LogWarning("No quests were added to priority list for '{QuestName}'", questInfo.Name);
_chatGui.Print("No quests to add (may be complete or already in priority).", "Questionable", 576);
}
}
internal static void ShowFilterContextMenu(QuestJournalComponent journalUi) internal static void ShowFilterContextMenu(QuestJournalComponent journalUi)
{ {
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Filter, "Filter")) if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Filter, "Filter"))

View file

@ -2,15 +2,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.24720.0 VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPaths", "QuestPaths\QuestPaths.csproj", "{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPaths", "QuestPaths\QuestPaths.csproj", "{1954490C-FF01-433A-8B69-B0CC3C33D09C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPaths", "GatheringPaths\GatheringPaths.csproj", "{C7436F2B-9500-4F27-AEFB-841907930A01}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatheringPaths", "GatheringPaths\GatheringPaths.csproj", "{552A0564-0233-447E-AC1B-82757CB41CCC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable", "Questionable\Questionable.csproj", "{C36AE435-8B30-4148-BE0E-E6540956DA17}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable", "Questionable\Questionable.csproj", "{22637734-9DB1-433D-873A-80889725EA55}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Questionable.Model", "Questionable.Model\Questionable.Model.csproj", "{5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "LLib\LLib.csproj", "{B91BB617-3180-4694-B139-0DCD37BEBA26}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "LLib\LLib.csproj", "{D25BDC58-3C06-4CC4-8C47-672EC22D21F4}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -20,46 +20,46 @@ Global
Release|x64 = Release|x64 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Debug|AnyCPU.Build.0 = Debug|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Debug|AnyCPU.Build.0 = Debug|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Debug|x64.ActiveCfg = Debug|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Debug|x64.ActiveCfg = Debug|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Debug|x64.Build.0 = Debug|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Debug|x64.Build.0 = Debug|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Release|AnyCPU.ActiveCfg = Release|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Release|AnyCPU.Build.0 = Release|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Release|AnyCPU.Build.0 = Release|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Release|x64.ActiveCfg = Release|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Release|x64.ActiveCfg = Release|AnyCPU
{E1F9E5C0-0D8A-4C9C-A2CD-3814C4D3B421}.Release|x64.Build.0 = Release|AnyCPU {1954490C-FF01-433A-8B69-B0CC3C33D09C}.Release|x64.Build.0 = Release|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Debug|AnyCPU.Build.0 = Debug|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Debug|AnyCPU.Build.0 = Debug|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Debug|x64.ActiveCfg = Debug|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Debug|x64.ActiveCfg = Debug|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Debug|x64.Build.0 = Debug|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Debug|x64.Build.0 = Debug|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Release|AnyCPU.ActiveCfg = Release|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Release|AnyCPU.Build.0 = Release|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Release|AnyCPU.Build.0 = Release|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Release|x64.ActiveCfg = Release|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Release|x64.ActiveCfg = Release|AnyCPU
{C7436F2B-9500-4F27-AEFB-841907930A01}.Release|x64.Build.0 = Release|AnyCPU {552A0564-0233-447E-AC1B-82757CB41CCC}.Release|x64.Build.0 = Release|AnyCPU
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Debug|AnyCPU.ActiveCfg = Debug|x64 {22637734-9DB1-433D-873A-80889725EA55}.Debug|AnyCPU.ActiveCfg = Debug|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Debug|AnyCPU.Build.0 = Debug|x64 {22637734-9DB1-433D-873A-80889725EA55}.Debug|AnyCPU.Build.0 = Debug|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Debug|x64.ActiveCfg = Debug|x64 {22637734-9DB1-433D-873A-80889725EA55}.Debug|x64.ActiveCfg = Debug|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Debug|x64.Build.0 = Debug|x64 {22637734-9DB1-433D-873A-80889725EA55}.Debug|x64.Build.0 = Debug|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Release|AnyCPU.ActiveCfg = Release|x64 {22637734-9DB1-433D-873A-80889725EA55}.Release|AnyCPU.ActiveCfg = Release|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Release|AnyCPU.Build.0 = Release|x64 {22637734-9DB1-433D-873A-80889725EA55}.Release|AnyCPU.Build.0 = Release|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Release|x64.ActiveCfg = Release|x64 {22637734-9DB1-433D-873A-80889725EA55}.Release|x64.ActiveCfg = Release|x64
{C36AE435-8B30-4148-BE0E-E6540956DA17}.Release|x64.Build.0 = Release|x64 {22637734-9DB1-433D-873A-80889725EA55}.Release|x64.Build.0 = Release|x64
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Debug|AnyCPU.ActiveCfg = Debug|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Debug|AnyCPU.Build.0 = Debug|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Debug|AnyCPU.Build.0 = Debug|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Debug|x64.ActiveCfg = Debug|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Debug|x64.ActiveCfg = Debug|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Debug|x64.Build.0 = Debug|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Debug|x64.Build.0 = Debug|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Release|AnyCPU.ActiveCfg = Release|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Release|AnyCPU.Build.0 = Release|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Release|AnyCPU.Build.0 = Release|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Release|x64.ActiveCfg = Release|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Release|x64.ActiveCfg = Release|AnyCPU
{2B7F9D9F-E084-4AFF-86BF-751C3C1A020F}.Release|x64.Build.0 = Release|AnyCPU {5BFCA116-AFB3-4CC0-9AA6-BF38AA873113}.Release|x64.Build.0 = Release|AnyCPU
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Debug|AnyCPU.ActiveCfg = Debug|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Debug|AnyCPU.ActiveCfg = Debug|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Debug|AnyCPU.Build.0 = Debug|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Debug|AnyCPU.Build.0 = Debug|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Debug|x64.ActiveCfg = Debug|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Debug|x64.ActiveCfg = Debug|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Debug|x64.Build.0 = Debug|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Debug|x64.Build.0 = Debug|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Release|AnyCPU.ActiveCfg = Release|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Release|AnyCPU.ActiveCfg = Release|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Release|AnyCPU.Build.0 = Release|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Release|AnyCPU.Build.0 = Release|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Release|x64.ActiveCfg = Release|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Release|x64.ActiveCfg = Release|x64
{B91BB617-3180-4694-B139-0DCD37BEBA26}.Release|x64.Build.0 = Release|x64 {D25BDC58-3C06-4CC4-8C47-672EC22D21F4}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE