diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 7cd71c4df..9a64589a4 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -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 _taskFactories; private readonly object _lock = new(); @@ -35,6 +37,7 @@ internal sealed class QuestController QuestRegistry questRegistry, IKeyState keyState, Configuration configuration, + YesAlreadyIpc yesAlreadyIpc, IEnumerable 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) diff --git a/Questionable/Controller/Steps/BaseFactory/WaitAtEnd.cs b/Questionable/Controller/Steps/BaseFactory/WaitAtEnd.cs index 8c9ed5e95..31ec90d9e 100644 --- a/Questionable/Controller/Steps/BaseFactory/WaitAtEnd.cs +++ b/Questionable/Controller/Steps/BaseFactory/WaitAtEnd.cs @@ -60,7 +60,7 @@ internal static class WaitAtEnd return [ serviceProvider.GetRequiredService() - .With(step.DataId.Value, step.Position.Value), + .With(step.DataId.Value, step.Position.Value, step.NpcWaitDistance ?? 0.05f), serviceProvider.GetRequiredService(), 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 index 000000000..d80be1f8e --- /dev/null +++ b/Questionable/Controller/Steps/InteractionFactory/SinglePlayerDuty.cs @@ -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 CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) + { + if (step.InteractionType != EInteractionType.SinglePlayerDuty) + return []; + + ArgumentNullException.ThrowIfNull(step.DataId); + return + [ + serviceProvider.GetRequiredService(), + serviceProvider.GetRequiredService() + .With(step.DataId.Value, true), + serviceProvider.GetRequiredService() + ]; + } + + 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 index 000000000..8b69f7890 --- /dev/null +++ b/Questionable/External/YesAlreadyIpc.cs @@ -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>("YesAlready.StopRequests", out var data)) + data.Add(nameof(Questionable)); + } + + public void RestoreYesAlready() + { + _pluginLog.Debug("Restoring YesAlready"); + if (_pluginInterface.TryGetData>("YesAlready.StopRequests", out var data)) + data.Remove(nameof(Questionable)); + } + + public void Dispose() => RestoreYesAlready(); +} diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index ee58324d7..4046b3bbf 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -69,6 +69,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // individual tasks serviceCollection.AddTransient(); @@ -93,6 +94,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin serviceCollection.AddTaskWithFactory(); serviceCollection.AddTaskWithFactory(); serviceCollection.AddTaskWithFactory(); + serviceCollection.AddTaskWithFactory(); serviceCollection .AddTaskWithFactory