skipAetheryteCondition.InSameTerritory, emptyAetheryte.InSameTerritory),
AssignmentList(nameof(SkipAetheryteCondition.InTerritory),
skipAetheryteCondition.InTerritory),
+ AssignmentList(nameof(SkipAetheryteCondition.QuestsAccepted),
+ skipAetheryteCondition.QuestsAccepted),
+ AssignmentList(nameof(skipAetheryteCondition.QuestsCompleted),
+ skipAetheryteCondition.QuestsCompleted),
Assignment(nameof(SkipAetheryteCondition.AetheryteLocked),
skipAetheryteCondition.AetheryteLocked, emptyAetheryte.AetheryteLocked)
.AsSyntaxNodeOrToken(),
"Z": 342.85498
},
"TerritoryId": 1188,
- "InteractionType": "CompleteQuest"
+ "InteractionType": "CompleteQuest",
+ "Mount": true
}
]
}
{
"Sequence": 1,
"Steps": [
+ {
+ "Position": {
+ "X": 323.5058,
+ "Y": -16.330368,
+ "Z": -254.18399
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "WalkTo"
+ },
{
"DataId": 1050656,
"Position": {
"Z": 427.2068
},
"TerritoryId": 1190,
- "InteractionType": "Interact"
+ "InteractionType": "Interact",
+ "Mount": true
}
]
},
{
"Sequence": 3,
"Steps": [
+ {
+ "Position": {
+ "X": 369.3906,
+ "Y": 5.9371996,
+ "Z": 417.16574
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "WalkTo",
+ "$": "Shaaloani Hhusatahwi Saloon Stairs (top)"
+ },
+ {
+ "Position": {
+ "X": 359.11545,
+ "Y": 1.9823306,
+ "Z": 419.5714
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "WalkTo",
+ "$": "Shaaloani Hhusatahwi Saloon Stairs (bottom)",
+ "DisableNavmesh": true
+ },
{
"DataId": 1051286,
"Position": {
{
"Sequence": 255,
"Steps": [
+ {
+ "DataId": 2013948,
+ "Position": {
+ "X": 610.7728,
+ "Y": 9.597839,
+ "Z": 233.05103
+ },
+ "TerritoryId": 1189,
+ "InteractionType": "AttuneAetherCurrent",
+ "AetherCurrentId": 2818440
+ },
{
"DataId": 1051073,
"Position": {
"Steps": [
{
"Position": {
- "X": -510.96463,
- "Y": -0.47684515,
- "Z": -305.96155
+ "X": -510.37933,
+ "Y": -0.39999998,
+ "Z": -277.78192
},
"TerritoryId": 1188,
- "InteractionType": "WalkTo",
- "Comment": "Waypoint after swimming through the river"
+ "InteractionType": "WalkTo"
+ },
+ {
+ "Position": {
+ "X": -521.0261,
+ "Y": -0.40000004,
+ "Z": -329.19336
+ },
+ "TerritoryId": 1188,
+ "InteractionType": "WalkTo"
},
{
"DataId": 2013936,
"Y": 9.773315,
"Z": -533.135
},
- "StopDistance": 5,
+ "StopDistance": 7,
"TerritoryId": 1188,
"InteractionType": "AcceptQuest"
}
{
"Sequence": 255,
"Steps": [
+ {
+ "DataId": 1048782,
+ "Position": {
+ "X": -68.52832,
+ "Y": 6.536739,
+ "Z": -486.53394
+ },
+ "TerritoryId": 1188,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5064
+ },
+ {
+ "DataId": 1051237,
+ "Position": {
+ "X": -251.20929,
+ "Y": 5.5572896,
+ "Z": -554.89435
+ },
+ "TerritoryId": 1188,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5081
+ },
{
"DataId": 1046537,
"Position": {
{
"Sequence": 1,
"Steps": [
+ {
+ "TerritoryId": 1187,
+ "InteractionType": "AttuneAetheryte",
+ "Aetheryte": "Urqopacha - Wachunpelo"
+ },
{
"DataId": 1046557,
"Position": {
128
]
},
- {
- "TerritoryId": 1187,
- "InteractionType": "AttuneAetheryte",
- "Aetheryte": "Urqopacha - Wachunpelo"
- },
{
"DataId": 1046559,
"Position": {
{
"Sequence": 255,
"Steps": [
+ {
+ "DataId": 1050684,
+ "Position": {
+ "X": 391.37854,
+ "Y": -156.07434,
+ "Z": -388.50995
+ },
+ "TerritoryId": 1187,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5039,
+ "Comment": "Traveler to the Rescue"
+ },
+ {
+ "DataId": 1051195,
+ "Position": {
+ "X": 383.29138,
+ "Y": -154.50243,
+ "Z": -420.49292
+ },
+ "TerritoryId": 1187,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5051,
+ "Comment": "Crisis of Corruption"
+ },
{
"DataId": 1046537,
"Position": {
"Y": -19.725424,
"Z": 203.72314
},
- "StopDistance": 5,
+ "StopDistance": 7,
"TerritoryId": 1185,
"InteractionType": "CompleteQuest"
}
"Y": -19.725424,
"Z": 203.72314
},
+ "StopDistance": 7,
"TerritoryId": 1185,
"InteractionType": "AcceptQuest"
}
{
"Sequence": 3,
"Steps": [
+ {
+ "DataId": 1051263,
+ "Position": {
+ "X": -521.0193,
+ "Y": 121.63345,
+ "Z": 319.38647
+ },
+ "TerritoryId": 1188,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5085
+ },
+ {
+ "DataId": 1048855,
+ "Position": {
+ "X": -491.63043,
+ "Y": 121.63846,
+ "Z": 271.50366
+ },
+ "TerritoryId": 1188,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5074
+ },
{
"DataId": 1046876,
"Position": {
"Y": 119.49004,
"Z": 190.72253
},
+ "StopDistance": 5,
"TerritoryId": 1188,
"InteractionType": "AcceptQuest"
}
},
"TerritoryId": 1188,
"InteractionType": "Interact",
- "AetheryteShortcut": "Kozama'uka - Earthenshire"
+ "AetheryteShortcut": "Kozama'uka - Earthenshire",
+ "Fly": true
}
]
},
},
"TerritoryId": 1188,
"InteractionType": "WalkTo",
- "TargetTerritoryId": 1187
+ "TargetTerritoryId": 1187,
+ "Fly": true
},
{
"DataId": 1046814,
{
"Sequence": 1,
"Steps": [
+ {
+ "DataId": 1051207,
+ "Position": {
+ "X": 425.07043,
+ "Y": 118.935005,
+ "Z": 606.13403
+ },
+ "StopDistance": 5,
+ "TerritoryId": 1187,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5055
+ },
+ {
+ "DataId": 1048730,
+ "Position": {
+ "X": 399.0692,
+ "Y": 122.53533,
+ "Z": 542.9922
+ },
+ "StopDistance": 5,
+ "TerritoryId": 1187,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5047
+ },
{
"DataId": 1046926,
"Position": {
{
"Sequence": 1,
"Steps": [
+ {
+ "DataId": 1050872,
+ "Position": {
+ "X": -408.71295,
+ "Y": 20.420113,
+ "Z": -398.8861
+ },
+ "TerritoryId": 1189,
+ "InteractionType": "AcceptQuest",
+ "DialogueChoices": [
+ {
+ "Type": "List",
+ "ExcelSheet": "quest/051/KinGzd201_05110",
+ "Prompt": "TEXT_KINGZD201_05110_Q1_000_000",
+ "Answer": "TEXT_KINGZD201_05110_A1_000_001"
+ }
+ ],
+ "PickUpQuestId": 5110
+ },
+ {
+ "DataId": 1051073,
+ "Position": {
+ "X": 41.09253,
+ "Y": 8.205902,
+ "Z": -629.8467
+ },
+ "TerritoryId": 1189,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5094
+ },
{
"DataId": 1047577,
"Position": {
{
"Sequence": 2,
"Steps": [
- {
- "DataId": 2013948,
- "Position": {
- "X": 610.7728,
- "Y": 9.597839,
- "Z": 233.05103
- },
- "TerritoryId": 1189,
- "InteractionType": "AttuneAetherCurrent",
- "AetherCurrentId": 2818440
- },
- {
- "Position": {
- "X": 614.25964,
- "Y": -29.554798,
- "Z": 202.75368
- },
- "TerritoryId": 1189,
- "InteractionType": "WalkTo",
- "DisableNavmesh": true,
- "Mount": false
- },
{
"DataId": 1048230,
"Position": {
"Z": 214.83167
},
"TerritoryId": 1189,
- "InteractionType": "Interact",
- "DisableNavmesh": true
+ "InteractionType": "Interact"
}
]
},
{
"Sequence": 1,
"Steps": [
+ {
+ "DataId": 1051052,
+ "Position": {
+ "X": 585.90063,
+ "Y": -142.49187,
+ "Z": 510.21594
+ },
+ "TerritoryId": 1189,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5103
+ },
+ {
+ "DataId": 1050884,
+ "Position": {
+ "X": 531.0597,
+ "Y": -142.49185,
+ "Z": 492.0271
+ },
+ "TerritoryId": 1189,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5114
+ },
{
"DataId": 1047701,
"Position": {
{
"Sequence": 3,
"Steps": [
+ {
+ "DataId": 1050655,
+ "Position": {
+ "X": 289.02112,
+ "Y": -15.566031,
+ "Z": -478.78235
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5138
+ },
+ {
+ "Position": {
+ "X": 386.84927,
+ "Y": -0.84392637,
+ "Z": 435.0579
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "WalkTo",
+ "AetheryteShortcut": "Shaaloani - Hhusatahwi",
+ "SkipConditions": {
+ "StepIf": {
+ "QuestsCompleted": [
+ 5140
+ ]
+ },
+ "AetheryteShortcutIf": {
+ "QuestsCompleted": [
+ 5140
+ ]
+ }
+ }
+ },
+ {
+ "DataId": 1051283,
+ "Position": {
+ "X": 374.19702,
+ "Y": -0.24794838,
+ "Z": 437.2472
+ },
+ "StopDistance": 6,
+ "TerritoryId": 1190,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5140
+ },
+ {
+ "DataId": 1049324,
+ "Position": {
+ "X": -108.659546,
+ "Y": 4.055336,
+ "Z": 319.5697
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5130
+ },
{
"DataId": 1047001,
"Position": {
},
"TerritoryId": 1190,
"InteractionType": "Interact",
+ "AetheryteShortcut": "Shaaloani - Sheshenewezi Springs",
"DialogueChoices": [
{
"Type": "YesNo",
{
"Sequence": 7,
"Steps": [
+ {
+ "DataId": 1051316,
+ "Position": {
+ "X": -380.30066,
+ "Y": 18.718708,
+ "Z": -114.24432
+ },
+ "TerritoryId": 1190,
+ "InteractionType": "AcceptQuest",
+ "PickUpQuestId": 5144
+ },
{
"DataId": 1047082,
"Position": {
"QuestsAccepted": {
"type": "array",
"items": {
- "type": "number"
+ "type": ["number", "string"]
}
},
"QuestsCompleted": {
"type": "array",
"items": {
- "type": "number"
+ "type": ["number", "string"]
}
},
"AetheryteLocked": {
"type": "integer"
}
},
+ "QuestsAccepted": {
+ "type": "array",
+ "items": {
+ "type": ["number", "string"]
+ }
+ },
+ "QuestsCompleted": {
+ "type": "array",
+ "items": {
+ "type": ["number", "string"]
+ }
+ },
"AetheryteLocked": {
"$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte"
},
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Questionable.Model.Questing.Converter;
+
+public sealed class ElementIdListConverter : JsonConverter<List<ElementId>>
+{
+ public override List<ElementId> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TokenType != JsonTokenType.StartArray)
+ throw new JsonException();
+
+ reader.Read();
+
+ List<ElementId> values = [];
+ while (reader.TokenType != JsonTokenType.EndArray)
+ {
+
+ if (reader.TokenType == JsonTokenType.Number)
+ values.Add(new QuestId(reader.GetUInt16()));
+ else
+ values.Add(ElementId.FromString(reader.GetString() ?? throw new JsonException()));
+
+ reader.Read();
+ }
+
+ return values;
+ }
+
+ public override void Write(Utf8JsonWriter writer, List<ElementId> value, JsonSerializerOptions options)
+ {
+ throw new NotImplementedException();
+ }
+}
using System.Collections.Generic;
+using System.Text.Json.Serialization;
using Questionable.Model.Common;
+using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public bool Never { get; set; }
public bool InSameTerritory { get; set; }
public List<ushort> InTerritory { get; set; } = new();
+
+ [JsonConverter(typeof(ElementIdListConverter))]
+ public List<ElementId> QuestsAccepted { get; set; } = new();
+
+ [JsonConverter(typeof(ElementIdListConverter))]
+ public List<ElementId> QuestsCompleted { get; set; } = new();
+
public EAetheryteLocation? AetheryteLocked { get; set; }
public EAetheryteLocation? AetheryteUnlocked { get; set; }
public bool RequiredQuestVariablesNotMet { get; set; }
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Serialization;
using Questionable.Model.Common;
+using Questionable.Model.Questing.Converter;
namespace Questionable.Model.Questing;
public List<ushort> InTerritory { get; set; } = new();
public List<ushort> NotInTerritory { get; set; } = new();
public SkipItemConditions? Item { get; set; }
+
+ [JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsAccepted { get; set; } = new();
+
+ [JsonConverter(typeof(ElementIdListConverter))]
public List<ElementId> QuestsCompleted { get; set; } = new();
+
public EAetheryteLocation? AetheryteLocked { get; set; }
public EAetheryteLocation? AetheryteUnlocked { get; set; }
public NearPositionCondition? NearPosition { get; set; }
MovementController movementController,
AetheryteFunctions aetheryteFunctions,
GameFunctions gameFunctions,
+ QuestFunctions questFunctions,
IClientState clientState,
AetheryteData aetheryteData,
TerritoryData territoryData,
public ITask Use(EAetheryteLocation from, EAetheryteLocation to, SkipAetheryteCondition? skipConditions = null)
{
return new UseAethernetShortcut(from, to, skipConditions ?? new(),
- loggerFactory.CreateLogger<UseAethernetShortcut>(), aetheryteFunctions, gameFunctions, clientState,
- aetheryteData, territoryData, lifestreamIpc, movementController, condition);
+ loggerFactory.CreateLogger<UseAethernetShortcut>(), aetheryteFunctions, gameFunctions, questFunctions,
+ clientState, aetheryteData, territoryData, lifestreamIpc, movementController, condition);
}
}
ILogger<UseAethernetShortcut> logger,
AetheryteFunctions aetheryteFunctions,
GameFunctions gameFunctions,
+ QuestFunctions questFunctions,
IClientState clientState,
AetheryteData aetheryteData,
TerritoryData territoryData,
return false;
}
+ if (skipConditions.QuestsCompleted.Count > 0 &&
+ skipConditions.QuestsCompleted.All(questFunctions.IsQuestComplete))
+ {
+ logger.LogInformation("Skipping aethernet shortcut, all prequisite quests are complete");
+ return true;
+ }
+
+ if (skipConditions.QuestsAccepted.Count > 0 &&
+ skipConditions.QuestsAccepted.All(questFunctions.IsQuestAccepted))
+ {
+ logger.LogInformation("Skipping aethernet shortcut, all prequisite quests are accepted");
+ return true;
+ }
+
if (skipConditions.AetheryteLocked != null &&
!aetheryteFunctions.IsAetheryteUnlocked(skipConditions.AetheryteLocked.Value))
{
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Numerics;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
return true;
}
+ if (skipConditions.QuestsCompleted.Count > 0 &&
+ skipConditions.QuestsCompleted.All(questFunctions.IsQuestComplete))
+ {
+ logger.LogInformation("Skipping aetheryte, all prequisite quests are complete");
+ return true;
+ }
+
+ if (skipConditions.QuestsAccepted.Count > 0 &&
+ skipConditions.QuestsAccepted.All(questFunctions.IsQuestAccepted))
+ {
+ logger.LogInformation("Skipping aetheryte, all prequisite quests are accepted");
+ return true;
+ }
+
if (skipConditions.AetheryteLocked != null &&
!aetheryteFunctions.IsAetheryteUnlocked(skipConditions.AetheryteLocked.Value))
{