From 9aa07afff89c05e434b58e09562ae777907623da Mon Sep 17 00:00:00 2001 From: Liza Carvelli Date: Fri, 3 Jan 2025 01:46:31 +0100 Subject: [PATCH] Don't try queueing for duties when ilvl is too low --- .../Steps/Common/SendNotification.cs | 2 +- .../Controller/Steps/Interactions/Duty.cs | 48 ++++++++++++++++--- Questionable/Data/TerritoryData.cs | 35 +++++++++----- Questionable/External/AutoDutyIpc.cs | 12 ++--- Questionable/QuestionablePlugin.cs | 3 ++ Questionable/Windows/ConfigWindow.cs | 2 +- 6 files changed, 75 insertions(+), 27 deletions(-) diff --git a/Questionable/Controller/Steps/Common/SendNotification.cs b/Questionable/Controller/Steps/Common/SendNotification.cs index e83a1186..cf116028 100644 --- a/Questionable/Controller/Steps/Common/SendNotification.cs +++ b/Questionable/Controller/Steps/Common/SendNotification.cs @@ -24,7 +24,7 @@ internal static class SendNotification new Task(step.InteractionType, step.Comment), EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) => new Task(step.InteractionType, step.ContentFinderConditionId.HasValue - ? territoryData.GetContentFinderConditionName(step.ContentFinderConditionId.Value) + ? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name : step.Comment), EInteractionType.SinglePlayerDuty => new Task(step.InteractionType, quest.Info.Name), _ => null, diff --git a/Questionable/Controller/Steps/Interactions/Duty.cs b/Questionable/Controller/Steps/Interactions/Duty.cs index fab5c6ed..5e20accf 100644 --- a/Questionable/Controller/Steps/Interactions/Duty.cs +++ b/Questionable/Controller/Steps/Interactions/Duty.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using Dalamud.Game.ClientState.Conditions; using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game; +using LLib.Gear; +using Questionable.Controller.Steps.Common; using Questionable.Controller.Steps.Shared; using Questionable.Data; using Questionable.External; @@ -41,23 +44,54 @@ internal static class Duty } internal sealed class StartAutoDutyExecutor( + GearStatsCalculator gearStatsCalculator, AutoDutyIpc autoDutyIpc, TerritoryData territoryData, - IClientState clientState) : TaskExecutor + IClientState clientState, + IChatGui chatGui, + SendNotification.Executor sendNotificationExecutor) : TaskExecutor { protected override bool Start() { + if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId, + out var cfcData)) + throw new TaskException("Failed to get territory ID for content finder condition"); + + unsafe + { + InventoryManager* inventoryManager = InventoryManager.Instance(); + if (inventoryManager == null) + throw new TaskException("Inventory unavailable"); + + var equippedItems = inventoryManager->GetInventoryContainer(InventoryType.EquippedItems); + if (equippedItems == null) + throw new TaskException("Equipped items unavailable"); + + var currentItemLevel = gearStatsCalculator.CalculateAverageItemLevel(equippedItems); + if (cfcData.RequiredItemLevel > currentItemLevel) + { + string errorText = + $"Could not use AutoDuty to queue for {cfcData.Name}, required item level: {cfcData.RequiredItemLevel}, current item level: {currentItemLevel}."; + if (!sendNotificationExecutor.Start(new SendNotification.Task(EInteractionType.Duty, errorText))) + chatGui.PrintError(errorText, CommandHandler.MessageTag, CommandHandler.TagColor); + + return false; + } + } + autoDutyIpc.StartInstance(Task.ContentFinderConditionId); return true; } public override ETaskResult Update() { - if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId, - out uint territoryId)) + if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId, + out var cfcData)) throw new TaskException("Failed to get territory ID for content finder condition"); - return clientState.TerritoryType == territoryId ? ETaskResult.TaskComplete : ETaskResult.StillRunning; + return clientState.TerritoryType == cfcData.TerritoryId + ? ETaskResult.TaskComplete + : ETaskResult.StillRunning; } } @@ -75,11 +109,11 @@ internal static class Duty public override ETaskResult Update() { - if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId, - out uint territoryId)) + if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId, + out var cfcData)) throw new TaskException("Failed to get territory ID for content finder condition"); - return clientState.TerritoryType != territoryId && autoDutyIpc.IsStopped() + return clientState.TerritoryType != cfcData.TerritoryId && autoDutyIpc.IsStopped() ? ETaskResult.TaskComplete : ETaskResult.StillRunning; } diff --git a/Questionable/Data/TerritoryData.cs b/Questionable/Data/TerritoryData.cs index 970718b2..f269b138 100644 --- a/Questionable/Data/TerritoryData.cs +++ b/Questionable/Data/TerritoryData.cs @@ -1,12 +1,11 @@ using System; -using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using Dalamud.Game; using Dalamud.Plugin.Services; using Dalamud.Utility; -using FFXIVClientStructs.FFXIV.Client.Game.Character; using Lumina.Excel.Sheets; namespace Questionable.Data; @@ -17,8 +16,7 @@ internal sealed class TerritoryData private readonly ImmutableHashSet _territoriesWithMount; private readonly ImmutableDictionary _dutyTerritories; private readonly ImmutableDictionary _instanceNames; - private readonly ImmutableDictionary _contentFinderConditionNames; - private readonly ImmutableDictionary _contentFinderConditionIds; + private readonly ImmutableDictionary _contentFinderConditions; public TerritoryData(IDataManager dataManager) { @@ -46,12 +44,10 @@ internal sealed class TerritoryData .Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6) .ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToDalamudString().ToString()); - _contentFinderConditionNames = dataManager.GetExcelSheet() + _contentFinderConditions = dataManager.GetExcelSheet() .Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6) - .ToImmutableDictionary(x => x.RowId, x => FixName(x.Name.ToDalamudString().ToString(), dataManager.Language)); - _contentFinderConditionIds = dataManager.GetExcelSheet() - .Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6) - .ToImmutableDictionary(x => x.RowId, x => x.TerritoryType.RowId); + .Select(x => new ContentFinderConditionData(x, dataManager.Language)) + .ToImmutableDictionary(x => x.ContentFinderConditionId, x => x); } public string? GetName(ushort territoryId) => _territoryNames.GetValueOrDefault(territoryId); @@ -74,10 +70,12 @@ internal sealed class TerritoryData public string? GetInstanceName(ushort instanceId) => _instanceNames.GetValueOrDefault(instanceId); - public string? GetContentFinderConditionName(uint cfcId) => _contentFinderConditionNames.GetValueOrDefault(cfcId); + public ContentFinderConditionData? GetContentFinderCondition(uint cfcId) => + _contentFinderConditions.GetValueOrDefault(cfcId); - public bool TryGetTerritoryIdForContentFinderCondition(uint cfcId, out uint territoryId) => - _contentFinderConditionIds.TryGetValue(cfcId, out territoryId); + public bool TryGetContentFinderCondition(uint cfcId, + [NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData) => + _contentFinderConditions.TryGetValue(cfcId, out contentFinderConditionData); private static string FixName(string name, ClientLanguage language) { @@ -86,4 +84,17 @@ internal sealed class TerritoryData return string.Concat(name[0].ToString().ToUpper(CultureInfo.InvariantCulture), name.AsSpan(1)); } + + public sealed record ContentFinderConditionData( + uint ContentFinderConditionId, + string Name, + uint TerritoryId, + ushort RequiredItemLevel) + { + public ContentFinderConditionData(ContentFinderCondition condition, ClientLanguage clientLanguage) + : this(condition.RowId, FixName(condition.Name.ToDalamudString().ToString(), clientLanguage), + condition.TerritoryType.RowId, condition.ItemLevelRequired) + { + } + } } diff --git a/Questionable/External/AutoDutyIpc.cs b/Questionable/External/AutoDutyIpc.cs index 1089efcc..71bae7fd 100644 --- a/Questionable/External/AutoDutyIpc.cs +++ b/Questionable/External/AutoDutyIpc.cs @@ -38,7 +38,7 @@ internal sealed class AutoDutyIpc return false; if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) && - _territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId.Value, out _)) + _territoryData.TryGetContentFinderCondition(cfcId.Value, out _)) return true; return autoDutyEnabled && HasPath(cfcId.Value); @@ -46,28 +46,28 @@ internal sealed class AutoDutyIpc public bool HasPath(uint cfcId) { - if (!_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId, out uint territoryType)) + if (!_territoryData.TryGetContentFinderCondition(cfcId, out var cfcData)) return false; try { - return _contentHasPath.InvokeFunc(territoryType); + return _contentHasPath.InvokeFunc(cfcData.TerritoryId); } catch (IpcError e) { - _logger.LogWarning("Unable to query AutoDuty for path in territory {TerritoryType}: {Message}", territoryType, e.Message); + _logger.LogWarning("Unable to query AutoDuty for path in territory {TerritoryType}: {Message}", cfcData.TerritoryId, e.Message); return false; } } public void StartInstance(uint cfcId) { - if (!_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId, out uint territoryType)) + if (!_territoryData.TryGetContentFinderCondition(cfcId, out var cfcData)) throw new TaskException($"Unknown ContentFinderConditionId {cfcId}"); try { - _run.InvokeAction(territoryType, 0, true); + _run.InvokeAction(cfcData.TerritoryId, 0, true); } catch (IpcError e) { diff --git a/Questionable/QuestionablePlugin.cs b/Questionable/QuestionablePlugin.cs index f5fa51ee..a4b5bae9 100644 --- a/Questionable/QuestionablePlugin.cs +++ b/Questionable/QuestionablePlugin.cs @@ -7,6 +7,7 @@ using Dalamud.Interface.Windowing; using Dalamud.Plugin; using Dalamud.Plugin.Services; using LLib; +using LLib.Gear; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Questionable.Controller; @@ -130,6 +131,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + + serviceCollection.AddSingleton(); } private static void AddTaskFactories(ServiceCollection serviceCollection) diff --git a/Questionable/Windows/ConfigWindow.cs b/Questionable/Windows/ConfigWindow.cs index 397faeba..131f3726 100644 --- a/Questionable/Windows/ConfigWindow.cs +++ b/Questionable/Windows/ConfigWindow.cs @@ -99,7 +99,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig { Expansion = (EExpansionVersion)x.TerritoryType.Value.ExVersion.RowId, CfcId = x.RowId, - Name = territoryData.GetContentFinderConditionName(x.RowId) ?? "?", + Name = territoryData.GetContentFinderCondition(x.RowId)?.Name ?? "?", TerritoryId = x.TerritoryType.RowId, ContentType = x.ContentType.RowId, Level = x.ClassJobLevelRequired,