Add some 90/96 MIN/BTN leves

sb-p2
Liza 2024-08-11 18:59:42 +02:00
parent 79d65b3350
commit 69944db8d1
Signed by: liza
GPG Key ID: 7199F8D727D55F67
23 changed files with 576 additions and 36 deletions

View File

@ -1,5 +1,5 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>2.5</Version> <Version>2.6</Version>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -147,6 +148,7 @@ public sealed class RendererPlugin : IDalamudPlugin
{ {
JsonSerializerOptions options = new() JsonSerializerOptions options = new()
{ {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true, WriteIndented = true,
}; };
@ -161,6 +163,7 @@ public sealed class RendererPlugin : IDalamudPlugin
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions
{ {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
Indented = true Indented = true
}); });
newNode.WriteTo(writer, options); newNode.WriteTo(writer, options);
@ -234,7 +237,7 @@ public sealed class RendererPlugin : IDalamudPlugin
Enabled = true, Enabled = true,
overlayText = overlayText =
$"{location.Root.Groups.IndexOf(group)} // {node.DataId} / {node.Locations.IndexOf(x)}", $"{location.Root.Groups.IndexOf(group)} // {node.DataId} / {node.Locations.IndexOf(x)}",
overlayBGColor = isUnsaved ? 0xFF2020FF : 0, overlayBGColor = isUnsaved ? 0xFF2020FF : 0xFF000000,
}, },
new Element(ElementType.CircleAtFixedCoordinates) new Element(ElementType.CircleAtFixedCoordinates)
{ {

View File

@ -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
}
}
]
}
]
}
]
}

View File

@ -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
}
]
}
]
}
]
}

View File

@ -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
}
]
}
]
}
]
}

View File

@ -2,6 +2,7 @@
"$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json", "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json",
"Author": "liza", "Author": "liza",
"TerritoryId": 1189, "TerritoryId": 1189,
"AetheryteShortcut": "Yak T'el - Mamook",
"Groups": [ "Groups": [
{ {
"Nodes": [ "Nodes": [
@ -112,4 +113,4 @@
] ]
} }
] ]
} }

View File

@ -34,6 +34,11 @@
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/AethernetShard" "$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": { "Groups": {
"type": "array", "type": "array",
"items": { "items": {
@ -49,6 +54,9 @@
"minimum": 30000, "minimum": 30000,
"maximum": 50000 "maximum": 50000
}, },
"Fly": {
"type": "boolean"
},
"Locations": { "Locations": {
"type": "array", "type": "array",
"items": { "items": {

View File

@ -143,6 +143,7 @@ public class GatheringSourceGenerator : ISourceGenerator
{ {
try try
{ {
var emptyRoot = new GatheringRoot();
return ObjectCreationExpression( return ObjectCreationExpression(
IdentifierName(nameof(GatheringRoot))) IdentifierName(nameof(GatheringRoot)))
.WithInitializer( .WithInitializer(
@ -151,10 +152,17 @@ public class GatheringSourceGenerator : ISourceGenerator
SeparatedList<ExpressionSyntax>( SeparatedList<ExpressionSyntax>(
SyntaxNodeList( SyntaxNodeList(
AssignmentList(nameof(GatheringRoot.Author), root.Author).AsSyntaxNodeOrToken(), 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(), .AsSyntaxNodeOrToken(),
Assignment(nameof(GatheringRoot.AetheryteShortcut), root.AetheryteShortcut, null),
Assignment(nameof(GatheringRoot.AethernetShortcut), root.AethernetShortcut, null),
AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken())))); AssignmentList(nameof(GatheringRoot.Groups), root.Groups).AsSyntaxNodeOrToken()))));
} }
catch (Exception e) catch (Exception e)

View File

@ -408,6 +408,8 @@ public static class RoslynShortcuts
Assignment(nameof(GatheringNode.DataId), nodeLocation.DataId, Assignment(nameof(GatheringNode.DataId), nodeLocation.DataId,
emptyLocation.DataId) emptyLocation.DataId)
.AsSyntaxNodeOrToken(), .AsSyntaxNodeOrToken(),
Assignment(nameof(GatheringNode.Fly), nodeLocation.Fly, emptyLocation.Fly)
.AsSyntaxNodeOrToken(),
AssignmentList(nameof(GatheringNode.Locations), nodeLocation.Locations) AssignmentList(nameof(GatheringNode.Locations), nodeLocation.Locations)
.AsSyntaxNodeOrToken())))); .AsSyntaxNodeOrToken()))));
} }

View File

@ -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
}
]
}
]
}
]
}

View File

@ -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
}
]
}
]
}
]
}

View File

@ -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
}
]
}
]
}
]
}

View File

@ -30,8 +30,7 @@
"AlternativeItemId": 2003553, "AlternativeItemId": 2003553,
"ItemCount": 999 "ItemCount": 999
} }
], ]
"$.0": "41635 → 970"
} }
] ]
} }

