From d7ce9051f46efc4b052d00a92f0438fe31f07822 Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 9 Aug 2024 00:53:05 +0200 Subject: [PATCH] Moonfire Faire + add logic for skipping steps depending on (un)locked aetherytes --- .../5182_Fire Red, Beast Green.json | 171 ++++++++++++++++++ .../5183_Festival Fan Frenzy.json | 115 ++++++++++++ QuestPaths/quest-v1.json | 21 ++- .../Questing/Converter/EmoteConverter.cs | 1 + Questionable.Model/Questing/EEmote.cs | 1 + .../Questing/SkipAetheryteCondition.cs | 3 + .../Questing/SkipStepConditions.cs | 5 + Questionable/Controller/GameUiController.cs | 18 +- .../Steps/Shared/AethernetShortcut.cs | 21 +++ .../Steps/Shared/AetheryteShortcut.cs | 16 +- .../Controller/Steps/Shared/SkipCondition.cs | 14 ++ Questionable/Data/QuestData.cs | 3 +- Questionable/Model/QuestInfo.cs | 2 + 13 files changed, 385 insertions(+), 6 deletions(-) create mode 100644 QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5182_Fire Red, Beast Green.json create mode 100644 QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5183_Festival Fan Frenzy.json diff --git a/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5182_Fire Red, Beast Green.json b/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5182_Fire Red, Beast Green.json new file mode 100644 index 000000000..4b146eedd --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5182_Fire Red, Beast Green.json @@ -0,0 +1,171 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "JerryWester", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1050816, + "Position": { + "X": 14.328186, + "Y": 45.665993, + "Z": 131.33435 + }, + "TerritoryId": 128, + "InteractionType": "AcceptQuest", + "AetheryteShortcut": "Limsa Lominsa", + "AethernetShortcut": [ + "[Limsa Lominsa] Aetheryte Plaza", + "[Limsa Lominsa] The Aftcastle" + ], + "SkipConditions": { + "AetheryteShortcutIf": { + "InSameTerritory": true, + "InTerritory": [ + 129 + ] + } + } + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1000868, + "Position": { + "X": -192.00433, + "Y": 0.9999907, + "Z": 211.68835 + }, + "TerritoryId": 129, + "InteractionType": "Interact", + "AethernetShortcut": [ + "[Limsa Lominsa] The Aftcastle", + "[Limsa Lominsa] Fishermens' Guild" + ], + "SkipConditions": { + "StepIf": { + "AetheryteUnlocked": "Eastern La Noscea - Costa Del Sol", + "InTerritory": [137] + }, + "AethernetShortcutIf": { + "AetheryteUnlocked": "Eastern La Noscea - Costa Del Sol" + } + }, + "TargetTerritoryId": 137 + }, + { + "TerritoryId": 137, + "InteractionType": "AttuneAetheryte", + "Aetheryte": "Eastern La Noscea - Costa Del Sol", + "SkipConditions": { + "StepIf": { + "AetheryteUnlocked": "Eastern La Noscea - Costa Del Sol" + } + } + }, + { + "Position": { + "X": 732.0986, + "Y": 11.349089, + "Z": 262.19138 + }, + "TerritoryId": 137, + "InteractionType": "WalkTo" + }, + { + "DataId": 1050817, + "Position": { + "X": 735.25586, + "Y": 11.306824, + "Z": 261.8601 + }, + "StopDistance": 5, + "TerritoryId": 137, + "InteractionType": "Interact", + "AetheryteShortcut": "Eastern La Noscea - Costa Del Sol", + "Fly": true + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1050818, + "Position": { + "X": 681.3915, + "Y": 9.601691, + "Z": 202.86865 + }, + "StopDistance": 5, + "TerritoryId": 137, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 3, + "Steps": [ + { + "DataId": 1050819, + "Position": { + "X": 770.13806, + "Y": 9.687993, + "Z": 246.29578 + }, + "TerritoryId": 137, + "InteractionType": "Interact" + } + ] + }, + { + "Sequence": 4, + "Steps": [ + { + "DataId": 2014098, + "Position": { + "X": 769.0698, + "Y": 9.719971, + "Z": 246.99768 + }, + "TerritoryId": 137, + "InteractionType": "Interact", + "DialogueChoices": [ + { + "Type": "List", + "Prompt": "TEXT_FESSUX001_05182_Q1_000_000", + "Answer": "TEXT_FESSUX001_05182_A1_000_001" + } + ] + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "DataId": 1050820, + "Position": { + "X": 695.46045, + "Y": 9.614362, + "Z": 295.70447 + }, + "TerritoryId": 137, + "InteractionType": "CompleteQuest", + "DialogueChoices": [ + { + "Type": "List", + "Prompt": "TEXT_FESSUX001_05182_Q2_000_000", + "Answer": "TEXT_FESSUX001_05182_A2_000_001" + } + ], + "NextQuestId": 5183 + } + ] + } + ] +} diff --git a/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5183_Festival Fan Frenzy.json b/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5183_Festival Fan Frenzy.json new file mode 100644 index 000000000..4a95c4c43 --- /dev/null +++ b/QuestPaths/7.x - Dawntrail/Seasonal Events/Moonfire Faire (2024)/5183_Festival Fan Frenzy.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json", + "Author": "JerryWester", + "QuestSequence": [ + { + "Sequence": 0, + "Steps": [ + { + "DataId": 1050828, + "Position": { + "X": 694.5753, + "Y": 9.578133, + "Z": 297.59656 + }, + "StopDistance": 5, + "TerritoryId": 137, + "InteractionType": "AcceptQuest" + } + ] + }, + { + "Sequence": 1, + "Steps": [ + { + "DataId": 1050824, + "Position": { + "X": 507.68274, + "Y": 9.541115, + "Z": 428.54944 + }, + "TerritoryId": 137, + "InteractionType": "Emote", + "Emote": "uchiwasshoi", + "Fly": true, + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 128 + ] + }, + { + "DataId": 1050825, + "Position": { + "X": 641.44336, + "Y": 11.697773, + "Z": 526.604 + }, + "TerritoryId": 137, + "InteractionType": "Emote", + "Emote": "uchiwasshoi", + "Fly": true, + "CompletionQuestVariablesFlags": [ + null, + null, + null, + null, + null, + 64 + ] + } + ] + }, + { + "Sequence": 2, + "Steps": [ + { + "DataId": 1050829, + "Position": { + "X": 694.2092, + "Y": 9.619679, + "Z": 294.81946 + }, + "TerritoryId": 137, + "InteractionType": "Interact", + "Fly": true + } + ] + }, + { + "Sequence": 255, + "Steps": [ + { + "Position": { + "X": 732.0986, + "Y": 11.349089, + "Z": 262.19138 + }, + "TerritoryId": 137, + "InteractionType": "WalkTo" + }, + { + "DataId": 1050817, + "Position": { + "X": 735.25586, + "Y": 11.306824, + "Z": 261.8601 + }, + "TerritoryId": 137, + "InteractionType": "CompleteQuest", + "StopDistance": 5, + "DialogueChoices": [ + { + "Type": "List", + "Prompt": "TEXT_FESSUX002_05183_Q1_000_000", + "Answer": "TEXT_FESSUX002_05183_A1_000_002" + } + ] + } + ] + } + ] +} diff --git a/QuestPaths/quest-v1.json b/QuestPaths/quest-v1.json index 313239f43..25d083b6c 100644 --- a/QuestPaths/quest-v1.json +++ b/QuestPaths/quest-v1.json @@ -236,6 +236,12 @@ "type": "number" } }, + "AetheryteLocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" + }, + "AetheryteUnlocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" + }, "ExtraCondition": { "type": "string", "enum": [ @@ -259,6 +265,12 @@ "items": { "type": "integer" } + }, + "AetheryteLocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" + }, + "AetheryteUnlocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" } }, "additionalProperties": false @@ -271,6 +283,12 @@ }, "InSameTerritory": { "type": "boolean" + }, + "AetheryteLocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" + }, + "AetheryteUnlocked": { + "$ref": "https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json#/$defs/Aetheryte" } }, "additionalProperties": false @@ -694,7 +712,8 @@ "respect", "lookout", "kneel", - "bow" + "bow", + "uchiwasshoi" ] } } diff --git a/Questionable.Model/Questing/Converter/EmoteConverter.cs b/Questionable.Model/Questing/Converter/EmoteConverter.cs index 20c97694c..5de1c5c5b 100644 --- a/Questionable.Model/Questing/Converter/EmoteConverter.cs +++ b/Questionable.Model/Questing/Converter/EmoteConverter.cs @@ -29,5 +29,6 @@ public sealed class EmoteConverter() : EnumConverter(Values) { EEmote.Lookout, "lookout" }, { EEmote.Kneel, "kneel" }, { EEmote.Bow, "bow" }, + { EEmote.Uchiwasshoi, "uchiwasshoi" }, }; } diff --git a/Questionable.Model/Questing/EEmote.cs b/Questionable.Model/Questing/EEmote.cs index 022930e90..c03be6110 100644 --- a/Questionable.Model/Questing/EEmote.cs +++ b/Questionable.Model/Questing/EEmote.cs @@ -30,4 +30,5 @@ public enum EEmote Lookout = 22, Kneel = 19, Bow = 5, + Uchiwasshoi = 278, } diff --git a/Questionable.Model/Questing/SkipAetheryteCondition.cs b/Questionable.Model/Questing/SkipAetheryteCondition.cs index 870abe667..ad636e323 100644 --- a/Questionable.Model/Questing/SkipAetheryteCondition.cs +++ b/Questionable.Model/Questing/SkipAetheryteCondition.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Questionable.Model.Common; namespace Questionable.Model.Questing; @@ -7,4 +8,6 @@ public sealed class SkipAetheryteCondition public bool Never { get; set; } public bool InSameTerritory { get; set; } public List InTerritory { get; set; } = new(); + public EAetheryteLocation? AetheryteLocked { get; set; } + public EAetheryteLocation? AetheryteUnlocked { get; set; } } diff --git a/Questionable.Model/Questing/SkipStepConditions.cs b/Questionable.Model/Questing/SkipStepConditions.cs index c336abe66..dd0a3f3ed 100644 --- a/Questionable.Model/Questing/SkipStepConditions.cs +++ b/Questionable.Model/Questing/SkipStepConditions.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Questionable.Model.Common; namespace Questionable.Model.Questing; @@ -15,6 +16,8 @@ public sealed class SkipStepConditions public SkipItemConditions? Item { get; set; } public List QuestsAccepted { get; set; } = new(); public List QuestsCompleted { get; set; } = new(); + public EAetheryteLocation? AetheryteLocked { get; set; } + public EAetheryteLocation? AetheryteUnlocked { get; set; } public EExtraSkipCondition? ExtraCondition { get; set; } public bool HasSkipConditions() @@ -30,6 +33,8 @@ public sealed class SkipStepConditions Item != null || QuestsAccepted.Count > 0 || QuestsCompleted.Count > 0 || + AetheryteLocked != null || + AetheryteUnlocked != null || ExtraCondition != null; } diff --git a/Questionable/Controller/GameUiController.cs b/Questionable/Controller/GameUiController.cs index 829953c1e..e57aef5fe 100644 --- a/Questionable/Controller/GameUiController.cs +++ b/Questionable/Controller/GameUiController.cs @@ -786,9 +786,23 @@ internal sealed class GameUiController : IDisposable string questName = addon->AtkTextNode250->NodeText.ToString(); if (_questController.CurrentQuest is { Quest.Id: LeveId } && GameFunctions.GameStringEquals(_questController.CurrentQuest.Quest.Info.Name, questName)) + { + _logger.LogInformation("JournalResult has the current leve, auto-accepting it"); addon->FireCallbackInt(0); - else - addon->FireCallbackInt(1); + } + else if (_targetManager.Target is { } target) + { + var issuedLeves = _questData.GetAllByIssuerDataId(target.DataId) + .Where(x => x.QuestId is LeveId) + .ToList(); + + if (issuedLeves.Any(x => GameFunctions.GameStringEquals(x.Name, questName))) + { + _logger.LogInformation( + "JournalResult has a leve but not the one we're currently on, auto-declining it"); + addon->FireCallbackInt(1); + } + } } } diff --git a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs index 82643de17..236f270c4 100644 --- a/Questionable/Controller/Steps/Shared/AethernetShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AethernetShortcut.cs @@ -63,6 +63,27 @@ internal static class AethernetShortcut logger.LogInformation("Skipping aethernet shortcut because the target is in the same territory"); return false; } + + if (SkipConditions.InTerritory.Contains(clientState.TerritoryType)) + { + logger.LogInformation( + "Skipping aethernet shortcut because the target is in the specified territory"); + return false; + } + + if (SkipConditions.AetheryteLocked != null && + !gameFunctions.IsAetheryteUnlocked(SkipConditions.AetheryteLocked.Value)) + { + logger.LogInformation("Skipping aethernet shortcut because the target aetheryte is locked"); + return false; + } + + if (SkipConditions.AetheryteUnlocked != null && + gameFunctions.IsAetheryteUnlocked(SkipConditions.AetheryteUnlocked.Value)) + { + logger.LogInformation("Skipping aethernet shortcut because the target aetheryte is unlocked"); + return false; + } } if (gameFunctions.IsAetheryteUnlocked(From) && diff --git a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs index b73f9585b..cf6ecec0c 100644 --- a/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs +++ b/Questionable/Controller/Steps/Shared/AetheryteShortcut.cs @@ -71,13 +71,27 @@ internal static class AetheryteShortcut if (Step != null) { var skipConditions = Step.SkipConditions?.AetheryteShortcutIf ?? new(); - if (skipConditions is { Never: false, InTerritory.Count: > 0 }) + if (skipConditions is { Never: false }) { if (skipConditions.InTerritory.Contains(territoryType)) { logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (InTerritory)"); return false; } + + if (skipConditions.AetheryteLocked != null && + !gameFunctions.IsAetheryteUnlocked(skipConditions.AetheryteLocked.Value)) + { + logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (AetheryteLocked)"); + return false; + } + + if (skipConditions.AetheryteUnlocked != null && + gameFunctions.IsAetheryteUnlocked(skipConditions.AetheryteUnlocked.Value)) + { + logger.LogInformation("Skipping aetheryte teleport due to SkipCondition (AetheryteUnlocked)"); + return false; + } } if (ExpectedTerritoryId == territoryType) diff --git a/Questionable/Controller/Steps/Shared/SkipCondition.cs b/Questionable/Controller/Steps/Shared/SkipCondition.cs index 3bab5526d..d5e8e5d12 100644 --- a/Questionable/Controller/Steps/Shared/SkipCondition.cs +++ b/Questionable/Controller/Steps/Shared/SkipCondition.cs @@ -151,6 +151,20 @@ internal static class SkipCondition return true; } + if (SkipConditions.AetheryteLocked != null && + !gameFunctions.IsAetheryteUnlocked(SkipConditions.AetheryteLocked.Value)) + { + logger.LogInformation("Skipping step, as aetheryte is locked"); + return true; + } + + if (SkipConditions.AetheryteUnlocked != null && + gameFunctions.IsAetheryteUnlocked(SkipConditions.AetheryteUnlocked.Value)) + { + logger.LogInformation("Skipping step, as aetheryte is unlocked"); + return true; + } + if (Step is { DataId: not null, InteractionType: EInteractionType.AttuneAetherCurrent } && gameFunctions.IsAetherCurrentUnlocked(Step.DataId.Value)) { diff --git a/Questionable/Data/QuestData.cs b/Questionable/Data/QuestData.cs index 7ea55ca97..8f42db9aa 100644 --- a/Questionable/Data/QuestData.cs +++ b/Questionable/Data/QuestData.cs @@ -20,7 +20,6 @@ internal sealed class QuestData ..dataManager.GetExcelSheet()! .Where(x => x.RowId > 0) .Where(x => x.IssuerLocation.Row > 0) - .Where(x => x.Festival.Row == 0) .Select(x => new QuestInfo(x)), ..dataManager.GetExcelSheet()! .Where(x => x.RowId > 0) @@ -50,7 +49,7 @@ internal sealed class QuestData public List GetAllByJournalGenre(uint journalGenre) { return _quests.Values - .Where(x => x is QuestInfo) + .Where(x => x is QuestInfo { IsSeasonalEvent: false }) .Cast() .Where(x => x.JournalGenre == journalGenre) .OrderBy(x => x.SortKey) diff --git a/Questionable/Model/QuestInfo.cs b/Questionable/Model/QuestInfo.cs index 6737aab0d..769ad7cbc 100644 --- a/Questionable/Model/QuestInfo.cs +++ b/Questionable/Model/QuestInfo.cs @@ -53,6 +53,7 @@ internal sealed class QuestInfo : IQuestInfo GrandCompany = (GrandCompany)quest.GrandCompany.Row; BeastTribe = (EBeastTribe)quest.BeastTribe.Row; ClassJobs = QuestInfoUtils.AsList(quest.ClassJobCategory0.Value!); + IsSeasonalEvent = quest.Festival.Row != 0; } @@ -74,6 +75,7 @@ internal sealed class QuestInfo : IQuestInfo public GrandCompany GrandCompany { get; } public EBeastTribe BeastTribe { get; } public IReadOnlyList ClassJobs { get; } + public bool IsSeasonalEvent { get; } [UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.Members)] public enum QuestJoin : byte