Various tiny fixes for issues introduced in 0.6 v0.7
authorLiza Carvelli <liza@carvel.li>
Sun, 9 Jun 2024 20:44:35 +0000 (22:44 +0200)
committerLiza Carvelli <liza@carvel.li>
Sun, 9 Jun 2024 20:44:56 +0000 (22:44 +0200)
QuestPaths/Endwalker/MSQ/D-Thavnair2/4415_Warm Hearts, Rekindled Hopes.json
QuestPaths/Endwalker/MSQ/E-Elpis/4420_Hope Upon a Flower.json
Questionable/Controller/MovementController.cs
Questionable/Controller/Steps/BaseFactory/AethernetShortcut.cs
Questionable/Controller/Steps/BaseFactory/AetheryteShortcut.cs
Questionable/Controller/Steps/BaseFactory/Move.cs
Questionable/Controller/Steps/InteractionFactory/Say.cs
Questionable/Data/AetheryteData.cs
Questionable/GameFunctions.cs
Questionable/Questionable.csproj
Questionable/QuestionablePlugin.cs

index 08e581a06fdd7997ef792f5659609b1c0bc55c67..1b19646c41da094c5fe468401f20c97da7894451 100644 (file)
@@ -99,7 +99,8 @@
           "TerritoryId": 957,
           "InteractionType": "WalkTo",
           "DisableNavmesh": true,
-          "Mount": true
+          "Mount": true,
+          "Comment": "FIXME Returning to the surface means navmesh won't move anymore, but the path is still 'running'"
         },
         {
           "Position": {
index 41e2d48e998f91d5cade1249dbe5544c59aa1ab0..ca79349244e48bfb9b30e4581a47dadaa18c5108 100644 (file)
@@ -34,7 +34,6 @@
             "[Crystarium] The Cabinet of Curiosity",
             "[Crystarium] The Dossal Gate"
           ],
-          "Comment": "TODO Check target territory id",
           "TargetTerritoryId": 844
         }
       ]
@@ -63,7 +62,7 @@
             null,
             null,
             null,
-            16
+            -16
           ]
         },
         {
index a3d978651d593024523212316eaafd4be3444adb..999ecc9ade8fc9a1bd861e31a88829bff42b33b9 100644 (file)
@@ -173,7 +173,10 @@ internal sealed class MovementController : IDisposable
         ResetPathfinding();
 
         if (InputManager.IsAutoRunning())
+        {
+            _logger.LogInformation("Turning off auto-move");
             _gameFunctions.ExecuteCommand("/automove off");
+        }
 
         Destination = new DestinationData(dataId, to, stopDistance ?? (DefaultStopDistance - 0.2f), fly, sprint);
         MovementStartedAt = DateTime.MaxValue;
@@ -227,7 +230,10 @@ internal sealed class MovementController : IDisposable
         ResetPathfinding();
 
         if (InputManager.IsAutoRunning())
+        {
+            _logger.LogInformation("Turning off auto-move [stop]");
             _gameFunctions.ExecuteCommand("/automove off");
+        }
     }
 
     public void Dispose()
index a1d1fafa8a6f66e987c87aac67a0a6099c232897..988d5cd4921456fad625b12e678006bb9e461387 100644 (file)
@@ -108,9 +108,19 @@ internal static class AethernetShortcut
                 return ETaskResult.StillRunning;
             }
 
-            if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
-                    clientState.TerritoryType, To) > 11)
-                return ETaskResult.StillRunning;
+            if (aetheryteData.IsCityAetheryte(To))
+            {
+                if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
+                        clientState.TerritoryType, To) > 11)
+                    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;
         }
