diff --git a/QuestPaths/6.x - Endwalker/Allied Societies/Loporrits/Dailies/4689_Money Makes the Moon Go Round.json b/QuestPaths/6.x - Endwalker/Allied Societies/Loporrits/Dailies/4689_Money Makes the Moon Go Round.json index 10d5d1e8..b1d281b4 100644 --- a/QuestPaths/6.x - Endwalker/Allied Societies/Loporrits/Dailies/4689_Money Makes the Moon Go Round.json +++ b/QuestPaths/6.x - Endwalker/Allied Societies/Loporrits/Dailies/4689_Money Makes the Moon Go Round.json @@ -57,7 +57,8 @@ "Z": -273.68756 }, "TerritoryId": 959, - "InteractionType": "WalkTo" + "InteractionType": "WalkTo", + "Fly": true }, { "DataId": 1044403, diff --git a/Questionable/Controller/Steps/Common/NextQuest.cs b/Questionable/Controller/Steps/Common/NextQuest.cs index 4efe08ae..f338c88c 100644 --- a/Questionable/Controller/Steps/Common/NextQuest.cs +++ b/Questionable/Controller/Steps/Common/NextQuest.cs @@ -9,9 +9,9 @@ namespace Questionable.Controller.Steps.Common; internal static class NextQuest { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.CompleteQuest) return null; diff --git a/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs b/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs index f3a4ed51..23abcb3c 100644 --- a/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs +++ b/Questionable/Controller/Steps/Gathering/TurnInDelivery.cs @@ -13,9 +13,9 @@ namespace Questionable.Controller.Steps.Gathering; internal static class TurnInDelivery { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (quest.Id is not SatisfactionSupplyNpcId || sequence.Sequence != 1) return null; diff --git a/Questionable/Controller/Steps/ITaskFactory.cs b/Questionable/Controller/Steps/ITaskFactory.cs index 287f029f..19d5de0b 100644 --- a/Questionable/Controller/Steps/ITaskFactory.cs +++ b/Questionable/Controller/Steps/ITaskFactory.cs @@ -6,12 +6,5 @@ namespace Questionable.Controller.Steps; internal interface ITaskFactory { - ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step); - - IEnumerable CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) - { - var task = CreateTask(quest, sequence, step); - if (task != null) - yield return task; - } + IEnumerable CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step); } diff --git a/Questionable/Controller/Steps/Interactions/Action.cs b/Questionable/Controller/Steps/Interactions/Action.cs index cf60b6c7..802d2d8c 100644 --- a/Questionable/Controller/Steps/Interactions/Action.cs +++ b/Questionable/Controller/Steps/Interactions/Action.cs @@ -33,9 +33,6 @@ internal static class Action return [unmount, task]; } } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); } internal sealed class UseOnObject(GameFunctions gameFunctions, ILogger logger) : ITask diff --git a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs index 7df86e78..d4387288 100644 --- a/Questionable/Controller/Steps/Interactions/AetherCurrent.cs +++ b/Questionable/Controller/Steps/Interactions/AetherCurrent.cs @@ -11,9 +11,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class AetherCurrent { - internal sealed class Factory(IServiceProvider serviceProvider, AetherCurrentData aetherCurrentData, IChatGui chatGui) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider, AetherCurrentData aetherCurrentData, IChatGui chatGui) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.AttuneAetherCurrent) return null; diff --git a/Questionable/Controller/Steps/Interactions/AethernetShard.cs b/Questionable/Controller/Steps/Interactions/AethernetShard.cs index c1e14010..06079acb 100644 --- a/Questionable/Controller/Steps/Interactions/AethernetShard.cs +++ b/Questionable/Controller/Steps/Interactions/AethernetShard.cs @@ -11,9 +11,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class AethernetShard { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.AttuneAethernetShard) return null; diff --git a/Questionable/Controller/Steps/Interactions/Aetheryte.cs b/Questionable/Controller/Steps/Interactions/Aetheryte.cs index 4a47b744..61033749 100644 --- a/Questionable/Controller/Steps/Interactions/Aetheryte.cs +++ b/Questionable/Controller/Steps/Interactions/Aetheryte.cs @@ -10,9 +10,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class Aetheryte { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.AttuneAetheryte) return null; diff --git a/Questionable/Controller/Steps/Interactions/Dive.cs b/Questionable/Controller/Steps/Interactions/Dive.cs index 3976eb73..3b8712f4 100644 --- a/Questionable/Controller/Steps/Interactions/Dive.cs +++ b/Questionable/Controller/Steps/Interactions/Dive.cs @@ -18,9 +18,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class Dive { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.Dive) return null; diff --git a/Questionable/Controller/Steps/Interactions/Duty.cs b/Questionable/Controller/Steps/Interactions/Duty.cs index 35a73dd9..ed80dd4c 100644 --- a/Questionable/Controller/Steps/Interactions/Duty.cs +++ b/Questionable/Controller/Steps/Interactions/Duty.cs @@ -10,9 +10,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class Duty { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.Duty) return null; diff --git a/Questionable/Controller/Steps/Interactions/Emote.cs b/Questionable/Controller/Steps/Interactions/Emote.cs index fafa0fd8..35cd64b7 100644 --- a/Questionable/Controller/Steps/Interactions/Emote.cs +++ b/Questionable/Controller/Steps/Interactions/Emote.cs @@ -36,9 +36,6 @@ internal static class Emote return [unmount, task]; } } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); } internal sealed class UseOnObject(ChatFunctions chatFunctions) : AbstractDelayedTask diff --git a/Questionable/Controller/Steps/Interactions/EquipItem.cs b/Questionable/Controller/Steps/Interactions/EquipItem.cs index 84952fe7..abd72c7c 100644 --- a/Questionable/Controller/Steps/Interactions/EquipItem.cs +++ b/Questionable/Controller/Steps/Interactions/EquipItem.cs @@ -16,9 +16,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class EquipItem { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.EquipItem) return null; diff --git a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs index c97ec7dc..e94f819f 100644 --- a/Questionable/Controller/Steps/Interactions/EquipRecommended.cs +++ b/Questionable/Controller/Steps/Interactions/EquipRecommended.cs @@ -10,9 +10,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class EquipRecommended { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.EquipRecommended) return null; @@ -21,9 +21,9 @@ internal static class EquipRecommended } } - internal sealed class BeforeDutyOrInstance(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class BeforeDutyOrInstance(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.Duty && step.InteractionType != EInteractionType.SinglePlayerDuty && diff --git a/Questionable/Controller/Steps/Interactions/Interact.cs b/Questionable/Controller/Steps/Interactions/Interact.cs index 9fc57638..50aae41a 100644 --- a/Questionable/Controller/Steps/Interactions/Interact.cs +++ b/Questionable/Controller/Steps/Interactions/Interact.cs @@ -42,9 +42,6 @@ internal static class Interact .With(step.DataId.Value, quest, step.InteractionType, step.TargetTerritoryId != null || quest.Id is SatisfactionSupplyNpcId); } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); } internal sealed class DoInteract(GameFunctions gameFunctions, ICondition condition, ILogger logger) diff --git a/Questionable/Controller/Steps/Interactions/Jump.cs b/Questionable/Controller/Steps/Interactions/Jump.cs index 0b0b099d..dd2dc92a 100644 --- a/Questionable/Controller/Steps/Interactions/Jump.cs +++ b/Questionable/Controller/Steps/Interactions/Jump.cs @@ -11,9 +11,9 @@ namespace Questionable.Controller.Steps.Interactions; internal static class Jump { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.Jump) return null; diff --git a/Questionable/Controller/Steps/Interactions/Say.cs b/Questionable/Controller/Steps/Interactions/Say.cs index ee900af3..f203d42f 100644 --- a/Questionable/Controller/Steps/Interactions/Say.cs +++ b/Questionable/Controller/Steps/Interactions/Say.cs @@ -28,9 +28,6 @@ internal static class Say var task = serviceProvider.GetRequiredService().With(excelString); return [unmount, task]; } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); } internal sealed class UseChat(ChatFunctions chatFunctions) : AbstractDelayedTask diff --git a/Questionable/Controller/Steps/Interactions/UseItem.cs b/Questionable/Controller/Steps/Interactions/UseItem.cs index d32bb0a4..ead22098 100644 --- a/Questionable/Controller/Steps/Interactions/UseItem.cs +++ b/Questionable/Controller/Steps/Interactions/UseItem.cs @@ -100,9 +100,6 @@ internal static class UseItem } } - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); - private IEnumerable CreateVesperBayFallbackTask() { logger.LogWarning("No vesper bay aetheryte tickets in inventory, navigating via ferry in Limsa instead"); diff --git a/Questionable/Controller/Steps/Leves/InitiateLeve.cs b/Questionable/Controller/Steps/Leves/InitiateLeve.cs index 42cd8a48..545324a4 100644 --- a/Questionable/Controller/Steps/Leves/InitiateLeve.cs +++ b/Questionable/Controller/Steps/Leves/InitiateLeve.cs @@ -30,9 +30,6 @@ internal static class InitiateLeve yield return serviceProvider.GetRequiredService(); yield return new WaitConditionTask(() => condition[ConditionFlag.BoundByDuty], "Wait(BoundByDuty)"); } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new NotImplementedException(); } internal sealed unsafe class SkipInitiateIfActive : ITask diff --git a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs index 1c45596d..d550cb66 100644 --- a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs @@ -20,9 +20,9 @@ namespace Questionable.Controller.Steps.Shared; internal static class AethernetShortcut { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.AethernetShortcut == null) return null; diff --git a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs index 9da8a019..59cd75f3 100644 --- a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs @@ -17,9 +17,9 @@ internal static class AetheryteShortcut { internal sealed class Factory( IServiceProvider serviceProvider, - AetheryteData aetheryteData) : ITaskFactory + AetheryteData aetheryteData) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.AetheryteShortcut == null) return null; diff --git a/Questionable/Controller/Steps/Shared/Craft.cs b/Questionable/Controller/Steps/Shared/Craft.cs index ef46af8d..2aeff864 100644 --- a/Questionable/Controller/Steps/Shared/Craft.cs +++ b/Questionable/Controller/Steps/Shared/Craft.cs @@ -1,9 +1,15 @@ using System; +using System.Collections.Generic; using System.Linq; using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI.Agent; +using FFXIVClientStructs.FFXIV.Component.GUI; using LLib.GameData; using Lumina.Excel.GeneratedSheets; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Questionable.Controller.Steps.Common; using Questionable.External; using Questionable.Model.Questing; using Quest = Questionable.Model.Quest; @@ -14,19 +20,27 @@ internal static class Craft { internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public IEnumerable CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.Craft) - return null; + return []; ArgumentNullException.ThrowIfNull(step.ItemId); ArgumentNullException.ThrowIfNull(step.ItemCount); - return serviceProvider.GetRequiredService() - .With(step.ItemId.Value, step.ItemCount.Value); + return + [ + serviceProvider.GetRequiredService(), + serviceProvider.GetRequiredService() + .With(step.ItemId.Value, step.ItemCount.Value) + ]; } } - internal sealed class DoCraft(IDataManager dataManager, IClientState clientState, ArtisanIpc artisanIpc) : ITask + internal sealed class DoCraft( + IDataManager dataManager, + IClientState clientState, + ArtisanIpc artisanIpc, + ILogger logger) : ITask { private uint _itemId; private int _itemCount; @@ -40,11 +54,17 @@ internal static class Craft public bool Start() { + if (HasRequestedItems()) + { + logger.LogInformation("Already own {ItemCount}x {ItemId}", _itemCount, _itemId); + return false; + } + RecipeLookup? recipeLookup = dataManager.GetExcelSheet()!.GetRow(_itemId); if (recipeLookup == null) throw new TaskException($"Item {_itemId} is not craftable"); - uint recipeId = ((EClassJob)clientState.LocalPlayer!.ClassJob.Id) switch + uint recipeId = (EClassJob)clientState.LocalPlayer!.ClassJob.Id switch { EClassJob.Carpenter => recipeLookup.CRP.Row, EClassJob.Blacksmith => recipeLookup.BSM.Row, @@ -59,7 +79,8 @@ internal static class Craft if (recipeId == 0) { - recipeId = new[]{ + recipeId = new[] + { recipeLookup.CRP.Row, recipeLookup.BSM.Row, recipeLookup.ARM.Row, @@ -75,15 +96,49 @@ internal static class Craft if (recipeId == 0) throw new TaskException($"Unable to determine recipe for item {_itemId}"); - if (!artisanIpc.CraftItem((ushort)recipeId, _itemCount)) + int remainingItemCount = _itemCount - GetOwnedItemCount(); + logger.LogInformation( + "Starting craft for item {ItemId} with recipe {RecipeId} for {RemainingItemCount} items", + _itemId, recipeId, remainingItemCount); + if (!artisanIpc.CraftItem((ushort)recipeId, remainingItemCount)) throw new TaskException($"Failed to start Artisan craft for recipe {recipeId}"); return true; } - public ETaskResult Update() + public unsafe ETaskResult Update() { + if (HasRequestedItems() && !artisanIpc.IsCrafting()) + { + AgentRecipeNote* agentRecipeNote = AgentRecipeNote.Instance(); + if (agentRecipeNote != null && agentRecipeNote->IsAgentActive()) + { + uint addonId = agentRecipeNote->GetAddonId(); + if (addonId == 0) + return ETaskResult.StillRunning; + + AtkUnitBase* addon = AtkStage.Instance()->RaptureAtkUnitManager->GetAddonById((ushort)addonId); + if (addon != null) + { + logger.LogInformation("Closing crafting window"); + addon->Close(true); + return ETaskResult.TaskComplete; + } + } + } + return ETaskResult.StillRunning; } + + private bool HasRequestedItems() => GetOwnedItemCount() >= _itemCount; + + private unsafe int GetOwnedItemCount() + { + InventoryManager* inventoryManager = InventoryManager.Instance(); + return inventoryManager->GetInventoryItemCount(_itemId, isHq: false, checkEquipped: false) + + inventoryManager->GetInventoryItemCount(_itemId, isHq: true, checkEquipped: false); + } + + public override string ToString() => $"Craft {_itemCount}x {_itemId} (with Artisan)"; } } diff --git a/Questionable/Controller/Steps/Shared/GatheringRequiredItems.cs b/Questionable/Controller/Steps/Shared/GatheringRequiredItems.cs index a58c288e..9fdf9033 100644 --- a/Questionable/Controller/Steps/Shared/GatheringRequiredItems.cs +++ b/Questionable/Controller/Steps/Shared/GatheringRequiredItems.cs @@ -105,9 +105,6 @@ internal static class GatheringRequiredItems minCollectability: (short)requiredGatheredItems.Collectability) >= requiredGatheredItems.ItemCount; } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new NotImplementedException(); } internal sealed class StartGathering(GatheringController gatheringController) : ITask diff --git a/Questionable/Controller/Steps/Shared/Move.cs b/Questionable/Controller/Steps/Shared/Move.cs index 83b0f932..256badef 100644 --- a/Questionable/Controller/Steps/Shared/Move.cs +++ b/Questionable/Controller/Steps/Shared/Move.cs @@ -59,9 +59,6 @@ internal static class Move return []; } - - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); } internal sealed class MoveBuilder( diff --git a/Questionable/Controller/Steps/Shared/SkipCondition.cs b/Questionable/Controller/Steps/Shared/SkipCondition.cs index f750cc8b..eed128c5 100644 --- a/Questionable/Controller/Steps/Shared/SkipCondition.cs +++ b/Questionable/Controller/Steps/Shared/SkipCondition.cs @@ -20,9 +20,9 @@ namespace Questionable.Controller.Steps.Shared; internal static class SkipCondition { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { var skipConditions = step.SkipConditions?.StepIf; if (skipConditions is { Never: true }) diff --git a/Questionable/Controller/Steps/Shared/StepDisabled.cs b/Questionable/Controller/Steps/Shared/StepDisabled.cs index 609f3143..430a8981 100644 --- a/Questionable/Controller/Steps/Shared/StepDisabled.cs +++ b/Questionable/Controller/Steps/Shared/StepDisabled.cs @@ -8,9 +8,9 @@ namespace Questionable.Controller.Steps.Shared; internal static class StepDisabled { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (!step.Disabled) return null; diff --git a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs index 97e53f7d..a1d29c42 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtEnd.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtEnd.cs @@ -136,9 +136,6 @@ internal static class WaitAtEnd } } - public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step) - => throw new InvalidOperationException(); - private static NextStep Next(Quest quest, QuestSequence sequence) { return new NextStep(quest.Id, sequence.Sequence); diff --git a/Questionable/Controller/Steps/Shared/WaitAtStart.cs b/Questionable/Controller/Steps/Shared/WaitAtStart.cs index b39e301d..1e7944c5 100644 --- a/Questionable/Controller/Steps/Shared/WaitAtStart.cs +++ b/Questionable/Controller/Steps/Shared/WaitAtStart.cs @@ -8,9 +8,9 @@ namespace Questionable.Controller.Steps.Shared; internal static class WaitAtStart { - internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory + internal sealed class Factory(IServiceProvider serviceProvider) : SimpleTaskFactory { - public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) + public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.DelaySecondsAtStart == null) return null; diff --git a/Questionable/Controller/Steps/SimpleTaskFactory.cs b/Questionable/Controller/Steps/SimpleTaskFactory.cs new file mode 100644 index 00000000..624886b7 --- /dev/null +++ b/Questionable/Controller/Steps/SimpleTaskFactory.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Questionable.Model; +using Questionable.Model.Questing; + +namespace Questionable.Controller.Steps; + +internal abstract class SimpleTaskFactory : ITaskFactory +{ + public abstract ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step); + + public IEnumerable CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step) + { + var task = CreateTask(quest, sequence, step); + if (task != null) + yield return task; + } +} diff --git a/Questionable/External/ArtisanIpc.cs b/Questionable/External/ArtisanIpc.cs index b64d5137..742d9ab1 100644 --- a/Questionable/External/ArtisanIpc.cs +++ b/Questionable/External/ArtisanIpc.cs @@ -9,11 +9,13 @@ internal sealed class ArtisanIpc { private readonly ILogger _logger; private readonly ICallGateSubscriber _craftItem; + private readonly ICallGateSubscriber _getEnduranceStatus; public ArtisanIpc(IDalamudPluginInterface pluginInterface, ILogger logger) { _logger = logger; _craftItem = pluginInterface.GetIpcSubscriber("Artisan.CraftItem"); + _getEnduranceStatus = pluginInterface.GetIpcSubscriber("Artisan.GetEnduranceStatus"); } public bool CraftItem(ushort recipeId, int quantity) @@ -31,4 +33,20 @@ internal sealed class ArtisanIpc return false; } } + + /// + /// This ignores crafting lists, but we can't create/use those. + /// + public bool IsCrafting() + { + try + { + return _getEnduranceStatus.InvokeFunc(); + } + catch (IpcError e) + { + _logger.LogError(e, "Unable to check for Artisan endurance status"); + return false; + } + } } diff --git a/Questionable/Functions/GameFunctions.cs b/Questionable/Functions/GameFunctions.cs index e1c20069..32b35ce7 100644 --- a/Questionable/Functions/GameFunctions.cs +++ b/Questionable/Functions/GameFunctions.cs @@ -401,6 +401,15 @@ internal sealed unsafe class GameFunctions if (IsLoadingScreenVisible()) return true; + if (_condition[ConditionFlag.Crafting]) + { + if (!AgentRecipeNote.Instance()->IsAgentActive()) + return true; + + if (!_condition[ConditionFlag.PreparingToCraft]) + return true; + } + return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] || _condition[ConditionFlag.Occupied33] || _condition[ConditionFlag.Occupied38] || _condition[ConditionFlag.Occupied39] || _condition[ConditionFlag.OccupiedInEvent] ||