open single player duty dialogues
authorLiza Carvelli <liza@carvel.li>
Sun, 16 Jun 2024 15:43:42 +0000 (17:43 +0200)
committerLiza Carvelli <liza@carvel.li>
Sun, 16 Jun 2024 15:43:42 +0000 (17:43 +0200)
Questionable/Controller/QuestController.cs
Questionable/Controller/Steps/BaseFactory/WaitAtEnd.cs
Questionable/Controller/Steps/InteractionFactory/SinglePlayerDuty.cs [new file with mode: 0644]
Questionable/External/YesAlreadyIpc.cs [new file with mode: 0644]
Questionable/QuestionablePlugin.cs

index 7cd71c4df919e1dd5fb13e24864cc086f2da1be9..9a64589a4e2fe6564a34b4c1448d22db92fe6beb 100644 (file)
@@ -5,6 +5,7 @@ using Dalamud.Game.ClientState.Keys;
 using Dalamud.Plugin.Services;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps;
+using Questionable.External;
 using Questionable.Model;
 using Questionable.Model.V1;
 
@@ -19,6 +20,7 @@ internal sealed class QuestController
     private readonly QuestRegistry _questRegistry;
     private readonly IKeyState _keyState;
     private readonly Configuration _configuration;
+    private readonly YesAlreadyIpc _yesAlreadyIpc;
     private readonly IReadOnlyList<ITaskFactory> _taskFactories;
 
     private readonly object _lock = new();
@@ -35,6 +37,7 @@ internal sealed class QuestController
         QuestRegistry questRegistry,
         IKeyState keyState,
         Configuration configuration,
+        YesAlreadyIpc yesAlreadyIpc,
         IEnumerable<ITaskFactory> taskFactories)
     {
         _clientState = clientState;
@@ -44,6 +47,7 @@ internal sealed class QuestController
         _questRegistry = questRegistry;
         _keyState = keyState;
         _configuration = configuration;
+        _yesAlreadyIpc = yesAlreadyIpc;
         _taskFactories = taskFactories.ToList().AsReadOnly();
     }
 
@@ -273,6 +277,9 @@ internal sealed class QuestController
 
         if (_taskQueue.Count > 0)
             _taskQueue.Clear();
+
+        _movementController.Stop();
+        _yesAlreadyIpc.DisableYesAlready();
     }
 
     public void Stop(string label, bool continueIfAutomatic = false)
index 8c9ed5e952ffac151a0a9687a5dcf010233eab02..31ec90d9e334bd833c48e320b949769cfb761bcc 100644 (file)
@@ -60,7 +60,7 @@ internal static class WaitAtEnd
                     return
                     [
                         serviceProvider.GetRequiredService<WaitObjectAtPosition>()
-                            .With(step.DataId.Value, step.Position.Value),
+                            .With(step.DataId.Value, step.Position.Value, step.NpcWaitDistance ?? 0.05f),
                         serviceProvider.GetRequiredService<WaitDelay>(),
                         Next(quest, sequence, step)
                     ];
