Rework the mount/allied society quest logic
authorLiza Carvelli <liza@carvel.li>
Mon, 25 Nov 2024 15:53:37 +0000 (16:53 +0100)
committerLiza Carvelli <liza@carvel.li>
Mon, 25 Nov 2024 15:53:37 +0000 (16:53 +0100)
Questionable/Controller/Steps/QuestCleanUp.cs [new file with mode: 0644]
Questionable/Functions/QuestFunctions.cs
Questionable/QuestionablePlugin.cs

diff --git a/Questionable/Controller/Steps/QuestCleanUp.cs b/Questionable/Controller/Steps/QuestCleanUp.cs
new file mode 100644 (file)
index 0000000..b3cd5b5
--- /dev/null
@@ -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<ushort, MountConfiguration> AlliedSocietyMountConfiguration = new()
+    {
+        { 369, new(1051798, EAetheryteLocation.KozamaukaDockPoga) }
+    };
+
+    internal sealed class CheckAlliedSocietyMount(GameFunctions gameFunctions, AetheryteData aetheryteData, ILogger<CheckAlliedSocietyMount> 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);
+}
index dc507a0a31b0744563d61f56598b831c74b2f54c..1ef56c4e42d3e59d2f4e451eed2a369900229a43 100644 (file)
@@ -243,7 +243,6 @@ internal sealed unsafe class QuestFunctions
         {
             return questId.Value switch
             {
-                5215 => EAlliedSociety.None,
                 >= 5199 and <= 5226 => EAlliedSociety.Pelupelu,
                 _ => EAlliedSociety.None,
             };
index 8cc59d16e9fca2dc019eb4b2c00e781308316772..7b17db4c0138a1303be8e19787951844c18958fe 100644 (file)
@@ -133,6 +133,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
     private static void AddTaskFactories(ServiceCollection serviceCollection)
     {
         // individual tasks
+        serviceCollection.AddTaskFactory<QuestCleanUp.CheckAlliedSocietyMount>();
         serviceCollection
             .AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>();
         serviceCollection.AddTaskExecutor<DoGather.Task, DoGather.GatherExecutor>();