forked from aly/qstbak
127 lines
3.8 KiB
C#
127 lines
3.8 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using Dalamud.Game.ClientState.Objects.Enums;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Plugin.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using Questionable.Functions;
|
|
using Questionable.Model;
|
|
|
|
namespace Questionable.Controller.Steps.Movement;
|
|
|
|
internal sealed class MoveToObjectExecutor(MovementController movementController, GameFunctions gameFunctions, IClientState clientState, IObjectTable objectTable, ILogger<MoveToObjectExecutor> logger) : TaskExecutor<MoveToObject>()
|
|
{
|
|
private DateTime _startedLookingAt = DateTime.MaxValue;
|
|
|
|
private Vector3 _destination;
|
|
|
|
private bool _moving;
|
|
|
|
protected override bool Start()
|
|
{
|
|
if (!base.Task.Step.DataId.HasValue)
|
|
{
|
|
logger.LogWarning("MoveToObject task has no DataId");
|
|
return false;
|
|
}
|
|
if (clientState.TerritoryType != base.Task.Step.TerritoryId)
|
|
{
|
|
logger.LogInformation("Not in correct territory yet, waiting");
|
|
return true;
|
|
}
|
|
_startedLookingAt = DateTime.Now;
|
|
return TryStartMovement();
|
|
}
|
|
|
|
private IGameObject? FindDistantObjectByDataId(uint dataId)
|
|
{
|
|
IGameObject gameObject = objectTable[0];
|
|
if (gameObject == null)
|
|
{
|
|
return null;
|
|
}
|
|
float num = base.Task.Step.CalculateActualStopDistance();
|
|
IGameObject result = null;
|
|
float num2 = float.MaxValue;
|
|
foreach (IGameObject item in objectTable)
|
|
{
|
|
ObjectKind objectKind = item.ObjectKind;
|
|
bool flag = ((objectKind == ObjectKind.Player || objectKind - 8 <= ObjectKind.BattleNpc || objectKind == ObjectKind.Housing) ? true : false);
|
|
if (!flag && item.BaseId == dataId)
|
|
{
|
|
float num3 = Vector3.Distance(gameObject.Position, item.Position);
|
|
if (!(num3 <= num) && num3 < num2)
|
|
{
|
|
result = item;
|
|
num2 = num3;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private bool TryStartMovement()
|
|
{
|
|
IGameObject gameObject = FindDistantObjectByDataId(base.Task.Step.DataId.Value);
|
|
if (gameObject == null)
|
|
{
|
|
gameObject = gameFunctions.FindObjectByDataId(base.Task.Step.DataId.Value, null, warnIfMissing: false);
|
|
if (gameObject == null)
|
|
{
|
|
logger.LogInformation("Object {DataId} not found yet, waiting", base.Task.Step.DataId);
|
|
return true;
|
|
}
|
|
IGameObject gameObject2 = objectTable[0];
|
|
float num = base.Task.Step.CalculateActualStopDistance();
|
|
if (gameObject2 != null && Vector3.Distance(gameObject2.Position, gameObject.Position) <= num)
|
|
{
|
|
logger.LogInformation("Only nearby objects with DataId {DataId} remain, skipping", base.Task.Step.DataId);
|
|
return true;
|
|
}
|
|
}
|
|
_destination = gameObject.Position;
|
|
logger.LogInformation("Moving to object {DataId} at {Position}", base.Task.Step.DataId, _destination);
|
|
movementController.NavigateTo(EMovementType.Quest, base.Task.Step.DataId, _destination, fly: false, base.Task.Step.Sprint ?? true, base.Task.Step.CalculateActualStopDistance());
|
|
_moving = true;
|
|
return true;
|
|
}
|
|
|
|
public override ETaskResult Update()
|
|
{
|
|
if (clientState.TerritoryType != base.Task.Step.TerritoryId)
|
|
{
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
if (!_moving)
|
|
{
|
|
if (_startedLookingAt != DateTime.MaxValue && DateTime.Now > _startedLookingAt.AddSeconds(3.0))
|
|
{
|
|
logger.LogInformation("Object {DataId} not found after timeout, skipping step", base.Task.Step.DataId);
|
|
return ETaskResult.TaskComplete;
|
|
}
|
|
if (!TryStartMovement())
|
|
{
|
|
return ETaskResult.TaskComplete;
|
|
}
|
|
if (!_moving)
|
|
{
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
}
|
|
if (movementController.IsPathfinding || movementController.IsPathRunning)
|
|
{
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
DateTime movementStartedAt = movementController.MovementStartedAt;
|
|
if (movementStartedAt == DateTime.MaxValue || movementStartedAt.AddSeconds(2.0) >= DateTime.Now)
|
|
{
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
return ETaskResult.TaskComplete;
|
|
}
|
|
|
|
public override bool ShouldInterruptOnDamage()
|
|
{
|
|
return false;
|
|
}
|
|
}
|