forked from aly/qstbak
muffin v7.4.18
This commit is contained in:
parent
53aa9fdee8
commit
f82b9ce2a2
50 changed files with 142364 additions and 230361 deletions
|
|
@ -22,6 +22,10 @@ internal static class Action
|
|||
{
|
||||
return Array.Empty<ITask>();
|
||||
}
|
||||
if (step.DataIds.Count > 0)
|
||||
{
|
||||
return Array.Empty<ITask>();
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(step.Action, "step.Action");
|
||||
ITask task = OnObject(step.DataId, quest, step.Action.Value, step.CompletionQuestVariablesFlags);
|
||||
if (step.Action.Value.RequiresMount())
|
||||
|
|
@ -86,6 +90,9 @@ internal static class Action
|
|||
_continueAt = DateTime.Now.AddSeconds(0.5);
|
||||
return true;
|
||||
}
|
||||
logger.LogInformation("Object {DataId} is untargetable, using action {Action} without target", base.Task.DataId, base.Task.Action);
|
||||
_usedAction = gameFunctions.UseAction(base.Task.Action);
|
||||
_continueAt = DateTime.Now.AddSeconds(0.5);
|
||||
return true;
|
||||
}
|
||||
_usedAction = gameFunctions.UseAction(base.Task.Action);
|
||||
|
|
@ -104,11 +111,18 @@ internal static class Action
|
|||
if (base.Task.DataId.HasValue)
|
||||
{
|
||||
IGameObject gameObject = gameFunctions.FindObjectByDataId(base.Task.DataId.Value);
|
||||
if (gameObject == null || !gameObject.IsTargetable)
|
||||
if (gameObject == null)
|
||||
{
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
_usedAction = gameFunctions.UseAction(gameObject, base.Task.Action);
|
||||
if (gameObject.IsTargetable)
|
||||
{
|
||||
_usedAction = gameFunctions.UseAction(gameObject, base.Task.Action);
|
||||
}
|
||||
else
|
||||
{
|
||||
_usedAction = gameFunctions.UseAction(base.Task.Action);
|
||||
}
|
||||
_continueAt = DateTime.Now.AddSeconds(0.5);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,347 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Controller.Steps.Interactions;
|
||||
|
||||
internal static class ClearObjectsWithAction
|
||||
{
|
||||
internal sealed class Factory : ITaskFactory
|
||||
{
|
||||
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
|
||||
{
|
||||
if (step.InteractionType != EInteractionType.Action)
|
||||
{
|
||||
return Array.Empty<ITask>();
|
||||
}
|
||||
if (step.DataIds.Count == 0)
|
||||
{
|
||||
return Array.Empty<ITask>();
|
||||
}
|
||||
if (!step.Action.HasValue)
|
||||
{
|
||||
return Array.Empty<ITask>();
|
||||
}
|
||||
return new global::_003C_003Ez__ReadOnlySingleElementList<ITask>(new ClearTask(step.DataIds, step.Action.Value, step.TerritoryId, step.CalculateActualStopDistance(), step.WaypointPositions));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record ClearTask(List<uint> DataIds, EAction Action, ushort TerritoryId, float StopDistance, List<Vector3> WaypointPositions) : ITask
|
||||
{
|
||||
public bool ShouldRedoOnInterrupt()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"ClearObjects({Action}, {DataIds.Count} types)";
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ClearTaskExecutor(MovementController movementController, GameFunctions gameFunctions, IClientState clientState, IObjectTable objectTable, ILogger<ClearTaskExecutor> logger) : TaskExecutor<ClearTask>()
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
FindingObject,
|
||||
MovingToObject,
|
||||
UsingAction,
|
||||
WaitingAfterAction,
|
||||
MovingToWaypoint,
|
||||
WaitingForTransition
|
||||
}
|
||||
|
||||
private const float VisitedPositionRadius = 5f;
|
||||
|
||||
private State _state;
|
||||
|
||||
private DateTime _noObjectFoundSince = DateTime.MaxValue;
|
||||
|
||||
private DateTime _waitUntil = DateTime.MinValue;
|
||||
|
||||
private DateTime _waypointReachedAt = DateTime.MaxValue;
|
||||
|
||||
private Vector3 _lastPlayerPosition;
|
||||
|
||||
private readonly List<Vector3> _visitedPositions = new List<Vector3>();
|
||||
|
||||
private readonly List<int> _triedWaypointIndices = new List<int>();
|
||||
|
||||
protected override bool Start()
|
||||
{
|
||||
if (clientState.TerritoryType != base.Task.TerritoryId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return TryFindAndMove();
|
||||
}
|
||||
|
||||
private bool IsVisitedPosition(Vector3 position)
|
||||
{
|
||||
foreach (Vector3 visitedPosition in _visitedPositions)
|
||||
{
|
||||
if (Vector3.Distance(visitedPosition, position) <= 5f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private IGameObject? FindNearestUnvisitedObject()
|
||||
{
|
||||
IGameObject gameObject = objectTable[0];
|
||||
if (gameObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
IGameObject result = null;
|
||||
float num = float.MaxValue;
|
||||
foreach (IGameObject item in objectTable)
|
||||
{
|
||||
ObjectKind objectKind = item.ObjectKind;
|
||||
if ((objectKind == ObjectKind.Player || objectKind - 8 <= ObjectKind.BattleNpc || objectKind == ObjectKind.Housing) ? true : false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = false;
|
||||
foreach (uint dataId in base.Task.DataIds)
|
||||
{
|
||||
if (item.BaseId == dataId)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag && !IsVisitedPosition(item.Position))
|
||||
{
|
||||
float num2 = Vector3.Distance(gameObject.Position, item.Position);
|
||||
if (num2 < num)
|
||||
{
|
||||
result = item;
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool AnyMatchingObjectsExist()
|
||||
{
|
||||
foreach (IGameObject item in objectTable)
|
||||
{
|
||||
ObjectKind objectKind = item.ObjectKind;
|
||||
if ((objectKind == ObjectKind.Player || objectKind - 8 <= ObjectKind.BattleNpc || objectKind == ObjectKind.Housing) ? true : false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (uint dataId in base.Task.DataIds)
|
||||
{
|
||||
if (item.BaseId == dataId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryFindAndMove()
|
||||
{
|
||||
IGameObject gameObject = FindNearestUnvisitedObject();
|
||||
if (gameObject == null)
|
||||
{
|
||||
_state = State.FindingObject;
|
||||
if (_noObjectFoundSince == DateTime.MaxValue)
|
||||
{
|
||||
_noObjectFoundSince = DateTime.Now;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
_noObjectFoundSince = DateTime.MaxValue;
|
||||
Vector3 position = gameObject.Position;
|
||||
logger.LogInformation("Moving to object {DataId} at {Position}", gameObject.BaseId, position);
|
||||
movementController.NavigateTo(EMovementType.Quest, gameObject.BaseId, position, fly: false, sprint: true, base.Task.StopDistance);
|
||||
_state = State.MovingToObject;
|
||||
return true;
|
||||
}
|
||||
|
||||
private (Vector3 Position, int Index)? FindNextWaypoint()
|
||||
{
|
||||
IGameObject gameObject = objectTable[0];
|
||||
if (gameObject == null || base.Task.WaypointPositions.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
(Vector3, int)? result = null;
|
||||
float num = float.MaxValue;
|
||||
for (int i = 0; i < base.Task.WaypointPositions.Count; i++)
|
||||
{
|
||||
if (!_triedWaypointIndices.Contains(i))
|
||||
{
|
||||
float num2 = Vector3.Distance(gameObject.Position, base.Task.WaypointPositions[i]);
|
||||
if (num2 < num)
|
||||
{
|
||||
result = (base.Task.WaypointPositions[i], i);
|
||||
num = num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void NavigateToNextWaypoint()
|
||||
{
|
||||
(Vector3, int)? tuple = FindNextWaypoint();
|
||||
if (!tuple.HasValue)
|
||||
{
|
||||
logger.LogInformation("All waypoints tried without transition, resetting");
|
||||
_triedWaypointIndices.Clear();
|
||||
tuple = FindNextWaypoint();
|
||||
if (!tuple.HasValue)
|
||||
{
|
||||
logger.LogWarning("No waypoint positions configured, waiting for transition");
|
||||
_state = State.WaitingForTransition;
|
||||
_lastPlayerPosition = objectTable[0]?.Position ?? Vector3.Zero;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_triedWaypointIndices.Add(tuple.Value.Item2);
|
||||
logger.LogInformation("Moving to waypoint {Index} at {Position}", tuple.Value.Item2, tuple.Value.Item1);
|
||||
movementController.NavigateTo(EMovementType.Quest, null, tuple.Value.Item1, fly: false, sprint: true, 0f);
|
||||
_state = State.MovingToWaypoint;
|
||||
}
|
||||
|
||||
public override ETaskResult Update()
|
||||
{
|
||||
if (clientState.TerritoryType != base.Task.TerritoryId)
|
||||
{
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
switch (_state)
|
||||
{
|
||||
case State.FindingObject:
|
||||
if (_noObjectFoundSince != DateTime.MaxValue && DateTime.Now > _noObjectFoundSince.AddSeconds(3.0))
|
||||
{
|
||||
if (AnyMatchingObjectsExist())
|
||||
{
|
||||
logger.LogInformation("Matching objects still exist, clearing visited positions and retrying");
|
||||
_visitedPositions.Clear();
|
||||
_noObjectFoundSince = DateTime.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation("No matching objects remain, moving to waypoint");
|
||||
NavigateToNextWaypoint();
|
||||
}
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
TryFindAndMove();
|
||||
return ETaskResult.StillRunning;
|
||||
case State.MovingToObject:
|
||||
{
|
||||
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;
|
||||
}
|
||||
IGameObject gameObject2 = FindNearestUnvisitedObject();
|
||||
IGameObject gameObject3 = objectTable[0];
|
||||
if (gameObject2 != null && gameObject3 != null && Vector3.Distance(gameObject3.Position, gameObject2.Position) <= 5f)
|
||||
{
|
||||
_visitedPositions.Add(gameObject2.Position);
|
||||
_state = State.UsingAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation("Target no longer valid at destination, finding next");
|
||||
TryFindAndMove();
|
||||
}
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
case State.UsingAction:
|
||||
if (gameFunctions.UseAction(base.Task.Action))
|
||||
{
|
||||
logger.LogInformation("Used action {Action}", base.Task.Action);
|
||||
_waitUntil = DateTime.Now.AddSeconds(1.0);
|
||||
_state = State.WaitingAfterAction;
|
||||
}
|
||||
return ETaskResult.StillRunning;
|
||||
case State.WaitingAfterAction:
|
||||
if (DateTime.Now < _waitUntil)
|
||||
{
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
TryFindAndMove();
|
||||
return ETaskResult.StillRunning;
|
||||
case State.MovingToWaypoint:
|
||||
{
|
||||
if (movementController.IsPathfinding || movementController.IsPathRunning)
|
||||
{
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
DateTime movementStartedAt2 = movementController.MovementStartedAt;
|
||||
if (movementStartedAt2 == DateTime.MaxValue || movementStartedAt2.AddSeconds(2.0) >= DateTime.Now)
|
||||
{
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
logger.LogInformation("Reached waypoint, waiting for zone transition");
|
||||
_state = State.WaitingForTransition;
|
||||
_lastPlayerPosition = objectTable[0]?.Position ?? Vector3.Zero;
|
||||
_waypointReachedAt = DateTime.Now;
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
case State.WaitingForTransition:
|
||||
{
|
||||
IGameObject gameObject = objectTable[0];
|
||||
if (gameObject != null)
|
||||
{
|
||||
float num = Vector3.Distance(_lastPlayerPosition, gameObject.Position);
|
||||
if (num > 50f)
|
||||
{
|
||||
logger.LogInformation("Zone transition detected (moved {Distance}), resuming plant clearing", num);
|
||||
_visitedPositions.Clear();
|
||||
_triedWaypointIndices.Clear();
|
||||
_noObjectFoundSince = DateTime.MaxValue;
|
||||
_state = State.FindingObject;
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
}
|
||||
if (FindNearestUnvisitedObject() != null)
|
||||
{
|
||||
logger.LogInformation("New objects detected, resuming plant clearing");
|
||||
_visitedPositions.Clear();
|
||||
_triedWaypointIndices.Clear();
|
||||
_noObjectFoundSince = DateTime.MaxValue;
|
||||
TryFindAndMove();
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
if (_waypointReachedAt != DateTime.MaxValue && DateTime.Now > _waypointReachedAt.AddSeconds(3.0))
|
||||
{
|
||||
logger.LogInformation("No transition at this waypoint, trying next");
|
||||
NavigateToNextWaypoint();
|
||||
}
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
default:
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -130,10 +130,8 @@ internal static class Dive
|
|||
List<List<nint>> list = new List<List<nint>>(num);
|
||||
CollectionsMarshal.SetCount(list, num);
|
||||
Span<List<nint>> span = CollectionsMarshal.AsSpan(list);
|
||||
int num2 = 0;
|
||||
span[num2] = GetKeysToPress(key, keyModifier);
|
||||
num2++;
|
||||
span[num2] = GetKeysToPress(key2, keyModifier2);
|
||||
span[0] = GetKeysToPress(key, keyModifier);
|
||||
span[1] = GetKeysToPress(key2, keyModifier2);
|
||||
List<nint> list2 = (from x in list
|
||||
where x != null
|
||||
select (x)).MinBy((List<nint> x) => x.Count);
|
||||
|
|
@ -144,12 +142,12 @@ internal static class Dive
|
|||
foreach (nint item in list2)
|
||||
{
|
||||
_keysToPress.Enqueue((256u, item));
|
||||
for (int num3 = 0; num3 < 15; num3++)
|
||||
for (int num2 = 0; num2 < 15; num2++)
|
||||
{
|
||||
_keysToPress.Enqueue((0u, 0));
|
||||
}
|
||||
}
|
||||
for (int num4 = 0; num4 < 5; num4++)
|
||||
for (int num3 = 0; num3 < 5; num3++)
|
||||
{
|
||||
_keysToPress.Enqueue((0u, 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,12 +175,10 @@ internal static class EquipItem
|
|||
case 10u:
|
||||
case 11u:
|
||||
{
|
||||
int index = 1;
|
||||
List<ushort> list4 = new List<ushort>(index);
|
||||
CollectionsMarshal.SetCount(list4, index);
|
||||
Span<ushort> span4 = CollectionsMarshal.AsSpan(list4);
|
||||
int num = 0;
|
||||
span4[num] = (ushort)(item.Value.EquipSlotCategory.RowId - 1);
|
||||
int num = 1;
|
||||
List<ushort> list4 = new List<ushort>(num);
|
||||
CollectionsMarshal.SetCount(list4, num);
|
||||
CollectionsMarshal.AsSpan(list4)[0] = (ushort)(item.Value.EquipSlotCategory.RowId - 1);
|
||||
return list4;
|
||||
}
|
||||
case 12u:
|
||||
|
|
@ -188,21 +186,17 @@ internal static class EquipItem
|
|||
int num = 2;
|
||||
List<ushort> list3 = new List<ushort>(num);
|
||||
CollectionsMarshal.SetCount(list3, num);
|
||||
Span<ushort> span3 = CollectionsMarshal.AsSpan(list3);
|
||||
int index = 0;
|
||||
span3[index] = 11;
|
||||
index++;
|
||||
span3[index] = 12;
|
||||
Span<ushort> span = CollectionsMarshal.AsSpan(list3);
|
||||
span[0] = 11;
|
||||
span[1] = 12;
|
||||
return list3;
|
||||
}
|
||||
case 13u:
|
||||
{
|
||||
int index = 1;
|
||||
List<ushort> list2 = new List<ushort>(index);
|
||||
CollectionsMarshal.SetCount(list2, index);
|
||||
Span<ushort> span2 = CollectionsMarshal.AsSpan(list2);
|
||||
int num = 0;
|
||||
span2[num] = 0;
|
||||
int num = 1;
|
||||
List<ushort> list2 = new List<ushort>(num);
|
||||
CollectionsMarshal.SetCount(list2, num);
|
||||
CollectionsMarshal.AsSpan(list2)[0] = 0;
|
||||
return list2;
|
||||
}
|
||||
case 17u:
|
||||
|
|
@ -210,9 +204,7 @@ internal static class EquipItem
|
|||
int num = 1;
|
||||
List<ushort> list = new List<ushort>(num);
|
||||
CollectionsMarshal.SetCount(list, num);
|
||||
Span<ushort> span = CollectionsMarshal.AsSpan(list);
|
||||
int index = 0;
|
||||
span[index] = 13;
|
||||
CollectionsMarshal.AsSpan(list)[0] = 13;
|
||||
return list;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ internal static class FateFarming
|
|||
|
||||
private ushort _trackedFateId;
|
||||
|
||||
private bool _fateWasActive;
|
||||
|
||||
protected override bool Start()
|
||||
{
|
||||
_trackedFateId = gameFunctions.GetCurrentFateId();
|
||||
|
|
@ -138,6 +140,13 @@ internal static class FateFarming
|
|||
logger.LogInformation("Required status {StatusId} lost during FATE action loop, ending cycle to re-apply", base.Task.RequiredStatusId.Value);
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
bool flag = gameFunctions.GetCurrentFateId() != 0;
|
||||
if (_fateWasActive && !flag)
|
||||
{
|
||||
logger.LogInformation("FATE {FateId} is no longer active, cycle complete", _trackedFateId);
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
_fateWasActive = flag;
|
||||
if (_trackedFateId == 0)
|
||||
{
|
||||
_trackedFateId = gameFunctions.GetCurrentFateId();
|
||||
|
|
@ -156,8 +165,8 @@ internal static class FateFarming
|
|||
IGameObject gameObject = gameFunctions.FindObjectByDataId(target.DataId, null, warnIfMissing: false);
|
||||
if (gameObject != null && gameObject.IsTargetable)
|
||||
{
|
||||
bool flag = gameFunctions.UseAction(gameObject, target.Action);
|
||||
_nextActionAt = (flag ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
|
||||
bool flag2 = gameFunctions.UseAction(gameObject, target.Action);
|
||||
_nextActionAt = (flag2 ? DateTime.Now.AddSeconds(2.5) : DateTime.Now.AddSeconds(0.5));
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,9 +67,7 @@ internal static class Jump
|
|||
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;
|
||||
CollectionsMarshal.AsSpan(list)[0] = base.Task.JumpDestination.Position;
|
||||
movementController.NavigateTo(EMovementType.Quest, dataId, list, fly: false, sprint: false, base.Task.JumpDestination.StopDistance ?? num);
|
||||
_003Cframework_003EP.RunOnTick(delegate
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue