From 69944db8d1b2b476bc29ec6210df426d2474c6e1 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Sun, 11 Aug 2024 18:59:42 +0200 Subject: [PATCH] Add some 90/96 MIN/BTN leves --- Directory.Build.targets | 2 +- GatheringPathRenderer/RendererPlugin.cs | 5 +- .../7.x - Dawntrail/Kozama'uka/946__BTN.json | 105 ++++++++++++++++ .../7.x - Dawntrail/Urqopacha/961__MIN.json | 118 ++++++++++++++++++ .../7.x - Dawntrail/Yak T'el/955__BTN.json | 117 +++++++++++++++++ .../7.x - Dawntrail/Yak T'el/970__MIN.json | 3 +- GatheringPaths/gatheringlocation-v1.json | 8 ++ .../GatheringSourceGenerator.cs | 14 ++- QuestPathGenerator/RoslynShortcuts.cs | 2 + .../Leves/BTN/L1770_All Stars.json | 38 ++++++ .../L1779_New Start for the Cinderfield.json | 38 ++++++ .../Leves/MIN/L1785_Old and Bubbly.json | 38 ++++++ .../Leves/MIN/L1794_Vestiges of War.json | 3 +- Questionable.Model/Gathering/GatheringNode.cs | 1 + Questionable.Model/Gathering/GatheringRoot.cs | 1 + .../Questing/EInteractionType.cs | 3 + Questionable/Controller/GameUiController.cs | 49 +++++--- .../Controller/GatheringController.cs | 13 +- .../Steps/Gathering/MoveToLandingLocation.cs | 8 +- .../Controller/Steps/Interactions/Interact.cs | 3 + .../Controller/Steps/Leves/InitiateLeve.cs | 30 +++++ Questionable/QuestionablePlugin.cs | 5 +- .../QuestComponents/CreationUtilsComponent.cs | 8 +- 23 files changed, 576 insertions(+), 36 deletions(-) create mode 100644 GatheringPaths/7.x - Dawntrail/Kozama'uka/946__BTN.json create mode 100644 GatheringPaths/7.x - Dawntrail/Urqopacha/961__MIN.json create mode 100644 GatheringPaths/7.x - Dawntrail/Yak T'el/955__BTN.json create mode 100644 QuestPaths/7.x - Dawntrail/Leves/BTN/L1770_All Stars.json create mode 100644 QuestPaths/7.x - Dawntrail/Leves/BTN/L1779_New Start for the Cinderfield.json create mode 100644 QuestPaths/7.x - Dawntrail/Leves/MIN/L1785_Old and Bubbly.json diff --git a/Directory.Build.targets b/Directory.Build.targets index 8d0cd323..b914cd1e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,5 @@ - 2.5 + 2.6 diff --git a/GatheringPathRenderer/RendererPlugin.cs b/GatheringPathRenderer/RendererPlugin.cs index 55dee984..636100ad 100644 --- a/GatheringPathRenderer/RendererPlugin.cs +++ b/GatheringPathRenderer/RendererPlugin.cs @@ -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 index 00000000..b97d0790 --- /dev/null +++ b/GatheringPaths/7.x - Dawntrail/Kozama'uka/946__BTN.json @@ -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 index 00000000..566b0c30 --- /dev/null +++ b/GatheringPaths/7.x - Dawntrail/Urqopacha/961__MIN.json @@ -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 index 00000000..68779daa --- /dev/null +++ b/GatheringPaths/7.x - Dawntrail/Yak T'el/955__BTN.json @@ -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 + } + ] + } + ] + } + ] +} diff --git a/GatheringPaths/7.x - Dawntrail/Yak T'el/970__MIN.json b/GatheringPaths/7.x - Dawntrail/Yak T'el/970__MIN.json index 3cafe531..27cfb7e2 100644 --- a/GatheringPaths/7.x - Dawntrail/Yak T'el/970__MIN.json +++ b/GatheringPaths/7.x - Dawntrail/Yak T'el/970__MIN.json @@ -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": [ @@ -112,4 +113,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/GatheringPaths/gatheringlocation-v1.json b/GatheringPaths/gatheringlocation-v1.json index baac742c..ffb288ab 100644 --- a/GatheringPaths/gatheringlocation-v1.json +++ b/GatheringPaths/gatheringlocation-v1.json @@ -34,6 +34,11 @@ "$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": { diff --git a/QuestPathGenerator/GatheringSourceGenerator.cs b/QuestPathGenerator/GatheringSourceGenerator.cs index 589aabb2..6ba6efbb 100644 --- a/QuestPathGenerator/GatheringSourceGenerator.cs +++ b/QuestPathGenerator/GatheringSourceGenerator.cs @@ -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( 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) diff --git a/QuestPathGenerator/RoslynShortcuts.cs b/QuestPathGenerator/RoslynShortcuts.cs index 21b4a820..d8ff117d 100644 --- a/QuestPathGenerator/RoslynShortcuts.cs +++ b/QuestPathGenerator/RoslynShortcuts.cs @@ -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 index 00000000..293ab4d6 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Leves/BTN/L1770_All Stars.json @@ -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 index 00000000..d7abd609 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Leves/BTN/L1779_New Start for the Cinderfield.json @@ -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 index 00000000..e5f1f299 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Leves/MIN/L1785_Old and Bubbly.json @@ -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 + } + ] + } + ] + } + ] +} diff --git a/QuestPaths/7.x - Dawntrail/Leves/MIN/L1794_Vestiges of War.json b/QuestPaths/7.x - Dawntrail/Leves/MIN/L1794_Vestiges of War.json index ecbe236a..75e19368 100644 --- a/QuestPaths/7.x - Dawntrail/Leves/MIN/L1794_Vestiges of War.json +++ b/QuestPaths/7.x - Dawntrail/Leves/MIN/L1794_Vestiges of War.json @@ -30,8 +30,7 @@ "AlternativeItemId": 2003553, "ItemCount": 999 } - ], - "$.0": "41635 → 970" + ] } ] } diff --git a/Questionable.Model/Gathering/GatheringNode.cs b/Questionable.Model/Gathering/GatheringNode.cs index a88f53eb..9a3ed58c 100644 --- a/Questionable.Model/Gathering/GatheringNode.cs +++ b/Questionable.Model/Gathering/GatheringNode.cs @@ -5,6 +5,7 @@ namespace Questionable.Model.Gathering; public sealed class GatheringNode { public uint DataId { get; set; } + public bool Fly { get; set; } public List Locations { get; set; } = []; } diff --git a/Questionable.Model/Gathering/GatheringRoot.cs b/Questionable.Model/Gathering/GatheringRoot.cs index 9011f562..b1f98ca8 100644 --- a/Questionable.Model/Gathering/GatheringRoot.cs +++ b/Questionable.Model/Gathering/GatheringRoot.cs @@ -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 Groups { get; set; } = []; } diff --git a/Questionable.Model/Questing/EInteractionType.cs b/Questionable.Model/Questing/EInteractionType.cs index b52458ca..4ad64815 100644 --- a/Questionable.Model/Questing/EInteractionType.cs +++ b/Questionable.Model/Questing/EInteractionType.cs @@ -36,4 +36,7 @@ public enum EInteractionType AcceptLeve, InitiateLeve, CompleteLeve, + + // unmapped extra types below + InternalGather, } diff --git a/Questionable/Controller/GameUiController.cs b/Questionable/Controller/GameUiController.cs index 3a518a1b..4b366c7d 100644 --- a/Questionable/Controller/GameUiController.cs +++ b/Questionable/Controller/GameUiController.cs @@ -846,24 +846,43 @@ internal sealed class GameUiController : IDisposable _logger.LogInformation("Leve {Index} = {Id}, {Name}", i, questInfo.QuestId, questInfo.Name); */ - _framework.RunOnTick(() => - { - _questController.SetPendingQuest(nextQuest); - _questController.SetNextQuest(null); - - 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)); + _framework.RunOnTick(() => AcceptLeveOrWait(nextQuest), 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) { if (excelRef == null) diff --git a/Questionable/Controller/GatheringController.cs b/Questionable/Controller/GatheringController.cs index 446c38c2..53878e53 100644 --- a/Questionable/Controller/GatheringController.cs +++ b/Questionable/Controller/GatheringController.cs @@ -144,7 +144,8 @@ internal sealed unsafe class GatheringController : MiniTaskController 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() - .With(_currentRequest.Root.TerritoryId, currentNode)); + .With(_currentRequest.Root.TerritoryId, + currentNode.Fly || _currentRequest.Root.FlyBetweenNodes, + currentNode)); _taskQueue.Enqueue(_serviceProvider.GetRequiredService() - .With(currentNode.DataId, null, EInteractionType.None, true)); + .With(currentNode.DataId, null, EInteractionType.InternalGather, true)); _taskQueue.Enqueue(_serviceProvider.GetRequiredService() .With(_currentRequest.Data, currentNode)); if (_currentRequest.Data.Collectability > 0) @@ -197,8 +200,8 @@ internal sealed unsafe class GatheringController : MiniTaskController - _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 diff --git a/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs b/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs index ff27374e..84b9c888 100644 --- a/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs +++ b/Questionable/Controller/Steps/Gathering/MoveToLandingLocation.cs @@ -20,12 +20,14 @@ internal sealed class MoveToLandingLocation( ILogger 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() .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}"; } diff --git a/Questionable/Controller/Steps/Interactions/Interact.cs b/Questionable/Controller/Steps/Interactions/Interact.cs index e45a2da7..dc50ac06 100644 --- a/Questionable/Controller/Steps/Interactions/Interact.cs +++ b/Questionable/Controller/Steps/Interactions/Interact.cs @@ -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; diff --git a/Questionable/Controller/Steps/Leves/InitiateLeve.cs b/Questionable/Controller/Steps/Leves/InitiateLeve.cs index 1c9ee563..42cd8a48 100644 --- a/Questionable/Controller/Steps/Leves/InitiateLeve.cs +++ b/Questionable/Controller/Steps/Leves/InitiateLeve.cs @@ -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().With(quest.Id); yield return serviceProvider.GetRequiredService().With(quest.Id); yield return serviceProvider.GetRequiredService().With(quest.Id); yield return serviceProvider.GetRequiredService(); @@ -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!; diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index a8e5bfe9..4b3b635d 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -158,7 +158,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin .AddTaskWithFactory(); serviceCollection - .AddTaskWithFactory(); serviceCollection diff --git a/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs b/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs index 61bb0563..52bcd659 100644 --- a/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs +++ b/Questionable/Windows/QuestComponents/CreationUtilsComponent.cs @@ -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