index 5220876d0ad216ded699d73a9eb20d83e6f78f0f..58ecb1280e3ee49a0138028b5fd49767df32d91e 100644 (file)
@@ -13,7 +13,10 @@ namespace Questionable.Controller.Steps.BaseFactory;
 
 internal static class AetheryteShortcut
 {
-    internal sealed class Factory(IServiceProvider serviceProvider, GameFunctions gameFunctions) : ITaskFactory
+    internal sealed class Factory(
+        IServiceProvider serviceProvider,
+        GameFunctions gameFunctions,
+        AetheryteData aetheryteData) : ITaskFactory
     {
         public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
         {
@@ -21,7 +24,7 @@ internal static class AetheryteShortcut
                 return [];
 
             var task = serviceProvider.GetRequiredService<UseAetheryteShortcut>()
-                .With(step, step.AetheryteShortcut.Value);
+                .With(step, step.AetheryteShortcut.Value, aetheryteData.TerritoryIds[step.AetheryteShortcut.Value]);
             return [new WaitConditionTask(gameFunctions.CanTeleport, "CanTeleport"), task];
         }
 
@@ -41,10 +44,17 @@ internal static class AetheryteShortcut
         public QuestStep Step { get; set; } = null!;
         public EAetheryteLocation TargetAetheryte { get; set; }
 
-        public ITask With(QuestStep step, EAetheryteLocation targetAetheryte)
+        /// <summary>
+        /// If using an aethernet shortcut after, the aetheryte's territory-id and the step's territory-id can differ,
+        /// we always use the aetheryte's territory-id.
+        /// </summary>
+        public ushort ExpectedTerritoryId { get; set; }
+
+        public ITask With(QuestStep step, EAetheryteLocation targetAetheryte, ushort expectedTerritoryId)
         {
             Step = step;
             TargetAetheryte = targetAetheryte;
+            ExpectedTerritoryId = expectedTerritoryId;
             return this;
         }
 
@@ -52,7 +62,7 @@ internal static class AetheryteShortcut
         {
             _continueAt = DateTime.Now.AddSeconds(8);
             ushort territoryType = clientState.TerritoryType;
-            if (Step.TerritoryId == territoryType)
+            if (ExpectedTerritoryId == territoryType)
             {
                 Vector3 pos = clientState.LocalPlayer!.Position;
                 if (aetheryteData.CalculateDistance(pos, territoryType, TargetAetheryte) < 11 ||
@@ -84,8 +94,7 @@ internal static class AetheryteShortcut
 
         public ETaskResult Update()
         {
-
-            if (DateTime.Now >= _continueAt && clientState.TerritoryType == Step.TerritoryId)
+            if (DateTime.Now >= _continueAt && clientState.TerritoryType == ExpectedTerritoryId)
                 return ETaskResult.TaskComplete;
 
             return ETaskResult.StillRunning;
index a3d6e1e0d7544fc4b3a0737c17c7cf36d8033f8d..61f7957a22a0bb2e595ff153f98fee137c842419 100644 (file)
@@ -60,8 +60,10 @@ internal static class Move
                 yield break;
             }
 
-            yield return new WaitConditionTask(() => clientState.TerritoryType == Step.TerritoryId, $"Wait(territory: {Step.TerritoryId}");
-            yield return new WaitConditionTask(() => movementController.IsNavmeshReady, "Wait(navmesh ready)");
+            yield return new WaitConditionTask(() => clientState.TerritoryType == Step.TerritoryId,
+                $"Wait(territory: {Step.TerritoryId})");
+            yield return new WaitConditionTask(() => movementController.IsNavmeshReady,
+                "Wait(navmesh ready)");
 
             float distance;
             if (Step.InteractionType == EInteractionType.WalkTo)
index 9ec51c3792261657189f6a9ff616b8ab52be265b..7f82e9e13d7d5be93c36b0648bde3fb23ede393c 100644 (file)
@@ -13,7 +13,7 @@ internal static class Say
     {
         public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
         {
-            if (step.InteractionType != EInteractionType.Emote)
+            if (step.InteractionType != EInteractionType.Say)
                 return [];
 
 
index bd66ac674d4a10b979dfa4c7203a032eff92f7c0..377fb0ce42b91ad3fe5ecbc680bed9e2afcecb60 100644 (file)
@@ -10,6 +10,29 @@ namespace Questionable.Data;
 
 internal sealed class AetheryteData
 {
+    public AetheryteData(IDataManager dataManager)
+    {
+        Dictionary<EAetheryteLocation, string> aethernetNames = new();
+        Dictionary<EAetheryteLocation, ushort> territoryIds = new();
+        foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
+        {
+            string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
+            if (!string.IsNullOrEmpty(aethernetName))
+                aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
+
+            if (aetheryte.Territory != null && aetheryte.Territory.Row > 0)
+                territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.Row;
+        }
+
+        AethernetNames = aethernetNames.AsReadOnly();
+        TerritoryIds = territoryIds.AsReadOnly();
+
+        TownTerritoryIds = dataManager.GetExcelSheet<TerritoryType>()!
+            .Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name) && x.TerritoryIntendedUse == 0)
+            .Select(x => (ushort)x.RowId)
+            .ToList();
+    }
+
     public ReadOnlyDictionary<EAetheryteLocation, Vector3> Locations { get; } =
         new Dictionary<EAetheryteLocation, Vector3>
             {
@@ -196,24 +219,7 @@ internal sealed class AetheryteData
 
     public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
     public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
-
-    public AetheryteData(IDataManager dataManager)
-    {
-        Dictionary<EAetheryteLocation, string> aethernetNames = new();
-        Dictionary<EAetheryteLocation, ushort> territoryIds = new();
-        foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
-        {
-            string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
-            if (!string.IsNullOrEmpty(aethernetName))
-                aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
-
-            if (aetheryte.Territory != null && aetheryte.Territory.Row > 0)
-                territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.Row;
-        }
-
-        AethernetNames = aethernetNames.AsReadOnly();
-        TerritoryIds = territoryIds.AsReadOnly();
-    }
+    public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
 
     public float CalculateDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
     {
@@ -225,4 +231,10 @@ internal sealed class AetheryteData
 
         return (fromPosition - toPosition).Length();
     }
+
+    public bool IsCityAetheryte(EAetheryteLocation aetheryte)
+    {
+        var territoryId = TerritoryIds[aetheryte];
+        return TownTerritoryIds.Contains(territoryId);
+    }
 }
index 3ca4c08d93dfe4da407650d02f1a5fd03caf398f..c868f286b3ec16a5328af8dedd9cfec90f315a64 100644 (file)
@@ -441,16 +441,26 @@ internal sealed unsafe class GameFunctions
         {
             if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, 71) == 0)
             {
-                _logger.LogInformation("Using SDS Fenrir as mount");
-                return ActionManager.Instance()->UseAction(ActionType.Mount, 71);
+                if (ActionManager.Instance()->UseAction(ActionType.Mount, 71))
+                {
+                    _logger.LogInformation("Using SDS Fenrir as mount");
+                    return true;
+                }
+
+                return false;
             }
         }
         else
         {
             if (ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 9) == 0)
             {
-                _logger.LogInformation("Using mount roulette");
-                return ActionManager.Instance()->UseAction(ActionType.GeneralAction, 9);
+                if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 9))
+                {
+                    _logger.LogInformation("Using mount roulette");
+                    return true;
+                }
+
+                return false;
             }
         }
 
@@ -485,14 +495,17 @@ internal sealed unsafe class GameFunctions
                     contentFinderConditionId, contentId);
         }
         else
