158 lines
5.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|