diff --git a/GatheringPathRenderer/RendererPlugin.cs b/GatheringPathRenderer/RendererPlugin.cs index 95edf94c..f3c52afc 100644 --- a/GatheringPathRenderer/RendererPlugin.cs +++ b/GatheringPathRenderer/RendererPlugin.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -6,6 +7,7 @@ using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; using Dalamud.Game.ClientState.Objects; using Dalamud.Interface.Windowing; using Dalamud.Plugin; @@ -155,6 +157,10 @@ public sealed class RendererPlugin : IDalamudPlugin Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault, WriteIndented = true, + TypeInfoResolver = new DefaultJsonTypeInfoResolver + { + Modifiers = { NoEmptyCollectionModifier } + }, }; using (var stream = File.Create(targetFile.FullName)) { @@ -176,6 +182,17 @@ public sealed class RendererPlugin : IDalamudPlugin Reload(); } + private static void NoEmptyCollectionModifier(JsonTypeInfo typeInfo) + { + foreach (var property in typeInfo.Properties) + { + if (typeof(ICollection).IsAssignableFrom(property.PropertyType)) + { + property.ShouldSerialize = (_, val) => val is ICollection { Count: > 0 }; + } + } + } + private void TerritoryChanged(ushort territoryId) => Redraw(); private void ClassJobChanged(uint classJobId) @@ -234,7 +251,8 @@ public sealed class RendererPlugin : IDalamudPlugin refZ = x.Position.Y, Filled = true, radius = locationOverride?.MinimumDistance ?? x.CalculateMinimumDistance(), - Donut = (locationOverride?.MaximumDistance ?? x.CalculateMaximumDistance()) - (locationOverride?.MinimumDistance ?? x.CalculateMinimumDistance()), + Donut = (locationOverride?.MaximumDistance ?? x.CalculateMaximumDistance()) - + (locationOverride?.MinimumDistance ?? x.CalculateMinimumDistance()), color = _colors[location.Root.Groups.IndexOf(group) % _colors.Count], Enabled = true, coneAngleMin = minimumAngle, diff --git a/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/353_The Makers' Quarter_MIN.json b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/353_The Makers' Quarter_MIN.json index d462b453..494cd5de 100644 --- a/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/353_The Makers' Quarter_MIN.json +++ b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/353_The Makers' Quarter_MIN.json @@ -9,7 +9,14 @@ "AethernetShortcut": [ "[Idyllshire] Aetheryte Plaza", "[Idyllshire] Epilogue Gate (Eastern Hinterlands)" - ] + ], + "SkipConditions": { + "AetheryteShortcutIf": { + "InTerritory": [ + 399 + ] + } + } } ], "Groups": [ diff --git a/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/361_The Answering Quarter_BTN.json b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/361_The Answering Quarter_BTN.json index 64e5cb8d..613830f1 100644 --- a/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/361_The Answering Quarter_BTN.json +++ b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/361_The Answering Quarter_BTN.json @@ -9,7 +9,14 @@ "AethernetShortcut": [ "[Idyllshire] Aetheryte Plaza", "[Idyllshire] Prologue Gate (Western Hinterlands)" - ] + ], + "SkipConditions": { + "AetheryteShortcutIf": { + "InTerritory": [ + 399 + ] + } + } } ], "Groups": [ diff --git a/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/723_Quickspill Delta_BTN.json b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/723_Quickspill Delta_BTN.json new file mode 100644 index 00000000..99a15edf --- /dev/null +++ b/GatheringPaths/3.x - Heavensward/The Dravanian Hinterlands/723_Quickspill Delta_BTN.json @@ -0,0 +1,119 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json", + "Author": "liza", + "Steps": [ + { + "TerritoryId": 399, + "InteractionType": "None", + "AetheryteShortcut": "Idyllshire", + "AethernetShortcut": [ + "[Idyllshire] Aetheryte Plaza", + "[Idyllshire] Prologue Gate (Western Hinterlands)" + ], + "SkipConditions": { + "AetheryteShortcutIf": { + "InTerritory": [ + 399 + ] + } + } + } + ], + "Groups": [ + { + "Nodes": [ + { + "DataId": 33285, + "Locations": [ + { + "Position": { + "X": -426.4134, + "Y": 137.5601, + "Z": 514.3357 + } + } + ] + }, + { + "DataId": 33286, + "Locations": [ + { + "Position": { + "X": -448.7838, + "Y": 137.5986, + "Z": 514.3243 + } + }, + { + "Position": { + "X": -433.5015, + "Y": 137.6451, + "Z": 487.8173 + } + } + ] + } + ] + }, + { + "Nodes": [ + { + "DataId": 33288, + "Locations": [ + { + "Position": { + "X": -354.5423, + "Y": 137.5715, + "Z": 638.9959 + } + } + ] + }, + { + "DataId": 33287, + "Locations": [ + { + "Position": { + "X": -352.4377, + "Y": 137.5906, + "Z": 604.364 + } + } + ] + } + ] + }, + { + "Nodes": [ + { + "DataId": 33284, + "Locations": [ + { + "Position": { + "X": -254.4776, + "Y": 137.97, + "Z": 591.0092 + }, + "MinimumAngle": -20, + "MaximumAngle": 85 + } + ] + }, + { + "DataId": 33283, + "Locations": [ + { + "Position": { + "X": -263.1079, + "Y": 137.4419, + "Z": 569.8724 + }, + "MinimumAngle": -10, + "MaximumAngle": 190 + } + ] + } + ] + } + ] +} diff --git a/Questionable.Model/Questing/QuestStep.cs b/Questionable.Model/Questing/QuestStep.cs index 58a7a5b6..152abc74 100644 --- a/Questionable.Model/Questing/QuestStep.cs +++ b/Questionable.Model/Questing/QuestStep.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Text.Json.Serialization; using Questionable.Model.Common; @@ -7,20 +8,23 @@ using Questionable.Model.Questing.Converter; namespace Questionable.Model.Questing; +[SuppressMessage("ReSharper", "CollectionNeverUpdated.Global")] public sealed class QuestStep { public const float DefaultStopDistance = 3f; - public EInteractionType InteractionType { get; set; } - public uint? DataId { get; set; } [JsonConverter(typeof(VectorConverter))] public Vector3? Position { get; set; } public float? StopDistance { get; set; } - public float? NpcWaitDistance { get; set; } public ushort TerritoryId { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public EInteractionType InteractionType { get; set; } + + public float? NpcWaitDistance { get; set; } public ushort? TargetTerritoryId { get; set; } public float? DelaySecondsAtStart { get; set; } @@ -57,8 +61,8 @@ public sealed class QuestStep public EAction? Action { get; set; } public EEnemySpawnType? EnemySpawnType { get; set; } - public IList KillEnemyDataIds { get; set; } = new List(); - public IList ComplexCombatData { get; set; } = new List(); + public List KillEnemyDataIds { get; set; } = []; + public List ComplexCombatData { get; set; } = []; public float? CombatDelaySecondsAtStart { get; set; } public JumpDestination? JumpDestination { get; set; } @@ -67,9 +71,9 @@ public sealed class QuestStep public List?> RequiredQuestVariables { get; set; } = new(); public List RequiredGatheredItems { get; set; } = []; - public IList CompletionQuestVariablesFlags { get; set; } = new List(); - public IList DialogueChoices { get; set; } = new List(); - public IList PointMenuChoices { get; set; } = new List(); + public List CompletionQuestVariablesFlags { get; set; } = []; + public List DialogueChoices { get; set; } = []; + public List PointMenuChoices { get; set; } = []; // TODO: Not implemented [JsonConverter(typeof(ElementIdConverter))] diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index a9cc6550..c4805bb0 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -773,7 +773,6 @@ internal sealed class QuestController : MiniTaskController, IDi if (toastAware.OnErrorToast(message)) { isHandled = true; - return; } } } diff --git a/Questionable/Functions/QuestFunctions.cs b/Questionable/Functions/QuestFunctions.cs index 0ac8157f..c26acc8d 100644 --- a/Questionable/Functions/QuestFunctions.cs +++ b/Questionable/Functions/QuestFunctions.cs @@ -278,13 +278,13 @@ internal sealed unsafe class QuestFunctions if (!_questRegistry.TryGetQuest(x, out Quest? quest)) return false; - return quest.AllSteps().All(x => + return quest.AllSteps().All(y => { - if (x.Step.AetheryteShortcut is { } aetheryteShortcut && + if (y.Step.AetheryteShortcut is { } aetheryteShortcut && _aetheryteFunctions.IsAetheryteUnlocked(aetheryteShortcut)) return false; - if (x.Step.AethernetShortcut is { } aethernetShortcut && + if (y.Step.AethernetShortcut is { } aethernetShortcut && (!_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.From) || !_aetheryteFunctions.IsAetheryteUnlocked(aethernetShortcut.To))) return false;