Fix gathering for tribal quests
This commit is contained in:
parent
d4c1b4b3ac
commit
ed4d279432
@ -120,11 +120,15 @@ internal abstract class MiniTaskController<T>
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case ETaskResult.TaskComplete:
|
case ETaskResult.TaskComplete:
|
||||||
|
case ETaskResult.CreateNewTasks:
|
||||||
_logger.LogInformation("{Task} → {Result}, remaining tasks: {RemainingTaskCount}",
|
_logger.LogInformation("{Task} → {Result}, remaining tasks: {RemainingTaskCount}",
|
||||||
_taskQueue.CurrentTaskExecutor.CurrentTask, result, _taskQueue.RemainingTasks.Count());
|
_taskQueue.CurrentTaskExecutor.CurrentTask, result, _taskQueue.RemainingTasks.Count());
|
||||||
|
|
||||||
OnTaskComplete(_taskQueue.CurrentTaskExecutor.CurrentTask);
|
OnTaskComplete(_taskQueue.CurrentTaskExecutor.CurrentTask);
|
||||||
|
|
||||||
|
if (result == ETaskResult.CreateNewTasks && _taskQueue.CurrentTaskExecutor is IExtraTaskCreator extraTaskCreator)
|
||||||
|
_taskQueue.EnqueueAll(extraTaskCreator.CreateExtraTasks());
|
||||||
|
|
||||||
_taskQueue.CurrentTaskExecutor = null;
|
_taskQueue.CurrentTaskExecutor = null;
|
||||||
|
|
||||||
// handled in next update
|
// handled in next update
|
||||||
|
@ -11,6 +11,11 @@ internal enum ETaskResult
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
SkipRemainingTasksForStep,
|
SkipRemainingTasksForStep,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assumes the task executor implements <see cref="IExtraTaskCreator"/>.
|
||||||
|
/// </summary>
|
||||||
|
CreateNewTasks,
|
||||||
|
|
||||||
NextStep,
|
NextStep,
|
||||||
End,
|
End,
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using LLib.GameData;
|
using LLib.GameData;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@ -19,14 +18,7 @@ namespace Questionable.Controller.Steps.Shared;
|
|||||||
|
|
||||||
internal static class Gather
|
internal static class Gather
|
||||||
{
|
{
|
||||||
internal sealed class Factory(
|
internal sealed class Factory : ITaskFactory
|
||||||
IServiceProvider serviceProvider,
|
|
||||||
MovementController movementController,
|
|
||||||
GatheringPointRegistry gatheringPointRegistry,
|
|
||||||
IClientState clientState,
|
|
||||||
GatheringData gatheringData,
|
|
||||||
TerritoryData territoryData,
|
|
||||||
ILogger<Factory> logger) : ITaskFactory
|
|
||||||
{
|
{
|
||||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||||
{
|
{
|
||||||
@ -35,46 +27,70 @@ internal static class Gather
|
|||||||
|
|
||||||
foreach (var itemToGather in step.ItemsToGather)
|
foreach (var itemToGather in step.ItemsToGather)
|
||||||
{
|
{
|
||||||
EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
|
yield return new DelayedGatheringTask(itemToGather, quest);
|
||||||
if (!gatheringData.TryGetGatheringPointId(itemToGather.ItemId, currentClassJob,
|
|
||||||
out GatheringPointId? gatheringPointId))
|
|
||||||
throw new TaskException($"No gathering point found for item {itemToGather.ItemId}");
|
|
||||||
|
|
||||||
if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
|
|
||||||
throw new TaskException($"No path found for gathering point {gatheringPointId}");
|
|
||||||
|
|
||||||
if (HasRequiredItems(itemToGather))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
using (var _ = logger.BeginScope("Gathering(inner)"))
|
|
||||||
{
|
|
||||||
QuestSequence gatheringSequence = new QuestSequence
|
|
||||||
{
|
|
||||||
Sequence = 0,
|
|
||||||
Steps = gatheringRoot.Steps
|
|
||||||
};
|
|
||||||
foreach (var gatheringStep in gatheringSequence.Steps)
|
|
||||||
{
|
|
||||||
foreach (var task in serviceProvider.GetRequiredService<TaskCreator>()
|
|
||||||
.CreateTasks(quest, gatheringSequence, gatheringStep))
|
|
||||||
if (task is WaitAtEnd.NextStep)
|
|
||||||
yield return new SkipMarker();
|
|
||||||
else
|
|
||||||
yield return task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort territoryId = gatheringRoot.Steps.Last().TerritoryId;
|
|
||||||
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
|
||||||
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
|
||||||
|
|
||||||
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
|
||||||
"Wait(navmesh ready)");
|
|
||||||
|
|
||||||
yield return new GatheringTask(gatheringPointId, itemToGather);
|
|
||||||
yield return new WaitAtEnd.WaitDelay();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed record DelayedGatheringTask(GatheredItem GatheredItem, Quest Quest) : ITask
|
||||||
|
{
|
||||||
|
public override string ToString() => $"Gathering(pending for {GatheredItem.ItemId})";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class DelayedGatheringExecutor(
|
||||||
|
MovementController movementController,
|
||||||
|
GatheringData gatheringData,
|
||||||
|
GatheringPointRegistry gatheringPointRegistry,
|
||||||
|
TerritoryData territoryData,
|
||||||
|
IClientState clientState,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
ILogger<DelayedGatheringExecutor> logger) : TaskExecutor<DelayedGatheringTask>, IExtraTaskCreator
|
||||||
|
{
|
||||||
|
protected override bool Start() => true;
|
||||||
|
|
||||||
|
public override ETaskResult Update() => ETaskResult.CreateNewTasks;
|
||||||
|
|
||||||
|
public IEnumerable<ITask> CreateExtraTasks()
|
||||||
|
{
|
||||||
|
EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
|
||||||
|
if (!gatheringData.TryGetGatheringPointId(Task.GatheredItem.ItemId, currentClassJob,
|
||||||
|
out GatheringPointId? gatheringPointId))
|
||||||
|
throw new TaskException($"No gathering point found for item {Task.GatheredItem.ItemId}");
|
||||||
|
|
||||||
|
if (!gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? gatheringRoot))
|
||||||
|
throw new TaskException($"No path found for gathering point {gatheringPointId}");
|
||||||
|
|
||||||
|
if (HasRequiredItems(Task.GatheredItem))
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
using (var _ = logger.BeginScope("Gathering(inner)"))
|
||||||
|
{
|
||||||
|
QuestSequence gatheringSequence = new QuestSequence
|
||||||
|
{
|
||||||
|
Sequence = 0,
|
||||||
|
Steps = gatheringRoot.Steps
|
||||||
|
};
|
||||||
|
foreach (var gatheringStep in gatheringSequence.Steps)
|
||||||
|
{
|
||||||
|
foreach (var task in serviceProvider.GetRequiredService<TaskCreator>()
|
||||||
|
.CreateTasks(Task.Quest, gatheringSequence, gatheringStep))
|
||||||
|
if (task is WaitAtEnd.NextStep)
|
||||||
|
yield return new SkipMarker();
|
||||||
|
else
|
||||||
|
yield return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort territoryId = gatheringRoot.Steps.Last().TerritoryId;
|
||||||
|
yield return new WaitCondition.Task(() => clientState.TerritoryType == territoryId,
|
||||||
|
$"Wait(territory: {territoryData.GetNameAndId(territoryId)})");
|
||||||
|
|
||||||
|
yield return new WaitCondition.Task(() => movementController.IsNavmeshReady,
|
||||||
|
"Wait(navmesh ready)");
|
||||||
|
|
||||||
|
yield return new GatheringTask(gatheringPointId, Task.GatheredItem);
|
||||||
|
yield return new WaitAtEnd.WaitDelay();
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe bool HasRequiredItems(GatheredItem itemToGather)
|
private unsafe bool HasRequiredItems(GatheredItem itemToGather)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Questionable.Model;
|
||||||
|
|
||||||
namespace Questionable.Controller.Steps;
|
namespace Questionable.Controller.Steps;
|
||||||
|
|
||||||
@ -16,6 +18,11 @@ internal interface ITaskExecutor
|
|||||||
ETaskResult Update();
|
ETaskResult Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal interface IExtraTaskCreator : ITaskExecutor
|
||||||
|
{
|
||||||
|
IEnumerable<ITask> CreateExtraTasks();
|
||||||
|
}
|
||||||
|
|
||||||
internal abstract class TaskExecutor<T> : ITaskExecutor
|
internal abstract class TaskExecutor<T> : ITaskExecutor
|
||||||
where T : class, ITask
|
where T : class, ITask
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,11 @@ internal sealed class TaskQueue
|
|||||||
_tasks.Add(task);
|
_tasks.Add(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnqueueAll(IEnumerable<ITask> tasks)
|
||||||
|
{
|
||||||
|
_tasks.InsertRange(0, tasks);
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryDequeue([NotNullWhen(true)] out ITask? task)
|
public bool TryDequeue([NotNullWhen(true)] out ITask? task)
|
||||||
{
|
{
|
||||||
task = _tasks.FirstOrDefault();
|
task = _tasks.FirstOrDefault();
|
||||||
|
@ -147,7 +147,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
.AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory,
|
.AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory,
|
||||||
StepDisabled.SkipDisabledStepsExecutor>();
|
StepDisabled.SkipDisabledStepsExecutor>();
|
||||||
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
|
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
|
||||||
serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
|
|
||||||
serviceCollection.AddTaskExecutor<Gather.SkipMarker, Gather.DoSkip>();
|
serviceCollection.AddTaskExecutor<Gather.SkipMarker, Gather.DoSkip>();
|
||||||
serviceCollection
|
serviceCollection
|
||||||
.AddTaskFactoryAndExecutor<AetheryteShortcut.Task, AetheryteShortcut.Factory,
|
.AddTaskFactoryAndExecutor<AetheryteShortcut.Task, AetheryteShortcut.Factory,
|
||||||
@ -156,6 +155,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
|||||||
.AddTaskExecutor<AetheryteShortcut.MoveAwayFromAetheryte, AetheryteShortcut.MoveAwayFromAetheryteExecutor>();
|
.AddTaskExecutor<AetheryteShortcut.MoveAwayFromAetheryte, AetheryteShortcut.MoveAwayFromAetheryteExecutor>();
|
||||||
serviceCollection
|
serviceCollection
|
||||||
.AddTaskFactoryAndExecutor<SkipCondition.SkipTask, SkipCondition.Factory, SkipCondition.CheckSkip>();
|
.AddTaskFactoryAndExecutor<SkipCondition.SkipTask, SkipCondition.Factory, SkipCondition.CheckSkip>();
|
||||||
|
serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
|
||||||
|
serviceCollection.AddTaskExecutor<Gather.DelayedGatheringTask, Gather.DelayedGatheringExecutor>();
|
||||||
serviceCollection
|
serviceCollection
|
||||||
.AddTaskFactoryAndExecutor<AethernetShortcut.Task, AethernetShortcut.Factory,
|
.AddTaskFactoryAndExecutor<AethernetShortcut.Task, AethernetShortcut.Factory,
|
||||||
AethernetShortcut.UseAethernetShortcut>();
|
AethernetShortcut.UseAethernetShortcut>();
|
||||||
|
Loading…
Reference in New Issue
Block a user