forked from liza/Questionable
Fix gathering for tribal quests
This commit is contained in:
parent
d4c1b4b3ac
commit
ed4d279432
@ -120,11 +120,15 @@ internal abstract class MiniTaskController<T>
|
||||
return;
|
||||
|
||||
case ETaskResult.TaskComplete:
|
||||
case ETaskResult.CreateNewTasks:
|
||||
_logger.LogInformation("{Task} → {Result}, remaining tasks: {RemainingTaskCount}",
|
||||
_taskQueue.CurrentTaskExecutor.CurrentTask, result, _taskQueue.RemainingTasks.Count());
|
||||
|
||||
OnTaskComplete(_taskQueue.CurrentTaskExecutor.CurrentTask);
|
||||
|
||||
if (result == ETaskResult.CreateNewTasks && _taskQueue.CurrentTaskExecutor is IExtraTaskCreator extraTaskCreator)
|
||||
_taskQueue.EnqueueAll(extraTaskCreator.CreateExtraTasks());
|
||||
|
||||
_taskQueue.CurrentTaskExecutor = null;
|
||||
|
||||
// handled in next update
|
||||
|
@ -11,6 +11,11 @@ internal enum ETaskResult
|
||||
/// </summary>
|
||||
SkipRemainingTasksForStep,
|
||||
|
||||
/// <summary>
|
||||
/// Assumes the task executor implements <see cref="IExtraTaskCreator"/>.
|
||||
/// </summary>
|
||||
CreateNewTasks,
|
||||
|
||||
NextStep,
|
||||
End,
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ using System.Linq;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using LLib.GameData;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -19,14 +18,7 @@ namespace Questionable.Controller.Steps.Shared;
|
||||
|
||||
internal static class Gather
|
||||
{
|
||||
internal sealed class Factory(
|
||||
IServiceProvider serviceProvider,
|
||||
MovementController movementController,
|
||||
GatheringPointRegistry gatheringPointRegistry,
|
||||
IClientState clientState,
|
||||
GatheringData gatheringData,
|
||||
TerritoryData territoryData,
|
||||
ILogger<Factory> logger) : ITaskFactory
|
||||
internal sealed class Factory : ITaskFactory
|
||||
{
|
||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||
{
|
||||
@ -35,46 +27,70 @@ internal static class Gather
|
||||
|
||||
foreach (var itemToGather in step.ItemsToGather)
|
||||
{
|
||||
EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
|
||||
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();
|
||||
yield return new DelayedGatheringTask(itemToGather, quest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Questionable.Model;
|
||||
|
||||
namespace Questionable.Controller.Steps;
|
||||
|
||||
@ -16,6 +18,11 @@ internal interface ITaskExecutor
|
||||
ETaskResult Update();
|
||||
}
|
||||
|
||||
internal interface IExtraTaskCreator : ITaskExecutor
|
||||
{
|
||||
IEnumerable<ITask> CreateExtraTasks();
|
||||
}
|
||||
|
||||
internal abstract class TaskExecutor<T> : ITaskExecutor
|
||||
where T : class, ITask
|
||||
{
|
||||
|
@ -18,6 +18,11 @@ internal sealed class TaskQueue
|
||||
_tasks.Add(task);
|
||||
}
|
||||
|
||||
public void EnqueueAll(IEnumerable<ITask> tasks)
|
||||
{
|
||||
_tasks.InsertRange(0, tasks);
|
||||
}
|
||||
|
||||
public bool TryDequeue([NotNullWhen(true)] out ITask? task)
|
||||
{
|
||||
task = _tasks.FirstOrDefault();
|
||||
|
@ -147,7 +147,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
.AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory,
|
||||
StepDisabled.SkipDisabledStepsExecutor>();
|
||||
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
|
||||
serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
|
||||
serviceCollection.AddTaskExecutor<Gather.SkipMarker, Gather.DoSkip>();
|
||||
serviceCollection
|
||||
.AddTaskFactoryAndExecutor<AetheryteShortcut.Task, AetheryteShortcut.Factory,
|
||||
@ -156,6 +155,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
.AddTaskExecutor<AetheryteShortcut.MoveAwayFromAetheryte, AetheryteShortcut.MoveAwayFromAetheryteExecutor>();
|
||||
serviceCollection
|
||||
.AddTaskFactoryAndExecutor<SkipCondition.SkipTask, SkipCondition.Factory, SkipCondition.CheckSkip>();
|
||||
serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
|
||||
serviceCollection.AddTaskExecutor<Gather.DelayedGatheringTask, Gather.DelayedGatheringExecutor>();
|
||||
serviceCollection
|
||||
.AddTaskFactoryAndExecutor<AethernetShortcut.Task, AethernetShortcut.Factory,
|
||||
AethernetShortcut.UseAethernetShortcut>();
|
||||
|
Loading…
Reference in New Issue
Block a user