View File

@ -5,6 +5,7 @@ namespace Questionable.Model.Gathering;
public sealed class GatheringNode public sealed class GatheringNode
{ {
public uint DataId { get; set; } public uint DataId { get; set; }
public bool Fly { get; set; }
public List<GatheringLocation> Locations { get; set; } = []; public List<GatheringLocation> Locations { get; set; } = [];
} }

View File

@ -16,5 +16,6 @@ public sealed class GatheringRoot
public EAetheryteLocation? AetheryteShortcut { get; set; } public EAetheryteLocation? AetheryteShortcut { get; set; }
public AethernetShortcut? AethernetShortcut { get; set; } public AethernetShortcut? AethernetShortcut { get; set; }
public bool FlyBetweenNodes { get; set; } = true;
public List<GatheringNodeGroup> Groups { get; set; } = []; public List<GatheringNodeGroup> Groups { get; set; } = [];
} }

View File

@ -36,4 +36,7 @@ public enum EInteractionType
AcceptLeve, AcceptLeve,
InitiateLeve, InitiateLeve,
CompleteLeve, CompleteLeve,
// unmapped extra types below
InternalGather,
} }

View File

@ -846,24 +846,43 @@ internal sealed class GameUiController : IDisposable
_logger.LogInformation("Leve {Index} = {Id}, {Name}", i, questInfo.QuestId, questInfo.Name); _logger.LogInformation("Leve {Index} = {Id}, {Name}", i, questInfo.QuestId, questInfo.Name);
*/ */
_framework.RunOnTick(() => _framework.RunOnTick(() => AcceptLeveOrWait(nextQuest), TimeSpan.FromMilliseconds(100));
{
_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));
} }
} }
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) private StringOrRegex? ResolveReference(Quest? quest, string? excelSheet, ExcelRef? excelRef, bool isRegExp)
{ {
if (excelRef == null) if (excelRef == null)

View File

@ -144,7 +144,8 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
Y = currentNode.Locations.Select(x => x.Position.Y).Max() + 5f, Y = currentNode.Locations.Select(x => x.Position.Y).Max() + 5f,
Z = currentNode.Locations.Sum(x => x.Position.Z) / currentNode.Locations.Count, 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); Vector3? pointOnFloor = _navmeshIpc.GetPointOnFloor(averagePosition, true);
if (pointOnFloor != null) if (pointOnFloor != null)
pointOnFloor = pointOnFloor.Value with { Y = pointOnFloor.Value.Y + (fly ? 3f : 0f) }; 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>() _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>() _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>() _taskQueue.Enqueue(_serviceProvider.GetRequiredService<DoGather>()
.With(_currentRequest.Data, currentNode)); .With(_currentRequest.Data, currentNode));
if (_currentRequest.Data.Collectability > 0) if (_currentRequest.Data.Collectability > 0)
@ -197,8 +200,8 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
int currentIndex = (currentRequest.CurrentIndex + i) % currentRequest.Nodes.Count; int currentIndex = (currentRequest.CurrentIndex + i) % currentRequest.Nodes.Count;
var currentNode = currentRequest.Nodes[currentIndex]; var currentNode = currentRequest.Nodes[currentIndex];
var locationsAsObjects = currentNode.Locations.Select(x => var locationsAsObjects = currentNode.Locations.Select(x =>
_objectTable.FirstOrDefault(y => _objectTable.FirstOrDefault(y =>
currentNode.DataId == y.DataId && Vector3.Distance(x.Position, y.Position) < 0.1f)) currentNode.DataId == y.DataId && Vector3.Distance(x.Position, y.Position) < 0.1f))
.ToList(); .ToList();
// Are any of the nodes too far away to be found? This is likely around ~100 yalms. All closer gathering // Are any of the nodes too far away to be found? This is likely around ~100 yalms. All closer gathering

View File

