Fix gold saucer aethernet shard distances
authorLiza Carvelli <liza@carvel.li>
Fri, 13 Jun 2025 20:46:53 +0000 (22:46 +0200)
committerLiza Carvelli <liza@carvel.li>
Fri, 13 Jun 2025 20:46:53 +0000 (22:46 +0200)
Questionable/Controller/CombatController.cs
Questionable/Controller/MovementController.cs
Questionable/Controller/Steps/Movement/MoveExecutor.cs
Questionable/Controller/Steps/Shared/AethernetShortcut.cs
Questionable/Data/AetheryteData.cs

index a00bafc..e6090e2 100644 (file)
@@ -20,6 +20,7 @@ using Questionable.Controller.Utils;
 using Questionable.Functions;
 using Questionable.Model;
 using Questionable.Model.Questing;
+using Questionable.Model.Questing.Converter;
 
 namespace Questionable.Controller;
 
@@ -423,14 +424,14 @@ internal sealed class CombatController : IDisposable
                 _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);
             }
         }
     }
index c69694c..aa8deaa 100644 (file)
@@ -184,7 +184,7 @@ internal sealed class MovementController : IDisposable
             }
             else if ((localPlayerPosition - Destination.Position).Length() < Destination.StopDistance)
             {
-                if (Destination.IgnoreDistanceToObject)
+                if (localPlayerPosition.Y - Destination.Position.Y <= Destination.VerticalStopDistance)
                 {
                     Stop();
                 }
@@ -255,12 +255,12 @@ internal sealed class MovementController : IDisposable
         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);
         }
     }
 
@@ -272,7 +272,7 @@ internal sealed class MovementController : IDisposable
 
     [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();
 
@@ -283,18 +283,18 @@ internal sealed class MovementController : IDisposable
         }
 
         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++;
@@ -322,13 +322,13 @@ internal sealed class MovementController : IDisposable
     }
 
     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);
@@ -468,7 +468,7 @@ internal sealed class MovementController : IDisposable
         float StopDistance,
         bool IsFlying,
         bool CanSprint,
-        bool IgnoreDistanceToObject,
+        float VerticalStopDistance,
         bool Land,
         bool UseNavmesh)
     {
index 1789de9..341c2be 100644 (file)
@@ -68,7 +68,7 @@ internal sealed class MoveExecutor : TaskExecutor<MoveTask>, IToastAware
                     fly: Task.Fly,
                     sprint: Task.Sprint ?? _mountDuringMovement == null,
                     stopDistance: Task.StopDistance,
-                    ignoreDistanceToObject: Task.IgnoreDistanceToObject,
+                    verticalStopDistance: Task.IgnoreDistanceToObject ? float.MaxValue : null,
                     land: Task.Land);
         }
         else
@@ -78,7 +78,7 @@ internal sealed class MoveExecutor : TaskExecutor<MoveTask>, IToastAware
                     fly: Task.Fly,
                     sprint: Task.Sprint ?? _mountDuringMovement == null,
                     stopDistance: Task.StopDistance,
-                    ignoreDistanceToObject: Task.IgnoreDistanceToObject,
+                    verticalStopDistance: Task.IgnoreDistanceToObject ? float.MaxValue : null,
                     land: Task.Land);
         }
     }
index ff1c585..5fa97ac 100644 (file)
@@ -3,7 +3,6 @@ using System.Collections.Generic;
 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;
@@ -75,9 +74,6 @@ internal static class AethernetShortcut
         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)
@@ -198,9 +194,12 @@ internal static class AethernetShortcut
                 _ 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()
@@ -245,16 +244,18 @@ internal static class AethernetShortcut
                 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
index 818132d..117dfb2 100644 (file)
@@ -3,7 +3,6 @@ using System.Collections.ObjectModel;
 using System.Linq;
 using System.Numerics;
 using Dalamud.Plugin.Services;
-using Dalamud.Utility;
 using Lumina.Excel.Sheets;
 using Questionable.Model.Common;
 
@@ -13,33 +12,24 @@ internal sealed class AetheryteData
 {
     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;
 
@@ -47,18 +37,16 @@ internal sealed class AetheryteData
                 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();
 
@@ -309,7 +297,7 @@ internal sealed class AetheryteData
     /// <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) },
@@ -319,10 +307,9 @@ internal sealed class AetheryteData
             { 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)
     {
@@ -356,4 +343,6 @@ internal sealed class AetheryteData
     }
 
     public bool IsAirshipLanding(EAetheryteLocation aetheryte) => AirshipLandingLocations.ContainsKey(aetheryte);
+
+    public bool IsGoldSaucerAetheryte(EAetheryteLocation aetheryte) => TerritoryIds[aetheryte] is 144 or 388;
 }