using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
+using Questionable.Model.Questing.Converter;
namespace Questionable.Controller;
_logger.LogInformation("Moving to {TargetName} ({DataId}) to attack", gameObject.Name,
gameObject.DataId);
_movementController.NavigateTo(EMovementType.Combat, null, [gameObject.Position], false, false,
- maxDistance + hitboxOffset - 0.25f, true);
+ maxDistance + hitboxOffset - 0.25f, verticalStopDistance: float.MaxValue);
}
else
{
_logger.LogInformation("Moving to {TargetName} ({DataId}) to attack (with navmesh)", gameObject.Name,
gameObject.DataId);
_movementController.NavigateTo(EMovementType.Combat, null, gameObject.Position, false, false,
- maxDistance + hitboxOffset - 0.25f, true);
+ maxDistance + hitboxOffset - 0.25f, verticalStopDistance: float.MaxValue);
}
}
}
}
else if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance)
{
- if (Destination.IgnoreDistanceToObject)
+ if (localPlayerPosition.Y - Destination.Position.Y <= Destination.VerticalStopDistance)
{
Stop();
}
if (destination.UseNavmesh)
{
NavigateTo(EMovementType.None, destination.DataId, destination.Position, false, false,
- destination.StopDistance, destination.IgnoreDistanceToObject);
+ destination.StopDistance, destination.VerticalStopDistance);
}
else
{
NavigateTo(EMovementType.None, destination.DataId, [destination.Position], false, false,
- destination.StopDistance, destination.IgnoreDistanceToObject);
+ destination.StopDistance, destination.VerticalStopDistance);
}
}
[MemberNotNull(nameof(Destination))]
private void PrepareNavigation(EMovementType type, uint? dataId, Vector3 to, bool fly, bool sprint,
- float? stopDistance, bool ignoreDistanceToObject, bool land, bool useNavmesh)
+ float? stopDistance, float verticalStopDistance, bool land, bool useNavmesh)
{
ResetPathfinding();
}
Destination = new DestinationData(type, dataId, to, stopDistance ?? (QuestStep.DefaultStopDistance - 0.2f), fly,
- sprint, ignoreDistanceToObject, land, useNavmesh);
+ sprint, verticalStopDistance, land, useNavmesh);
MovementStartedAt = DateTime.MaxValue;
}
public void NavigateTo(EMovementType type, uint? dataId, Vector3 to, bool fly, bool sprint,
- float? stopDistance = null, bool ignoreDistanceToObject = false, bool land = false)
+ float? stopDistance = null, float? verticalStopDistance = null, bool land = false)
{
fly |= _condition[ConditionFlag.Diving];
if (fly && land)
to = to with { Y = to.Y + 2.6f };
- PrepareNavigation(type, dataId, to, fly, sprint, stopDistance, ignoreDistanceToObject, land, true);
+ PrepareNavigation(type, dataId, to, fly, sprint, stopDistance, verticalStopDistance ?? DefaultVerticalInteractionDistance, land, true);
_logger.LogInformation("Pathfinding to {Destination}", Destination);
Destination.NavmeshCalculations++;
}
public void NavigateTo(EMovementType type, uint? dataId, List<Vector3> to, bool fly, bool sprint,
- float? stopDistance, bool ignoreDistanceToObject = false, bool land = false)
+ float? stopDistance, float? verticalStopDistance = null, bool land = false)
{
fly |= _condition[ConditionFlag.Diving];
if (fly && land && to.Count > 0)
to[^1] = to[^1] with { Y = to[^1].Y + 2.6f };
- PrepareNavigation(type, dataId, to.Last(), fly, sprint, stopDistance, ignoreDistanceToObject, land, false);
+ PrepareNavigation(type, dataId, to.Last(), fly, sprint, stopDistance, verticalStopDistance ?? DefaultVerticalInteractionDistance, land, false);
_logger.LogInformation("Moving to {Destination}", Destination);
_navmeshIpc.MoveTo(to, fly);
float StopDistance,
bool IsFlying,
bool CanSprint,
- bool IgnoreDistanceToObject,
+ float VerticalStopDistance,
bool Land,
bool UseNavmesh)
{
fly: Task.Fly,
sprint: Task.Sprint ?? _mountDuringMovement == null,
stopDistance: Task.StopDistance,
- ignoreDistanceToObject: Task.IgnoreDistanceToObject,
+ verticalStopDistance: Task.IgnoreDistanceToObject ? float.MaxValue : null,
land: Task.Land);
}
else
fly: Task.Fly,
sprint: Task.Sprint ?? _mountDuringMovement == null,
stopDistance: Task.StopDistance,
- ignoreDistanceToObject: Task.IgnoreDistanceToObject,
+ verticalStopDistance: Task.IgnoreDistanceToObject ? float.MaxValue : null,
land: Task.Land);
}
}
using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
-using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps.Common;
private bool _triedMounting;
private DateTime _continueAt = DateTime.MinValue;
- public EAetheryteLocation From => Task.From;
- public EAetheryteLocation To => Task.To;
-
protected override bool Start()
{
if (!Task.SkipConditions.Never)
_ when AetheryteConverter.IsLargeAetheryte(Task.From) => 10.9f,
_ => 6.9f,
};
+
+ bool goldSaucerAethernetShard = aetheryteData.IsGoldSaucerAetheryte(Task.From) &&
+ !AetheryteConverter.IsLargeAetheryte(Task.From);
movementController.NavigateTo(EMovementType.Quest, (uint)Task.From, aetheryteData.Locations[Task.From],
- false, true,
- distance);
+ false, true, distance,
+ verticalStopDistance: goldSaucerAethernetShard ? 5f : null);
}
private void DoTeleport()
return ETaskResult.StillRunning;
}
+ Vector3? position = clientState.LocalPlayer?.Position;
+ if (position == null)
+ return ETaskResult.StillRunning;
+
if (aetheryteData.IsAirshipLanding(Task.To))
{
- if (aetheryteData.CalculateAirshipLandingDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
- clientState.TerritoryType, Task.To) > 5)
+ if (aetheryteData.CalculateAirshipLandingDistance(position.Value, clientState.TerritoryType, Task.To) > 5)
return ETaskResult.StillRunning;
}
- else if (aetheryteData.IsCityAetheryte(Task.To))
+ else if (aetheryteData.IsCityAetheryte(Task.To) || aetheryteData.IsGoldSaucerAetheryte(Task.To))
{
- if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
- clientState.TerritoryType, Task.To) > 20)
+ if (aetheryteData.CalculateDistance(position.Value, clientState.TerritoryType, Task.To) > 20)
return ETaskResult.StillRunning;
}
else
using System.Linq;
using System.Numerics;
using Dalamud.Plugin.Services;
-using Dalamud.Utility;
using Lumina.Excel.Sheets;
using Questionable.Model.Common;
{
public AetheryteData(IDataManager dataManager)
{
- Dictionary<EAetheryteLocation, string> aethernetNames = new();
Dictionary<EAetheryteLocation, ushort> territoryIds = new();
Dictionary<EAetheryteLocation, ushort> aethernetGroups = new();
- void ConfigureAetheryte(EAetheryteLocation aetheryteLocation, string name, ushort territoryId,
+ void ConfigureAetheryte(EAetheryteLocation aetheryteLocation, ushort territoryId,
ushort aethernetGroup)
{
- aethernetNames[aetheryteLocation] = name;
territoryIds[aetheryteLocation] = territoryId;
aethernetGroups[aetheryteLocation] = aethernetGroup;
}
- void ConfigureAetheryteWithPlaceName(EAetheryteLocation aetheryteLocation, uint placeNameId, ushort territoryId)
+ void ConfigureAetheryteWithAutoGroup(EAetheryteLocation aetheryteLocation, ushort territoryId)
{
- ConfigureAetheryte(aetheryteLocation,
- dataManager.GetExcelSheet<PlaceName>().GetRow(placeNameId).Name.ToDalamudString().TextValue,
- territoryId,
- (ushort)((int)aetheryteLocation / 100));
+ ConfigureAetheryte(aetheryteLocation, territoryId, (ushort)((int)aetheryteLocation / 100));
}
foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>().Where(x => x.RowId > 0))
{
- string? aethernetName = aetheryte.AethernetName.ValueNullable?.Name.ToString();
- if (!string.IsNullOrEmpty(aethernetName))
- aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
-
if (aetheryte.Territory.RowId > 0)
territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.RowId;
aethernetGroups[(EAetheryteLocation)aetheryte.RowId] = aetheryte.AethernetGroup;
}
- ConfigureAetheryte(EAetheryteLocation.IshgardFirmament, "Firmament", 886,
- aethernetGroups[EAetheryteLocation.Ishgard]);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentMendicantsCourt, 3436, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentMattock, 3473, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentNewNest, 3475, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmanentSaintRoellesDais, 3474, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentFeatherfall, 3525, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentHoarfrostHall, 3528, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FirmamentWesternRisensongQuarter, 3646, 886);
- ConfigureAetheryteWithPlaceName(EAetheryteLocation.FIrmamentEasternRisensongQuarter, 3645, 886);
-
- AethernetNames = aethernetNames.AsReadOnly();
+ ConfigureAetheryte(EAetheryteLocation.IshgardFirmament, 886, aethernetGroups[EAetheryteLocation.Ishgard]);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentMendicantsCourt, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentMattock, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentNewNest, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmanentSaintRoellesDais, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentFeatherfall, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentHoarfrostHall, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FirmamentWesternRisensongQuarter, 886);
+ ConfigureAetheryteWithAutoGroup(EAetheryteLocation.FIrmamentEasternRisensongQuarter, 886);
+
TerritoryIds = territoryIds.AsReadOnly();
AethernetGroups = aethernetGroups.AsReadOnly();
/// <summary>
/// Airship landings are special as they're one-way only (except for Radz-at-Han, which is a normal aetheryte).
/// </summary>
- public ReadOnlyDictionary<EAetheryteLocation, Vector3> AirshipLandingLocations { get; } =
+ private ReadOnlyDictionary<EAetheryteLocation, Vector3> AirshipLandingLocations { get; } =
new Dictionary<EAetheryteLocation, Vector3>
{
{ EAetheryteLocation.LimsaAirship, new(-19.44352f, 91.99999f, -9.892939f) },
{ EAetheryteLocation.IshgardFirmament, new(9.92315f, -15.2f, 173.5059f) },
}.AsReadOnly();
- public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
public ReadOnlyDictionary<EAetheryteLocation, ushort> AethernetGroups { get; }
- public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
+ private IReadOnlyList<ushort> TownTerritoryIds { get; set; }
public float CalculateDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
{
}
public bool IsAirshipLanding(EAetheryteLocation aetheryte) => AirshipLandingLocations.ContainsKey(aetheryte);
+
+ public bool IsGoldSaucerAetheryte(EAetheryteLocation aetheryte) => TerritoryIds[aetheryte] is 144 or 388;
}