-            _logger.LogError("Could not find content for content finder condition (cf: {ContentFinderId})", contentFinderConditionId);
+            _logger.LogError("Could not find content for content finder condition (cf: {ContentFinderId})",
+                contentFinderConditionId);
     }
 
     public string? GetDialogueText(Quest currentQuest, string? excelSheetName, string key)
     {
         if (excelSheetName == null)
         {
-            var questRow = _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId + 0x10000);
+            var questRow =
+                _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.QuestId +
+                    0x10000);
             if (questRow == null)
             {
                 _logger.LogError("Could not find quest row for {QuestId}", currentQuest.QuestId);
@@ -526,10 +539,10 @@ internal sealed unsafe class GameFunctions
             return true;
 
         return _condition[ConditionFlag.Occupied] || _condition[ConditionFlag.Occupied30] ||
-            _condition[ConditionFlag.Occupied33] || _condition[ConditionFlag.Occupied38] ||
-            _condition[ConditionFlag.Occupied39] || _condition[ConditionFlag.OccupiedInEvent] ||
-            _condition[ConditionFlag.OccupiedInQuestEvent] || _condition[ConditionFlag.OccupiedInCutSceneEvent] ||
-            _condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] ||
-            _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51];
+               _condition[ConditionFlag.Occupied33] || _condition[ConditionFlag.Occupied38] ||
+               _condition[ConditionFlag.Occupied39] || _condition[ConditionFlag.OccupiedInEvent] ||
+               _condition[ConditionFlag.OccupiedInQuestEvent] || _condition[ConditionFlag.OccupiedInCutSceneEvent] ||
+               _condition[ConditionFlag.Casting] || _condition[ConditionFlag.Unknown57] ||
+               _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51];
     }
 }
index c7874da728893c3d17bd8396f39975357a81f3c1..b24b3ae358c2c4f0c443d7948ae68b46c748fbad 100644 (file)
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>net8.0-windows</TargetFramework>
-        <Version>0.6</Version>
+        <Version>0.7</Version>
         <LangVersion>12</LangVersion>
         <Nullable>enable</Nullable>
         <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
index ca86fa00960506eaac788ce813640e0f7bc841a1..b3575820c28a4666e29a688a75a52f9542f66846 100644 (file)
@@ -92,9 +92,6 @@ public sealed class QuestionablePlugin : IDalamudPlugin
         serviceCollection.AddTaskWithFactory<Say.Factory, Say.UseChat>();
         serviceCollection.AddTaskWithFactory<UseItem.Factory, UseItem.UseOnGround, UseItem.UseOnObject, UseItem.Use>();
 
-        // TODO sort this in properly
-        serviceCollection.AddTaskWithFactory<ZoneChange.Factory, ZoneChange.WaitForZone>();
-
         serviceCollection
             .AddTaskWithFactory<WaitAtEnd.Factory,
                 WaitAtEnd.WaitDelay,