Questionable/Questionable/Controller/Steps/BaseFactory/AethernetShortcut.cs

137 lines
4.9 KiB
C#

using System;
using System.Numerics;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Questionable.Data;
using Questionable.External;
using Questionable.Model;
using Questionable.Model.V1;
using Questionable.Model.V1.Converter;
namespace Questionable.Controller.Steps.BaseFactory;
internal static class AethernetShortcut
{
internal sealed class Factory(IServiceProvider serviceProvider) : ITaskFactory
{
public ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
{
if (step.AethernetShortcut == null)
return null;
return serviceProvider.GetRequiredService<UseAethernetShortcut>()
.With(step.AethernetShortcut.From, step.AethernetShortcut.To);
}
}
internal sealed class UseAethernetShortcut(
ILogger<UseAethernetShortcut> logger,
GameFunctions gameFunctions,
IClientState clientState,
AetheryteData aetheryteData,
LifestreamIpc lifestreamIpc,
MovementController movementController) : ISkippableTask
{
private bool _moving;
private bool _teleported;
public EAetheryteLocation From { get; set; }
public EAetheryteLocation To { get; set; }
public ITask With(EAetheryteLocation from, EAetheryteLocation to)
{
From = from;
To = to;
return this;
}
public bool Start()
{
if (gameFunctions.IsAetheryteUnlocked(From) &&
gameFunctions.IsAetheryteUnlocked(To))
{
ushort territoryType = clientState.TerritoryType;
Vector3 playerPosition = clientState.LocalPlayer!.Position;
// closer to the source
if (aetheryteData.CalculateDistance(playerPosition, territoryType, From) <
aetheryteData.CalculateDistance(playerPosition, territoryType, To))
{
if (aetheryteData.CalculateDistance(playerPosition, territoryType, From) < 11)
{
logger.LogInformation("Using lifestream to teleport to {Destination}", To);
lifestreamIpc.Teleport(To);
_teleported = true;
return true;
}
else
{
logger.LogInformation("Moving to aethernet shortcut");
_moving = true;
movementController.NavigateTo(EMovementType.Quest, (uint)From, aetheryteData.Locations[From],
false, true,
AetheryteConverter.IsLargeAetheryte(From) ? 10.9f : 6.9f);
return true;
}
}
}
else
logger.LogWarning(
"Aethernet shortcut not unlocked (from: {FromAetheryte}, to: {ToAetheryte}), walking manually",
From, To);
return false;
}
public ETaskResult Update()
{
if (_moving)
{
var movementStartedAt = movementController.MovementStartedAt;
if (movementStartedAt == DateTime.MaxValue || movementStartedAt.AddSeconds(2) >= DateTime.Now)
return ETaskResult.StillRunning;
if (!movementController.IsPathfinding && !movementController.IsPathRunning)
_moving = false;
return ETaskResult.StillRunning;
}
if (!_teleported)
{
logger.LogInformation("Using lifestream to teleport to {Destination}", To);
lifestreamIpc.Teleport(To);
_teleported = true;
return ETaskResult.StillRunning;
}
if (aetheryteData.IsAirshipLanding(To))
{
if (aetheryteData.CalculateAirshipLandingDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
clientState.TerritoryType, To) > 5)
return ETaskResult.StillRunning;
}
else if (aetheryteData.IsCityAetheryte(To))
{
if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
clientState.TerritoryType, To) > 20)
return ETaskResult.StillRunning;
}
else
{
// some overworld location (e.g. 'Tesselation (Lakeland)' would end up here
if (clientState.TerritoryType != aetheryteData.TerritoryIds[To])
return ETaskResult.StillRunning;
}
return ETaskResult.TaskComplete;
}
public override string ToString() => $"UseAethernet({From} -> {To})";
}
}