qstbak/Questionable/Questionable.Controller.Steps.Interactions/Jump.cs
2025-10-09 07:47:19 +10:00

158 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using Microsoft.Extensions.Logging;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Controller.Steps.Interactions;
internal static class Jump
{
internal sealed class Factory : SimpleTaskFactory
{
public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.InteractionType != EInteractionType.Jump)
{
return null;
}
ArgumentNullException.ThrowIfNull(step.JumpDestination, "step.JumpDestination");
if (step.JumpDestination.Type == EJumpType.SingleJump)
{
return new SingleJumpTask(step.DataId, step.JumpDestination, step.Comment);
}
return new RepeatedJumpTask(step.DataId, step.JumpDestination, step.Comment);
}
}
internal interface IJumpTask : ITask
{
uint? DataId { get; }
JumpDestination JumpDestination { get; }
string? Comment { get; }
}
internal sealed record SingleJumpTask(uint? DataId, JumpDestination JumpDestination, string? Comment) : IJumpTask, ITask
{
public override string ToString()
{
return "Jump(" + Comment + ")";
}
}
internal abstract class JumpBase<T>(MovementController movementController, IClientState clientState, IFramework framework) : TaskExecutor<T>() where T : class, IJumpTask
{
protected unsafe override bool Start()
{
float num = base.Task.JumpDestination.CalculateStopDistance();
if ((_003CclientState_003EP.LocalPlayer.Position - base.Task.JumpDestination.Position).Length() <= num)
{
return false;
}
MovementController movementController = _003CmovementController_003EP;
uint? dataId = base.Task.DataId;
int num2 = 1;
List<Vector3> list = new List<Vector3>(num2);
CollectionsMarshal.SetCount(list, num2);
Span<Vector3> span = CollectionsMarshal.AsSpan(list);
int index = 0;
span[index] = base.Task.JumpDestination.Position;
movementController.NavigateTo(EMovementType.Quest, dataId, list, fly: false, sprint: false, base.Task.JumpDestination.StopDistance ?? num);
_003Cframework_003EP.RunOnTick(delegate
{
ActionManager.Instance()->UseAction(ActionType.GeneralAction, 2u, 3758096384uL, 0u, ActionManager.UseActionMode.None, 0u, null);
}, TimeSpan.FromSeconds(base.Task.JumpDestination.DelaySeconds ?? 0.5f));
return true;
}
public override ETaskResult Update()
{
if (_003CmovementController_003EP.IsPathfinding || _003CmovementController_003EP.IsPathRunning)
{
return ETaskResult.StillRunning;
}
DateTime movementStartedAt = _003CmovementController_003EP.MovementStartedAt;
if (movementStartedAt == DateTime.MaxValue || movementStartedAt.AddSeconds(1.0) >= DateTime.Now)
{
return ETaskResult.StillRunning;
}
return ETaskResult.TaskComplete;
}
public override bool ShouldInterruptOnDamage()
{
return true;
}
}
internal sealed class DoSingleJump : JumpBase<SingleJumpTask>
{
public DoSingleJump(MovementController movementController, IClientState clientState, IFramework framework)
: base(movementController, clientState, framework)
{
}
}
internal sealed record RepeatedJumpTask(uint? DataId, JumpDestination JumpDestination, string? Comment) : IJumpTask, ITask
{
public override string ToString()
{
return "RepeatedJump(" + Comment + ")";
}
}
internal sealed class DoRepeatedJumps : JumpBase<RepeatedJumpTask>
{
private readonly IClientState _clientState;
private DateTime _continueAt;
private int _attempts;
public DoRepeatedJumps(MovementController movementController, IClientState clientState, IFramework framework, ICondition condition, ILogger<DoRepeatedJumps> logger)
{
_003Ccondition_003EP = condition;
_003Clogger_003EP = logger;
_clientState = clientState;
_continueAt = DateTime.MinValue;
base._002Ector(movementController, clientState, framework);
}
protected override bool Start()
{
_continueAt = DateTime.Now + TimeSpan.FromSeconds(2f * (base.Task.JumpDestination.DelaySeconds ?? 0.5f));
return base.Start();
}
public unsafe override ETaskResult Update()
{
if (DateTime.Now < _continueAt || _003Ccondition_003EP[ConditionFlag.Jumping])
{
return ETaskResult.StillRunning;
}
float num = base.Task.JumpDestination.CalculateStopDistance();
if ((_clientState.LocalPlayer.Position - base.Task.JumpDestination.Position).Length() <= num || _clientState.LocalPlayer.Position.Y >= base.Task.JumpDestination.Position.Y - 0.5f)
{
return ETaskResult.TaskComplete;
}
_003Clogger_003EP.LogTrace("Y-Heights for jumps: player={A}, target={B}", _clientState.LocalPlayer.Position.Y, base.Task.JumpDestination.Position.Y - 0.5f);
if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 2u, 3758096384uL, 0u, ActionManager.UseActionMode.None, 0u, null))
{
_attempts++;
}
if (_attempts >= 50)
{
throw new TaskException("Tried to jump too many times, didn't reach the target");
}
_continueAt = DateTime.Now + TimeSpan.FromSeconds(base.Task.JumpDestination.DelaySeconds ?? 0.5f);
return ETaskResult.StillRunning;
}
}
}