Add some 90/96 MIN/BTN leves
authorLiza Carvelli <liza@carvel.li>
Sun, 11 Aug 2024 16:59:42 +0000 (18:59 +0200)
committerLiza Carvelli <liza@carvel.li>
Sun, 11 Aug 2024 17:00:13 +0000 (19:00 +0200)
23 files changed:
Directory.Build.targets
GatheringPathRenderer/RendererPlugin.cs
GatheringPaths/7.x - Dawntrail/Kozama'uka/946__BTN.json [new file with mode: 0644]
GatheringPaths/7.x - Dawntrail/Urqopacha/961__MIN.json [new file with mode: 0644]
GatheringPaths/7.x - Dawntrail/Yak T'el/955__BTN.json [new file with mode: 0644]
GatheringPaths/7.x - Dawntrail/Yak T'el/970__MIN.json
GatheringPaths/gatheringlocation-v1.json
QuestPathGenerator/GatheringSourceGenerator.cs
QuestPathGenerator/RoslynShortcuts.cs
QuestPaths/7.x - Dawntrail/Leves/BTN/L1770_All Stars.json [new file with mode: 0644]
QuestPaths/7.x - Dawntrail/Leves/BTN/L1779_New Start for the Cinderfield.json [new file with mode: 0644]
QuestPaths/7.x - Dawntrail/Leves/MIN/L1785_Old and Bubbly.json [new file with mode: 0644]
QuestPaths/7.x - Dawntrail/Leves/MIN/L1794_Vestiges of War.json
Questionable.Model/Gathering/GatheringNode.cs
Questionable.Model/Gathering/GatheringRoot.cs
Questionable.Model/Questing/EInteractionType.cs
Questionable/Controller/GameUiController.cs
Questionable/Controller/GatheringController.cs
Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs
Questionable/Controller/Steps/Interactions/Interact.cs
Questionable/Controller/Steps/Leves/InitiateLeve.cs
Questionable/QuestionablePlugin.cs
Questionable/Windows/QuestComponents/CreationUtilsComponent.cs

index 8d0cd3238e5260a411a15a8183d395e20af035fe..b914cd1eba4a990cf5d7a7ae789cd5f1fdfc8661 100644 (file)
@@ -1,5 +1,5 @@
 <Project>
     <PropertyGroup>
-        <Version>2.5</Version>
+        <Version>2.6</Version>
     </PropertyGroup>
 </Project>
index 55dee9847cfc0ef11a2654ba8f998c8ca0e1b350..636100ad39c73e4619cf366745f5e4783a86dd59 100644 (file)
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Text.Encodings.Web;
 using System.Text.Json;
 using System.Text.Json.Nodes;
 using System.Text.Json.Serialization;
@@ -147,6 +148,7 @@ public sealed class RendererPlugin : IDalamudPlugin
     {
         JsonSerializerOptions options = new()
         {
+            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
             DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
             WriteIndented = true,
         };
@@ -161,6 +163,7 @@ public sealed class RendererPlugin : IDalamudPlugin
 
             using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions
             {
+                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
                 Indented = true
             });
             newNode.WriteTo(writer, options);
@@ -234,7 +237,7 @@ public sealed class RendererPlugin : IDalamudPlugin
                                     Enabled = true,
                                     overlayText =
                                         $"{location.Root.Groups.IndexOf(group)} // {node.DataId} / {node.Locations.IndexOf(x)}",
