Add Quest and Leve support to IUnlockState (#2581)

* Fix AgentInterfacePtr.FocusAddon

* Add Quest support to IUnlockState

* Reorder, bail out early in Recipe and McGuffin

* Add Leve support to IUnlockState

* Fix warning

* Disable log spam
This commit is contained in:
Haselnussbomber 2026-01-25 05:03:57 +01:00 committed by GitHub
parent 3b8f0bc92f
commit b601bfdbfb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 6 deletions

View file

@ -81,7 +81,7 @@ public readonly unsafe struct AgentInterfacePtr(nint address) : IEquatable<Agent
/// Focuses the AtkUnitBase.
/// </summary>
/// <returns> <c>true</c> when the addon was focused, <c>false</c> otherwise. </returns>
public readonly bool FocusAddon() => this.IsNull && this.Struct->FocusAddon();
public readonly bool FocusAddon() => !this.IsNull && this.Struct->FocusAddon();
/// <summary>Determines whether the specified AgentInterfacePtr is equal to the current AgentInterfacePtr.</summary>
/// <param name="other">The AgentInterfacePtr to compare with the current AgentInterfacePtr.</param>

View file

@ -311,9 +311,12 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
}
/// <inheritdoc/>
public bool IsMcGuffinUnlocked(McGuffin row)
public bool IsLeveCompleted(Leve row)
{
return PlayerState.Instance()->IsMcGuffinUnlocked(row.RowId);
if (!this.IsLoaded)
return false;
return QuestManager.Instance()->IsLevequestComplete((ushort)row.RowId);
}
/// <inheritdoc/>
@ -328,6 +331,15 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
return this.IsUnlockLinkUnlocked(row.UnlockLink);
}
/// <inheritdoc/>
public bool IsMcGuffinUnlocked(McGuffin row)
{
if (!this.IsLoaded)
return false;
return PlayerState.Instance()->IsMcGuffinUnlocked(row.RowId);
}
/// <inheritdoc/>
public bool IsMountUnlocked(Mount row)
{
@ -376,9 +388,21 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
return UIState.IsPublicContentUnlocked(row.RowId);
}
/// <inheritdoc/>
public bool IsQuestCompleted(Quest row)
{
if (!this.IsLoaded)
return false;
return QuestManager.IsQuestComplete(row.RowId);
}
/// <inheritdoc/>
public bool IsRecipeUnlocked(Recipe row)
{
if (!this.IsLoaded)
return false;
return this.recipeData.IsRecipeUnlocked(row);
}
@ -509,6 +533,9 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
if (rowRef.TryGetValue<Item>(out var itemRow))
return this.IsItemUnlocked(itemRow);
if (rowRef.TryGetValue<Leve>(out var leveRow))
return this.IsLeveCompleted(leveRow);
if (rowRef.TryGetValue<MJILandmark>(out var mjiLandmarkRow))
return this.IsMJILandmarkUnlocked(mjiLandmarkRow);
@ -536,6 +563,9 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
if (rowRef.TryGetValue<PublicContentSheet>(out var publicContentRow))
return this.IsPublicContentUnlocked(publicContentRow);
if (rowRef.TryGetValue<Quest>(out var questRow))
return this.IsQuestCompleted(questRow);
if (rowRef.TryGetValue<Recipe>(out var recipeRow))
return this.IsRecipeUnlocked(recipeRow);
@ -596,6 +626,8 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
if (!this.IsLoaded)
return;
Log.Verbose("Checking for new unlocks...");
this.UpdateUnlocksForSheet<ActionSheet>();
this.UpdateUnlocksForSheet<AetherCurrent>();
this.UpdateUnlocksForSheet<AetherCurrentCompFlgSet>();
@ -629,6 +661,7 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
this.UpdateUnlocksForSheet<Ornament>();
this.UpdateUnlocksForSheet<Perform>();
this.UpdateUnlocksForSheet<PublicContentSheet>();
this.UpdateUnlocksForSheet<Quest>();
this.UpdateUnlocksForSheet<Recipe>();
this.UpdateUnlocksForSheet<SecretRecipeBook>();
this.UpdateUnlocksForSheet<Trait>();
@ -637,6 +670,7 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
// Not implemented:
// - DescriptionPage: quite complex
// - QuestAcceptAdditionCondition: ignored
// - Leve: AgentUpdateFlag.UnlocksUpdate is not set and the completed status can be unset again!
// For some other day:
// - FishingSpot
@ -676,7 +710,7 @@ internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
unlockedRowIds.Add(row.RowId);
Log.Verbose($"Unlock detected: {typeof(T).Name}#{row.RowId}");
// Log.Verbose($"Unlock detected: {typeof(T).Name}#{row.RowId}");
foreach (var action in Delegate.EnumerateInvocationList(this.Unlock))
{
@ -796,7 +830,7 @@ internal class UnlockStatePluginScoped : IInternalDisposableService, IUnlockStat
public bool IsItemUnlocked(Item row) => this.unlockStateService.IsItemUnlocked(row);
/// <inheritdoc/>
public bool IsMcGuffinUnlocked(McGuffin row) => this.unlockStateService.IsMcGuffinUnlocked(row);
public bool IsLeveCompleted(Leve row) => this.unlockStateService.IsLeveCompleted(row);
/// <inheritdoc/>
public bool IsMJILandmarkUnlocked(MJILandmark row) => this.unlockStateService.IsMJILandmarkUnlocked(row);
@ -804,6 +838,9 @@ internal class UnlockStatePluginScoped : IInternalDisposableService, IUnlockStat
/// <inheritdoc/>
public bool IsMKDLoreUnlocked(MKDLore row) => this.unlockStateService.IsMKDLoreUnlocked(row);
/// <inheritdoc/>
public bool IsMcGuffinUnlocked(McGuffin row) => this.unlockStateService.IsMcGuffinUnlocked(row);
/// <inheritdoc/>
public bool IsMountUnlocked(Mount row) => this.unlockStateService.IsMountUnlocked(row);
@ -822,6 +859,9 @@ internal class UnlockStatePluginScoped : IInternalDisposableService, IUnlockStat
/// <inheritdoc/>
public bool IsPublicContentUnlocked(PublicContentSheet row) => this.unlockStateService.IsPublicContentUnlocked(row);
/// <inheritdoc/>
public bool IsQuestCompleted(Quest row) => this.unlockStateService.IsQuestCompleted(row);
/// <inheritdoc/>
public bool IsRecipeUnlocked(Recipe row) => this.unlockStateService.IsRecipeUnlocked(row);

View file

@ -3,11 +3,11 @@ using System.Numerics;
using System.Text;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Data;
using Dalamud.Interface.ImGuiNotification;
using Dalamud.Interface.ImGuiNotification.Internal;
using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
using Dalamud.Interface.Utility.Raii;
using Lumina.Excel.Sheets;

View file

@ -205,6 +205,13 @@ public interface IUnlockState : IDalamudService
/// <returns><see langword="true"/> if unlocked; otherwise, <see langword="false"/>.</returns>
bool IsItemUnlocked(Item row);
/// <summary>
/// Determines whether the specified Leve is completed.
/// </summary>
/// <param name="row">The Leve row to check.</param>
/// <returns><see langword="true"/> if completed; otherwise, <see langword="false"/>.</returns>
bool IsLeveCompleted(Leve row);
/// <summary>
/// Determines whether the specified McGuffin is unlocked.
/// </summary>
@ -268,6 +275,13 @@ public interface IUnlockState : IDalamudService
/// <returns><see langword="true"/> if unlocked; otherwise, <see langword="false"/>.</returns>
bool IsPublicContentUnlocked(PublicContent row);
/// <summary>
/// Determines whether the specified Quest is completed.
/// </summary>
/// <param name="row">The Quest row to check.</param>
/// <returns><see langword="true"/> if completed; otherwise, <see langword="false"/>.</returns>
bool IsQuestCompleted(Quest row);
/// <summary>
/// Determines whether the specified Recipe is unlocked.
/// </summary>