138 lines
4.2 KiB
C#
138 lines
4.2 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using Dalamud.Plugin.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using Questionable.Controller.Steps;
|
|
using Questionable.Controller.Steps.Common;
|
|
using Questionable.Controller.Steps.Interactions;
|
|
using Questionable.Controller.Steps.Shared;
|
|
using Questionable.Functions;
|
|
using Questionable.Model.Questing;
|
|
using Questionable.Navigation;
|
|
|
|
namespace Questionable.Controller;
|
|
|
|
internal sealed class SeasonalDutyController : MiniTaskController<SeasonalDutyController>
|
|
{
|
|
private readonly MovementController _movementController;
|
|
|
|
private readonly GameFunctions _gameFunctions;
|
|
|
|
private readonly IClientState _clientState;
|
|
|
|
private readonly SmartNavRouteEnqueuer _routeEnqueuer;
|
|
|
|
private SeasonalDutyDefinition? _currentDuty;
|
|
|
|
private int _completedCycles;
|
|
|
|
private int? _cycleLimit;
|
|
|
|
private DateTime _startTime;
|
|
|
|
public bool IsRunning => _currentDuty != null;
|
|
|
|
public TaskQueue TaskQueue => _taskQueue;
|
|
|
|
public SeasonalDutyDefinition? CurrentDuty => _currentDuty;
|
|
|
|
public int CompletedCycles => _completedCycles;
|
|
|
|
public int? CycleLimit => _cycleLimit;
|
|
|
|
public TimeSpan ElapsedTime
|
|
{
|
|
get
|
|
{
|
|
if (!IsRunning)
|
|
{
|
|
return TimeSpan.Zero;
|
|
}
|
|
return DateTime.UtcNow - _startTime;
|
|
}
|
|
}
|
|
|
|
public SeasonalDutyController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider, InterruptHandler interruptHandler, IDataManager dataManager, Configuration configuration, ILogger<SeasonalDutyController> logger, MovementController movementController, GameFunctions gameFunctions, IClientState clientState, SmartNavRouteEnqueuer routeEnqueuer)
|
|
: base(chatGui, condition, serviceProvider, interruptHandler, dataManager, configuration, logger)
|
|
{
|
|
_movementController = movementController;
|
|
_gameFunctions = gameFunctions;
|
|
_clientState = clientState;
|
|
_routeEnqueuer = routeEnqueuer;
|
|
}
|
|
|
|
public void Start(SeasonalDutyDefinition duty, int? cycleLimit = null)
|
|
{
|
|
_currentDuty = duty;
|
|
_completedCycles = 0;
|
|
_cycleLimit = cycleLimit;
|
|
_startTime = DateTime.UtcNow;
|
|
_logger.LogInformation("Starting seasonal duty farming: {DutyName} (limit: {Limit})", duty.Name, cycleLimit?.ToString(CultureInfo.InvariantCulture) ?? "unlimited");
|
|
EnqueueDutyCycle();
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (_currentDuty == null || _movementController.IsPathfinding || _movementController.IsPathRunning || _gameFunctions.IsOccupied())
|
|
{
|
|
return;
|
|
}
|
|
if (_taskQueue.AllTasksComplete)
|
|
{
|
|
_completedCycles++;
|
|
if (_cycleLimit.HasValue && _completedCycles >= _cycleLimit.Value)
|
|
{
|
|
_logger.LogInformation("Seasonal duty cycle limit reached ({Cycles}/{Limit})", _completedCycles, _cycleLimit.Value);
|
|
Stop("Cycle limit reached");
|
|
return;
|
|
}
|
|
EnqueueDutyCycle();
|
|
}
|
|
UpdateCurrentTask();
|
|
}
|
|
|
|
private void EnqueueDutyCycle()
|
|
{
|
|
if (_currentDuty == null)
|
|
{
|
|
return;
|
|
}
|
|
SeasonalDutyDefinition duty = _currentDuty;
|
|
_logger.LogDebug("Enqueuing seasonal duty cycle for {DutyName}", duty.Name);
|
|
if (_clientState.TerritoryType != duty.DutyTerritoryId)
|
|
{
|
|
_routeEnqueuer.Enqueue(_taskQueue, duty.TerritoryId, duty.NpcPosition);
|
|
_taskQueue.Enqueue(new Mount.UnmountTask());
|
|
bool interacted = false;
|
|
_taskQueue.Enqueue(new WaitCondition.Task(delegate
|
|
{
|
|
if (_clientState.TerritoryType == _currentDuty.DutyTerritoryId)
|
|
{
|
|
return true;
|
|
}
|
|
if (!interacted)
|
|
{
|
|
interacted = _gameFunctions.InteractWith(duty.NpcDataId);
|
|
}
|
|
return false;
|
|
}, $"InteractAndWait(territory: {duty.DutyTerritoryId})"));
|
|
}
|
|
_taskQueue.Enqueue(new ClearObjectsWithAction.ClearTask(duty.DataIds, duty.Action, duty.DutyTerritoryId, duty.StopDistance, duty.WaypointPositions));
|
|
_taskQueue.Enqueue(new WaitCondition.Task(() => _clientState.TerritoryType != _currentDuty.DutyTerritoryId, "Wait(duty end)"));
|
|
_taskQueue.Enqueue(new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(3L)));
|
|
}
|
|
|
|
public override void Stop(string label)
|
|
{
|
|
base.Stop(label);
|
|
if (_currentDuty != null)
|
|
{
|
|
_logger.LogInformation("Stopping seasonal duty farming: {Label} (completed {Cycles} cycles)", label, _completedCycles);
|
|
_routeEnqueuer.ClearDestination();
|
|
_currentDuty = null;
|
|
_completedCycles = 0;
|
|
_cycleLimit = null;
|
|
_taskQueue.Reset();
|
|
}
|
|
}
|
|
}
|