1
0
Fork 0
forked from aly/qstbak
qstbak/Questionable/Questionable.Controller.Steps.Movement/MoveToObjectExecutor.cs
2026-08-17 20:29:32 +10:00

132 lines
3.9 KiB
C#

using System;
using System.Numerics;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.ClientState.Objects.SubKinds;
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 long? _startedLookingAt;
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.LogDebug("Not in correct territory yet, waiting");
return true;
}
_startedLookingAt = Environment.TickCount64;
return TryStartMovement();
}
private IGameObject? FindDistantObjectByDataId(uint dataId)
{
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
if (localPlayer == 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.Pc || objectKind - 8 <= ObjectKind.BattleNpc || objectKind == ObjectKind.HousingEventObject) ? true : false);
if (!flag && item.BaseId == dataId)
{
float num3 = Vector3.Distance(localPlayer.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.LogDebug("Object {DataId} not found yet, waiting", base.Task.Step.DataId);
return true;
}
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
float num = base.Task.Step.CalculateActualStopDistance();
if (localPlayer != null && Vector3.Distance(localPlayer.Position, gameObject.Position) <= num)
{
logger.LogDebug("Only nearby objects with DataId {DataId} remain, skipping", base.Task.Step.DataId);
return true;
}
}
_destination = gameObject.Position;
logger.LogDebug("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)
{
long? startedLookingAt = _startedLookingAt;
if (startedLookingAt.HasValue)
{
long valueOrDefault = startedLookingAt.GetValueOrDefault();
if (Environment.TickCount64 > valueOrDefault + 3000)
{
logger.LogDebug("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;
}
if (!movementController.HasBeenMovingForAtLeast(2000))
{
return ETaskResult.StillRunning;
}
return ETaskResult.TaskComplete;
}
public override bool ShouldInterruptOnDamage()
{
return false;
}
}