1
0
forked from liza/Questionable

Attempt to handle Revisit triggering

This commit is contained in:
Liza 2024-08-11 21:48:01 +02:00
parent 606b9d52ba
commit 9d8c67155f
Signed by: liza
GPG Key ID: 7199F8D727D55F67
8 changed files with 121 additions and 27 deletions

View File

@ -16,12 +16,15 @@
"Z": 405.1829
},
"MinimumAngle": 100,
"MaximumAngle": 250
"MaximumAngle": 250,
"MinimumDistance": 1.5,
"MaximumDistance": 3
}
]
},
{
"DataId": 31345,
"Fly": false,
"Locations": [
{
"Position": {
@ -29,8 +32,10 @@
"Y": 216.5585,
"Z": 412.4353
},
"MinimumAngle": 50,
"MaximumAngle": 165
"MinimumAngle": 75,
"MaximumAngle": 145,
"MinimumDistance": 1.5,
"MaximumDistance": 3
},
{
"Position": {
@ -39,7 +44,9 @@
"Z": 421.5481
},
"MinimumAngle": 0,
"MaximumAngle": 145
"MaximumAngle": 145,
"MinimumDistance": 1.5,
"MaximumDistance": 3
},
{
"Position": {
@ -48,7 +55,9 @@
"Z": 408.2164
},
"MinimumAngle": 155,
"MaximumAngle": 225
"MaximumAngle": 225,
"MinimumDistance": 1.5,
"MaximumDistance": 3
}
]
}
@ -155,4 +164,4 @@
]
}
]
}
}

View File

@ -5,7 +5,7 @@ namespace Questionable.Model.Gathering;
public sealed class GatheringNode
{
public uint DataId { get; set; }
public bool Fly { get; set; }
public bool? Fly { get; set; }
public List<GatheringLocation> Locations { get; set; } = [];
}

View File

@ -16,6 +16,6 @@ public sealed class GatheringRoot
public EAetheryteLocation? AetheryteShortcut { get; set; }
public AethernetShortcut? AethernetShortcut { get; set; }
public bool FlyBetweenNodes { get; set; } = true;
public bool? FlyBetweenNodes { get; set; }
public List<GatheringNodeGroup> Groups { get; set; } = [];
}

View File