@ -20,12 +20,14 @@ internal sealed class MoveToLandingLocation(
ILogger<MoveToLandingLocation> logger) : ITask ILogger<MoveToLandingLocation> logger) : ITask
{ {
private ushort _territoryId; private ushort _territoryId;
private bool _flyBetweenNodes;
private GatheringNode _gatheringNode = null!; private GatheringNode _gatheringNode = null!;
private ITask _moveTask = null!; private ITask _moveTask = null!;
public ITask With(ushort territoryId, GatheringNode gatheringNode) public ITask With(ushort territoryId, bool flyBetweenNodes, GatheringNode gatheringNode)
{ {
_territoryId = territoryId; _territoryId = territoryId;
_flyBetweenNodes = flyBetweenNodes;
_gatheringNode = gatheringNode; _gatheringNode = gatheringNode;
return this; return this;
} }
@ -47,7 +49,7 @@ internal sealed class MoveToLandingLocation(
logger.LogInformation("Preliminary landing location: {Location}, with degrees = {Degrees}, range = {Range}", logger.LogInformation("Preliminary landing location: {Location}, with degrees = {Degrees}, range = {Range}",
target.ToString("G", CultureInfo.InvariantCulture), degrees, range); target.ToString("G", CultureInfo.InvariantCulture), degrees, range);
bool fly = gameFunctions.IsFlyingUnlocked(_territoryId); bool fly = _flyBetweenNodes && gameFunctions.IsFlyingUnlocked(_territoryId);
_moveTask = serviceProvider.GetRequiredService<Move.MoveInternal>() _moveTask = serviceProvider.GetRequiredService<Move.MoveInternal>()
.With(_territoryId, target, 0.25f, dataId: _gatheringNode.DataId, fly: fly, .With(_territoryId, target, 0.25f, dataId: _gatheringNode.DataId, fly: fly,
ignoreDistanceToObject: true); ignoreDistanceToObject: true);
@ -56,5 +58,5 @@ internal sealed class MoveToLandingLocation(
public ETaskResult Update() => _moveTask.Update(); public ETaskResult Update() => _moveTask.Update();
public override string ToString() => $"Land/{_moveTask}"; public override string ToString() => $"Land/{_moveTask}/{_flyBetweenNodes}";
} }

View File

@ -116,6 +116,9 @@ internal static class Interact
if (_interactionState == EInteractionState.InteractionConfirmed) if (_interactionState == EInteractionState.InteractionConfirmed)
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
if (InteractionType == EInteractionType.InternalGather && condition[ConditionFlag.Gathering])
return ETaskResult.TaskComplete;
IGameObject? gameObject = gameFunctions.FindObjectByDataId(DataId); IGameObject? gameObject = gameFunctions.FindObjectByDataId(DataId);
if (gameObject == null || !gameObject.IsTargetable || !HasAnyMarker(gameObject)) if (gameObject == null || !gameObject.IsTargetable || !HasAnyMarker(gameObject))
return ETaskResult.StillRunning; return ETaskResult.StillRunning;

View File

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services; 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.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using LLib.GameUI; using LLib.GameUI;
@ -22,6 +24,7 @@ internal static class InitiateLeve
if (step.InteractionType != EInteractionType.InitiateLeve) if (step.InteractionType != EInteractionType.InitiateLeve)
yield break; yield break;
yield return serviceProvider.GetRequiredService<SkipInitiateIfActive>().With(quest.Id);
yield return serviceProvider.GetRequiredService<OpenJournal>().With(quest.Id); yield return serviceProvider.GetRequiredService<OpenJournal>().With(quest.Id);
yield return serviceProvider.GetRequiredService<Initiate>().With(quest.Id); yield return serviceProvider.GetRequiredService<Initiate>().With(quest.Id);
yield return serviceProvider.GetRequiredService<SelectDifficulty>(); yield return serviceProvider.GetRequiredService<SelectDifficulty>();
@ -32,6 +35,33 @@ internal static class InitiateLeve
=> throw new NotImplementedException(); => 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 internal sealed unsafe class OpenJournal : ITask
{ {
private ElementId _elementId = null!; private ElementId _elementId = null!;

View File

@ -158,7 +158,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin
.AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready, .AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready,
SinglePlayerDuty.RestoreYesAlready>(); SinglePlayerDuty.RestoreYesAlready>();
serviceCollection serviceCollection
.AddTaskWithFactory<InitiateLeve.Factory, InitiateLeve.OpenJournal, InitiateLeve.Initiate, .AddTaskWithFactory<InitiateLeve.Factory,
InitiateLeve.SkipInitiateIfActive,
InitiateLeve.OpenJournal,
InitiateLeve.Initiate,
InitiateLeve.SelectDifficulty>(); InitiateLeve.SelectDifficulty>();
serviceCollection serviceCollection

View File

@ -119,10 +119,10 @@ internal sealed class CreationUtilsComponent
ImGui.Text($"Ico: {director->IconId}"); ImGui.Text($"Ico: {director->IconId}");
if (director->EventHandlerInfo != null) if (director->EventHandlerInfo != null)
{ {
ImGui.Text($" EHI: {director->EventHandlerInfo->EventId.ContentId}"); ImGui.Text($" EHI CI: {director->EventHandlerInfo->EventId.ContentId}");
ImGui.Text($" EHI: {director->EventHandlerInfo->EventId.Id}"); ImGui.Text($" EHI EI: {director->EventHandlerInfo->EventId.Id}");
ImGui.Text($" EHI: {director->EventHandlerInfo->EventId.EntryId}"); ImGui.Text($" EHI EEI: {director->EventHandlerInfo->EventId.EntryId}");
ImGui.Text($" EHI: {director->EventHandlerInfo->Flags}"); ImGui.Text($" EHI F: {director->EventHandlerInfo->Flags}");
} }
} }
#endif #endif