},
"TerritoryId": 1190,
"InteractionType": "WalkTo",
- "$": "Shaaloani Hhusatahwi Saloon Stairs (top)"
+ "$": "Shaaloani Hhusatahwi Saloon Stairs (top)",
+ "Mount": true
},
{
"Position": {
{
"Sequence": 3,
"Steps": [
+ {
+ "Position": {
+ "X": -163.63573,
+ "Y": 45.171337,
+ "Z": 12.003954
+ },
+ "TerritoryId": 1185,
+ "InteractionType": "WalkTo"
+ },
{
"DataId": 1047026,
"Position": {
"Z": 0.6866455
},
"TerritoryId": 1171,
- "InteractionType": "Interact"
+ "InteractionType": "Interact",
+ "DelaySecondsAtStart": 3
}
]
},
"Z": -117.162285
},
"TerritoryId": 1186,
- "InteractionType": "WalkTo"
+ "InteractionType": "WalkTo",
+ "RestartNavigationIfCancelled": false
},
{
"TerritoryId": 1186,
"InteractionType": "AttuneAethernetShard",
- "AethernetShard": "[Solution Nine] Resolution"
+ "AethernetShard": "[Solution Nine] Resolution",
+ "DelaySecondsAtStart": 2
},
{
"DataId": 1048073,
"Z": 5.1162424
},
"TerritoryId": 1186,
- "InteractionType": "WalkTo"
+ "InteractionType": "WalkTo",
+ "RestartNavigationIfCancelled": false
},
{
"DataId": 1048172,
"Z": 9.201172
},
"TerritoryId": 1186,
- "InteractionType": "Interact"
+ "InteractionType": "Interact",
+ "DelaySecondsAtStart": 2
}
]
},
internal static class AethernetShortcut
{
- internal sealed class Factory(MovementController movementController)
+ internal sealed class Factory(
+ MovementController movementController,
+ AetheryteData aetheryteData,
+ TerritoryData territoryData,
+ IClientState clientState)
: ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
"Wait(navmesh ready)");
yield return new Task(step.AethernetShortcut.From, step.AethernetShortcut.To,
step.SkipConditions?.AethernetShortcutIf ?? new());
+
+ if (AetheryteShortcut.MoveAwayFromAetheryteExecutor.AppliesTo(step.AethernetShortcut.To))
+ {
+ yield return new WaitCondition.Task(
+ () => clientState.TerritoryType == aetheryteData.TerritoryIds[step.AethernetShortcut.To],
+ $"Wait(territory: {territoryData.GetNameAndId(aetheryteData.TerritoryIds[step.AethernetShortcut.To])})");
+ yield return new AetheryteShortcut.MoveAwayFromAetheryte(step.AethernetShortcut.To);
+ }
}
}
new(0, 8.442986f, -9),
];
- Vector3 closestPoint = nearbyPoints.MinBy(x => (playerPosition - x).Length());
+ Vector3 closestPoint = nearbyPoints.MinBy(x => Vector3.Distance(playerPosition, x));
_moving = true;
movementController.NavigateTo(EMovementType.Quest, (uint)Task.From, closestPoint, false, true,
0.25f);
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Numerics;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
+using Questionable.Controller.Steps.Common;
using Questionable.Controller.Utils;
using Questionable.Data;
using Questionable.Functions;
internal static class AetheryteShortcut
{
- internal sealed class Factory(AetheryteData aetheryteData) : ITaskFactory
+ internal sealed class Factory(AetheryteData aetheryteData, TerritoryData territoryData, IClientState clientState)
+ : ITaskFactory
{
public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
{
yield return new Task(step, quest.Id, step.AetheryteShortcut.Value,
aetheryteData.TerritoryIds[step.AetheryteShortcut.Value]);
yield return new WaitAtEnd.WaitDelay(TimeSpan.FromSeconds(0.5));
+
+ if (MoveAwayFromAetheryteExecutor.AppliesTo(step.AetheryteShortcut.Value) &&
+ step.AethernetShortcut?.From != step.AetheryteShortcut.Value)
+ {
+ yield return new WaitCondition.Task(
+ () => clientState.TerritoryType == aetheryteData.TerritoryIds[step.AetheryteShortcut.Value],
+ $"Wait(territory: {territoryData.GetNameAndId(aetheryteData.TerritoryIds[step.AetheryteShortcut.Value])})");
+ yield return new MoveAwayFromAetheryte(step.AetheryteShortcut.Value);
+ }
}
}
}
}
}
+
+ internal sealed record MoveAwayFromAetheryte(EAetheryteLocation TargetAetheryte) : ITask
+ {
+ public override string ToString() => $"MoveAway({TargetAetheryte})";
+ }
+
+ internal sealed class MoveAwayFromAetheryteExecutor(
+ MoveTo.MoveExecutor moveExecutor,
+ AetheryteData aetheryteData,
+ IClientState clientState) : TaskExecutor<MoveAwayFromAetheryte>
+ {
+ private static readonly Dictionary<EAetheryteLocation, List<Vector3>> AetherytesToMoveFrom = new()
+ {
+ {
+ EAetheryteLocation.SolutionNine,
+ [
+ new(0f, 8.8f, 15.5f),
+ new(0f, 8.8f, -15.5f),
+ new(15.5f, 8.8f, 0f),
+ new(-15.5f, 8.8f, 0f)
+ ]
+ }
+ };
+
+ public static bool AppliesTo(EAetheryteLocation location) => AetherytesToMoveFrom.ContainsKey(location);
+
+ protected override bool Start()
+ {
+ // only relevant if we're actually near the s9 aetheryte at the end
+ Vector3 playerPosition = clientState.LocalPlayer!.Position;
+ if (aetheryteData.CalculateDistance(playerPosition, clientState.TerritoryType, Task.TargetAetheryte) >= 20)
+ return false;
+
+ Vector3 closestPoint = AetherytesToMoveFrom[Task.TargetAetheryte]
+ .MinBy(x => Vector3.Distance(x, playerPosition));
+ MoveTo.MoveTask task = new MoveTo.MoveTask(aetheryteData.TerritoryIds[Task.TargetAetheryte],
+ closestPoint, Mount: false, StopDistance: 0.25f, DisableNavmesh: true,
+ InteractionType: EInteractionType.None, RestartNavigation: false);
+ return moveExecutor.Start(task);
+ }
+
+ public override ETaskResult Update() => moveExecutor.Update();
+ }
}
private static void AddTaskFactories(ServiceCollection serviceCollection)
{
// individual tasks
- serviceCollection.AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>();
+ serviceCollection
+ .AddTaskExecutor<MoveToLandingLocation.Task, MoveToLandingLocation.MoveToLandingLocationExecutor>();
serviceCollection.AddTaskExecutor<DoGather.Task, DoGather.GatherExecutor>();
serviceCollection.AddTaskExecutor<DoGatherCollectable.Task, DoGatherCollectable.GatherCollectableExecutor>();
serviceCollection.AddTaskExecutor<SwitchClassJob.Task, SwitchClassJob.SwitchClassJobExecutor>();
// task factories
serviceCollection
- .AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory, StepDisabled.SkipDisabledStepsExecutor>();
+ .AddTaskFactoryAndExecutor<StepDisabled.SkipRemainingTasks, StepDisabled.Factory,
+ StepDisabled.SkipDisabledStepsExecutor>();
serviceCollection.AddTaskFactory<EquipRecommended.BeforeDutyOrInstance>();
serviceCollection.AddTaskFactoryAndExecutor<Gather.GatheringTask, Gather.Factory, Gather.StartGathering>();
serviceCollection.AddTaskExecutor<Gather.SkipMarker, Gather.DoSkip>();
serviceCollection
.AddTaskFactoryAndExecutor<AetheryteShortcut.Task, AetheryteShortcut.Factory,
AetheryteShortcut.UseAetheryteShortcut>();
+ serviceCollection
+ .AddTaskExecutor<AetheryteShortcut.MoveAwayFromAetheryte, AetheryteShortcut.MoveAwayFromAetheryteExecutor>();
serviceCollection
.AddTaskFactoryAndExecutor<SkipCondition.SkipTask, SkipCondition.Factory, SkipCondition.CheckSkip>();
serviceCollection
serviceCollection.AddTaskExecutor<MoveTo.WaitForNearDataId, MoveTo.WaitForNearDataIdExecutor>();
serviceCollection.AddTaskExecutor<MoveTo.LandTask, MoveTo.LandExecutor>();
- serviceCollection.AddTaskFactoryAndExecutor<NextQuest.SetQuestTask, NextQuest.Factory, NextQuest.NextQuestExecutor>();
+ serviceCollection
+ .AddTaskFactoryAndExecutor<NextQuest.SetQuestTask, NextQuest.Factory, NextQuest.NextQuestExecutor>();
serviceCollection
.AddTaskFactoryAndExecutor<AetherCurrent.Attune, AetherCurrent.Factory, AetherCurrent.DoAttune>();
serviceCollection
TurnInDelivery.SatisfactionSupplyTurnIn>();
serviceCollection.AddTaskFactory<InitiateLeve.Factory>();
- serviceCollection.AddTaskExecutor<InitiateLeve.SkipInitiateIfActive, InitiateLeve.SkipInitiateIfActiveExecutor>();
+ serviceCollection
+ .AddTaskExecutor<InitiateLeve.SkipInitiateIfActive, InitiateLeve.SkipInitiateIfActiveExecutor>();
serviceCollection.AddTaskExecutor<InitiateLeve.OpenJournal, InitiateLeve.OpenJournalExecutor>();
serviceCollection.AddTaskExecutor<InitiateLeve.Initiate, InitiateLeve.InitiateExecutor>();
serviceCollection.AddTaskExecutor<InitiateLeve.SelectDifficulty, InitiateLeve.SelectDifficultyExecutor>();