@ -1,13 +1,18 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text.RegularExpressions;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.Game.Event;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using LLib;
using Lumina.Excel.GeneratedSheets;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps;
@ -32,6 +37,7 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
private readonly IObjectTable _objectTable;
private readonly IServiceProvider _serviceProvider;
private readonly ICondition _condition;
private readonly Regex _revisitRegex;
private CurrentRequest? _currentRequest;
@ -44,7 +50,9 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
IChatGui chatGui,
ILogger<GatheringController> logger,
IServiceProvider serviceProvider,
ICondition condition)
ICondition condition,
IDataManager dataManager,
IPluginLog pluginLog)
: base(chatGui, logger)
{
_movementController = movementController;
@ -54,6 +62,9 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
_objectTable = objectTable;
_serviceProvider = serviceProvider;
_condition = condition;
_revisitRegex = dataManager.GetRegex<LogMessage>(5574, x => x.Text, pluginLog)
?? throw new InvalidDataException("No regex found for revisit message");
}
public bool Start(GatheringRequest gatheringRequest)
@ -88,13 +99,19 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
public EStatus Update()
{
if (_currentRequest == null)
{
Stop("No request");
return EStatus.Complete;
}
if (_movementController.IsPathfinding || _movementController.IsPathfinding)
return EStatus.Moving;
if (HasRequestedItems() && !_condition[ConditionFlag.Gathering])
{
Stop("Has all items");
return EStatus.Complete;
}
if (_currentTask == null && _taskQueue.Count == 0)
GoToNextNode();
@ -136,6 +153,9 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<MountTask>()
.With(_currentRequest.Root.TerritoryId, MountTask.EMountIf.Always));
bool fly = currentNode.Fly.GetValueOrDefault(_currentRequest.Root.FlyBetweenNodes.GetValueOrDefault(true)) &&
_gameFunctions.IsFlyingUnlocked(_currentRequest.Root.TerritoryId);
if (currentNode.Locations.Count > 1)
{
Vector3 averagePosition = new Vector3
@ -144,8 +164,7 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
Y = currentNode.Locations.Select(x => x.Position.Y).Max() + 5f,
Z = currentNode.Locations.Sum(x => x.Position.Z) / currentNode.Locations.Count,
};
bool fly = (currentNode.Fly || _currentRequest.Root.FlyBetweenNodes)
&& _gameFunctions.IsFlyingUnlocked(_currentRequest.Root.TerritoryId);
Vector3? pointOnFloor = _navmeshIpc.GetPointOnFloor(averagePosition, true);
if (pointOnFloor != null)
pointOnFloor = pointOnFloor.Value with { Y = pointOnFloor.Value.Y + (fly ? 3f : 0f) };
@ -156,17 +175,19 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
}
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<MoveToLandingLocation>()
.With(_currentRequest.Root.TerritoryId,
currentNode.Fly || _currentRequest.Root.FlyBetweenNodes,
currentNode));
.With(_currentRequest.Root.TerritoryId, fly, currentNode));
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<Interact.DoInteract>()
.With(currentNode.DataId, null, EInteractionType.InternalGather, true));
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGather>()
.With(_currentRequest.Data, currentNode));
if (_currentRequest.Data.Collectability > 0)
foreach (bool revisitRequired in new[] { false, true })
{
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGatherCollectable>()
.With(_currentRequest.Data, currentNode));
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGather>()
.With(_currentRequest.Data, currentNode, revisitRequired));
if (_currentRequest.Data.Collectability > 0)
{
_taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGatherCollectable>()
.With(_currentRequest.Data, currentNode, revisitRequired));
}
}
}
@ -232,6 +253,21 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
return base.GetRemainingTaskNames();
}
public void OnNormalToast(SeString message)
{
if (_revisitRegex.IsMatch(message.TextValue))
{
if (_currentTask is IRevisitAware currentTaskRevisitAware)
currentTaskRevisitAware.OnRevisit();
foreach (ITask task in _taskQueue)
{
if (task is IRevisitAware taskRevisitAware)
taskRevisitAware.OnRevisit();
}
}
}
private sealed class CurrentRequest
{
public required GatheringRequest Data { get; init; }

View File

@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
@ -90,6 +91,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
_taskFactories = taskFactories.ToList().AsReadOnly();
_condition.ConditionChange += OnConditionChange;
_toastGui.Toast += OnNormalToast;
_toastGui.ErrorToast += OnErrorToast;
}
@ -786,6 +788,11 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
conditionChangeAware.OnConditionChange(flag, value);
}
private void OnNormalToast(ref SeString message, ref ToastOptions options, ref bool ishandled)
{
_gatheringController.OnNormalToast(message);
}
private void OnErrorToast(ref SeString message, ref bool ishandled)
{
if (_currentTask is IToastAware toastAware)
@ -795,6 +802,7 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
public void Dispose()
{
_toastGui.ErrorToast -= OnErrorToast;
_toastGui.Toast -= OnNormalToast;
_condition.ConditionChange -= OnConditionChange;
}

View File

@ -22,20 +22,24 @@ internal sealed class DoGather(
IGameGui gameGui,
IClientState clientState,
ICondition condition,
ILogger<DoGather> logger) : ITask
ILogger<DoGather> logger) : ITask, IRevisitAware
{
private const uint StatusGatheringRateUp = 218;
private GatheringController.GatheringRequest _currentRequest = null!;
private GatheringNode _currentNode = null!;
private bool _revisitRequired;
private bool _revisitTriggered;
private bool _wasGathering;
private SlotInfo? _slotToGather;
private Queue<EAction>? _actionQueue;
public ITask With(GatheringController.GatheringRequest currentRequest, GatheringNode currentNode)
public ITask With(GatheringController.GatheringRequest currentRequest, GatheringNode currentNode,
bool revisitRequired)
{
_currentRequest = currentRequest;
_currentNode = currentNode;
_revisitRequired = revisitRequired;
return this;
}
@ -43,8 +47,17 @@ internal sealed class DoGather(
public unsafe ETaskResult Update()
{
if (gatheringController.HasNodeDisappeared(_currentNode))
if (_revisitRequired && !_revisitTriggered)
{
logger.LogInformation("No revisit");
return ETaskResult.TaskComplete;
}
if (gatheringController.HasNodeDisappeared(_currentNode))
{
logger.LogInformation("Node disappeared");
return ETaskResult.TaskComplete;
}
if (gameFunctions.GetFreeInventorySlots() == 0)
throw new TaskException("Inventory full");
@ -225,7 +238,12 @@ internal sealed class DoGather(
return ActionManager.Instance()->GetActionStatus(ActionType.Action, (uint)action) == 0;
}
public override string ToString() => "DoGather";
public void OnRevisit()
{
_revisitTriggered = true;
}
public override string ToString() => $"DoGather{(_revisitRequired ? " if revist" : "")}";
private sealed record SlotInfo(int Index, uint ItemId, int GatheringChance, int BoonChance, int Quantity);

View File

@ -17,16 +17,19 @@ internal sealed class DoGatherCollectable(
GameFunctions gameFunctions,
IClientState clientState,
IGameGui gameGui,
ILogger<DoGatherCollectable> logger) : ITask
ILogger<DoGatherCollectable> logger) : ITask, IRevisitAware
{
private GatheringController.GatheringRequest _currentRequest = null!;
private GatheringNode _currentNode = null!;
private bool _revisitRequired;
private bool _revisitTriggered;
private Queue<EAction>? _actionQueue;
public ITask With(GatheringController.GatheringRequest currentRequest, GatheringNode currentNode)
public ITask With(GatheringController.GatheringRequest currentRequest, GatheringNode currentNode, bool revisitRequired)
{
_currentRequest = currentRequest;
_currentNode = currentNode;
_revisitRequired = revisitRequired;
return this;
}
@ -34,8 +37,17 @@ internal sealed class DoGatherCollectable(
public unsafe ETaskResult Update()
{
if (gatheringController.HasNodeDisappeared(_currentNode))
if (_revisitRequired && !_revisitTriggered)
{
logger.LogInformation("No revisit");
return ETaskResult.TaskComplete;
}
if (gatheringController.HasNodeDisappeared(_currentNode))
{
logger.LogInformation("Node disappeared");
return ETaskResult.TaskComplete;
}
if (gatheringController.HasRequestedItems())
{
@ -150,8 +162,13 @@ internal sealed class DoGatherCollectable(
return botanistAction;
}
public void OnRevisit()
{
_revisitTriggered = true;
}
public override string ToString() =>
$"DoGatherCollectable({SeIconChar.Collectible.ToIconString()} {_currentRequest.Collectability})";
$"DoGatherCollectable({SeIconChar.Collectible.ToIconString()} {_currentRequest.Collectability}){(_revisitRequired ? " if revist" : "")}";
[SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")]
private sealed record NodeCondition(

View File

@ -0,0 +1,6 @@
namespace Questionable.Controller.Steps;
public interface IRevisitAware
{
void OnRevisit();
}