Don't try queueing for duties when ilvl is too low

This commit is contained in:
Liza 2025-01-03 01:46:31 +01:00
parent 6a29273c79
commit 9aa07afff8
Signed by: liza
GPG Key ID: 2C41B84815CF6445
6 changed files with 75 additions and 27 deletions

View File

@ -24,7 +24,7 @@ internal static class SendNotification
new Task(step.InteractionType, step.Comment), new Task(step.InteractionType, step.Comment),
EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) => EInteractionType.Duty when !autoDutyIpc.IsConfiguredToRunContent(step.ContentFinderConditionId, step.AutoDutyEnabled) =>
new Task(step.InteractionType, step.ContentFinderConditionId.HasValue new Task(step.InteractionType, step.ContentFinderConditionId.HasValue
? territoryData.GetContentFinderConditionName(step.ContentFinderConditionId.Value) ? territoryData.GetContentFinderCondition(step.ContentFinderConditionId.Value)?.Name
: step.Comment), : step.Comment),
EInteractionType.SinglePlayerDuty => new Task(step.InteractionType, quest.Info.Name), EInteractionType.SinglePlayerDuty => new Task(step.InteractionType, quest.Info.Name),
_ => null, _ => null,

View File

@ -2,6 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using LLib.Gear;
using Questionable.Controller.Steps.Common;
using Questionable.Controller.Steps.Shared; using Questionable.Controller.Steps.Shared;
using Questionable.Data; using Questionable.Data;
using Questionable.External; using Questionable.External;
@ -41,23 +44,54 @@ internal static class Duty
} }
internal sealed class StartAutoDutyExecutor( internal sealed class StartAutoDutyExecutor(
GearStatsCalculator gearStatsCalculator,
AutoDutyIpc autoDutyIpc, AutoDutyIpc autoDutyIpc,
TerritoryData territoryData, TerritoryData territoryData,
IClientState clientState) : TaskExecutor<StartAutoDutyTask> IClientState clientState,
IChatGui chatGui,
SendNotification.Executor sendNotificationExecutor) : TaskExecutor<StartAutoDutyTask>
{ {
protected override bool Start() 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); autoDutyIpc.StartInstance(Task.ContentFinderConditionId);
return true; return true;
} }
public override ETaskResult Update() public override ETaskResult Update()
{ {
if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId, if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId,
out uint territoryId)) out var cfcData))
throw new TaskException("Failed to get territory ID for content finder condition"); 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() public override ETaskResult Update()
{ {
if (!territoryData.TryGetTerritoryIdForContentFinderCondition(Task.ContentFinderConditionId, if (!territoryData.TryGetContentFinderCondition(Task.ContentFinderConditionId,
out uint territoryId)) out var cfcData))
throw new TaskException("Failed to get territory ID for content finder condition"); 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.TaskComplete
: ETaskResult.StillRunning; : ETaskResult.StillRunning;
} }

View File

