diff --git a/Dalamud/Game/UnlockState/ItemActionType.cs b/Dalamud/Game/UnlockState/ItemActionType.cs
deleted file mode 100644
index 8e3d79b84..000000000
--- a/Dalamud/Game/UnlockState/ItemActionType.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using Lumina.Excel.Sheets;
-
-namespace Dalamud.Game.UnlockState;
-
-///
-/// Enum for .
-///
-internal enum ItemActionType : ushort
-{
- ///
- /// No item action.
- ///
- None = 0,
-
- ///
- /// Unlocks a companion (minion).
- ///
- Companion = 853,
-
- ///
- /// Unlocks a chocobo companion barding.
- ///
- BuddyEquip = 1013,
-
- ///
- /// Unlocks a mount.
- ///
- Mount = 1322,
-
- ///
- /// Unlocks recipes from a crafting recipe book.
- ///
- SecretRecipeBook = 2136,
-
- ///
- /// Unlocks various types of content (e.g. Riding Maps, Blue Mage Totems, Emotes, Hairstyles).
- ///
- UnlockLink = 2633,
-
- ///
- /// Unlocks a Triple Triad Card.
- ///
- TripleTriadCard = 3357,
-
- ///
- /// Unlocks gathering nodes of a Folklore Tome.
- ///
- FolkloreTome = 4107,
-
- ///
- /// Unlocks an Orchestrion Roll.
- ///
- OrchestrionRoll = 25183,
-
- ///
- /// Unlocks portrait designs.
- ///
- FramersKit = 29459,
-
- ///
- /// Unlocks Bozjan Field Notes.
- ///
- /// These are server-side but are cached client-side.
- FieldNotes = 19743,
-
- ///
- /// Unlocks an Ornament (fashion accessory).
- ///
- Ornament = 20086,
-
- ///
- /// Unlocks Glasses.
- ///
- Glasses = 37312,
-
- ///
- /// Company Seal Vouchers, which convert the item into Company Seals when used.
- ///
- CompanySealVouchers = 41120,
-
- ///
- /// Unlocks Occult Records in Occult Crescent.
- ///
- OccultRecords = 43141,
-
- ///
- /// Unlocks Phantom Jobs in Occult Crescent.
- ///
- SoulShards = 43142,
-
- ///
- /// Star Contributor Certificate, which grants the Star Contributor status in Cosmic Exploration.
- ///
- StarContributorCertificate = 45189,
-}
diff --git a/Dalamud/Game/UnlockState/RecipeData.cs b/Dalamud/Game/UnlockState/RecipeData.cs
deleted file mode 100644
index c419ba4fd..000000000
--- a/Dalamud/Game/UnlockState/RecipeData.cs
+++ /dev/null
@@ -1,283 +0,0 @@
-using System.Linq;
-
-using CommunityToolkit.HighPerformance;
-
-using Dalamud.Data;
-using Dalamud.Game.Gui;
-
-using FFXIVClientStructs.FFXIV.Client.Game;
-using FFXIVClientStructs.FFXIV.Client.Game.UI;
-using FFXIVClientStructs.Interop;
-
-using Lumina.Excel.Sheets;
-
-namespace Dalamud.Game.UnlockState;
-
-///
-/// Represents recipe-related data for all crafting classes.
-///
-[ServiceManager.EarlyLoadedService]
-internal unsafe class RecipeData : IInternalDisposableService
-{
- [ServiceManager.ServiceDependency]
- private readonly DataManager dataManager = Service.Get();
-
- [ServiceManager.ServiceDependency]
- private readonly ClientState.ClientState clientState = Service.Get();
-
- [ServiceManager.ServiceDependency]
- private readonly GameGui gameGui = Service.Get();
-
- private readonly ushort[] craftTypeLevels;
- private readonly byte[] unlockedNoteBookDivisionsCount;
- private readonly byte[] unlockedSecretNoteBookDivisionsCount;
- private readonly ushort[,] noteBookDivisionIds;
- private byte[]? cachedUnlockedSecretRecipeBooks;
- private byte[]? cachedUnlockLinks;
- private byte[]? cachedCompletedQuests;
-
- ///
- /// Initializes a new instance of the class.
- ///
- [ServiceManager.ServiceConstructor]
- public RecipeData()
- {
- var numCraftTypes = this.dataManager.GetExcelSheet().Count();
- var numSecretNotBookDivisions = this.dataManager.GetExcelSheet().Count(row => row.RowId is >= 1000 and < 2000);
-
- this.unlockedNoteBookDivisionsCount = new byte[numCraftTypes];
- this.unlockedSecretNoteBookDivisionsCount = new byte[numCraftTypes];
- this.noteBookDivisionIds = new ushort[numCraftTypes, numSecretNotBookDivisions];
-
- this.craftTypeLevels = new ushort[numCraftTypes];
-
- this.clientState.Login += this.Update;
- this.clientState.Logout += this.OnLogout;
- this.clientState.LevelChanged += this.OnlevelChanged;
- this.gameGui.AgentUpdate += this.OnAgentUpdate;
- }
-
- ///
- void IInternalDisposableService.DisposeService()
- {
- this.clientState.Login -= this.Update;
- this.clientState.Logout -= this.OnLogout;
- this.clientState.LevelChanged -= this.OnlevelChanged;
- this.gameGui.AgentUpdate -= this.OnAgentUpdate;
- }
-
- ///
- /// Determines whether the specified Recipe is unlocked.
- ///
- /// The Recipe row to check.
- /// if unlocked; otherwise, .
- public bool IsRecipeUnlocked(Recipe row)
- {
- // E8 ?? ?? ?? ?? 48 63 76 (2025.09.04)
- var division = row.RecipeNotebookList.RowId != 0 && row.RecipeNotebookList.IsValid
- ? (row.RecipeNotebookList.RowId - 1000) / 8 + 1000
- : ((uint)row.RecipeLevelTable.Value.ClassJobLevel - 1) / 5;
-
- // E8 ?? ?? ?? ?? 33 ED 84 C0 75 (2025.09.04)
- foreach (var craftTypeRow in this.dataManager.GetExcelSheet())
- {
- var craftType = (byte)craftTypeRow.RowId;
-
- if (division < this.unlockedNoteBookDivisionsCount[craftType])
- return true;
-
- if (this.unlockedNoteBookDivisionsCount[craftType] == 0)
- continue;
-
- if (division is 5000 or 5001)
- return true;
-
- if (division < 1000)
- continue;
-
- if (this.unlockedSecretNoteBookDivisionsCount[craftType] == 0)
- continue;
-
- if (this.noteBookDivisionIds.GetRowSpan(craftType).Contains((ushort)division))
- return true;
- }
-
- return false;
- }
-
- private void OnLogout(int type, int code)
- {
- this.cachedUnlockedSecretRecipeBooks = null;
- this.cachedUnlockLinks = null;
- this.cachedCompletedQuests = null;
- }
-
- private void OnlevelChanged(uint classJobId, uint level)
- {
- if (this.dataManager.GetExcelSheet().TryGetRow(classJobId, out var classJobRow) &&
- classJobRow.ClassJobCategory.RowId == 33) // Crafter
- {
- this.Update();
- }
- }
-
- private void OnAgentUpdate(AgentUpdateFlag agentUpdateFlag)
- {
- if (agentUpdateFlag.HasFlag(AgentUpdateFlag.UnlocksUpdate))
- this.Update();
- }
-
- private void Update()
- {
- // based on Client::Game::UI::RecipeNote.InitializeStructs
-
- if (!this.clientState.IsLoggedIn || !this.NeedsUpdate())
- return;
-
- Array.Clear(this.unlockedNoteBookDivisionsCount, 0, this.unlockedNoteBookDivisionsCount.Length);
- Array.Clear(this.unlockedSecretNoteBookDivisionsCount, 0, this.unlockedSecretNoteBookDivisionsCount.Length);
- Array.Clear(this.noteBookDivisionIds, 0, this.noteBookDivisionIds.Length);
-
- foreach (var craftTypeRow in this.dataManager.GetExcelSheet())
- {
- var craftType = (byte)craftTypeRow.RowId;
- var craftTypeLevel = RecipeNote.Instance()->GetCraftTypeLevel(craftType);
- if (craftTypeLevel == 0)
- continue;
-
- var noteBookDivisionIndex = -1;
-
- foreach (var noteBookDivisionRow in this.dataManager.GetExcelSheet())
- {
- if (noteBookDivisionRow.RowId < 1000)
- {
- if (craftTypeLevel >= noteBookDivisionRow.CraftOpeningLevel)
- this.unlockedNoteBookDivisionsCount[craftType]++;
- }
- else if (noteBookDivisionRow.RowId < 2000)
- {
- noteBookDivisionIndex++;
-
- // For future Lumina.Excel update, replace with:
- // if (!notebookDivisionRow.AllowedCraftTypes[craftType])
- // continue;
-
- switch (craftTypeRow.RowId)
- {
- case 0 when !noteBookDivisionRow.CRPCraft: continue;
- case 1 when !noteBookDivisionRow.BSMCraft: continue;
- case 2 when !noteBookDivisionRow.ARMCraft: continue;
- case 3 when !noteBookDivisionRow.GSMCraft: continue;
- case 4 when !noteBookDivisionRow.LTWCraft: continue;
- case 5 when !noteBookDivisionRow.WVRCraft: continue;
- case 6 when !noteBookDivisionRow.ALCCraft: continue;
- case 7 when !noteBookDivisionRow.CULCraft: continue;
- }
-
- if (noteBookDivisionRow.GatheringOpeningLevel != byte.MaxValue)
- continue;
-
- // For future Lumina.Excel update, replace with:
- // if (notebookDivisionRow.RequiresSecretRecipeBookGroupUnlock)
- if (noteBookDivisionRow.Unknown1)
- {
- var secretRecipeBookUnlocked = false;
-
- // For future Lumina.Excel update, iterate over notebookDivisionRow.SecretRecipeBookGroups
- for (var i = 0; i < 2; i++)
- {
- // For future Lumina.Excel update, replace with:
- // if (secretRecipeBookGroup.RowId == 0 || !secretRecipeBookGroup.IsValid)
- // continue;
- var secretRecipeBookGroupRowId = i switch
- {
- 0 => noteBookDivisionRow.Unknown2,
- 1 => noteBookDivisionRow.Unknown2,
- _ => default,
- };
-
- if (secretRecipeBookGroupRowId == 0)
- continue;
-
- if (!this.dataManager.GetExcelSheet().TryGetRow(secretRecipeBookGroupRowId, out var secretRecipeBookGroupRow))
- continue;
-
- // For future Lumina.Excel update, replace with:
- // var bitIndex = secretRecipeBookGroup.Value.UnlockBitIndex[craftType];
-
- var bitIndex = craftType switch
- {
- 0 => secretRecipeBookGroupRow.Unknown0,
- 1 => secretRecipeBookGroupRow.Unknown1,
- 2 => secretRecipeBookGroupRow.Unknown2,
- 3 => secretRecipeBookGroupRow.Unknown3,
- 4 => secretRecipeBookGroupRow.Unknown4,
- 5 => secretRecipeBookGroupRow.Unknown5,
- 6 => secretRecipeBookGroupRow.Unknown6,
- 7 => secretRecipeBookGroupRow.Unknown7,
- _ => default,
- };
-
- if (PlayerState.Instance()->UnlockedSecretRecipeBooksBitArray.Get(bitIndex))
- {
- secretRecipeBookUnlocked = true;
- break;
- }
- }
-
- if (noteBookDivisionRow.CraftOpeningLevel > craftTypeLevel && !secretRecipeBookUnlocked)
- continue;
- }
- else if (craftTypeLevel < noteBookDivisionRow.CraftOpeningLevel)
- {
- continue;
- }
- else if (noteBookDivisionRow.QuestUnlock.RowId != 0 && !UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(noteBookDivisionRow.QuestUnlock.RowId))
- {
- continue;
- }
-
- this.unlockedSecretNoteBookDivisionsCount[craftType]++;
- this.noteBookDivisionIds[craftType, noteBookDivisionIndex] = (ushort)noteBookDivisionRow.RowId;
- }
- }
- }
- }
-
- private bool NeedsUpdate()
- {
- var changed = false;
-
- foreach (var craftTypeRow in this.dataManager.GetExcelSheet())
- {
- var craftType = (byte)craftTypeRow.RowId;
- var craftTypeLevel = RecipeNote.Instance()->GetCraftTypeLevel(craftType);
-
- if (this.craftTypeLevels[craftType] != craftTypeLevel)
- {
- this.craftTypeLevels[craftType] = craftTypeLevel;
- changed |= true;
- }
- }
-
- if (this.cachedUnlockedSecretRecipeBooks == null || !PlayerState.Instance()->UnlockedSecretRecipeBooks.SequenceEqual(this.cachedUnlockedSecretRecipeBooks))
- {
- this.cachedUnlockedSecretRecipeBooks = PlayerState.Instance()->UnlockedSecretRecipeBooks.ToArray();
- changed |= true;
- }
-
- if (this.cachedUnlockLinks == null || !UIState.Instance()->UnlockLinks.SequenceEqual(this.cachedUnlockLinks))
- {
- this.cachedUnlockLinks = UIState.Instance()->UnlockLinks.ToArray();
- changed |= true;
- }
-
- if (this.cachedCompletedQuests == null || !QuestManager.Instance()->CompletedQuests.SequenceEqual(this.cachedCompletedQuests))
- {
- this.cachedCompletedQuests = QuestManager.Instance()->CompletedQuests.ToArray();
- changed |= true;
- }
-
- return changed;
- }
-}
diff --git a/Dalamud/Game/UnlockState/UnlockState.cs b/Dalamud/Game/UnlockState/UnlockState.cs
deleted file mode 100644
index a4b9381cc..000000000
--- a/Dalamud/Game/UnlockState/UnlockState.cs
+++ /dev/null
@@ -1,858 +0,0 @@
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-
-using Dalamud.Data;
-using Dalamud.Game.Gui;
-using Dalamud.IoC;
-using Dalamud.IoC.Internal;
-using Dalamud.Logging.Internal;
-using Dalamud.Plugin.Services;
-
-using FFXIVClientStructs.FFXIV.Client.Game;
-using FFXIVClientStructs.FFXIV.Client.Game.InstanceContent;
-using FFXIVClientStructs.FFXIV.Client.Game.UI;
-using FFXIVClientStructs.FFXIV.Component.Exd;
-
-using Lumina.Excel;
-using Lumina.Excel.Sheets;
-
-using ActionSheet = Lumina.Excel.Sheets.Action;
-using InstanceContentSheet = Lumina.Excel.Sheets.InstanceContent;
-using PublicContentSheet = Lumina.Excel.Sheets.PublicContent;
-
-namespace Dalamud.Game.UnlockState;
-
-#pragma warning disable UnlockState
-
-///
-/// This class provides unlock state of various content in the game.
-///
-[ServiceManager.EarlyLoadedService]
-internal unsafe class UnlockState : IInternalDisposableService, IUnlockState
-{
- private static readonly ModuleLog Log = new(nameof(UnlockState));
-
- private readonly ConcurrentDictionary> cachedUnlockedRowIds = [];
-
- [ServiceManager.ServiceDependency]
- private readonly DataManager dataManager = Service.Get();
-
- [ServiceManager.ServiceDependency]
- private readonly ClientState.ClientState clientState = Service.Get();
-
- [ServiceManager.ServiceDependency]
- private readonly GameGui gameGui = Service.Get();
-
- [ServiceManager.ServiceDependency]
- private readonly RecipeData recipeData = Service.Get();
-
- [ServiceManager.ServiceConstructor]
- private UnlockState()
- {
- this.clientState.Login += this.OnLogin;
- this.clientState.Logout += this.OnLogout;
- this.gameGui.AgentUpdate += this.OnAgentUpdate;
- }
-
- ///
- public event IUnlockState.UnlockDelegate Unlock;
-
- private bool IsLoaded => PlayerState.Instance()->IsLoaded;
-
- ///
- void IInternalDisposableService.DisposeService()
- {
- this.clientState.Login -= this.OnLogin;
- this.clientState.Logout -= this.OnLogout;
- this.gameGui.AgentUpdate -= this.OnAgentUpdate;
- }
-
- ///
- public bool IsActionUnlocked(ActionSheet row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink.RowId);
- }
-
- ///
- public bool IsAetherCurrentUnlocked(AetherCurrent row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsAetherCurrentUnlocked(row.RowId);
- }
-
- ///
- public bool IsAetherCurrentCompFlgSetUnlocked(AetherCurrentCompFlgSet row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsAetherCurrentZoneComplete(row.RowId);
- }
-
- ///
- public bool IsAozActionUnlocked(AozAction row)
- {
- if (!this.IsLoaded)
- return false;
-
- if (row.RowId == 0 || !row.Action.IsValid)
- return false;
-
- return UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(row.Action.Value.UnlockLink.RowId);
- }
-
- ///
- public bool IsBannerBgUnlocked(BannerBg row)
- {
- return row.UnlockCondition.IsValid && this.IsBannerConditionUnlocked(row.UnlockCondition.Value);
- }
-
- ///
- public bool IsBannerConditionUnlocked(BannerCondition row)
- {
- if (row.RowId == 0)
- return false;
-
- if (!this.IsLoaded)
- return false;
-
- var rowPtr = ExdModule.GetBannerConditionByIndex(row.RowId);
- if (rowPtr == null)
- return false;
-
- return ExdModule.GetBannerConditionUnlockState(rowPtr) == 0;
- }
-
- ///
- public bool IsBannerDecorationUnlocked(BannerDecoration row)
- {
- return row.UnlockCondition.IsValid && this.IsBannerConditionUnlocked(row.UnlockCondition.Value);
- }
-
- ///
- public bool IsBannerFacialUnlocked(BannerFacial row)
- {
- return row.UnlockCondition.IsValid && this.IsBannerConditionUnlocked(row.UnlockCondition.Value);
- }
-
- ///
- public bool IsBannerFrameUnlocked(BannerFrame row)
- {
- return row.UnlockCondition.IsValid && this.IsBannerConditionUnlocked(row.UnlockCondition.Value);
- }
-
- ///
- public bool IsBannerTimelineUnlocked(BannerTimeline row)
- {
- return row.UnlockCondition.IsValid && this.IsBannerConditionUnlocked(row.UnlockCondition.Value);
- }
-
- ///
- public bool IsBuddyActionUnlocked(BuddyAction row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsBuddyEquipUnlocked(BuddyEquip row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.Instance()->Buddy.CompanionInfo.IsBuddyEquipUnlocked(row.RowId);
- }
-
- ///
- public bool IsCharaMakeCustomizeUnlocked(CharaMakeCustomize row)
- {
- return row.IsPurchasable && this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsChocoboTaxiStandUnlocked(ChocoboTaxiStand row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.Instance()->IsChocoboTaxiStandUnlocked(row.RowId);
- }
-
- ///
- public bool IsCompanionUnlocked(Companion row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.Instance()->IsCompanionUnlocked(row.RowId);
- }
-
- ///
- public bool IsCraftActionUnlocked(CraftAction row)
- {
- return this.IsUnlockLinkUnlocked(row.QuestRequirement.RowId);
- }
-
- ///
- public bool IsCSBonusContentTypeUnlocked(CSBonusContentType row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsEmoteUnlocked(Emote row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsEmjVoiceNpcUnlocked(EmjVoiceNpc row)
- {
- return this.IsUnlockLinkUnlocked(row.Unknown26);
- }
-
- ///
- public bool IsEmjCostumeUnlocked(EmjCostume row)
- {
- return this.dataManager.GetExcelSheet().TryGetRow(row.RowId, out var emjVoiceNpcRow)
- && this.IsEmjVoiceNpcUnlocked(emjVoiceNpcRow)
- && QuestManager.IsQuestComplete(row.Unknown1);
- }
-
- ///
- public bool IsGeneralActionUnlocked(GeneralAction row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsGlassesUnlocked(Glasses row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsGlassesUnlocked((ushort)row.RowId);
- }
-
- ///
- public bool IsHowToUnlocked(HowTo row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.Instance()->IsHowToUnlocked(row.RowId);
- }
-
- ///
- public bool IsInstanceContentUnlocked(InstanceContentSheet row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.IsInstanceContentUnlocked(row.RowId);
- }
-
- ///
- public unsafe bool IsItemUnlocked(Item row)
- {
- if (row.ItemAction.RowId == 0)
- return false;
-
- if (!this.IsLoaded)
- return false;
-
- // To avoid the ExdModule.GetItemRowById call, which can return null if the excel page
- // is not loaded, we're going to imitate the IsItemActionUnlocked call first:
- switch ((ItemActionType)row.ItemAction.Value.Type)
- {
- case ItemActionType.Companion:
- return UIState.Instance()->IsCompanionUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.BuddyEquip:
- return UIState.Instance()->Buddy.CompanionInfo.IsBuddyEquipUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.Mount:
- return PlayerState.Instance()->IsMountUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.SecretRecipeBook:
- return PlayerState.Instance()->IsSecretRecipeBookUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.UnlockLink:
- case ItemActionType.OccultRecords:
- return UIState.Instance()->IsUnlockLinkUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.TripleTriadCard when row.AdditionalData.Is():
- return UIState.Instance()->IsTripleTriadCardUnlocked((ushort)row.AdditionalData.RowId);
-
- case ItemActionType.FolkloreTome:
- return PlayerState.Instance()->IsFolkloreBookUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.OrchestrionRoll when row.AdditionalData.Is():
- return PlayerState.Instance()->IsOrchestrionRollUnlocked(row.AdditionalData.RowId);
-
- case ItemActionType.FramersKit:
- return PlayerState.Instance()->IsFramersKitUnlocked(row.AdditionalData.RowId);
-
- case ItemActionType.Ornament:
- return PlayerState.Instance()->IsOrnamentUnlocked(row.ItemAction.Value.Data[0]);
-
- case ItemActionType.Glasses:
- return PlayerState.Instance()->IsGlassesUnlocked((ushort)row.AdditionalData.RowId);
-
- case ItemActionType.SoulShards when PublicContentOccultCrescent.GetState() is var occultCrescentState && occultCrescentState != null:
- var supportJobId = (byte)row.ItemAction.Value.Data[0];
- return supportJobId < occultCrescentState->SupportJobLevels.Length && occultCrescentState->SupportJobLevels[supportJobId] != 0;
-
- case ItemActionType.CompanySealVouchers:
- return false;
- }
-
- var nativeRow = ExdModule.GetItemRowById(row.RowId);
- return nativeRow != null && UIState.Instance()->IsItemActionUnlocked(nativeRow) == 1;
- }
-
- ///
- public bool IsMcGuffinUnlocked(McGuffin row)
- {
- return PlayerState.Instance()->IsMcGuffinUnlocked(row.RowId);
- }
-
- ///
- public bool IsMJILandmarkUnlocked(MJILandmark row)
- {
- return this.IsUnlockLinkUnlocked(row.UnlockLink);
- }
-
- ///
- public bool IsMKDLoreUnlocked(MKDLore row)
- {
- return this.IsUnlockLinkUnlocked(row.Unknown2);
- }
-
- ///
- public bool IsMountUnlocked(Mount row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsMountUnlocked(row.RowId);
- }
-
- ///
- public bool IsNotebookDivisionUnlocked(NotebookDivision row)
- {
- return this.IsUnlockLinkUnlocked(row.QuestUnlock.RowId);
- }
-
- ///
- public bool IsOrchestrionUnlocked(Orchestrion row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsOrchestrionRollUnlocked(row.RowId);
- }
-
- ///
- public bool IsOrnamentUnlocked(Ornament row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsOrnamentUnlocked(row.RowId);
- }
-
- ///
- public bool IsPerformUnlocked(Perform row)
- {
- return this.IsUnlockLinkUnlocked((uint)row.UnlockLink);
- }
-
- ///
- public bool IsPublicContentUnlocked(PublicContentSheet row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.IsPublicContentUnlocked(row.RowId);
- }
-
- ///
- public bool IsRecipeUnlocked(Recipe row)
- {
- return this.recipeData.IsRecipeUnlocked(row);
- }
-
- ///
- public bool IsSecretRecipeBookUnlocked(SecretRecipeBook row)
- {
- if (!this.IsLoaded)
- return false;
-
- return PlayerState.Instance()->IsSecretRecipeBookUnlocked(row.RowId);
- }
-
- ///
- public bool IsTraitUnlocked(Trait row)
- {
- return this.IsUnlockLinkUnlocked(row.Quest.RowId);
- }
-
- ///
- public bool IsTripleTriadCardUnlocked(TripleTriadCard row)
- {
- if (!this.IsLoaded)
- return false;
-
- return UIState.Instance()->IsTripleTriadCardUnlocked((ushort)row.RowId);
- }
-
- ///
- public bool IsItemUnlockable(Item row)
- {
- if (row.ItemAction.RowId == 0)
- return false;
-
- return (ItemActionType)row.ItemAction.Value.Type
- is ItemActionType.Companion
- or ItemActionType.BuddyEquip
- or ItemActionType.Mount
- or ItemActionType.SecretRecipeBook
- or ItemActionType.UnlockLink
- or ItemActionType.TripleTriadCard
- or ItemActionType.FolkloreTome
- or ItemActionType.OrchestrionRoll
- or ItemActionType.FramersKit
- or ItemActionType.Ornament
- or ItemActionType.Glasses
- or ItemActionType.OccultRecords
- or ItemActionType.SoulShards;
- }
-
- ///
- public bool IsRowRefUnlocked(RowRef rowRef) where T : struct, IExcelRow
- {
- return this.IsRowRefUnlocked((RowRef)rowRef);
- }
-
- ///
- public bool IsRowRefUnlocked(RowRef rowRef)
- {
- if (!this.IsLoaded || rowRef.IsUntyped)
- return false;
-
- if (rowRef.TryGetValue(out var actionRow))
- return this.IsActionUnlocked(actionRow);
-
- if (rowRef.TryGetValue(out var aetherCurrentRow))
- return this.IsAetherCurrentUnlocked(aetherCurrentRow);
-
- if (rowRef.TryGetValue(out var aetherCurrentCompFlgSetRow))
- return this.IsAetherCurrentCompFlgSetUnlocked(aetherCurrentCompFlgSetRow);
-
- if (rowRef.TryGetValue(out var aozActionRow))
- return this.IsAozActionUnlocked(aozActionRow);
-
- if (rowRef.TryGetValue(out var bannerBgRow))
- return this.IsBannerBgUnlocked(bannerBgRow);
-
- if (rowRef.TryGetValue(out var bannerConditionRow))
- return this.IsBannerConditionUnlocked(bannerConditionRow);
-
- if (rowRef.TryGetValue(out var bannerDecorationRow))
- return this.IsBannerDecorationUnlocked(bannerDecorationRow);
-
- if (rowRef.TryGetValue(out var bannerFacialRow))
- return this.IsBannerFacialUnlocked(bannerFacialRow);
-
- if (rowRef.TryGetValue(out var bannerFrameRow))
- return this.IsBannerFrameUnlocked(bannerFrameRow);
-
- if (rowRef.TryGetValue(out var bannerTimelineRow))
- return this.IsBannerTimelineUnlocked(bannerTimelineRow);
-
- if (rowRef.TryGetValue(out var buddyActionRow))
- return this.IsBuddyActionUnlocked(buddyActionRow);
-
- if (rowRef.TryGetValue(out var buddyEquipRow))
- return this.IsBuddyEquipUnlocked(buddyEquipRow);
-
- if (rowRef.TryGetValue(out var csBonusContentTypeRow))
- return this.IsCSBonusContentTypeUnlocked(csBonusContentTypeRow);
-
- if (rowRef.TryGetValue(out var charaMakeCustomizeRow))
- return this.IsCharaMakeCustomizeUnlocked(charaMakeCustomizeRow);
-
- if (rowRef.TryGetValue(out var chocoboTaxiStandRow))
- return this.IsChocoboTaxiStandUnlocked(chocoboTaxiStandRow);
-
- if (rowRef.TryGetValue(out var companionRow))
- return this.IsCompanionUnlocked(companionRow);
-
- if (rowRef.TryGetValue(out var craftActionRow))
- return this.IsCraftActionUnlocked(craftActionRow);
-
- if (rowRef.TryGetValue(out var emoteRow))
- return this.IsEmoteUnlocked(emoteRow);
-
- if (rowRef.TryGetValue(out var generalActionRow))
- return this.IsGeneralActionUnlocked(generalActionRow);
-
- if (rowRef.TryGetValue(out var glassesRow))
- return this.IsGlassesUnlocked(glassesRow);
-
- if (rowRef.TryGetValue(out var howToRow))
- return this.IsHowToUnlocked(howToRow);
-
- if (rowRef.TryGetValue(out var instanceContentRow))
- return this.IsInstanceContentUnlocked(instanceContentRow);
-
- if (rowRef.TryGetValue- (out var itemRow))
- return this.IsItemUnlocked(itemRow);
-
- if (rowRef.TryGetValue(out var mjiLandmarkRow))
- return this.IsMJILandmarkUnlocked(mjiLandmarkRow);
-
- if (rowRef.TryGetValue(out var mkdLoreRow))
- return this.IsMKDLoreUnlocked(mkdLoreRow);
-
- if (rowRef.TryGetValue(out var mcGuffinRow))
- return this.IsMcGuffinUnlocked(mcGuffinRow);
-
- if (rowRef.TryGetValue(out var mountRow))
- return this.IsMountUnlocked(mountRow);
-
- if (rowRef.TryGetValue(out var notebookDivisionRow))
- return this.IsNotebookDivisionUnlocked(notebookDivisionRow);
-
- if (rowRef.TryGetValue(out var orchestrionRow))
- return this.IsOrchestrionUnlocked(orchestrionRow);
-
- if (rowRef.TryGetValue(out var ornamentRow))
- return this.IsOrnamentUnlocked(ornamentRow);
-
- if (rowRef.TryGetValue(out var performRow))
- return this.IsPerformUnlocked(performRow);
-
- if (rowRef.TryGetValue(out var publicContentRow))
- return this.IsPublicContentUnlocked(publicContentRow);
-
- if (rowRef.TryGetValue(out var recipeRow))
- return this.IsRecipeUnlocked(recipeRow);
-
- if (rowRef.TryGetValue(out var secretRecipeBookRow))
- return this.IsSecretRecipeBookUnlocked(secretRecipeBookRow);
-
- if (rowRef.TryGetValue(out var traitRow))
- return this.IsTraitUnlocked(traitRow);
-
- if (rowRef.TryGetValue(out var tripleTriadCardRow))
- return this.IsTripleTriadCardUnlocked(tripleTriadCardRow);
-
- return false;
- }
-
- ///
- public bool IsUnlockLinkUnlocked(ushort unlockLink)
- {
- if (!this.IsLoaded)
- return false;
-
- if (unlockLink == 0)
- return false;
-
- return UIState.Instance()->IsUnlockLinkUnlocked(unlockLink);
- }
-
- ///
- public bool IsUnlockLinkUnlocked(uint unlockLink)
- {
- if (!this.IsLoaded)
- return false;
-
- if (unlockLink == 0)
- return false;
-
- return UIState.Instance()->IsUnlockLinkUnlockedOrQuestCompleted(unlockLink);
- }
-
- private void OnLogin()
- {
- this.Update();
- }
-
- private void OnLogout(int type, int code)
- {
- this.cachedUnlockedRowIds.Clear();
- }
-
- private void OnAgentUpdate(AgentUpdateFlag agentUpdateFlag)
- {
- if (agentUpdateFlag.HasFlag(AgentUpdateFlag.UnlocksUpdate))
- this.Update();
- }
-
- private void Update()
- {
- if (!this.IsLoaded)
- return;
-
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet
- ();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
- this.UpdateUnlocksForSheet();
-
- // Not implemented:
- // - DescriptionPage: quite complex
- // - QuestAcceptAdditionCondition: ignored
-
- // For some other day:
- // - FishingSpot
- // - Spearfishing
- // - Adventure (Sightseeing)
- // - MinerFolkloreTome
- // - BotanistFolkloreTome
- // - FishingFolkloreTome
- // - VVD or is that unlocked via quest?
- // - VVDNotebookContents?
- // - FramersKit (is that just an Item?)
- // - ... more?
-
- // Subrow sheets, which are incompatible with the current Unlock event, since RowRef doesn't carry the SubrowId:
- // - EmjCostume
-
- // Probably not happening, because it requires fetching data from server:
- // - Achievements
- // - Titles
- // - Bozjan Field Notes
- // - Support/Phantom Jobs, which require to be in Occult Crescent, because it checks the jobs level for != 0
- }
-
- private void UpdateUnlocksForSheet() where T : struct, IExcelRow
- {
- var unlockedRowIds = this.cachedUnlockedRowIds.GetOrAdd(typeof(T), _ => []);
-
- foreach (var row in this.dataManager.GetExcelSheet())
- {
- if (unlockedRowIds.Contains(row.RowId))
- continue;
-
- var rowRef = LuminaUtils.CreateRef(row.RowId);
-
- if (!this.IsRowRefUnlocked(rowRef))
- continue;
-
- unlockedRowIds.Add(row.RowId);
-
- Log.Verbose($"Unlock detected: {typeof(T).Name}#{row.RowId}");
-
- foreach (var action in Delegate.EnumerateInvocationList(this.Unlock))
- {
- try
- {
- action((RowRef)rowRef);
- }
- catch (Exception ex)
- {
- Log.Error(ex, "Exception during raise of {handler}", action.Method);
- }
- }
- }
- }
-}
-
-///
-/// Plugin-scoped version of a service.
-///
-[PluginInterface]
-[ServiceManager.ScopedService]
-#pragma warning disable SA1015
-[ResolveVia]
-#pragma warning restore SA1015
-internal class UnlockStatePluginScoped : IInternalDisposableService, IUnlockState
-{
- [ServiceManager.ServiceDependency]
- private readonly UnlockState unlockStateService = Service.Get();
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal UnlockStatePluginScoped()
- {
- this.unlockStateService.Unlock += this.UnlockForward;
- }
-
- ///
- public event IUnlockState.UnlockDelegate? Unlock;
-
- ///
- public bool IsActionUnlocked(ActionSheet row) => this.unlockStateService.IsActionUnlocked(row);
-
- ///
- public bool IsAetherCurrentCompFlgSetUnlocked(AetherCurrentCompFlgSet row) => this.unlockStateService.IsAetherCurrentCompFlgSetUnlocked(row);
-
- ///
- public bool IsAetherCurrentUnlocked(AetherCurrent row) => this.unlockStateService.IsAetherCurrentUnlocked(row);
-
- ///
- public bool IsAozActionUnlocked(AozAction row) => this.unlockStateService.IsAozActionUnlocked(row);
-
- ///
- public bool IsBannerBgUnlocked(BannerBg row) => this.unlockStateService.IsBannerBgUnlocked(row);
-
- ///
- public bool IsBannerConditionUnlocked(BannerCondition row) => this.unlockStateService.IsBannerConditionUnlocked(row);
-
- ///
- public bool IsBannerDecorationUnlocked(BannerDecoration row) => this.unlockStateService.IsBannerDecorationUnlocked(row);
-
- ///
- public bool IsBannerFacialUnlocked(BannerFacial row) => this.unlockStateService.IsBannerFacialUnlocked(row);
-
- ///
- public bool IsBannerFrameUnlocked(BannerFrame row) => this.unlockStateService.IsBannerFrameUnlocked(row);
-
- ///
- public bool IsBannerTimelineUnlocked(BannerTimeline row) => this.unlockStateService.IsBannerTimelineUnlocked(row);
-
- ///
- public bool IsBuddyActionUnlocked(BuddyAction row) => this.unlockStateService.IsBuddyActionUnlocked(row);
-
- ///
- public bool IsBuddyEquipUnlocked(BuddyEquip row) => this.unlockStateService.IsBuddyEquipUnlocked(row);
-
- ///
- public bool IsCharaMakeCustomizeUnlocked(CharaMakeCustomize row) => this.unlockStateService.IsCharaMakeCustomizeUnlocked(row);
-
- ///
- public bool IsChocoboTaxiStandUnlocked(ChocoboTaxiStand row) => this.unlockStateService.IsChocoboTaxiStandUnlocked(row);
-
- ///
- public bool IsCompanionUnlocked(Companion row) => this.unlockStateService.IsCompanionUnlocked(row);
-
- ///
- public bool IsCraftActionUnlocked(CraftAction row) => this.unlockStateService.IsCraftActionUnlocked(row);
-
- ///
- public bool IsCSBonusContentTypeUnlocked(CSBonusContentType row) => this.unlockStateService.IsCSBonusContentTypeUnlocked(row);
-
- ///
- public bool IsEmoteUnlocked(Emote row) => this.unlockStateService.IsEmoteUnlocked(row);
-
- ///
- public bool IsEmjVoiceNpcUnlocked(EmjVoiceNpc row) => this.unlockStateService.IsEmjVoiceNpcUnlocked(row);
-
- ///
- public bool IsEmjCostumeUnlocked(EmjCostume row) => this.unlockStateService.IsEmjCostumeUnlocked(row);
-
- ///
- public bool IsGeneralActionUnlocked(GeneralAction row) => this.unlockStateService.IsGeneralActionUnlocked(row);
-
- ///
- public bool IsGlassesUnlocked(Glasses row) => this.unlockStateService.IsGlassesUnlocked(row);
-
- ///
- public bool IsHowToUnlocked(HowTo row) => this.unlockStateService.IsHowToUnlocked(row);
-
- ///
- public bool IsInstanceContentUnlocked(InstanceContentSheet row) => this.unlockStateService.IsInstanceContentUnlocked(row);
-
- ///
- public bool IsItemUnlockable(Item row) => this.unlockStateService.IsItemUnlockable(row);
-
- ///
- public bool IsItemUnlocked(Item row) => this.unlockStateService.IsItemUnlocked(row);
-
- ///
- public bool IsMcGuffinUnlocked(McGuffin row) => this.unlockStateService.IsMcGuffinUnlocked(row);
-
- ///
- public bool IsMJILandmarkUnlocked(MJILandmark row) => this.unlockStateService.IsMJILandmarkUnlocked(row);
-
- ///
- public bool IsMKDLoreUnlocked(MKDLore row) => this.unlockStateService.IsMKDLoreUnlocked(row);
-
- ///
- public bool IsMountUnlocked(Mount row) => this.unlockStateService.IsMountUnlocked(row);
-
- ///
- public bool IsNotebookDivisionUnlocked(NotebookDivision row) => this.unlockStateService.IsNotebookDivisionUnlocked(row);
-
- ///
- public bool IsOrchestrionUnlocked(Orchestrion row) => this.unlockStateService.IsOrchestrionUnlocked(row);
-
- ///
- public bool IsOrnamentUnlocked(Ornament row) => this.unlockStateService.IsOrnamentUnlocked(row);
-
- ///
- public bool IsPerformUnlocked(Perform row) => this.unlockStateService.IsPerformUnlocked(row);
-
- ///
- public bool IsPublicContentUnlocked(PublicContentSheet row) => this.unlockStateService.IsPublicContentUnlocked(row);
-
- ///
- public bool IsRecipeUnlocked(Recipe row) => this.unlockStateService.IsRecipeUnlocked(row);
-
- ///
- public bool IsRowRefUnlocked(RowRef rowRef) => this.unlockStateService.IsRowRefUnlocked(rowRef);
-
- ///
- public bool IsRowRefUnlocked(RowRef rowRef) where T : struct, IExcelRow => this.unlockStateService.IsRowRefUnlocked(rowRef);
-
- ///
- public bool IsSecretRecipeBookUnlocked(SecretRecipeBook row) => this.unlockStateService.IsSecretRecipeBookUnlocked(row);
-
- ///
- public bool IsTraitUnlocked(Trait row) => this.unlockStateService.IsTraitUnlocked(row);
-
- ///
- public bool IsTripleTriadCardUnlocked(TripleTriadCard row) => this.unlockStateService.IsTripleTriadCardUnlocked(row);
-
- ///
- public bool IsUnlockLinkUnlocked(uint unlockLink) => this.unlockStateService.IsUnlockLinkUnlocked(unlockLink);
-
- ///
- public bool IsUnlockLinkUnlocked(ushort unlockLink) => this.unlockStateService.IsUnlockLinkUnlocked(unlockLink);
-
- ///
- void IInternalDisposableService.DisposeService()
- {
- this.unlockStateService.Unlock -= this.UnlockForward;
- }
-
- private void UnlockForward(RowRef rowRef) => this.Unlock?.Invoke(rowRef);
-}
diff --git a/Dalamud/Plugin/Services/IUnlockState.cs b/Dalamud/Plugin/Services/IUnlockState.cs
deleted file mode 100644
index 00f2df190..000000000
--- a/Dalamud/Plugin/Services/IUnlockState.cs
+++ /dev/null
@@ -1,328 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-using Lumina.Excel;
-using Lumina.Excel.Sheets;
-
-namespace Dalamud.Plugin.Services;
-
-#pragma warning disable SA1400 // Access modifier should be declared: Interface members are public by default
-
-///
-/// Interface for determining unlock state of various content in the game.
-///
-[Experimental("UnlockState")]
-public interface IUnlockState
-{
- ///
- /// A delegate type used for the event.
- ///
- /// A RowRef of the unlocked thing.
- delegate void UnlockDelegate(RowRef rowRef);
-
- ///
- /// Event triggered when something was unlocked.
- ///
- event UnlockDelegate? Unlock;
-
- ///
- /// Determines whether the specified Action is unlocked.
- ///
- /// The Action row to check.
- /// if unlocked; otherwise, .
- bool IsActionUnlocked(Lumina.Excel.Sheets.Action row);
-
- ///
- /// Determines whether the specified AetherCurrentCompFlgSet is unlocked.
- ///
- /// The AetherCurrentCompFlgSet row to check.
- /// if unlocked; otherwise, .
- bool IsAetherCurrentCompFlgSetUnlocked(AetherCurrentCompFlgSet row);
-
- ///
- /// Determines whether the specified AetherCurrent is unlocked.
- ///
- /// The AetherCurrent row to check.
- /// if unlocked; otherwise, .
- bool IsAetherCurrentUnlocked(AetherCurrent row);
-
- ///
- /// Determines whether the specified AozAction (Blue Mage Action) is unlocked.
- ///
- /// The AozAction row to check.
- /// if unlocked; otherwise, .
- bool IsAozActionUnlocked(AozAction row);
-
- ///
- /// Determines whether the specified BannerBg (Portrait Backgrounds) is unlocked.
- ///
- /// The BannerBg row to check.
- /// if unlocked; otherwise, .
- bool IsBannerBgUnlocked(BannerBg row);
-
- ///
- /// Determines whether the specified BannerCondition is unlocked.
- ///
- /// The BannerCondition row to check.
- /// if unlocked; otherwise, .
- bool IsBannerConditionUnlocked(BannerCondition row);
-
- ///
- /// Determines whether the specified BannerDecoration (Portrait Accents) is unlocked.
- ///
- /// The BannerDecoration row to check.
- /// if unlocked; otherwise, .
- bool IsBannerDecorationUnlocked(BannerDecoration row);
-
- ///
- /// Determines whether the specified BannerFacial (Portrait Expressions) is unlocked.
- ///
- /// The BannerFacial row to check.
- /// if unlocked; otherwise, .
- bool IsBannerFacialUnlocked(BannerFacial row);
-
- ///
- /// Determines whether the specified BannerFrame (Portrait Frames) is unlocked.
- ///
- /// The BannerFrame row to check.
- /// if unlocked; otherwise, .
- bool IsBannerFrameUnlocked(BannerFrame row);
-
- ///
- /// Determines whether the specified BannerTimeline (Portrait Poses) is unlocked.
- ///
- /// The BannerTimeline row to check.
- /// if unlocked; otherwise, .
- bool IsBannerTimelineUnlocked(BannerTimeline row);
-
- ///
- /// Determines whether the specified BuddyAction (Action of the players Chocobo Companion) is unlocked.
- ///
- /// The BuddyAction row to check.
- /// if unlocked; otherwise, .
- bool IsBuddyActionUnlocked(BuddyAction row);
-
- ///
- /// Determines whether the specified BuddyEquip (Equipment of the players Chocobo Companion) is unlocked.
- ///
- /// The BuddyEquip row to check.
- /// if unlocked; otherwise, .
- bool IsBuddyEquipUnlocked(BuddyEquip row);
-
- ///
- /// Determines whether the specified CharaMakeCustomize (Hairstyles and Face Paint patterns) is unlocked.
- ///
- /// The CharaMakeCustomize row to check.
- /// if unlocked; otherwise, .
- bool IsCharaMakeCustomizeUnlocked(CharaMakeCustomize row);
-
- ///
- /// Determines whether the specified ChocoboTaxiStand (Chocobokeeps of the Chocobo Porter service) is unlocked.
- ///
- /// The ChocoboTaxiStand row to check.
- /// if unlocked; otherwise, .
- bool IsChocoboTaxiStandUnlocked(ChocoboTaxiStand row);
-
- ///
- /// Determines whether the specified Companion (Minions) is unlocked.
- ///
- /// The Companion row to check.
- /// if unlocked; otherwise, .
- bool IsCompanionUnlocked(Companion row);
-
- ///
- /// Determines whether the specified CraftAction is unlocked.
- ///
- /// The CraftAction row to check.
- /// if unlocked; otherwise, .
- bool IsCraftActionUnlocked(CraftAction row);
-
- ///
- /// Determines whether the specified CSBonusContentType is unlocked.
- ///
- /// The CSBonusContentType row to check.
- /// if unlocked; otherwise, .
- bool IsCSBonusContentTypeUnlocked(CSBonusContentType row);
-
- ///
- /// Determines whether the specified Emote is unlocked.
- ///
- /// The Emote row to check.
- /// if unlocked; otherwise, .
- bool IsEmoteUnlocked(Emote row);
-
- ///
- /// Determines whether the specified EmjVoiceNpc (Doman Mahjong Characters) is unlocked.
- ///
- /// The EmjVoiceNpc row to check.
- /// if unlocked; otherwise, .
- bool IsEmjVoiceNpcUnlocked(EmjVoiceNpc row);
-
- ///
- /// Determines whether the specified EmjCostume (Doman Mahjong Character Costume) is unlocked.
- ///
- /// The EmjCostume row to check.
- /// if unlocked; otherwise, .
- bool IsEmjCostumeUnlocked(EmjCostume row);
-
- ///
- /// Determines whether the specified GeneralAction is unlocked.
- ///
- /// The GeneralAction row to check.
- /// if unlocked; otherwise, .
- bool IsGeneralActionUnlocked(GeneralAction row);
-
- ///
- /// Determines whether the specified Glasses is unlocked.
- ///
- /// The Glasses row to check.
- /// if unlocked; otherwise, .
- bool IsGlassesUnlocked(Glasses row);
-
- ///
- /// Determines whether the specified HowTo is unlocked.
- ///
- /// The HowTo row to check.
- /// if unlocked; otherwise, .
- bool IsHowToUnlocked(HowTo row);
-
- ///
- /// Determines whether the specified InstanceContent is unlocked.
- ///
- /// The InstanceContent row to check.
- /// if unlocked; otherwise, .
- bool IsInstanceContentUnlocked(InstanceContent row);
-
- ///
- /// Determines whether the specified Item is considered unlockable.
- ///
- /// The Item row to check.
- /// if unlockable; otherwise, .
- bool IsItemUnlockable(Item row);
-
- ///
- /// Determines whether the specified Item is unlocked.
- ///
- /// The Item row to check.
- /// if unlocked; otherwise, .
- bool IsItemUnlocked(Item row);
-
- ///
- /// Determines whether the specified McGuffin is unlocked.
- ///
- /// The McGuffin row to check.
- /// if unlocked; otherwise, .
- bool IsMcGuffinUnlocked(McGuffin row);
-
- ///
- /// Determines whether the specified MJILandmark (Island Sanctuary landmark) is unlocked.
- ///
- /// The MJILandmark row to check.
- /// if unlocked; otherwise, .
- bool IsMJILandmarkUnlocked(MJILandmark row);
-
- ///
- /// Determines whether the specified MKDLore (Occult Record) is unlocked.
- ///
- /// The MKDLore row to check.
- /// if unlocked; otherwise, .
- bool IsMKDLoreUnlocked(MKDLore row);
-
- ///
- /// Determines whether the specified Mount is unlocked.
- ///
- /// The Mount row to check.
- /// if unlocked; otherwise, .
- bool IsMountUnlocked(Mount row);
-
- ///
- /// Determines whether the specified NotebookDivision (Categories in Crafting/Gathering Log) is unlocked.
- ///
- /// The NotebookDivision row to check.
- /// if unlocked; otherwise, .
- bool IsNotebookDivisionUnlocked(NotebookDivision row);
-
- ///
- /// Determines whether the specified Orchestrion roll is unlocked.
- ///
- /// The Orchestrion row to check.
- /// if unlocked; otherwise, .
- bool IsOrchestrionUnlocked(Orchestrion row);
-
- ///
- /// Determines whether the specified Ornament (Fashion Accessories) is unlocked.
- ///
- /// The Ornament row to check.
- /// if unlocked; otherwise, .
- bool IsOrnamentUnlocked(Ornament row);
-
- ///
- /// Determines whether the specified Perform (Performance Instruments) is unlocked.
- ///
- /// The Perform row to check.
- /// if unlocked; otherwise, .
- bool IsPerformUnlocked(Perform row);
-
- ///
- /// Determines whether the specified PublicContent is unlocked.
- ///
- /// The PublicContent row to check.
- /// if unlocked; otherwise, .
- bool IsPublicContentUnlocked(PublicContent row);
-
- ///
- /// Determines whether the specified Recipe is unlocked.
- ///
- /// The Recipe row to check.
- /// if unlocked; otherwise, .
- bool IsRecipeUnlocked(Recipe row);
-
- ///
- /// Determines whether the underlying RowRef type is unlocked.
- ///
- /// The RowRef to check.
- /// if unlocked; otherwise, .
- bool IsRowRefUnlocked(RowRef rowRef);
-
- ///
- /// Determines whether the underlying RowRef type is unlocked.
- ///
- /// The type of the Excel row.
- /// The RowRef to check.
- /// if unlocked; otherwise, .
- bool IsRowRefUnlocked(RowRef rowRef) where T : struct, IExcelRow;
-
- ///
- /// Determines whether the specified SecretRecipeBook (Master Recipe Books) is unlocked.
- ///
- /// The SecretRecipeBook row to check.
- /// if unlocked; otherwise, .
- bool IsSecretRecipeBookUnlocked(SecretRecipeBook row);
-
- ///
- /// Determines whether the specified Trait is unlocked.
- ///
- /// The Trait row to check.
- /// if unlocked; otherwise, .
- bool IsTraitUnlocked(Trait row);
-
- ///
- /// Determines whether the specified TripleTriadCard is unlocked.
- ///
- /// The TripleTriadCard row to check.
- /// if unlocked; otherwise, .
- bool IsTripleTriadCardUnlocked(TripleTriadCard row);
-
- ///
- /// Determines whether the specified unlock link is unlocked or quest is completed.
- ///
- /// The unlock link id or quest id (quest ids in this case are over 65536).
- /// if unlocked; otherwise, .
- bool IsUnlockLinkUnlocked(uint unlockLink);
-
- ///
- /// Determines whether the specified unlock link is unlocked.
- ///
- /// The unlock link id.
- /// if unlocked; otherwise, .
- bool IsUnlockLinkUnlocked(ushort unlockLink);
-}
diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs
index 57f0da19c..0afa6b672 160000
--- a/lib/FFXIVClientStructs
+++ b/lib/FFXIVClientStructs
@@ -1 +1 @@
-Subproject commit 57f0da19c95146b88e487260a94a29e6ef359b40
+Subproject commit 0afa6b67288e5e667da74c1d3ad582e6c964644c