-                                    overlayBGColor = isUnsaved ? 0xFF2020FF : 0,
+                                    overlayBGColor = isUnsaved ? 0xFF2020FF : 0xFF000000,
                                 },
                                 new Element(ElementType.CircleAtFixedCoordinates)
                                 {
diff --git a/GatheringPaths/7.x - Dawntrail/Kozama'uka/946__BTN.json b/GatheringPaths/7.x - Dawntrail/Kozama'uka/946__BTN.json
new file mode 100644 (file)
index 0000000..b97d079
--- /dev/null
@@ -0,0 +1,105 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1188,
+  "AetheryteShortcut": "Kozama'uka - Ok'hanu",
+  "FlyBetweenNodes": true,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34520,
+          "Locations": [
+            {
+              "Position": {
+                "X": 759.8123,
+                "Y": 26.14559,
+                "Z": -561.7435
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34521,
+          "Locations": [
+            {
+              "Position": {
+                "X": 791.0515,
+                "Y": 25.74059,
+                "Z": -545.9295
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34522,
+          "Locations": [
+            {
+              "Position": {
+                "X": 821.4519,
+                "Y": 28.47348,
+                "Z": -533.9607
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34517,
+          "Locations": [
+            {
+              "Position": {
+                "X": 840.8483,
+                "Y": 34.05744,
+                "Z": -586.0533
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34518,
+          "Locations": [
+            {
+              "Position": {
+                "X": 837.7969,
+                "Y": 33.55795,
+                "Z": -619.7623
+              }
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34519,
+          "Locations": [
+            {
+              "Position": {
+                "X": 784.021,
+                "Y": 24.16835,
+                "Z": -598.9781
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/GatheringPaths/7.x - Dawntrail/Urqopacha/961__MIN.json b/GatheringPaths/7.x - Dawntrail/Urqopacha/961__MIN.json
new file mode 100644 (file)
index 0000000..566b0c3
--- /dev/null
@@ -0,0 +1,118 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1187,
+  "AetheryteShortcut": "Urqopacha - Wachunpelo",
+  "FlyBetweenNodes": false,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34646,
+          "Locations": [
+            {
+              "Position": {
+                "X": 227.4615,
+                "Y": -89.93336,
+                "Z": -225.4792
+              },
+              "MinimumAngle": 150,
+              "MaximumAngle": 250
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34641,
+          "Locations": [
+            {
+              "Position": {
+                "X": 249.5856,
+                "Y": -97.79176,
+                "Z": -217.3474
+              },
+              "MinimumAngle": 135,
+              "MaximumAngle": 215
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34642,
+          "Locations": [
+            {
+              "Position": {
+                "X": 257.8141,
+                "Y": -99.51778,
+                "Z": -217.7757
+              },
+              "MinimumAngle": 130,
+              "MaximumAngle": 240
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34643,
+          "Fly": true,
+          "Locations": [
+            {
+              "Position": {
+                "X": 274.7205,
+                "Y": -99.65348,
+                "Z": -201.6824
+              },
+              "MinimumAngle": 220,
+              "MaximumAngle": 270
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34644,
+          "Locations": [
+            {
+              "Position": {
+                "X": 278.0735,
+                "Y": -101.2599,
+                "Z": -194.8121
+              },
+              "MinimumAngle": 200,
+              "MaximumAngle": 300
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34645,
+          "Locations": [
+            {
+              "Position": {
+                "X": 308.4911,
+                "Y": -100.6525,
+                "Z": -174.6859
+              },
+              "MinimumAngle": 145,
+              "MaximumAngle": 210
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/GatheringPaths/7.x - Dawntrail/Yak T'el/955__BTN.json b/GatheringPaths/7.x - Dawntrail/Yak T'el/955__BTN.json
new file mode 100644 (file)
index 0000000..68779da
--- /dev/null
@@ -0,0 +1,117 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
+  "Author": "liza",
+  "TerritoryId": 1189,
+  "AetheryteShortcut": "Yak T'el - Iq Br'aax",
+  "FlyBetweenNodes": true,
+  "Groups": [
+    {
+      "Nodes": [
+        {
+          "DataId": 34601,
+          "Locations": [
+            {
+              "Position": {
+                "X": 484.1779,
+                "Y": 16.59889,
+                "Z": -304.2079
+              },
+              "MinimumAngle": -185,
+              "MaximumAngle": 20
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34599,
+          "Locations": [
+            {
+              "Position": {
+                "X": 509.181,
+                "Y": 21.64949,
+                "Z": -349.9709
+              },
+              "MinimumAngle": -25,
+              "MaximumAngle": 80
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34597,
+          "Locations": [
+            {
+              "Position": {
+                "X": 534.7657,
+                "Y": 19.33411,
+                "Z": -333.3713
+              },
+              "MinimumAngle": 155,
+              "MaximumAngle": 275
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34600,
+          "Locations": [
+            {
+              "Position": {
+                "X": 525.0291,
+                "Y": 11.97125,
+                "Z": -252.6589
+              },
+              "MinimumAngle": 145,
+              "MaximumAngle": 265
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34598,
+          "Locations": [
+            {
+              "Position": {
+                "X": 518.5205,
+                "Y": 9.694121,
+                "Z": -223.9382
+              },
+              "MinimumAngle": 65,
+              "MaximumAngle": 170
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "Nodes": [
+        {
+          "DataId": 34602,
+          "Locations": [
+            {
+              "Position": {
+                "X": 480.2552,
+                "Y": 10.94543,
+                "Z": -234.4949
+              },
+              "MinimumAngle": 95,
+              "MaximumAngle": 180
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
index 3cafe531295f995cd67910b6ca666b59d9d138d8..27cfb7e2de396953c16e83fadc91e8c0399c0d6a 100644 (file)
@@ -2,6 +2,7 @@
   "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
   "Author": "liza",
   "TerritoryId": 1189,
+  "AetheryteShortcut": "Yak T'el - Mamook",
   "Groups": [
     {
       "Nodes": [
       ]
     }
   ]
-}
\ No newline at end of file
+}
index baac742c5dfb5b988960b16196d1e586942e8e7c..ffb288ab5f656ffccdf1bc7b629d47e9286e8af7 100644 (file)
         "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard"
       }
     },
+    "FlyBetweenNodes": {
+      "description": "If nodes are close enough together, flying makes no sense due to the pathfinding overhead",
+      "type": "boolean",
+      "default": true
+    },
     "Groups": {
       "type": "array",
       "items": {
@@ -49,6 +54,9 @@
                   "minimum": 30000,
                   "maximum": 50000
                 },
+                "Fly": {
+                  "type": "boolean"
+                },
                 "Locations": {
                   "type": "array",
                   "items": {
index 589aabb2412acfb4334f478e9cd8bb2c5858f8f9..6ba6efbb1cbb516343782f3678d165ccc5b8d176 100644 (file)
@@ -143,6 +143,7 @@ public class GatheringSourceGenerator : ISourceGenerator
     {
         try
         {
+            var emptyRoot = new GatheringRoot();
             return ObjectCreationExpression(
                     IdentifierName(nameof(GatheringRoot)))
                 .WithInitializer(
@@ -151,10 +152,17 @@ public class GatheringSourceGenerator : ISourceGenerator
                         SeparatedList<ExpressionSyntax>(
                             SyntaxNodeList(
                                 AssignmentList(nameof(GatheringRoot.Author), root.Author).AsSyntaxNodeOrToken(),
-                                Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, default)
+                                Assignment(nameof(GatheringRoot.TerritoryId), root.TerritoryId, emptyRoot.TerritoryId)
+                                    .AsSyntaxNodeOrToken(),
+                                Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut,
+                                        emptyRoot.AetheryteShortcut)
+                                    .AsSyntaxNodeOrToken(),
+                                Assignment(nameof(GatheringRoot.AethernetShortcut), root.AethernetShortcut,
+                                        emptyRoot.AethernetShortcut)
+                                    .AsSyntaxNodeOrToken(),
+                                Assignment(nameof(GatheringRoot.FlyBetweenNodes), root.FlyBetweenNodes,
+                                        emptyRoot.FlyBetweenNodes)
                                     .AsSyntaxNodeOrToken(),
-                                Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut, null),
-                                Assignment(nameof(GatheringRoot.AethernetShortcut), root.AethernetShortcut, null),
                                 AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken()))));
         }
         catch (Exception e)
index 21b4a8206afb0b23426d54a29969e8d42c1f305a..d8ff117d14eda453bd1d50b5492349ae8e95038c 100644 (file)
@@ -408,6 +408,8 @@ public static class RoslynShortcuts
                                     Assignment(nameof(GatheringNode.DataId), nodeLocation.DataId,
                                             emptyLocation.DataId)
                                         .AsSyntaxNodeOrToken(),
+                                    Assignment(nameof(GatheringNode.Fly), nodeLocation.Fly, emptyLocation.Fly)
+                                        .AsSyntaxNodeOrToken(),
                                     AssignmentList(nameof(GatheringNode.Locations), nodeLocation.Locations)
                                         .AsSyntaxNodeOrToken()))));
             }
diff --git a/QuestPaths/7.x - Dawntrail/Leves/BTN/L1770_All Stars.json b/QuestPaths/7.x - Dawntrail/Leves/BTN/L1770_All Stars.json
new file mode 100644 (file)
index 0000000..293ab4d
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 1,
+      "Steps": [
+        {
+          "Position": {
+            "X": 767.05066,
+            "Y": 24.645323,
+            "Z": -561.67883
+          },
+          "TerritoryId": 1188,
+          "InteractionType": "InitiateLeve",
+          "AetheryteShortcut": "Kozama'uka - Ok'hanu",
+          "Fly": true,
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        },
+        {
+          "TerritoryId": 1188,
+          "InteractionType": "None",
+          "RequiredGatheredItems": [
+            {
+              "ItemId": 2003516,
+              "AlternativeItemId": 2003517,
+              "ItemCount": 999
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/7.x - Dawntrail/Leves/BTN/L1779_New Start for the Cinderfield.json b/QuestPaths/7.x - Dawntrail/Leves/BTN/L1779_New Start for the Cinderfield.json
new file mode 100644 (file)
index 0000000..d7abd60
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 1,
+      "Steps": [
+        {
+          "Position": {
+            "X": 518.05945,
+            "Y": 19.47163,
+            "Z": -335.71478
+          },
+          "TerritoryId": 1189,
+          "InteractionType": "InitiateLeve",
+          "AetheryteShortcut": "Yak T'el - Iq Br'aax",
+          "Fly": true,
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        },
+        {
+          "TerritoryId": 1189,
+          "InteractionType": "None",
+          "RequiredGatheredItems": [
+            {
+              "ItemId": 2003529,
+              "AlternativeItemId": 2003530,
+              "ItemCount": 999
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/7.x - Dawntrail/Leves/MIN/L1785_Old and Bubbly.json b/QuestPaths/7.x - Dawntrail/Leves/MIN/L1785_Old and Bubbly.json
new file mode 100644 (file)
index 0000000..e5f1f29
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 1,
+      "Steps": [
+        {
+          "Position": {
+            "X": 228.24704,
+            "Y": -91.93331,
+            "Z": -229.72751
+          },
+          "TerritoryId": 1187,
+          "InteractionType": "InitiateLeve",
+          "AetheryteShortcut": "Urqopacha - Wachunpelo",
+          "Fly": true,
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        },
+        {
+          "TerritoryId": 1187,
+          "InteractionType": "None",
+          "RequiredGatheredItems": [
+            {
+              "ItemId": 2003539,
+              "AlternativeItemId": 2003540,
+              "ItemCount": 999
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
index ecbe236ab70627cb9853424fb42b91d33511fdd1..75e19368ba644505fd18430d5b09be0f411fd981 100644 (file)
@@ -30,8 +30,7 @@
               "AlternativeItemId": 2003553,
               "ItemCount": 999
             }
-          ],
-          "$.0": "41635 → 970"
+          ]
         }
       ]
     }
index a88f53ebd5bd051ef3d2800321688bd2fd13a0b8..9a3ed58cb3f8677840199c76e7fc5c1dc4528721 100644 (file)
@@ -5,6 +5,7 @@ namespace Questionable.Model.Gathering;
 public sealed class GatheringNode
 {
     public uint DataId { get; set; }
+    public bool Fly { get; set; }
 
     public List<GatheringLocation> Locations { get; set; } = [];
 }
index 9011f5625c887db4c8ffe653352b37a09581ea51..b1f98ca853b39498c1c9d7e6666354880c1f5c7d 100644 (file)
@@ -16,5 +16,6 @@ public sealed class GatheringRoot
     public EAetheryteLocation? AetheryteShortcut { get; set; }
 
     public AethernetShortcut? AethernetShortcut { get; set; }
+    public bool FlyBetweenNodes { get; set; } = true;
     public List<GatheringNodeGroup> Groups { get; set; } = [];
 }
index b52458caf93f76c128d81f365e4a7d963f93ebad..4ad648154b0fbd556116b78c60d33dd822926e3d 100644 (file)
@@ -36,4 +36,7 @@ public enum EInteractionType
     AcceptLeve,
     InitiateLeve,
     CompleteLeve,
+
+    // unmapped extra types below
+    InternalGather,
 }
index 3a518a1b687b0bb16082be3bd32569665952a830..4b366c7dc98e47a1e9e58e92c187bbca279dafcf 100644 (file)
@@ -846,22 +846,41 @@ internal sealed class GameUiController : IDisposable
                 _logger.LogInformation("Leve {Index} = {Id}, {Name}", i, questInfo.QuestId, questInfo.Name);
             */
 
-            _framework.RunOnTick(() =>
-            {
-                _questController.SetPendingQuest(nextQuest);
-                _questController.SetNextQuest(null);
+            _framework.RunOnTick(() => AcceptLeveOrWait(nextQuest), TimeSpan.FromMilliseconds(100));
+        }
+    }
 
-                var agent = UIModule.Instance()->GetAgentModule()->GetAgentByInternalId(AgentId.LeveQuest);
-                var returnValue = stackalloc AtkValue[1];
-                var selectQuest = stackalloc AtkValue[]
-                {
-                    new() { Type = ValueType.Int, Int = 3 },
-                    new() { Type = ValueType.UInt, UInt = nextQuest.Quest.Id.Value }
-                };
-                agent->ReceiveEvent(returnValue, selectQuest, 2, 0);
-                addon->Close(true);
-            }, TimeSpan.FromMilliseconds(100));
+    private unsafe void AcceptLeveOrWait(QuestController.QuestProgress nextQuest, int counter = 0)
+    {
+        var agent = UIModule.Instance()->GetAgentModule()->GetAgentByInternalId(AgentId.LeveQuest);
+        if (agent->IsAgentActive() &&
+            _gameGui.TryGetAddonByName("GuildLeve", out AddonGuildLeve* addonGuildLeve) &&
+            LAddon.IsAddonReady(&addonGuildLeve->AtkUnitBase) &&
+            _gameGui.TryGetAddonByName("JournalDetail", out AtkUnitBase* addonJournalDetail) &&
+            LAddon.IsAddonReady(addonJournalDetail))
+        {
+            AcceptLeve(agent, addonGuildLeve, nextQuest);
         }
+        else if (counter >= 10)
+            _logger.LogWarning("Unable to accept leve?");
+        else
+            _framework.RunOnTick(() => AcceptLeveOrWait(nextQuest, counter + 1), TimeSpan.FromMilliseconds(100));
+    }
+
+    private unsafe void AcceptLeve(AgentInterface* agent, AddonGuildLeve* addon,
+        QuestController.QuestProgress nextQuest)
+    {
+        _questController.SetPendingQuest(nextQuest);
+        _questController.SetNextQuest(null);
+
+        var returnValue = stackalloc AtkValue[1];
+        var selectQuest = stackalloc AtkValue[]
+        {
+            new() { Type = ValueType.Int, Int = 3 },
+            new() { Type = ValueType.UInt, UInt = nextQuest.Quest.Id.Value }
+        };
+        agent->ReceiveEvent(returnValue, selectQuest, 2, 0);
+        addon->Close(true);
     }
 
     private StringOrRegex? ResolveReference(Quest? quest, string? excelSheet, ExcelRef? excelRef, bool isRegExp)
index 446c38c2188ddbfc83b0f708a0c63f4183c4e898..53878e531f01ccb369c84701db623230122fc9d8 100644 (file)
@@ -144,7 +144,8 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
                 Y = currentNode.Locations.Select(x => x.Position.Y).Max() + 5f,
                 Z = currentNode.Locations.Sum(x => x.Position.Z) / currentNode.Locations.Count,
             };
-            bool fly = _gameFunctions.IsFlyingUnlocked(_currentRequest.Root.TerritoryId);
+            bool fly = (currentNode.Fly || _currentRequest.Root.FlyBetweenNodes)
+                       && _gameFunctions.IsFlyingUnlocked(_currentRequest.Root.TerritoryId);
             Vector3? pointOnFloor = _navmeshIpc.GetPointOnFloor(averagePosition, true);
             if (pointOnFloor != null)
                 pointOnFloor = pointOnFloor.Value with { Y = pointOnFloor.Value.Y + (fly ? 3f : 0f) };
@@ -155,9 +156,11 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
         }
 
         _taskQueue.Enqueue(_serviceProvider.GetRequiredService<MoveToLandingLocation>()
-            .With(_currentRequest.Root.TerritoryId, currentNode));
+            .With(_currentRequest.Root.TerritoryId,
+                currentNode.Fly || _currentRequest.Root.FlyBetweenNodes,
+                currentNode));
         _taskQueue.Enqueue(_serviceProvider.GetRequiredService<Interact.DoInteract>()
-            .With(currentNode.DataId, null, EInteractionType.None, true));
+            .With(currentNode.DataId, null, EInteractionType.InternalGather, true));
         _taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGather>()
             .With(_currentRequest.Data, currentNode));
         if (_currentRequest.Data.Collectability > 0)
@@ -197,8 +200,8 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
             int currentIndex = (currentRequest.CurrentIndex + i) % currentRequest.Nodes.Count;
             var currentNode = currentRequest.Nodes[currentIndex];
             var locationsAsObjects = currentNode.Locations.Select(x =>
-                _objectTable.FirstOrDefault(y =>
-                    currentNode.DataId == y.DataId && Vector3.Distance(x.Position, y.Position) < 0.1f))
+                    _objectTable.FirstOrDefault(y =>
+                        currentNode.DataId == y.DataId && Vector3.Distance(x.Position, y.Position) < 0.1f))
                 .ToList();
 
             // Are any of the nodes too far away to be found? This is likely around ~100 yalms. All closer gathering
index ff27374ed2a96392884b1995abf3dce9cd7277cf..84b9c88896e7e8e648021609b921950ef016a780 100644 (file)
@@ -20,12 +20,14 @@ internal sealed class MoveToLandingLocation(
     ILogger<MoveToLandingLocation> logger) : ITask
 {
     private ushort _territoryId;
+    private bool _flyBetweenNodes;
     private GatheringNode _gatheringNode = null!;
     private ITask _moveTask = null!;
 
-    public ITask With(ushort territoryId, GatheringNode gatheringNode)
+    public ITask With(ushort territoryId, bool flyBetweenNodes, GatheringNode gatheringNode)
     {
         _territoryId = territoryId;
+        _flyBetweenNodes = flyBetweenNodes;
         _gatheringNode = gatheringNode;
         return this;
     }
@@ -47,7 +49,7 @@ internal sealed class MoveToLandingLocation(
         logger.LogInformation("Preliminary landing location: {Location}, with degrees = {Degrees}, range = {Range}",
             target.ToString("G", CultureInfo.InvariantCulture), degrees, range);
 
-        bool fly = gameFunctions.IsFlyingUnlocked(_territoryId);
+        bool fly = _flyBetweenNodes && gameFunctions.IsFlyingUnlocked(_territoryId);
         _moveTask = serviceProvider.GetRequiredService<Move.MoveInternal>()
             .With(_territoryId, target, 0.25f, dataId: _gatheringNode.DataId, fly: fly,
                 ignoreDistanceToObject: true);
@@ -56,5 +58,5 @@ internal sealed class MoveToLandingLocation(
 
     public ETaskResult Update() => _moveTask.Update();
 
-    public override string ToString() => $"Land/{_moveTask}";
+    public override string ToString() => $"Land/{_moveTask}/{_flyBetweenNodes}";
 }
index e45a2da753ef1369978e3924fdcb4ff167f32aa2..dc50ac06a060e9c6b6326dc3a725eefb733f09d6 100644 (file)
@@ -116,6 +116,9 @@ internal static class Interact
             if (_interactionState == EInteractionState.InteractionConfirmed)
                 return ETaskResult.TaskComplete;
 
+            if (InteractionType == EInteractionType.InternalGather && condition[ConditionFlag.Gathering])
+                return ETaskResult.TaskComplete;
+
             IGameObject? gameObject = gameFunctions.FindObjectByDataId(DataId);
             if (gameObject == null || !gameObject.IsTargetable || !HasAnyMarker(gameObject))
                 return ETaskResult.StillRunning;
index 1c9ee563ded434d22d5b815bb7ba7d3a62d4e0ad..42cd8a4846ab75360bc48e0c1ee77f0069dc057b 100644 (file)
@@ -2,6 +2,8 @@
 using System.Collections.Generic;
 using Dalamud.Game.ClientState.Conditions;
 using Dalamud.Plugin.Services;
+using FFXIVClientStructs.FFXIV.Client.Game.Event;
+using FFXIVClientStructs.FFXIV.Client.Game.UI;
 using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameUI;
@@ -22,6 +24,7 @@ internal static class InitiateLeve
             if (step.InteractionType != EInteractionType.InitiateLeve)
                 yield break;
 
+            yield return serviceProvider.GetRequiredService<SkipInitiateIfActive>().With(quest.Id);
             yield return serviceProvider.GetRequiredService<OpenJournal>().With(quest.Id);
             yield return serviceProvider.GetRequiredService<Initiate>().With(quest.Id);
             yield return serviceProvider.GetRequiredService<SelectDifficulty>();
@@ -32,6 +35,33 @@ internal static class InitiateLeve
             => throw new NotImplementedException();
     }
 
+    internal sealed unsafe class SkipInitiateIfActive : ITask
+    {
+        private ElementId _elementId = null!;
+
+        public ITask With(ElementId elementId)
+        {
+            _elementId = elementId;
+            return this;
+        }
+
+        public bool Start() => true;
+
+        public ETaskResult Update()
+        {
+            var director = UIState.Instance()->DirectorTodo.Director;
+            if (director != null &&
+                director->EventHandlerInfo != null &&
+                director->EventHandlerInfo->EventId.ContentId == EventHandlerType.GatheringLeveDirector &&
+                director->ContentId == _elementId.Value)
+                return ETaskResult.SkipRemainingTasksForStep;
+
+            return ETaskResult.TaskComplete;
+        }
+
+        public override string ToString() => $"CheckIfAlreadyActive({_elementId})";
+    }
+
     internal sealed unsafe class OpenJournal : ITask
     {
         private ElementId _elementId = null!;
index a8e5bfe96eb6feea36b527350daf990490b10466..4b3b635d19e5aef526a2acf6a6c2beb923f9ea55 100644 (file)
@@ -158,7 +158,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin
             .AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready,
                 SinglePlayerDuty.RestoreYesAlready>();
         serviceCollection
-            .AddTaskWithFactory<InitiateLeve.Factory, InitiateLeve.OpenJournal, InitiateLeve.Initiate,
+            .AddTaskWithFactory<InitiateLeve.Factory,
+                InitiateLeve.SkipInitiateIfActive,
+                InitiateLeve.OpenJournal,
+                InitiateLeve.Initiate,
                 InitiateLeve.SelectDifficulty>();
 
         serviceCollection
index 61bb05633c8122697a451ab77bf19c4163c26b48..52bcd65926adf3f8ffcf529400f42157f4b287e0 100644 (file)
@@ -119,10 +119,10 @@ internal sealed class CreationUtilsComponent
             ImGui.Text($"Ico: {director->IconId}");
             if (director->EventHandlerInfo != null)
             {
-                ImGui.Text($"  EHI: {director->EventHandlerInfo->EventId.ContentId}");
-                ImGui.Text($"  EHI: {director->EventHandlerInfo->EventId.Id}");
-                ImGui.Text($"  EHI: {director->EventHandlerInfo->EventId.EntryId}");
-                ImGui.Text($"  EHI: {director->EventHandlerInfo->Flags}");
+                ImGui.Text($"  EHI CI: {director->EventHandlerInfo->EventId.ContentId}");
+                ImGui.Text($"  EHI EI: {director->EventHandlerInfo->EventId.Id}");
+                ImGui.Text($"  EHI EEI: {director->EventHandlerInfo->EventId.EntryId}");
+                ImGui.Text($"  EHI F: {director->EventHandlerInfo->Flags}");
             }
         }
 #endif