@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Utility; using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
namespace Questionable.Data; namespace Questionable.Data;
@ -17,8 +16,7 @@ internal sealed class TerritoryData
private readonly ImmutableHashSet<ushort> _territoriesWithMount; private readonly ImmutableHashSet<ushort> _territoriesWithMount;
private readonly ImmutableDictionary<ushort, uint> _dutyTerritories; private readonly ImmutableDictionary<ushort, uint> _dutyTerritories;
private readonly ImmutableDictionary<uint, string> _instanceNames; private readonly ImmutableDictionary<uint, string> _instanceNames;
private readonly ImmutableDictionary<uint, string> _contentFinderConditionNames; private readonly ImmutableDictionary<uint, ContentFinderConditionData> _contentFinderConditions;
private readonly ImmutableDictionary<uint, uint> _contentFinderConditionIds;
public TerritoryData(IDataManager dataManager) 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) .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()); .ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToDalamudString().ToString());
_contentFinderConditionNames = dataManager.GetExcelSheet<ContentFinderCondition>() _contentFinderConditions = dataManager.GetExcelSheet<ContentFinderCondition>()
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6) .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)); .Select(x => new ContentFinderConditionData(x, dataManager.Language))
_contentFinderConditionIds = dataManager.GetExcelSheet<ContentFinderCondition>() .ToImmutableDictionary(x => x.ContentFinderConditionId, x => x);
.Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
.ToImmutableDictionary(x => x.RowId, x => x.TerritoryType.RowId);
} }
public string? GetName(ushort territoryId) => _territoryNames.GetValueOrDefault(territoryId); 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? 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) => public bool TryGetContentFinderCondition(uint cfcId,
_contentFinderConditionIds.TryGetValue(cfcId, out territoryId); [NotNullWhen(true)] out ContentFinderConditionData? contentFinderConditionData) =>
_contentFinderConditions.TryGetValue(cfcId, out contentFinderConditionData);
private static string FixName(string name, ClientLanguage language) 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)); 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)
{
}
}
} }

View File

@ -38,7 +38,7 @@ internal sealed class AutoDutyIpc
return false; return false;
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) && if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(cfcId.Value) &&
_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId.Value, out _)) _territoryData.TryGetContentFinderCondition(cfcId.Value, out _))
return true; return true;
return autoDutyEnabled && HasPath(cfcId.Value); return autoDutyEnabled && HasPath(cfcId.Value);
@ -46,28 +46,28 @@ internal sealed class AutoDutyIpc
public bool HasPath(uint cfcId) public bool HasPath(uint cfcId)
{ {
if (!_territoryData.TryGetTerritoryIdForContentFinderCondition(cfcId, out uint territoryType)) if (!_territoryData.TryGetContentFinderCondition(cfcId, out var cfcData))
return false; return false;
try try
{ {
return _contentHasPath.InvokeFunc(territoryType); return _contentHasPath.InvokeFunc(cfcData.TerritoryId);
} }
catch (IpcError e) 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; return false;
} }
} }
public void StartInstance(uint cfcId) 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}"); throw new TaskException($"Unknown ContentFinderConditionId {cfcId}");
try try
{ {
_run.InvokeAction(territoryType, 0, true); _run.InvokeAction(cfcData.TerritoryId, 0, true);
} }
catch (IpcError e) catch (IpcError e)
{ {

View File

@ -7,6 +7,7 @@ using Dalamud.Interface.Windowing;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using LLib; using LLib;
using LLib.Gear;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Questionable.Controller; using Questionable.Controller;
@ -130,6 +131,8 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddSingleton<NotificationMasterIpc>(); serviceCollection.AddSingleton<NotificationMasterIpc>();
serviceCollection.AddSingleton<AutomatonIpc>(); serviceCollection.AddSingleton<AutomatonIpc>();
serviceCollection.AddSingleton<AutoDutyIpc>(); serviceCollection.AddSingleton<AutoDutyIpc>();
serviceCollection.AddSingleton<GearStatsCalculator>();
} }
private static void AddTaskFactories(ServiceCollection serviceCollection) private static void AddTaskFactories(ServiceCollection serviceCollection)

View File

@ -99,7 +99,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
{ {
Expansion = (EExpansionVersion)x.TerritoryType.Value.ExVersion.RowId, Expansion = (EExpansionVersion)x.TerritoryType.Value.ExVersion.RowId,
CfcId = x.RowId, CfcId = x.RowId,
Name = territoryData.GetContentFinderConditionName(x.RowId) ?? "?", Name = territoryData.GetContentFinderCondition(x.RowId)?.Name ?? "?",
TerritoryId = x.TerritoryType.RowId, TerritoryId = x.TerritoryType.RowId,
ContentType = x.ContentType.RowId, ContentType = x.ContentType.RowId,
Level = x.ClassJobLevelRequired, Level = x.ClassJobLevelRequired,