diff --git a/Questionable/Controller/Steps/QuestCleanUp.cs b/Questionable/Controller/Steps/QuestCleanUp.cs new file mode 100644 index 00000000..b3cd5b50 --- /dev/null +++ b/Questionable/Controller/Steps/QuestCleanUp.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Logging; +using Questionable.Controller.Steps.Shared; +using Questionable.Data; +using Questionable.Functions; +using Questionable.Model; +using Questionable.Model.Common; +using Questionable.Model.Questing; + +namespace Questionable.Controller.Steps; + +internal static class QuestCleanUp +{ + private static readonly Dictionary AlliedSocietyMountConfiguration = new() + { + { 369, new(1051798, EAetheryteLocation.KozamaukaDockPoga) } + }; + + internal sealed class CheckAlliedSocietyMount(GameFunctions gameFunctions, AetheryteData aetheryteData, ILogger logger) : SimpleTaskFactory + { + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + { + if (sequence.Sequence == 0) + return null; + + // if you are on a allied society mount + if (gameFunctions.GetMountId() is { } mountId && + AlliedSocietyMountConfiguration.TryGetValue(mountId, out var mountConfiguration)) + { + logger.LogInformation("We are on a known allied society mount with id = {MountId}", mountId); + + // it doesn't particularly matter if we teleport to the same aetheryte twice in the same quest step, as + // the second (normal) teleport instance should detect that we're within range and not do anything + var targetAetheryte = step.AetheryteShortcut ?? mountConfiguration.ClosestAetheryte; + var teleportTask = new AetheryteShortcut.Task(null, quest.Id, targetAetheryte, aetheryteData.TerritoryIds[targetAetheryte]); + + // turn-in step can never be done while mounted on an allied society mount + if (sequence.Sequence == 255) + { + logger.LogInformation("Mount can't be used to finish quest, teleporting to {Aetheryte}", mountConfiguration.ClosestAetheryte); + return teleportTask; + } + + // if the quest uses no mount actions, that's not a mount quest + if (!quest.AllSteps().Any(x => x.Step.Action is { } action && action.RequiresMount())) + { + logger.LogInformation("Quest doesn't use any mount actions, teleporting to {Aetheryte}", mountConfiguration.ClosestAetheryte); + return teleportTask; + } + + // have any of the previous sequences interacted with the issuer? + var previousSequences = + quest.AllSequences() + .Where(x => x.Sequence > 0 // quest accept doesn't ever put us into a mount + && x.Sequence < sequence.Sequence) + .ToList(); + if (previousSequences.SelectMany(x => x.Steps).All(x => x.DataId != mountConfiguration.IssuerDataId)) + { + // this quest hasn't given us a mount yet + logger.LogInformation("Haven't talked to mount NPC for this allied society quest; {Aetheryte}", mountConfiguration.ClosestAetheryte); + return teleportTask; + } + } + + return null; + } + } + + private sealed record MountConfiguration(uint IssuerDataId, EAetheryteLocation ClosestAetheryte); +} diff --git a/Questionable/Functions/QuestFunctions.cs b/Questionable/Functions/QuestFunctions.cs index dc507a0a..1ef56c4e 100644 --- a/Questionable/Functions/QuestFunctions.cs +++ b/Questionable/Functions/QuestFunctions.cs @@ -243,7 +243,6 @@ internal sealed unsafe class QuestFunctions { return questId.Value switch { - 5215 => EAlliedSociety.None, >= 5199 and <= 5226 => EAlliedSociety.Pelupelu, _ => EAlliedSociety.None, }; diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index 8cc59d16..7b17db4c 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -133,6 +133,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin private static void AddTaskFactories(ServiceCollection serviceCollection) { // individual tasks + serviceCollection.AddTaskFactory(); serviceCollection .AddTaskExecutor(); serviceCollection.AddTaskExecutor();