@@ -179,18 +179,20 @@ internal static class WaitAtEnd
     {
         public uint DataId { get; set; }
         public Vector3 Destination { get; set; }
+        public float Distance { get; set; }
 
-        public ITask With(uint dataId, Vector3 destination)
+        public ITask With(uint dataId, Vector3 destination, float distance)
         {
             DataId = dataId;
             Destination = destination;
+            Distance = distance;
             return this;
         }
 
         public bool Start() => true;
 
         public ETaskResult Update() =>
-            gameFunctions.IsObjectAtPosition(DataId, Destination)
+            gameFunctions.IsObjectAtPosition(DataId, Destination, Distance)
                 ? ETaskResult.TaskComplete
                 : ETaskResult.StillRunning;
 
diff --git a/Questionable/Controller/Steps/InteractionFactory/SinglePlayerDuty.cs b/Questionable/Controller/Steps/InteractionFactory/SinglePlayerDuty.cs
new file mode 100644 (file)
index 0000000..d80be1f
--- /dev/null
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using Dalamud.Plugin.Services;
+using Microsoft.Extensions.DependencyInjection;
+using Questionable.External;
+using Questionable.Model;
+using Questionable.Model.V1;
+
+namespace Questionable.Controller.Steps.InteractionFactory;
+
+internal static class SinglePlayerDuty
+{
+    internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory
+    {
+        public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
+        {
+            if (step.InteractionType != EInteractionType.SinglePlayerDuty)
+                return [];
+
+            ArgumentNullException.ThrowIfNull(step.DataId);
+            return
+            [
+                serviceProvider.GetRequiredService<DisableYesAlready>(),
+                serviceProvider.GetRequiredService<Interact.DoInteract>()
+                    .With(step.DataId.Value, true),
+                serviceProvider.GetRequiredService<RestoreYesAlready>()
+            ];
+        }
+
+        public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
+            => throw new InvalidOperationException();
+    }
+
+    internal sealed class DisableYesAlready(YesAlreadyIpc yesAlreadyIpc) : ITask
+    {
+        public bool Start()
+        {
+            yesAlreadyIpc.DisableYesAlready();
+            return true;
+        }
+
+        public ETaskResult Update() => ETaskResult.TaskComplete;
+
+        public override string ToString() => "DisableYA";
+    }
+
+    internal sealed class RestoreYesAlready(YesAlreadyIpc yesAlreadyIpc, IGameGui gameGui) : ITask
+    {
+        public bool Start() => true;
+
+        public ETaskResult Update()
+        {
+            if (gameGui.GetAddonByName("SelectYesno") != nint.Zero ||
+                gameGui.GetAddonByName("DifficultySelectYesNo") != nint.Zero)
+                return ETaskResult.StillRunning;
+
+            yesAlreadyIpc.RestoreYesAlready();
+            return ETaskResult.TaskComplete;
+        }
+
+        public override string ToString() => "Wait(DialogClosed) → RestoreYA";
+    }
+}
diff --git a/Questionable/External/YesAlreadyIpc.cs b/Questionable/External/YesAlreadyIpc.cs
new file mode 100644 (file)
index 0000000..8b69f78
--- /dev/null
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using Dalamud.Plugin;
+using Dalamud.Plugin.Services;
+
+namespace Questionable.External;
+
+internal sealed class YesAlreadyIpc : IDisposable
+{
+    private readonly DalamudPluginInterface _pluginInterface;
+    private readonly IPluginLog _pluginLog;
+
+    public YesAlreadyIpc(DalamudPluginInterface pluginInterface, IPluginLog pluginLog)
+    {
+        _pluginInterface = pluginInterface;
+        _pluginLog = pluginLog;
+    }
+
+    public void DisableYesAlready()
+    {
+        _pluginLog.Debug("Disabling YesAlready");
+        if (_pluginInterface.TryGetData<HashSet<string>>("YesAlready.StopRequests", out var data))
+            data.Add(nameof(Questionable));
+    }
+
+    public void RestoreYesAlready()
+    {
+        _pluginLog.Debug("Restoring YesAlready");
+        if (_pluginInterface.TryGetData<HashSet<string>>("YesAlready.StopRequests", out var data))
+            data.Remove(nameof(Questionable));
+    }
+
+    public void Dispose() => RestoreYesAlready();
+}
index ee58324d76fea1b2edea47e70eafdf5647e792a0..4046b3bbf408eccee4d790accad445212b9de748 100644 (file)
@@ -69,6 +69,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
         serviceCollection.AddSingleton<TerritoryData>();
         serviceCollection.AddSingleton<NavmeshIpc>();
         serviceCollection.AddSingleton<LifestreamIpc>();
+        serviceCollection.AddSingleton<YesAlreadyIpc>();
 
         // individual tasks
         serviceCollection.AddTransient<MountTask>();
@@ -93,6 +94,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
         serviceCollection.AddTaskWithFactory<Say.Factory, Say.UseChat>();
         serviceCollection.AddTaskWithFactory<UseItem.Factory, UseItem.UseOnGround, UseItem.UseOnObject, UseItem.Use>();
         serviceCollection.AddTaskWithFactory<EquipItem.Factory, EquipItem.DoEquip>();
+        serviceCollection.AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready, SinglePlayerDuty.RestoreYesAlready>();
 
         serviceCollection
             .AddTaskWithFactory<WaitAtEnd.Factory,