diff --git a/Questionable/Controller/QuestController.cs b/Questionable/Controller/QuestController.cs index 562c7e52c..5619c1199 100644 --- a/Questionable/Controller/QuestController.cs +++ b/Questionable/Controller/QuestController.cs @@ -310,7 +310,8 @@ internal sealed class QuestController : MiniTaskController, IDi if (_clientState.LocalPlayer!.Level < quest.Info.Level) { - _logger.LogInformation("Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", + _logger.LogInformation( + "Stopping automation, player level ({PlayerLevel}) < quest level ({QuestLevel}", _clientState.LocalPlayer!.Level, quest.Info.Level); Stop("Quest level too high"); } @@ -364,7 +365,8 @@ internal sealed class QuestController : MiniTaskController, IDi if (questToRun.Sequence != currentSequence) { questToRun.SetSequence(currentSequence); - CheckNextTasks($"New sequence {questToRun == _startedQuest}/{_questFunctions.GetCurrentQuestInternal()}"); + CheckNextTasks( + $"New sequence {questToRun == _startedQuest}/{_questFunctions.GetCurrentQuestInternal()}"); } var q = questToRun.Quest; @@ -760,13 +762,28 @@ internal sealed class QuestController : MiniTaskController, IDi ]; EClassJob classJob = (EClassJob?)_clientState.LocalPlayer?.ClassJob.Id ?? EClassJob.Adventurer; + ushort[] shadowbringersRoleQuestChapters = QuestData.AllRoleQuestChapters.Select(x => x[0]).ToArray(); if (classJob != EClassJob.Adventurer) { priorityQuests.AddRange(_questRegistry.GetKnownClassJobQuests(classJob) - .Where(x => _questRegistry.TryGetQuest(x.QuestId, out Quest? quest) && quest.Info is QuestInfo + .Where(x => { - // ignore Endwalker/Dawntrail, as the class quests are optional - Expansion: EExpansionVersion.ARealmReborn or EExpansionVersion.Heavensward or EExpansionVersion.Stormblood or EExpansionVersion.Shadowbringers + if (!_questRegistry.TryGetQuest(x.QuestId, out Quest? quest) || + quest.Info is not QuestInfo questInfo) + return false; + + // if no shadowbringers role quest is complete, (at least one) is required + if (shadowbringersRoleQuestChapters.Contains(questInfo.NewGamePlusChapter)) + return !QuestData.FinalShadowbringersRoleQuests.Any(_questFunctions.IsQuestComplete); + + // ignore all other role quests + if (QuestData.AllRoleQuestChapters.Any(y => y.Contains(questInfo.NewGamePlusChapter))) + return false; + + // even job quests for the later expacs (after role quests were introduced) might have skills locked + // behind them, e.g. reaper and sage + + return true; }) .Select(x => x.QuestId)); } diff --git a/Questionable/Data/QuestData.cs b/Questionable/Data/QuestData.cs index 8b961c817..3e00ba1a8 100644 --- a/Questionable/Data/QuestData.cs +++ b/Questionable/Data/QuestData.cs @@ -14,6 +14,24 @@ internal sealed class QuestData { public static readonly IReadOnlyList CrystalTowerQuests = [new(1709), new(1200), new(1201), new(1202), new(1203), new(1474), new(494), new(495)]; + + public static readonly IReadOnlyList TankRoleQuests = [136, 154, 178]; + public static readonly IReadOnlyList HealerRoleQuests = [137, 155, 179]; + public static readonly IReadOnlyList MeleeRoleQuests = [138, 156, 180]; + public static readonly IReadOnlyList PhysicalRangedRoleQuests = [138, 157, 181]; + public static readonly IReadOnlyList CasterRoleQuests = [139, 158, 182]; + public static readonly IReadOnlyList> AllRoleQuestChapters = + [ + TankRoleQuests, + HealerRoleQuests, + MeleeRoleQuests, + PhysicalRangedRoleQuests, + CasterRoleQuests + ]; + + public static readonly IReadOnlyList FinalShadowbringersRoleQuests = + [new(3248), new(3272), new(3278), new(3628)]; + private readonly Dictionary _quests; public QuestData(IDataManager dataManager) @@ -134,11 +152,11 @@ internal sealed class QuestData chapterIds.AddRange(classJob switch { - _ when classJob.IsTank() => [136, 154, 178], - _ when classJob.IsHealer() => [137, 155, 179], - _ when classJob.IsMelee() => [138, 156, 180], - _ when classJob.IsPhysicalRanged() => [138, 157, 181], - _ when classJob.IsCaster() && classJob != EClassJob.BlueMage => [139, 158, 182], + _ when classJob.IsTank() => TankRoleQuests, + _ when classJob.IsHealer() => HealerRoleQuests, + _ when classJob.IsMelee() => MeleeRoleQuests, + _ when classJob.IsPhysicalRanged() => PhysicalRangedRoleQuests, + _ when classJob.IsCaster() && classJob != EClassJob.BlueMage => CasterRoleQuests, _ => [] });