partial API 11 updates
authorLiza Carvelli <liza@carvel.li>
Sat, 16 Nov 2024 20:53:37 +0000 (21:53 +0100)
committerLiza Carvelli <liza@carvel.li>
Sat, 16 Nov 2024 20:53:37 +0000 (21:53 +0100)
41 files changed:
GatheringPathRenderer/GatheringPathRenderer.csproj
LLib
Questionable/Controller/CombatModules/ItemUseModule.cs
Questionable/Controller/CombatModules/RotationSolverRebornModule.cs
Questionable/Controller/CommandHandler.cs
Questionable/Controller/ContextMenuController.cs
Questionable/Controller/GameUi/InteractionUiController.cs
Questionable/Controller/GatheringController.cs
Questionable/Controller/MiniTaskController.cs
Questionable/Controller/QuestController.cs
Questionable/Controller/Steps/Gathering/DoGather.cs
Questionable/Controller/Steps/Gathering/DoGatherCollectable.cs
Questionable/Controller/Steps/Interactions/EquipItem.cs
Questionable/Controller/Steps/Interactions/EquipRecommended.cs
Questionable/Controller/Steps/Shared/Craft.cs
Questionable/Controller/Steps/Shared/Gather.cs
Questionable/Controller/Steps/Shared/MoveTo.cs
Questionable/Controller/Steps/Shared/SkipCondition.cs
Questionable/Controller/Steps/Shared/SwitchClassJob.cs
Questionable/Data/AetherCurrentData.cs
Questionable/Data/AetheryteData.cs
Questionable/Data/GatheringData.cs
Questionable/Data/JournalData.cs
Questionable/Data/QuestData.cs
Questionable/Data/Sheets/QuestEx.cs [new file with mode: 0644]
Questionable/Data/TerritoryData.cs
Questionable/Functions/AetheryteFunctions.cs
Questionable/Functions/ChatFunctions.cs
Questionable/Functions/ExcelFunctions.cs
Questionable/Functions/GameFunctions.cs
Questionable/Functions/QuestFunctions.cs
Questionable/Model/LeveInfo.cs
Questionable/Model/QuestInfo.cs
Questionable/Model/QuestInfoUtils.cs
Questionable/Model/SatisfactionSupplyInfo.cs
Questionable/Questionable.csproj
Questionable/Windows/ConfigWindow.cs
Questionable/Windows/JournalComponents/GatheringJournalComponent.cs
Questionable/Windows/JournalComponents/QuestJournalComponent.cs
Questionable/Windows/QuestWindow.cs
vendor/ECommons

index fc157f207141d33d98f41e64c0873d36d77dc5bb..6009a518396e4428cc8ba295c51b7d92d6739f81 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Dalamud.NET.Sdk/10.0.0">
+<Project Sdk="Dalamud.NET.Sdk/11.0.0">
     <ItemGroup>
       <ProjectReference Include="..\LLib\LLib.csproj" />
       <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj" />
diff --git a/LLib b/LLib
index fde09c705b648f03c287814191a554f0a4b92cc4..538329a1e80acbcd09e28bd6dd459c35b5563c0a 160000 (submodule)
--- a/LLib
+++ b/LLib
@@ -1 +1 @@
-Subproject commit fde09c705b648f03c287814191a554f0a4b92cc4
+Subproject commit 538329a1e80acbcd09e28bd6dd459c35b5563c0a
index 91b4ca1dd44161f27c2ee921caba2664b68dd62c..ec9adfa129f0da8cf3b8d5313c199599dd45b789 100644 (file)
@@ -142,7 +142,7 @@ internal sealed class ItemUseModule : ICombatModule
         {
             BattleChara* battleChara = (BattleChara*)gameObject.Address;
             if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.Incapacitated)
-                return (battleChara->Flags2 & 128u) != 0;
+                return (battleChara->CombatTagType & 128u) != 0; // FIXME 7.1
 
             if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.HealthPercent)
                 return (100f * battleChara->Health / battleChara->MaxHealth) < _combatData.CombatItemUse.Value;
index a0b43b2fdf98b9a67f98136e1166a31f85192099..581e07a9665231e4d0b2afa606cee09cf1908528 100644 (file)
@@ -82,7 +82,7 @@ internal sealed class RotationSolverRebornModule : ICombatModule, IDisposable
 
         float hitboxOffset = player.HitboxRadius + gameObject.HitboxRadius;
         float actualDistance = Vector3.Distance(player.Position, gameObject.Position);
-        float maxDistance = player.ClassJob.GameData?.Role is 3 or 4 ? 20f : 2.9f;
+        float maxDistance = player.ClassJob.ValueNullable?.Role is 3 or 4 ? 20f : 2.9f;
         if (actualDistance - hitboxOffset >= maxDistance)
         {
             if (actualDistance - hitboxOffset <= 5)
index 42759d99860cd856a8bb1b45f97bfea4aa57e02c..c6085a18dbf97647b5c3c0e80501c76997a16091 100644 (file)
@@ -3,11 +3,10 @@ using System.Linq;
 using Dalamud.Game.ClientState.Objects;
 using Dalamud.Game.Command;
 using Dalamud.Plugin.Services;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.Functions;
 using Questionable.Model.Questing;
 using Questionable.Windows;
-using Questionable.Windows.QuestComponents;
 using Quest = Questionable.Model.Quest;
 
 namespace Questionable.Controller;
@@ -240,7 +239,7 @@ internal sealed class CommandHandler : IDisposable
         ushort? mountId = _gameFunctions.GetMountId();
         if (mountId != null)
         {
-            var row = _dataManager.GetExcelSheet<Mount>()!.GetRow(mountId.Value);
+            var row = _dataManager.GetExcelSheet<Mount>().GetRowOrDefault(mountId.Value);
             _chatGui.Print(
                 $"Mount ID: {mountId}, Name: {row?.Singular}, Obtainable: {(row?.Order == -1 ? "No" : "Yes")}",
                 MessageTag, TagColor);
index c3d6c4c5d3a74709eed68e971315f29ae17b4200..fca77dd8ab973cf0a48a0b4dc2df8ffecf6bec85 100644 (file)
@@ -79,7 +79,7 @@ internal sealed class ContextMenuController : IDisposable
     private void AddContextMenuEntry(IMenuOpenedArgs args, uint itemId, uint npcId, EExtendedClassJob extendedClassJob,
         string verb)
     {
-        EClassJob currentClassJob = (EClassJob)_clientState.LocalPlayer!.ClassJob.Id;
+        EClassJob currentClassJob = (EClassJob)_clientState.LocalPlayer!.ClassJob.RowId;
         EClassJob classJob = ClassJobUtils.AsIndividualJobs(extendedClassJob).Single();
         if (classJob != currentClassJob && currentClassJob is EClassJob.Miner or EClassJob.Botanist)
             return;
index 698d24dda7c2533027dd85b080d220c54dae0546..797093dd65671d34d80a66f14e13e1a8e8cb01bb 100644 (file)
@@ -16,7 +16,7 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib;
 using LLib.GameData;
 using LLib.GameUI;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps.Interactions;
 using Questionable.Data;
@@ -90,7 +90,7 @@ internal sealed class InteractionUiController : IDisposable
         _shopController = shopController;
         _logger = logger;
 
-        _returnRegex = _dataManager.GetExcelSheet<Addon>()!.GetRow(196)!.GetRegex(addon => addon.Text, pluginLog)!;
+        _returnRegex = _dataManager.GetExcelSheet<Addon>().GetRow(196).GetRegex(addon => addon.Text, pluginLog)!;
 
         _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
         _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "CutSceneSelectString", CutsceneSelectStringPostSetup);
@@ -713,7 +713,7 @@ internal sealed class InteractionUiController : IDisposable
             step.InteractionType == EInteractionType.Gather)
         {
             if (_gatheringData.TryGetGatheringPointId(step.ItemsToGather[0].ItemId,
-                    (EClassJob?)_clientState.LocalPlayer?.ClassJob.Id ?? EClassJob.Adventurer,
+                    (EClassJob?)_clientState.LocalPlayer?.ClassJob.RowId ?? EClassJob.Adventurer,
                     out GatheringPointId? gatheringPointId) &&
                 _gatheringPointRegistry.TryGetGatheringPoint(gatheringPointId, out GatheringRoot? root))
             {
@@ -757,19 +757,19 @@ internal sealed class InteractionUiController : IDisposable
         [NotNullWhen(true)] out string? warpText)
     {
         var warps = _dataManager.GetExcelSheet<Warp>()!
-            .Where(x => x.RowId > 0 && x.TerritoryType.Row == targetTerritoryId);
+            .Where(x => x.RowId > 0 && x.TerritoryType.RowId == targetTerritoryId);
         foreach (var entry in warps)
         {
-            string? excelName = entry.Name?.ToString();
-            string? excelQuestion = entry.Question?.ToString();
+            string? excelName = entry.Name.ToString();
+            string? excelQuestion = entry.Question.ToString();
 
-            if (excelQuestion != null && GameFunctions.GameStringEquals(excelQuestion, actualPrompt))
+            if (!string.IsNullOrEmpty(excelQuestion) && GameFunctions.GameStringEquals(excelQuestion, actualPrompt))
             {
                 warpId = entry.RowId;
                 warpText = excelQuestion;
                 return true;
             }
-            else if (excelName != null && GameFunctions.GameStringEquals(excelName, actualPrompt))
+            else if (!string.IsNullOrEmpty(excelName) && GameFunctions.GameStringEquals(excelName, actualPrompt))
             {
                 warpId = entry.RowId;
                 warpText = excelName;
index 8c7dedd4a6ff53054eb917eff99c5e3af4229f36..bbe6d2e49d93da1f9bcb43fdb7b0b04c76d354c4 100644 (file)
@@ -12,7 +12,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.Game.Event;
 using FFXIVClientStructs.FFXIV.Client.Game.UI;
 using LLib;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps;
 using Questionable.Controller.Steps.Gathering;
index dfa0bfc9ee0e07209959ef6ce6f6f6d275e8f8a6..0685081809b8ceefee8d23041e4086a8aef1464e 100644 (file)
@@ -5,7 +5,7 @@ using Dalamud.Game.ClientState.Conditions;
 using Dalamud.Game.Text.SeStringHandling;
 using Dalamud.Plugin.Services;
 using LLib;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps;
index 0fbd79fe7a392acbbd8f1cc0ca711b3017ed3641..d6ae32a8cc1e9b28f1123125f4c9c5104f2bc264 100644 (file)
@@ -8,20 +8,14 @@ using Dalamud.Game.Gui.Toast;
 using Dalamud.Game.Text.SeStringHandling;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
-using LLib;
-using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps;
-using Questionable.Controller.Steps.Interactions;
 using Questionable.Controller.Steps.Shared;
-using Questionable.Data;
 using Questionable.External;
 using Questionable.Functions;
 using Questionable.Model;
 using Questionable.Model.Questing;
 using Quest = Questionable.Model.Quest;
-using Mount = Questionable.Controller.Steps.Common.Mount;
 
 namespace Questionable.Controller;
 
index 701f8534570e1baa09e661aea8abede55d723a52..0f4c8c7f2d659ecfd5d0face5728bd6f5da56e32 100644 (file)
@@ -225,7 +225,7 @@ internal static class DoGather
 
         private EAction PickAction(EAction minerAction, EAction botanistAction)
         {
-            if ((EClassJob?)clientState.LocalPlayer?.ClassJob.Id == EClassJob.Miner)
+            if ((EClassJob?)clientState.LocalPlayer?.ClassJob.RowId == EClassJob.Miner)
                 return minerAction;
             else
                 return botanistAction;
index 167409434b801fd3eeb02b20f0275a9a20c9bd64..2b91f3538d579f2c3bb81e138211de5f59a2e2d3 100644 (file)
@@ -193,7 +193,7 @@ internal static class DoGatherCollectable
 
         private EAction PickAction(EAction minerAction, EAction botanistAction)
         {
-            if ((EClassJob?)clientState.LocalPlayer?.ClassJob.Id == EClassJob.Miner)
+            if ((EClassJob?)clientState.LocalPlayer?.ClassJob.RowId == EClassJob.Miner)
                 return minerAction;
             else
                 return botanistAction;
index c8159247f5c686ac830dbf738943fede07de18df..f5cd4e111c2ea740fbf26072d04e3344c301dd9f 100644 (file)
@@ -5,8 +5,7 @@ using Dalamud.Game.Text.SeStringHandling;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
 using LLib;
-using Lumina.Excel.GeneratedSheets;
-using Microsoft.Extensions.DependencyInjection;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Functions;
 using Questionable.Model.Questing;
@@ -63,13 +62,13 @@ internal static class EquipItem
         ];
 
         private int _attempts;
-        private Item _item = null!;
+        private Item? _item;
         private List<ushort> _targetSlots = null!;
         private DateTime _continueAt = DateTime.MaxValue;
 
         protected override bool Start()
         {
-            _item = dataManager.GetExcelSheet<Item>()!.GetRow(Task.ItemId) ??
+            _item = dataManager.GetExcelSheet<Item>().GetRowOrDefault(Task.ItemId) ??
                     throw new ArgumentOutOfRangeException(nameof(Task.ItemId));
             _targetSlots = GetEquipSlot(_item) ?? throw new InvalidOperationException("Not a piece of equipment");
 
@@ -118,7 +117,7 @@ internal static class EquipItem
                 var itemSlot = equippedContainer->GetInventorySlot(slot);
                 if (itemSlot != null && itemSlot->ItemId == Task.ItemId)
                 {
-                    logger.LogInformation("Already equipped {Item}, skipping step", _item.Name?.ToString());
+                    logger.LogInformation("Already equipped {Item}, skipping step", _item?.Name.ToString());
                     return;
                 }
             }
@@ -162,11 +161,13 @@ internal static class EquipItem
             throw new TaskException($"Could not equip item {Task.ItemId}.");
         }
 
-        private static List<ushort>? GetEquipSlot(Item item)
+        private static List<ushort>? GetEquipSlot(Item? item)
         {
-            return item.EquipSlotCategory.Row switch
+            if (item == null)
+                return [];
+            return item.Value.EquipSlotCategory.RowId switch
             {
-                >= 1 and <= 11 => [(ushort)(item.EquipSlotCategory.Row - 1)],
+                >= 1 and <= 11 => [(ushort)(item.Value.EquipSlotCategory.RowId - 1)],
                 12 => [11, 12], // rings
                 13 => [0],
                 17 => [13], // soul crystal
index cd4f79828f0b9d25b0338d3cca3e7c93d51d06fb..b923c237fb45c64df470a5101254cf343340461d 100644 (file)
@@ -45,7 +45,7 @@ internal static class EquipRecommended
 
         protected override bool Start()
         {
-            RecommendEquipModule.Instance()->SetupForClassJob((byte)clientState.LocalPlayer!.ClassJob.Id);
+            RecommendEquipModule.Instance()->SetupForClassJob((byte)clientState.LocalPlayer!.ClassJob.RowId);
             return true;
         }
 
index ad474fe2bdf5aa31cc8611175882abb6c2e4659b..26493ca0255b632d245aae9c7609b00307254142 100644 (file)
@@ -6,7 +6,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.External;
 using Questionable.Model.Questing;
@@ -55,20 +55,20 @@ internal static class Craft
                 return false;
             }
 
-            RecipeLookup? recipeLookup = dataManager.GetExcelSheet<RecipeLookup>()!.GetRow(Task.ItemId);
+            RecipeLookup? recipeLookup = dataManager.GetExcelSheet<RecipeLookup>().GetRowOrDefault(Task.ItemId);
             if (recipeLookup == null)
                 throw new TaskException($"Item {Task.ItemId} is not craftable");
 
-            uint recipeId = (EClassJob)clientState.LocalPlayer!.ClassJob.Id switch
+            uint recipeId = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId switch
             {
-                EClassJob.Carpenter => recipeLookup.CRP.Row,
-                EClassJob.Blacksmith => recipeLookup.BSM.Row,
-                EClassJob.Armorer => recipeLookup.ARM.Row,
-                EClassJob.Goldsmith => recipeLookup.GSM.Row,
-                EClassJob.Leatherworker => recipeLookup.LTW.Row,
-                EClassJob.Weaver => recipeLookup.WVR.Row,
-                EClassJob.Alchemist => recipeLookup.ALC.Row,
-                EClassJob.Culinarian => recipeLookup.CUL.Row,
+                EClassJob.Carpenter => recipeLookup.Value.CRP.RowId,
+                EClassJob.Blacksmith => recipeLookup.Value.BSM.RowId,
+                EClassJob.Armorer => recipeLookup.Value.ARM.RowId,
+                EClassJob.Goldsmith => recipeLookup.Value.GSM.RowId,
+                EClassJob.Leatherworker => recipeLookup.Value.LTW.RowId,
+                EClassJob.Weaver => recipeLookup.Value.WVR.RowId,
+                EClassJob.Alchemist => recipeLookup.Value.ALC.RowId,
+                EClassJob.Culinarian => recipeLookup.Value.CUL.RowId,
                 _ => 0
             };
 
@@ -76,14 +76,14 @@ internal static class Craft
             {
                 recipeId = new[]
                     {
-                        recipeLookup.CRP.Row,
-                        recipeLookup.BSM.Row,
-                        recipeLookup.ARM.Row,
-                        recipeLookup.GSM.Row,
-                        recipeLookup.LTW.Row,
-                        recipeLookup.WVR.Row,
-                        recipeLookup.ALC.Row,
-                        recipeLookup.WVR.Row
+                        recipeLookup.Value.CRP.RowId,
+                        recipeLookup.Value.BSM.RowId,
+                        recipeLookup.Value.ARM.RowId,
+                        recipeLookup.Value.GSM.RowId,
+                        recipeLookup.Value.LTW.RowId,
+                        recipeLookup.Value.WVR.RowId,
+                        recipeLookup.Value.ALC.RowId,
+                        recipeLookup.Value.WVR.RowId
                     }
                     .FirstOrDefault(x => x != 0);
             }
index 5724a2092d622d4412e887b6ca78521fadbc5f39..13671d8d9a14f8aa109cefa69b8ae61ce1407b38 100644 (file)
@@ -35,7 +35,7 @@ internal static class Gather
 
             foreach (var itemToGather in step.ItemsToGather)
             {
-                EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.Id;
+                EClassJob currentClassJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
                 if (!gatheringData.TryGetGatheringPointId(itemToGather.ItemId, currentClassJob,
                         out GatheringPointId? gatheringPointId))
                     throw new TaskException($"No gathering point found for item {itemToGather.ItemId}");
index eaead8ef311ab8d735049ca265acc5f64be0a05f..4df2870facd576ebc822fc50a9094ccc0830062e 100644 (file)
@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Numerics;
 using Dalamud.Game.ClientState.Conditions;
@@ -10,7 +9,7 @@ using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.Game.Character;
 using LLib;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps.Common;
 using Questionable.Data;
index 2951d8d82b93cc0478efe1e728dce457dbdc2676..68297c4ed2c96f6d43a9b4c0d6ee17c83c1262ca 100644 (file)
@@ -239,7 +239,7 @@ internal static class SkipCondition
             {
                 List<EClassJob> expectedJobs =
                     step.RequiredCurrentJob.SelectMany(ClassJobUtils.AsIndividualJobs).ToList();
-                EClassJob currentJob = (EClassJob)clientState.LocalPlayer!.ClassJob.Id;
+                EClassJob currentJob = (EClassJob)clientState.LocalPlayer!.ClassJob.RowId;
                 logger.LogInformation("Checking current job {CurrentJob} against {ExpectedJobs}", currentJob,
                     string.Join(",", expectedJobs));
                 if (!expectedJobs.Contains(currentJob))
index 48b153c3a4c2d9109cb366d570b83b5da193044b..59477feca962fc6e739927d73ab33a371aad8ab0 100644 (file)
@@ -31,7 +31,7 @@ internal static class SwitchClassJob
     {
         protected override unsafe bool StartInternal()
         {
-            if (clientState.LocalPlayer!.ClassJob.Id == (uint)Task.ClassJob)
+            if (clientState.LocalPlayer!.ClassJob.RowId == (uint)Task.ClassJob)
                 return false;
 
             var gearsetModule = RaptureGearsetModule.Instance();
index f83b99c0f911fcce6164c614c30da5a3c0f8b427..04bb7c37727fbbbe6a8c518551588a5004180598 100644 (file)
@@ -1,7 +1,7 @@
 using System.Collections.Immutable;
 using System.Linq;
 using Dalamud.Plugin.Services;
-using Lumina.Excel.GeneratedSheets2;
+using Lumina.Excel.Sheets;
 
 namespace Questionable.Data;
 
@@ -13,12 +13,12 @@ internal sealed class AetherCurrentData
     {
         _overworldCurrents = dataManager.GetExcelSheet<AetherCurrentCompFlgSet>()!
             .Where(x => x.RowId > 0)
-            .Where(x => x.Territory.Value != null)
+            .Where(x => x.Territory.IsValid)
             .ToImmutableDictionary(
-                x => (ushort)x.Territory.Row,
+                x => (ushort)x.Territory.RowId,
                 x => x.AetherCurrents
-                    .Where(y => y.Row > 0 && y.Value?.Quest.Row == 0)
-                    .Select(y => y.Row)
+                    .Where(y => y.RowId > 0 && y.Value.Quest.RowId == 0)
+                    .Select(y => y.RowId)
                     .ToImmutableList());
     }
 
index f921972fd6be2928230c1c3f33cd68db54864d56..1e8f34c23a815080da2db292384a9a7cedff277a 100644 (file)
@@ -4,7 +4,7 @@ using System.Linq;
 using System.Numerics;
 using Dalamud.Plugin.Services;
 using Dalamud.Utility;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.Model.Common;
 
 namespace Questionable.Data;
@@ -29,19 +29,19 @@ internal sealed class AetheryteData
         void ConfigureAetheryteWithPlaceName(EAetheryteLocation aetheryteLocation, uint placeNameId, ushort territoryId)
         {
             ConfigureAetheryte(aetheryteLocation,
-                dataManager.GetExcelSheet<PlaceName>()!.GetRow(placeNameId)!.Name.ToDalamudString().TextValue,
+                dataManager.GetExcelSheet<PlaceName>().GetRow(placeNameId).Name.ToDalamudString().TextValue,
                 territoryId,
                 (ushort)((int)aetheryteLocation / 100));
         }
 
-        foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>()!.Where(x => x.RowId > 0))
+        foreach (var aetheryte in dataManager.GetExcelSheet<Aetheryte>().Where(x => x.RowId > 0))
         {
-            string? aethernetName = aetheryte.AethernetName?.Value?.Name.ToString();
+            string? aethernetName = aetheryte.AethernetName.ValueNullable?.Name.ToString();
             if (!string.IsNullOrEmpty(aethernetName))
                 aethernetNames[(EAetheryteLocation)aetheryte.RowId] = aethernetName;
 
-            if (aetheryte.Territory != null && aetheryte.Territory.Row > 0)
-                territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.Row;
+            if (aetheryte.Territory.RowId > 0)
+                territoryIds[(EAetheryteLocation)aetheryte.RowId] = (ushort)aetheryte.Territory.RowId;
 
             if (aetheryte.AethernetGroup > 0)
                 aethernetGroups[(EAetheryteLocation)aetheryte.RowId] = aetheryte.AethernetGroup;
@@ -62,8 +62,8 @@ internal sealed class AetheryteData
         TerritoryIds = territoryIds.AsReadOnly();
         AethernetGroups = aethernetGroups.AsReadOnly();
 
-        TownTerritoryIds = dataManager.GetExcelSheet<TerritoryType>()!
-            .Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name) && x.TerritoryIntendedUse == 0)
+        TownTerritoryIds = dataManager.GetExcelSheet<TerritoryType>()
+            .Where(x => x.RowId > 0 && !string.IsNullOrEmpty(x.Name.ToString()) && x.TerritoryIntendedUse.RowId == 0)
             .Select(x => (ushort)x.RowId)
             .ToList();
     }
index c231f004a3b37163872c1b1b1ee9e5fc92d56bc9..1d11a1ba33cd79d3b658c65c5c85ba7eaaa67fe1 100644 (file)
@@ -3,8 +3,7 @@ using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Dalamud.Plugin.Services;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
-using Microsoft.Extensions.Logging;
+using Lumina.Excel.Sheets;
 using Questionable.Model.Gathering;
 
 namespace Questionable.Data;
@@ -18,43 +17,45 @@ internal sealed class GatheringData
 
     public GatheringData(IDataManager dataManager)
     {
-        Dictionary<uint, uint> gatheringItemToItem = dataManager.GetExcelSheet<GatheringItem>()!
-            .Where(x => x.RowId != 0 && x.Item != 0)
-            .ToDictionary(x => x.RowId, x => (uint)x.Item);
+        Dictionary<uint, uint> gatheringItemToItem = dataManager.GetExcelSheet<GatheringItem>()
+            .Where(x => x.RowId != 0 && x.Item.RowId != 0)
+            .ToDictionary(x => x.RowId, x => x.Item.RowId);
 
-        foreach (var gatheringPointBase in dataManager.GetExcelSheet<GatheringPointBase>()!)
+        foreach (var gatheringPointBase in dataManager.GetExcelSheet<GatheringPointBase>())
         {
-            foreach (var gatheringItemId in gatheringPointBase.Item.Where(x => x != 0))
+            foreach (var gatheringItem in gatheringPointBase.Item.Where(x => x.RowId != 0))
             {
-                if (gatheringItemToItem.TryGetValue((uint)gatheringItemId, out uint itemId))
+                if (gatheringItemToItem.TryGetValue(gatheringItem.RowId, out uint itemId))
                 {
-                    if (gatheringPointBase.GatheringType.Row is 0 or 1)
+                    if (gatheringPointBase.GatheringType.RowId is 0 or 1)
                         _minerGatheringPoints[itemId] = new GatheringPointId((ushort)gatheringPointBase.RowId);
-                    else if (gatheringPointBase.GatheringType.Row is 2 or 3)
+                    else if (gatheringPointBase.GatheringType.RowId is 2 or 3)
                         _botanistGatheringPoints[itemId] = new GatheringPointId((ushort)gatheringPointBase.RowId);
                 }
             }
         }
 
-        _itemIdToCollectability = dataManager.GetExcelSheet<SatisfactionSupply>()!
+        _itemIdToCollectability = dataManager.GetSubrowExcelSheet<SatisfactionSupply>()
             .Where(x => x.RowId > 0)
+            .SelectMany(x => x)
             .Where(x => x.Slot is 2)
             .Select(x => new
             {
-                ItemId = x.Item.Row,
+                ItemId = x.Item.RowId,
                 Collectability = x.CollectabilityHigh,
             })
             .Distinct()
             .ToDictionary(x => x.ItemId, x => x.Collectability);
 
-        _npcForCustomDeliveries = dataManager.GetExcelSheet<SatisfactionNpc>()!
+        _npcForCustomDeliveries = dataManager.GetExcelSheet<SatisfactionNpc>()
             .Where(x => x.RowId > 0)
-            .SelectMany(x => dataManager.GetExcelSheet<SatisfactionSupply>()!
-                .Where(y => y.RowId == x.SupplyIndex.Last())
+            .SelectMany(x => dataManager.GetSubrowExcelSheet<SatisfactionSupply>()
+                .Where(y => y.RowId == x.SatisfactionNpcParams.Last().SupplyIndex)
+                .SelectMany(y => y)
                 .Select(y => new
                 {
-                    ItemId = y.Item.Row,
-                    NpcId = x.Npc.Row
+                    ItemId = y.Item.RowId,
+                    NpcId = x.Npc.RowId
                 }))
             .Where(x => x.ItemId > 0)
             .Distinct()
index fca04e82387d1259338831884069b1df970d0104..f26f452aedabeff28e967b84fac2f9210479a4a4 100644 (file)
@@ -1,7 +1,8 @@
 using System.Collections.Generic;
 using System.Linq;
 using Dalamud.Plugin.Services;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
+using Microsoft.Extensions.Logging;
 using Questionable.Model;
 using Questionable.Model.Questing;
 
@@ -9,28 +10,36 @@ namespace Questionable.Data;
 
 internal sealed class JournalData
 {
-    public JournalData(IDataManager dataManager, QuestData questData)
+    public JournalData(IDataManager dataManager, QuestData questData, ILogger<JournalData> logger)
     {
-        var genres = dataManager.GetExcelSheet<JournalGenre>()!
+        var genres = dataManager.GetExcelSheet<JournalGenre>()
             .Where(x => x.RowId > 0 && x.Icon > 0)
             .Select(x => new Genre(x, questData.GetAllByJournalGenre(x.RowId)))
             .ToList();
+        foreach (var genre in genres)
+        {
+            logger.LogInformation("Genre {GenreId}: {GenreName} has {QuestCount} quests",
+                genre.Id, genre.Name, genre.QuestCount);
+        }
+        logger.LogInformation("Genre count: {GenreCount}", genres.Count);
+        var quest = questData.GetQuestInfo(new QuestId(5193));
+        logger.LogInformation("Q: {N}, {A}, {B}", quest.Name, quest.JournalGenre, quest.IssuerDataId);
 
-        var limsaStart = dataManager.GetExcelSheet<QuestRedo>()!.GetRow(1)!;
-        var gridaniaStart = dataManager.GetExcelSheet<QuestRedo>()!.GetRow(2)!;
-        var uldahStart = dataManager.GetExcelSheet<QuestRedo>()!.GetRow(3)!;
+        var limsaStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(1);
+        var gridaniaStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(2);
+        var uldahStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(3);
         var genreLimsa = new Genre(uint.MaxValue - 3, "Starting in Limsa Lominsa", 1,
-            new uint[] { 108, 109 }.Concat(limsaStart.Quest.Select(x => x.Row))
+            new uint[] { 108, 109 }.Concat(limsaStart.QuestRedoParam.Select(x => x.Quest.RowId))
                 .Where(x => x != 0)
                 .Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
                 .ToList());
         var genreGridania = new Genre(uint.MaxValue - 2, "Starting in Gridania", 1,
-            new uint[] { 85, 123, 124 }.Concat(gridaniaStart.Quest.Select(x => x.Row))
+            new uint[] { 85, 123, 124 }.Concat(gridaniaStart.QuestRedoParam.Select(x => x.Quest.RowId))
                 .Where(x => x != 0)
                 .Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
                 .ToList());
         var genreUldah = new Genre(uint.MaxValue - 1, "Starting in Ul'dah", 1,
-            new uint[] { 568, 569, 570 }.Concat(uldahStart.Quest.Select(x => x.Row))
+            new uint[] { 568, 569, 570 }.Concat(uldahStart.QuestRedoParam.Select(x => x.Quest.RowId))
                 .Where(x => x != 0)
                 .Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
                 .ToList());
@@ -41,12 +50,12 @@ internal sealed class JournalData
                 genreLimsa.Quests.Contains(x) || genreGridania.Quests.Contains(x) || genreUldah.Quests.Contains(x));
 
         Genres = genres.AsReadOnly();
-        Categories = dataManager.GetExcelSheet<JournalCategory>()!
+        Categories = dataManager.GetExcelSheet<JournalCategory>()
             .Where(x => x.RowId > 0)
             .Select(x => new Category(x, Genres.Where(y => y.CategoryId == x.RowId).ToList()))
             .ToList()
             .AsReadOnly();
-        Sections = dataManager.GetExcelSheet<JournalSection>()!
+        Sections = dataManager.GetExcelSheet<JournalSection>()
             .Select(x => new Section(x, Categories.Where(y => y.SectionId == x.RowId).ToList()))
             .ToList();
     }
@@ -61,7 +70,7 @@ internal sealed class JournalData
         {
             Id = journalGenre.RowId;
             Name = journalGenre.Name.ToString();
-            CategoryId = journalGenre.JournalCategory.Row;
+            CategoryId = journalGenre.JournalCategory.RowId;
             Quests = quests;
         }
 
@@ -84,7 +93,7 @@ internal sealed class JournalData
     {
         public uint Id { get; } = journalCategory.RowId;
         public string Name { get; } = journalCategory.Name.ToString();
-        public uint SectionId { get; } = journalCategory.JournalSection.Row;
+        public uint SectionId { get; } = journalCategory.JournalSection.RowId;
         public IReadOnlyList<Genre> Genres { get; } = genres;
         public int QuestCount => Genres.Sum(x => x.QuestCount);
     }
index e74f28e5dab96c599e6bf53215bab83d4dd1422e..b055a7d733ada5fd90d0d393155480bac8061416 100644 (file)
@@ -5,11 +5,11 @@ using System.Linq;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game.UI;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
+using Questionable.Data.Sheets;
 using Questionable.Model;
 using Questionable.Model.Questing;
-using Leve = Lumina.Excel.GeneratedSheets2.Leve;
-using Quest = Lumina.Excel.GeneratedSheets2.Quest;
+using Quest = Lumina.Excel.Sheets.Quest;
 
 namespace Questionable.Data;
 
@@ -18,13 +18,13 @@ internal sealed class QuestData
     public static readonly IReadOnlyList<QuestId> CrystalTowerQuests =
         [new(1709), new(1200), new(1201), new(1202), new(1203), new(1474), new(494), new(495)];
 
-    public static readonly IReadOnlyList<ushort> TankRoleQuests = [136, 154, 178];
-    public static readonly IReadOnlyList<ushort> HealerRoleQuests = [137, 155, 179];
-    public static readonly IReadOnlyList<ushort> MeleeRoleQuests = [138, 156, 180];
-    public static readonly IReadOnlyList<ushort> PhysicalRangedRoleQuests = [138, 157, 181];
-    public static readonly IReadOnlyList<ushort> CasterRoleQuests = [139, 158, 182];
+    public static readonly IReadOnlyList<uint> TankRoleQuests = [136, 154, 178];
+    public static readonly IReadOnlyList<uint> HealerRoleQuests = [137, 155, 179];
+    public static readonly IReadOnlyList<uint> MeleeRoleQuests = [138, 156, 180];
+    public static readonly IReadOnlyList<uint> PhysicalRangedRoleQuests = [138, 157, 181];
+    public static readonly IReadOnlyList<uint> CasterRoleQuests = [139, 158, 182];
 
-    public static readonly IReadOnlyList<IReadOnlyList<ushort>> AllRoleQuestChapters =
+    public static readonly IReadOnlyList<IReadOnlyList<uint>> AllRoleQuestChapters =
     [
         TankRoleQuests,
         HealerRoleQuests,
@@ -40,33 +40,33 @@ internal sealed class QuestData
 
     public QuestData(IDataManager dataManager)
     {
-        Dictionary<uint, ushort> questChapters =
+        Dictionary<uint, uint> questChapters =
             dataManager.GetExcelSheet<QuestChapter>()!
-                .Where(x => x.RowId > 0 && x.Quest.Row > 0)
-                .ToDictionary(x => x.Quest.Row, x => x.Redo);
+                .Where(x => x.RowId > 0 && x.Quest.RowId > 0)
+                .ToDictionary(x => x.Quest.RowId, x => x.Redo.RowId);
 
         Dictionary<uint, byte> startingCities = new();
         for (byte redoChapter = 1; redoChapter <= 3; ++redoChapter)
         {
-            var questRedo = dataManager.GetExcelSheet<QuestRedo>()!.GetRow(redoChapter)!;
-            foreach (var quest in questRedo.Quest.Where(x => x.Row > 0))
-                startingCities[quest.Row] = redoChapter;
+            var questRedo = dataManager.GetExcelSheet<QuestRedo>().GetRow(redoChapter);
+            foreach (var quest in questRedo.QuestRedoParam.Where(x => x.Quest.IsValid))
+                startingCities[quest.Quest.RowId] = redoChapter;
         }
 
         List<IQuestInfo> quests =
         [
-            ..dataManager.GetExcelSheet<Quest>()!
+            ..dataManager.GetExcelSheet<QuestEx>()
                 .Where(x => x.RowId > 0)
-                .Where(x => x.IssuerLocation.Row > 0)
+                .Where(x => x.IssuerLocation.RowId > 0)
                 .Select(x => new QuestInfo(x, questChapters.GetValueOrDefault(x.RowId),
                     startingCities.GetValueOrDefault(x.RowId)))
                 .Where(x => x.QuestId.Value != 1428),
-            ..dataManager.GetExcelSheet<SatisfactionNpc>()!
-                .Where(x => x.RowId > 0)
+            ..dataManager.GetExcelSheet<SatisfactionNpc>()
+                .Where(x => x is { RowId: > 0, Npc.RowId: > 0 })
                 .Select(x => new SatisfactionSupplyInfo(x)),
-            ..dataManager.GetExcelSheet<Leve>()!
+            ..dataManager.GetExcelSheet<Leve>()
                 .Where(x => x.RowId > 0)
-                .Where(x => x.LevelLevemete.Row != 0)
+                .Where(x => x.LevelLevemete.RowId != 0)
                 .Select(x => new LeveInfo(x)),
         ];
         _quests = quests.ToDictionary(x => x.QuestId, x => x);
@@ -230,7 +230,7 @@ internal sealed class QuestData
 
     public List<QuestInfo> GetClassJobQuests(EClassJob classJob)
     {
-        List<ushort> chapterIds = classJob switch
+        List<uint> chapterIds = classJob switch
         {
             EClassJob.Adventurer => throw new ArgumentOutOfRangeException(nameof(classJob)),
 
@@ -308,7 +308,7 @@ internal sealed class QuestData
         return GetQuestsInNewGamePlusChapters(chapterIds);
     }
 
-    private List<QuestInfo> GetQuestsInNewGamePlusChapters(List<ushort> chapterIds)
+    private List<QuestInfo> GetQuestsInNewGamePlusChapters(List<uint> chapterIds)
     {
         return _quests.Values
             .Where(x => x is QuestInfo)
diff --git a/Questionable/Data/Sheets/QuestEx.cs b/Questionable/Data/Sheets/QuestEx.cs
new file mode 100644 (file)
index 0000000..c4da017
--- /dev/null
@@ -0,0 +1,45 @@
+using Lumina.Excel;
+using Lumina.Excel.Sheets;
+using Lumina.Text.ReadOnly;
+
+namespace Questionable.Data.Sheets;
+
+// TODO Remove once fixed in dalamud
+[Sheet("Quest", 0x1F8C7430)]
+public readonly unsafe struct QuestEx(ExcelPage page, uint offset, uint row) : IExcelRow<QuestEx>
+{
+    public uint RowId => row;
+
+    public Quest Original { get; } = new(page, offset, row);
+
+    public RowRef IssuerStart => RowRef.GetFirstValidRowOrUntyped(page.Module, page.ReadUInt32(offset + 2456), [typeof(EObjName), typeof(ENpcResident)], 882056187, page.Language);
+    public RowRef<Level> IssuerLocation => new(page.Module, page.ReadUInt32(offset + 2460), page.Language);
+    public RowRef<JournalGenre> JournalGenre => new(page.Module, page.ReadUInt32(offset + 2468), page.Language);
+    public ushort SortKey => page.ReadUInt16(offset + 2502);
+    public readonly RowRef<ExVersion> Expansion => new(page.Module, (uint)page.ReadUInt8(offset + 2504), page.Language);
+    public readonly byte PreviousQuestJoin => page.ReadUInt8(offset + 2508);
+    public readonly RowRef<ClassJobCategory> ClassJobCategory0 => new(page.Module, (uint)page.ReadUInt8(offset + 2505), page.Language);
+    public readonly RowRef<ClassJobCategory> ClassJobCategory1 => new(page.Module, (uint)page.ReadUInt8(offset + 2507), page.Language);
+    public readonly RowRef<Festival> Festival => new(page.Module, (uint)page.ReadUInt8(offset + 2517), page.Language);
+    public readonly byte Unknown7 => page.ReadUInt8(offset + 2509);
+    public readonly byte QuestLockJoin => page.ReadUInt8(offset + 2510);
+    public readonly RowRef<GrandCompany> GrandCompany => new(page.Module, (uint)page.ReadUInt8(offset + 2514), page.Language);
+    public readonly byte InstanceContentJoin => page.ReadUInt8(offset + 2516);
+    public readonly RowRef<BeastTribe> BeastTribe => new(page.Module, (uint)page.ReadUInt8(offset + 2520), page.Language);
+    public bool IsRepeatable => page.ReadPackedBool(offset + 2535, 1);
+
+    public readonly Collection<RowRef<Quest>> PreviousQuest => new(page, offset, offset, &PreviousQuestCtor, 3);
+    private static RowRef<Quest> PreviousQuestCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page.Module, page.ReadUInt32(offset + 2424 + i * 4), page.Language);
+
+    public readonly Collection<RowRef<Quest>> QuestLock => new(page, offset, offset, &QuestLockCtor, 2);
+    private static RowRef<Quest> QuestLockCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page.Module, page.ReadUInt32(offset + 2436 + i * 4), page.Language);
+
+    public readonly Collection<ushort> ClassJobLevel => new(page, offset, offset, &ClassJobLevelCtor, 2);
+    private static ushort ClassJobLevelCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => page.ReadUInt16(offset + 2484 + i * 2);
+
+    public Collection<RowRef<InstanceContent>> InstanceContent => new(page, offset, offset, &InstanceContentCtor, 3);
+    private static RowRef<InstanceContent> InstanceContentCtor(ExcelPage page, uint parentOffset, uint offset, uint i) => new(page.Module, page.ReadUInt32(offset + 2444 + i * 4), page.Language);
+
+    static QuestEx IExcelRow<QuestEx>.Create(ExcelPage page, uint offset, uint row) =>
+        new(page, offset, row);
+}
index e2d471c34c8248466025b66112def5a6e1221d2d..ee91f6b44fe08fb5267fb54125f65d7d4b7e5e70 100644 (file)
@@ -4,7 +4,7 @@ using System.Globalization;
 using System.Linq;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game.Character;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 
 namespace Questionable.Data;
 
@@ -13,37 +13,37 @@ internal sealed class TerritoryData
     private readonly ImmutableDictionary<uint, string> _territoryNames;
     private readonly ImmutableHashSet<ushort> _territoriesWithMount;
     private readonly ImmutableDictionary<ushort, uint> _dutyTerritories;
-    private readonly ImmutableDictionary<ushort, string> _instanceNames;
+    private readonly ImmutableDictionary<uint, string> _instanceNames;
     private readonly ImmutableDictionary<uint, string> _contentFinderConditionNames;
 
     public TerritoryData(IDataManager dataManager)
     {
-        _territoryNames = dataManager.GetExcelSheet<TerritoryType>()!
+        _territoryNames = dataManager.GetExcelSheet<TerritoryType>()
             .Where(x => x.RowId > 0)
             .Select(x =>
                 new
                 {
                     x.RowId,
-                    Name = x.PlaceName.Value?.Name?.ToString() ?? x.PlaceNameZone?.Value?.Name?.ToString(),
+                    Name = x.PlaceName.ValueNullable?.Name.ToString() ?? x.PlaceNameZone.ValueNullable?.Name.ToString(),
                 })
             .Where(x => !string.IsNullOrEmpty(x.Name))
             .ToImmutableDictionary(x => x.RowId, x => x.Name!);
 
-        _territoriesWithMount = dataManager.GetExcelSheet<TerritoryType>()!
+        _territoriesWithMount = dataManager.GetExcelSheet<TerritoryType>()
             .Where(x => x.RowId > 0 && x.Mount)
             .Select(x => (ushort)x.RowId)
             .ToImmutableHashSet();
 
-        _dutyTerritories = dataManager.GetExcelSheet<TerritoryType>()!
-            .Where(x => x.RowId > 0 && x.ContentFinderCondition.Row != 0)
-            .ToImmutableDictionary(x => (ushort)x.RowId, x => x.ContentFinderCondition.Value!.ContentType.Row);
+        _dutyTerritories = dataManager.GetExcelSheet<TerritoryType>()
+            .Where(x => x.RowId > 0 && x.ContentFinderCondition.RowId != 0)
+            .ToImmutableDictionary(x => (ushort)x.RowId, x => x.ContentFinderCondition.Value.ContentType.RowId);
 
-        _instanceNames = dataManager.GetExcelSheet<ContentFinderCondition>()!
-            .Where(x => x.RowId > 0 && x.Content != 0 && x.ContentLinkType == 1 && x.ContentType.Row != 6)
-            .ToImmutableDictionary(x => x.Content, x => x.Name.ToString());
+        _instanceNames = dataManager.GetExcelSheet<ContentFinderCondition>()
+            .Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
+            .ToImmutableDictionary(x => x.Content.RowId, x => x.Name.ToString());
 
-        _contentFinderConditionNames = dataManager.GetExcelSheet<ContentFinderCondition>()!
-            .Where(x => x.RowId > 0 && x.Content != 0 && x.ContentLinkType == 1 && x.ContentType.Row != 6)
+        _contentFinderConditionNames = dataManager.GetExcelSheet<ContentFinderCondition>()
+            .Where(x => x.RowId > 0 && x.Content.RowId != 0 && x.ContentLinkType == 1 && x.ContentType.RowId != 6)
             .ToImmutableDictionary(x => x.RowId, x => x.Name.ToString());
     }
 
index afdedf4d8382a490c3fa29ed3288606dae465a72..65b075d000879281bba8845b9b210ff0f10e7cb4 100644 (file)
@@ -1,14 +1,12 @@
 using System;
-using System.Linq;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.Game.UI;
-using Lumina.Excel.GeneratedSheets;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Questionable.Model.Common;
 using Questionable.Model.Questing;
-using Action = Lumina.Excel.GeneratedSheets.Action;
+using Action = Lumina.Excel.Sheets.Action;
 
 namespace Questionable.Functions;
 
@@ -57,9 +55,10 @@ internal sealed unsafe class AetheryteFunctions
 
     public bool IsTeleportUnlocked()
     {
-        uint unlockLink = _dataManager.GetExcelSheet<Action>()!
-            .GetRow(5)!
-            .UnlockLink;
+        uint unlockLink = _dataManager.GetExcelSheet<Action>()
+            .GetRow(5)
+            .UnlockLink
+            .RowId;
         return UIState.Instance()->IsUnlockLinkUnlocked(unlockLink);
     }
 
index 5c31e4d82fcb45a17d90f1a6a6df32ac58ab565f..d53ed9bee014a33ab5f0f4dd95ae406b3da3fc7b 100644 (file)
@@ -12,7 +12,7 @@ using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.System.Framework;
 using FFXIVClientStructs.FFXIV.Client.System.Memory;
 using FFXIVClientStructs.FFXIV.Client.System.String;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Model.Questing;
 
@@ -41,11 +41,11 @@ internal sealed unsafe class ChatFunctions
         _sanitiseString =
             (delegate* unmanaged<Utf8String*, int, IntPtr, void>)sigScanner.ScanText(Signatures.SanitiseString);
 
-        _emoteCommands = dataManager.GetExcelSheet<Emote>()!
+        _emoteCommands = dataManager.GetExcelSheet<Emote>()
             .Where(x => x.RowId > 0)
-            .Where(x => x.TextCommand != null && x.TextCommand.Value != null)
-            .Select(x => (x.RowId, Command: x.TextCommand.Value!.Command?.ToString()))
-            .Where(x => x.Command != null && x.Command.StartsWith('/'))
+            .Where(x => x.TextCommand.IsValid)
+            .Select(x => (x.RowId, Command: x.TextCommand.Value.Command.ToString()))
+            .Where(x => !string.IsNullOrEmpty(x.Command) && x.Command.StartsWith('/'))
             .ToDictionary(x => (EEmote)x.RowId, x => x.Command!)
             .AsReadOnly();
     }
@@ -156,8 +156,8 @@ internal sealed unsafe class ChatFunctions
 
     private static class Signatures
     {
-        internal const string SendChat = "48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9";
-        internal const string SanitiseString = "E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 0F B6 F0 E8 ?? ?? ?? ?? 48 8D 4D C0";
+        internal const string SendChat = "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F2 48 8B F9 45 84 C9";
+        internal const string SanitiseString = "E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D AE";
     }
 
     [StructLayout(LayoutKind.Explicit)]
index e1278a593baca2e5937740b7e3ef33a6ce4b1dae..2043c5a60f8f868eb3ae0e2988e500477d850064 100644 (file)
@@ -3,13 +3,13 @@ using System.Linq;
 using Dalamud.Plugin.Services;
 using Dalamud.Utility;
 using LLib;
-using Lumina.Excel.CustomSheets;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Lumina.Text;
+using Lumina.Text.ReadOnly;
 using Microsoft.Extensions.Logging;
 using Questionable.Model;
 using Quest = Questionable.Model.Quest;
-using GimmickYesNo = Lumina.Excel.GeneratedSheets2.GimmickYesNo;
+using GimmickYesNo = Lumina.Excel.Sheets.GimmickYesNo;
 
 namespace Questionable.Functions;
 
@@ -33,12 +33,12 @@ internal sealed class ExcelFunctions
             return new StringOrRegex(seString?.ToDalamudString().ToString());
     }
 
-    public SeString? GetRawDialogueText(Quest? currentQuest, string? excelSheetName, string key)
+    public ReadOnlySeString? GetRawDialogueText(Quest? currentQuest, string? excelSheetName, string key)
     {
         if (currentQuest != null && excelSheetName == null)
         {
             var questRow =
-                _dataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets2.Quest>()!.GetRow((uint)currentQuest.Id.Value +
+                _dataManager.GetExcelSheet<Lumina.Excel.Sheets.Quest>().GetRowOrDefault((uint)currentQuest.Id.Value +
                     0x10000);
             if (questRow == null)
             {
@@ -46,18 +46,13 @@ internal sealed class ExcelFunctions
                 return null;
             }
 
-            excelSheetName = $"quest/{(currentQuest.Id.Value / 100):000}/{questRow.Id}";
+            excelSheetName = $"quest/{(currentQuest.Id.Value / 100):000}/{questRow.Value.RowId}";
         }
 
         ArgumentNullException.ThrowIfNull(excelSheetName);
-        var excelSheet = _dataManager.Excel.GetSheet<QuestDialogueText>(excelSheetName);
-        if (excelSheet == null)
-        {
-            _logger.LogError("Unknown excel sheet '{SheetName}'", excelSheetName);
-            return null;
-        }
-
-        return excelSheet.FirstOrDefault(x => x.Key == key)?.Value;
+        var excelSheet = _dataManager.GetExcelSheet<QuestDialogueText>(name: excelSheetName);
+        return excelSheet.Cast<QuestDialogueText?>()
+            .FirstOrDefault(x => x!.Value.Key == key)?.Value;
     }
 
     public StringOrRegex GetDialogueTextByRowId(string? excelSheet, uint rowId, bool isRegex)
@@ -69,36 +64,36 @@ internal sealed class ExcelFunctions
             return new StringOrRegex(seString?.ToDalamudString().ToString());
     }
 
-    public SeString? GetRawDialogueTextByRowId(string? excelSheet, uint rowId)
+    public ReadOnlySeString? GetRawDialogueTextByRowId(string? excelSheet, uint rowId)
     {
         if (excelSheet == "GimmickYesNo")
         {
-            var questRow = _dataManager.GetExcelSheet<GimmickYesNo>()!.GetRow(rowId);
+            var questRow = _dataManager.GetExcelSheet<GimmickYesNo>().GetRowOrDefault(rowId);
             return questRow?.Unknown0;
         }
         else if (excelSheet == "Warp")
         {
-            var questRow = _dataManager.GetExcelSheet<Warp>()!.GetRow(rowId);
+            var questRow = _dataManager.GetExcelSheet<Warp>().GetRowOrDefault(rowId);
             return questRow?.Name;
         }
         else if (excelSheet is "Addon")
         {
-            var questRow = _dataManager.GetExcelSheet<Addon>()!.GetRow(rowId);
+            var questRow = _dataManager.GetExcelSheet<Addon>().GetRowOrDefault(rowId);
             return questRow?.Text;
         }
         else if (excelSheet is "EventPathMove")
         {
-            var questRow = _dataManager.GetExcelSheet<EventPathMove>()!.GetRow(rowId);
-            return questRow?.Unknown10;
+            var questRow = _dataManager.GetExcelSheet<EventPathMove>().GetRowOrDefault(rowId);
+            return questRow?.Unknown0;
         }
         else if (excelSheet is "GilShop")
         {
-            var questRow = _dataManager.GetExcelSheet<GilShop>()!.GetRow(rowId);
+            var questRow = _dataManager.GetExcelSheet<GilShop>().GetRowOrDefault(rowId);
             return questRow?.Name;
         }
         else if (excelSheet is "ContentTalk" or null)
         {
-            var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);
+            var questRow = _dataManager.GetExcelSheet<ContentTalk>().GetRowOrDefault(rowId);
             return questRow?.Text;
         }
         else
index bb0313ae57c7cc73a7c70e0ba46e6758ca9a9875..d4a7e692e0f7afa3cd05a3da66b7004947965abc 100644 (file)
@@ -14,23 +14,22 @@ using FFXIVClientStructs.FFXIV.Client.Game.UI;
 using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameUI;
+using Lumina.Excel.Sheets;
 using Microsoft.Extensions.Logging;
 using Questionable.Model;
-using Questionable.Model.Common;
 using Questionable.Model.Questing;
-using Action = Lumina.Excel.GeneratedSheets2.Action;
+using Action = Lumina.Excel.Sheets.Action;
 using BattleChara = FFXIVClientStructs.FFXIV.Client.Game.Character.BattleChara;
-using ContentFinderCondition = Lumina.Excel.GeneratedSheets.ContentFinderCondition;
+using ContentFinderCondition = Lumina.Excel.Sheets.ContentFinderCondition;
 using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
 using Quest = Questionable.Model.Quest;
-using TerritoryType = Lumina.Excel.GeneratedSheets.TerritoryType;
 
 namespace Questionable.Functions;
 
 internal sealed unsafe class GameFunctions
 {
     private readonly ReadOnlyDictionary<ushort, byte> _territoryToAetherCurrentCompFlgSet;
-    private readonly ReadOnlyDictionary<uint, ushort> _contentFinderConditionToContentId;
+    private readonly ReadOnlyDictionary<uint, uint> _contentFinderConditionToContentId;
 
     private readonly QuestFunctions _questFunctions;
     private readonly IDataManager _dataManager;
@@ -63,14 +62,15 @@ internal sealed unsafe class GameFunctions
         _configuration = configuration;
         _logger = logger;
 
-        _territoryToAetherCurrentCompFlgSet = dataManager.GetExcelSheet<TerritoryType>()!
+        _territoryToAetherCurrentCompFlgSet = dataManager.GetExcelSheet<TerritoryType>()
             .Where(x => x.RowId > 0)
-            .Where(x => x.Unknown32 > 0)
-            .ToDictionary(x => (ushort)x.RowId, x => x.Unknown32)
+            .Where(x => x.Unknown3 > 0)
+            .ToDictionary(x => (ushort)x.RowId, x => x.Unknown4)
             .AsReadOnly();
-        _contentFinderConditionToContentId = dataManager.GetExcelSheet<ContentFinderCondition>()!
-            .Where(x => x.RowId > 0 && x.Content > 0)
-            .ToDictionary(x => x.RowId, x => x.Content)
+        _territoryToAetherCurrentCompFlgSet = new Dictionary<ushort, byte>().AsReadOnly();
+        _contentFinderConditionToContentId = dataManager.GetExcelSheet<ContentFinderCondition>()
+            .Where(x => x.RowId > 0 && x.Content.RowId > 0)
+            .ToDictionary(x => x.RowId, x => x.Content.RowId)
             .AsReadOnly();
     }
 
@@ -220,7 +220,7 @@ internal sealed unsafe class GameFunctions
 
     public bool UseAction(IGameObject gameObject, EAction action, bool checkCanUse = true)
     {
-        var actionRow = _dataManager.GetExcelSheet<Action>()!.GetRow((uint)action)!;
+        var actionRow = _dataManager.GetExcelSheet<Action>().GetRow((uint)action);
         if (checkCanUse && !ActionManager.CanUseActionOnTarget((uint)action, (GameObject*)gameObject.Address))
         {
             _logger.LogWarning("Can not use action {Action} on target {Target}", action, gameObject);
@@ -378,7 +378,7 @@ internal sealed unsafe class GameFunctions
 
     public void OpenDutyFinder(uint contentFinderConditionId)
     {
-        if (_contentFinderConditionToContentId.TryGetValue(contentFinderConditionId, out ushort contentId))
+        if (_contentFinderConditionToContentId.TryGetValue(contentFinderConditionId, out uint contentId))
         {
             if (UIState.IsInstanceContentUnlocked(contentId))
                 AgentContentsFinder.Instance()->OpenRegularDuty(contentFinderConditionId);
index b0a9239558559fe2585bbe783463344593dec60f..9211514dc5968630e5b90ed806ab6d65839e1408 100644 (file)
@@ -11,7 +11,7 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameData;
 using LLib.GameUI;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.Controller;
 using Questionable.Controller.Steps.Interactions;
 using Questionable.Data;
@@ -311,8 +311,8 @@ internal sealed unsafe class QuestFunctions
             ..QuestData.CrystalTowerQuests
         ];
 
-        EClassJob classJob = (EClassJob?)_clientState.LocalPlayer?.ClassJob.Id ?? EClassJob.Adventurer;
-        ushort[] shadowbringersRoleQuestChapters = QuestData.AllRoleQuestChapters.Select(x => x[0]).ToArray();
+        EClassJob classJob = (EClassJob?)_clientState.LocalPlayer?.ClassJob.RowId ?? EClassJob.Adventurer;
+        uint[] shadowbringersRoleQuestChapters = QuestData.AllRoleQuestChapters.Select(x => x[0]).ToArray();
         if (classJob != EClassJob.Adventurer)
         {
             priorityQuests.AddRange(_questRegistry.GetKnownClassJobQuests(classJob)
@@ -460,7 +460,7 @@ internal sealed unsafe class QuestFunctions
 
         // this only checks for the current class
         IQuestInfo questInfo = _questData.GetQuestInfo(leveId);
-        if (!questInfo.ClassJobs.Contains((EClassJob)_clientState.LocalPlayer!.ClassJob.Id) ||
+        if (!questInfo.ClassJobs.Contains((EClassJob)_clientState.LocalPlayer!.ClassJob.RowId) ||
             questInfo.Level > _clientState.LocalPlayer.Level)
             return true;
 
@@ -597,7 +597,7 @@ internal sealed unsafe class QuestFunctions
     public bool IsClassJobUnlocked(EClassJob classJob)
     {
         var classJobRow = _dataManager.GetExcelSheet<ClassJob>()!.GetRow((uint)classJob)!;
-        var questId = (ushort)classJobRow.UnlockQuest.Row;
+        var questId = (ushort)classJobRow.UnlockQuest.RowId;
         if (questId != 0)
             return IsQuestComplete(new QuestId(questId));
 
@@ -608,7 +608,7 @@ internal sealed unsafe class QuestFunctions
     public bool IsJobUnlocked(EClassJob classJob)
     {
         var classJobRow = _dataManager.GetExcelSheet<ClassJob>()!.GetRow((uint)classJob)!;
-        return IsClassJobUnlocked((EClassJob)classJobRow.ClassJobParent.Row);
+        return IsClassJobUnlocked((EClassJob)classJobRow.ClassJobParent.RowId);
     }
 
     public GrandCompany GetGrandCompany()
index 14878f71ccd818ba7dfdea36bb1e8aae586a583d..21eaf552be6f8bcde46776f4a00bf5c4cb2dd354 100644 (file)
@@ -1,7 +1,7 @@
 using System.Collections.Generic;
 using System.Collections.Immutable;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets2;
+using Lumina.Excel.Sheets;
 using Questionable.Model.Questing;
 
 namespace Questionable.Model;
@@ -11,13 +11,13 @@ internal sealed class LeveInfo : IQuestInfo
     public LeveInfo(Leve leve)
     {
         QuestId = new LeveId((ushort)leve.RowId);
-        Name = leve.Name;
+        Name = leve.Name.ToString();
         Level = leve.ClassJobLevel;
-        JournalGenre = leve.JournalGenre.Row;
+        JournalGenre = leve.JournalGenre.RowId;
         SortKey = QuestId.Value;
-        IssuerDataId = leve.LevelLevemete.Value!.Object.Row;
-        ClassJobs = QuestInfoUtils.AsList(leve.ClassJobCategory.Value!);
-        Expansion = (EExpansionVersion)leve.LevelLevemete.Value.Territory.Value!.ExVersion.Row;
+        IssuerDataId = leve.LevelLevemete.Value.Object.RowId;
+        ClassJobs = QuestInfoUtils.AsList(leve.ClassJobCategory.Value);
+        Expansion = (EExpansionVersion)leve.LevelLevemete.Value.Territory.Value.ExVersion.RowId;
     }
 
     public ElementId QuestId { get; }
index 6149209a78fb8ebd305c6d556d76e00b404d73b2..cca298902644335340654bcd30adf2caf9fab19c 100644 (file)
@@ -3,16 +3,15 @@ using System.Collections.Generic;
 using System.Collections.Immutable;
 using System.Linq;
 using FFXIVClientStructs.FFXIV.Client.UI.Agent;
-using JetBrains.Annotations;
 using LLib.GameData;
+using Questionable.Data.Sheets;
 using Questionable.Model.Questing;
-using ExcelQuest = Lumina.Excel.GeneratedSheets2.Quest;
 
 namespace Questionable.Model;
 
 internal sealed class QuestInfo : IQuestInfo
 {
-    public QuestInfo(ExcelQuest quest, ushort newGamePlusChapter, byte startingCity)
+    public QuestInfo(QuestEx quest, uint newGamePlusChapter, byte startingCity)
     {
         QuestId = new QuestId((ushort)(quest.RowId & 0xFFFF));
 
@@ -34,38 +33,38 @@ internal sealed class QuestInfo : IQuestInfo
             _ => "",
         };
 
-        Name = $"{quest.Name}{suffix}";
+        Name = $"{quest.Original.Name}{suffix}";
         Level = quest.ClassJobLevel[0];
-        IssuerDataId = quest.IssuerStart.Row;
+        IssuerDataId = quest.IssuerStart.RowId;
         IsRepeatable = quest.IsRepeatable;
         PreviousQuests =
             new List<PreviousQuestInfo>
                 {
-                    new(new QuestId((ushort)(quest.PreviousQuest[0].Row & 0xFFFF)), quest.Unknown7),
-                    new(new QuestId((ushort)(quest.PreviousQuest[1].Row & 0xFFFF))),
-                    new(new QuestId((ushort)(quest.PreviousQuest[2].Row & 0xFFFF)))
+                    new(new QuestId((ushort)(quest.PreviousQuest[0].RowId & 0xFFFF)), quest.Unknown7),
+                    new(new QuestId((ushort)(quest.PreviousQuest[1].RowId & 0xFFFF))),
+                    new(new QuestId((ushort)(quest.PreviousQuest[2].RowId & 0xFFFF)))
                 }
                 .Where(x => x.QuestId.Value != 0)
                 .ToImmutableList();
         PreviousQuestJoin = (EQuestJoin)quest.PreviousQuestJoin;
         QuestLocks = quest.QuestLock
-            .Select(x => new QuestId((ushort)(x.Row & 0xFFFFF)))
+            .Select(x => new QuestId((ushort)(x.RowId & 0xFFFFF)))
             .Where(x => x.Value != 0)
             .ToImmutableList();
         QuestLockJoin = (EQuestJoin)quest.QuestLockJoin;
-        JournalGenre = quest.JournalGenre?.Row;
+        JournalGenre = quest.JournalGenre.ValueNullable?.RowId;
         SortKey = quest.SortKey;
-        IsMainScenarioQuest = quest.JournalGenre?.Value?.JournalCategory?.Value?.JournalSection?.Row is 0 or 1;
-        CompletesInstantly = quest.TodoParams[0].ToDoCompleteSeq == 0;
-        PreviousInstanceContent = quest.InstanceContent.Select(x => (ushort)x.Row).Where(x => x != 0).ToList();
+        IsMainScenarioQuest = quest.JournalGenre.ValueNullable?.JournalCategory.ValueNullable?.JournalSection.ValueNullable?.RowId is 0 or 1;
+        CompletesInstantly = quest.Original.TodoParams[0].ToDoCompleteSeq == 0;
+        PreviousInstanceContent = quest.InstanceContent.Select(x => (ushort)x.RowId).Where(x => x != 0).ToList();
         PreviousInstanceContentJoin = (EQuestJoin)quest.InstanceContentJoin;
-        GrandCompany = (GrandCompany)quest.GrandCompany.Row;
-        AlliedSociety = (EAlliedSociety)quest.BeastTribe.Row;
-        ClassJobs = QuestInfoUtils.AsList(quest.ClassJobCategory0.Value!);
-        IsSeasonalEvent = quest.Festival.Row != 0;
+        GrandCompany = (GrandCompany)quest.GrandCompany.RowId;
+        AlliedSociety = (EAlliedSociety)quest.BeastTribe.RowId;
+        ClassJobs = QuestInfoUtils.AsList(quest.ClassJobCategory0.ValueNullable!);
+        IsSeasonalEvent = quest.Festival.RowId != 0;
         NewGamePlusChapter = newGamePlusChapter;
         StartingCity = startingCity;
-        Expansion = (EExpansionVersion)quest.Expansion.Row;
+        Expansion = (EExpansionVersion)quest.Expansion.RowId;
     }
 
 
@@ -88,7 +87,7 @@ internal sealed class QuestInfo : IQuestInfo
     public EAlliedSociety AlliedSociety { get; }
     public IReadOnlyList<EClassJob> ClassJobs { get; }
     public bool IsSeasonalEvent { get; }
-    public ushort NewGamePlusChapter { get; }
+    public uint NewGamePlusChapter { get; }
     public byte StartingCity { get; set; }
     public EExpansionVersion Expansion { get; }
 
index 4f44fd4aa27b532ff60e09e923c160a229d0af23..c22415bf6e205606e708c54ab1634371934575a2 100644 (file)
@@ -1,7 +1,8 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets2;
+using Lumina.Excel.Sheets;
 
 namespace Questionable.Model;
 
@@ -9,8 +10,12 @@ internal static class QuestInfoUtils
 {
     private static readonly Dictionary<uint, IReadOnlyList<EClassJob>> CachedClassJobs = new();
 
-    internal static IReadOnlyList<EClassJob> AsList(ClassJobCategory classJobCategory)
+    internal static IReadOnlyList<EClassJob> AsList(ClassJobCategory? optionalClassJobCategory)
     {
+        if (optionalClassJobCategory == null)
+            return Enum.GetValues<EClassJob>();
+
+        ClassJobCategory classJobCategory = optionalClassJobCategory.Value;
         if (CachedClassJobs.TryGetValue(classJobCategory.RowId, out IReadOnlyList<EClassJob>? classJobs))
             return classJobs;
 
@@ -57,8 +62,8 @@ internal static class QuestInfoUtils
                 { EClassJob.Dancer, classJobCategory.DNC },
                 { EClassJob.Reaper, classJobCategory.RPR },
                 { EClassJob.Sage, classJobCategory.SGE },
-                { EClassJob.Viper, classJobCategory.Unknown1 },
-                { EClassJob.Pictomancer, classJobCategory.Unknown2 }
+                { EClassJob.Viper, classJobCategory.VPR },
+                { EClassJob.Pictomancer, classJobCategory.PCT }
             }
             .Where(y => y.Value)
             .Select(y => y.Key)
index 41f6d5e25929604333b3f6181170623860ec1ff9..e2c25ad880f5687075900c2b21e848fa21222aff 100644 (file)
@@ -1,7 +1,7 @@
 using System.Collections.Generic;
 using System.Collections.Immutable;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.Model.Questing;
 
 namespace Questionable.Model;
@@ -11,12 +11,12 @@ internal sealed class SatisfactionSupplyInfo : IQuestInfo
     public SatisfactionSupplyInfo(SatisfactionNpc npc)
     {
         QuestId = new SatisfactionSupplyNpcId((ushort)npc.RowId);
-        Name = npc.Npc.Value!.Singular;
-        IssuerDataId = npc.Npc.Row;
+        Name = npc.Npc.Value.Singular.ToString();
+        IssuerDataId = npc.Npc.RowId;
         Level = npc.LevelUnlock;
         SortKey = QuestId.Value;
-        Expansion = (EExpansionVersion)npc.QuestRequired.Value!.Expansion.Row;
-        PreviousQuests = [new PreviousQuestInfo(new QuestId((ushort)(npc.QuestRequired.Row & 0xFFFF)))];
+        Expansion = (EExpansionVersion)npc.QuestRequired.Value!.Expansion.RowId;
+        PreviousQuests = [new PreviousQuestInfo(new QuestId((ushort)(npc.QuestRequired.RowId & 0xFFFF)))];
     }
 
     public ElementId QuestId { get; }
index 64df5619d2c04799f0c3b2509346744a7d4abb4f..6d44ba067e2a24553243db8dbf64fd9fbe7933c8 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Dalamud.NET.Sdk/10.0.0">
+<Project Sdk="Dalamud.NET.Sdk/11.0.0">
     <PropertyGroup>
         <OutputPath>dist</OutputPath>
         <PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
index 7bcd76817928817a460859e10933e24f18cb97e8..97847de52c8126a397018a5c68640e2591b10b58 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Dalamud.Game.Text;
@@ -10,7 +11,7 @@ using Dalamud.Plugin.Services;
 using Dalamud.Utility;
 using ImGuiNET;
 using LLib.ImGui;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.External;
 using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
 
@@ -36,7 +37,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
         _notificationMasterIpc = notificationMasterIpc;
         _configuration = configuration;
 
-        var mounts = dataManager.GetExcelSheet<Mount>()!
+        var mounts = dataManager.GetExcelSheet<Mount>()
             .Where(x => x is { RowId: > 0, Icon: > 0 })
             .Select(x => (MountId: x.RowId, Name: x.Singular.ToString()))
             .Where(x => !string.IsNullOrEmpty(x.Name))
index 81588465fc9ab8ee4110cb1f9074d7d758b3fbd6..53b1576e8bf4e303ce004e7064869610ce469112 100644 (file)
@@ -10,7 +10,7 @@ using Dalamud.Plugin.Services;
 using Dalamud.Utility.Signatures;
 using ImGuiNET;
 using LLib.GameData;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.Sheets;
 using Questionable.Controller;
 using Questionable.Model;
 using Questionable.Model.Gathering;
@@ -44,24 +44,24 @@ internal sealed class GatheringJournalComponent
         _gatheringPointRegistry = gatheringPointRegistry;
 
         // TODO some of the logic here would be better suited elsewhere, in particular the [item] → [gathering item] → [location] lookup
-        var routeToGatheringPoint = dataManager.GetExcelSheet<GatheringLeveRoute>()!
-            .Where(x => x.UnkData0[0].GatheringPoint != 0)
-            .SelectMany(x => x.UnkData0
-                .Where(y => y.GatheringPoint != 0)
+        var routeToGatheringPoint = dataManager.GetExcelSheet<GatheringLeveRoute>()
+            .Where(x => x.GatheringPoint[0].RowId != 0)
+            .SelectMany(x => x.GatheringPoint
+                .Where(y => y.RowId != 0)
                 .Select(y => new
                 {
                     RouteId = x.RowId,
-                    GatheringPointId = y.GatheringPoint
+                    GatheringPointId = y.RowId
                 }))
             .GroupBy(x => x.RouteId)
             .ToDictionary(x => x.Key, x => x.Select(y => y.GatheringPointId).ToList());
-        var gatheringLeveSheet = dataManager.GetExcelSheet<GatheringLeve>()!;
-        var territoryTypeSheet = dataManager.GetExcelSheet<TerritoryType>()!;
-        var gatheringPointToLeve = dataManager.GetExcelSheet<Leve>()!
+        var gatheringLeveSheet = dataManager.GetExcelSheet<GatheringLeve>();
+        var territoryTypeSheet = dataManager.GetExcelSheet<TerritoryType>();
+        var gatheringPointToLeve = dataManager.GetExcelSheet<Leve>()
             .Where(x => x.RowId > 0)
             .Select(x =>
             {
-                uint startZonePlaceName = x.PlaceNameStartZone.Row;
+                uint startZonePlaceName = x.PlaceNameStartZone.RowId;
                 startZonePlaceName = startZonePlaceName switch
                 {
                     27 => 28, // limsa
@@ -71,16 +71,17 @@ internal sealed class GatheringJournalComponent
                     _ => startZonePlaceName
                 };
 
-                var territoryType = territoryTypeSheet.FirstOrDefault(y => startZonePlaceName == y.PlaceName.Row)
+                var territoryType = territoryTypeSheet.Cast<TerritoryType?>()
+                                        .FirstOrDefault(y => startZonePlaceName == y!.Value.PlaceName.RowId)
                                     ?? throw new InvalidOperationException($"Unable to use {startZonePlaceName}");
                 return new
                 {
                     LeveId = x.RowId,
                     LeveName = x.Name.ToString(),
                     TerritoryType = (ushort)territoryType.RowId,
-                    TerritoryName = territoryType.PlaceName.Value?.Name.ToString(),
-                    Expansion = (EExpansionVersion)territoryType.ExVersion.Row,
-                    GatheringLeve = gatheringLeveSheet.GetRow((uint)x.DataId),
+                    TerritoryName = territoryType.PlaceName.ValueNullable?.Name.ToString(),
+                    Expansion = (EExpansionVersion)territoryType.ExVersion.RowId,
+                    GatheringLeve = gatheringLeveSheet.GetRowOrDefault(x.DataId.RowId),
                 };
             })
             .Where(x => x.GatheringLeve != null)
@@ -91,9 +92,9 @@ internal sealed class GatheringJournalComponent
                 x.TerritoryType,
                 x.TerritoryName,
                 x.Expansion,
-                GatheringPoints = x.GatheringLeve!.Route
-                    .Where(y => y.Row != 0)
-                    .SelectMany(y => routeToGatheringPoint[y.Row]),
+                GatheringPoints = x.GatheringLeve!.Value.Route
+                    .Where(y => y.RowId != 0)
+                    .SelectMany(y => routeToGatheringPoint[y.RowId]),
             })
             .SelectMany(x => x.GatheringPoints.Select(y => new
             {
@@ -110,40 +111,40 @@ internal sealed class GatheringJournalComponent
         var itemSheet = dataManager.GetExcelSheet<Item>()!;
 
         _gatheringItems = dataManager.GetExcelSheet<GatheringItem>()!
-            .Where(x => x.RowId != 0 && x.GatheringItemLevel.Row != 0)
+            .Where(x => x.RowId != 0 && x.GatheringItemLevel.RowId != 0)
             .Select(x => new
             {
                 GatheringItemId = (int)x.RowId,
-                Name = itemSheet.GetRow((uint)x.Item)?.Name.ToString()
+                Name = itemSheet.GetRowOrDefault(x.Item.RowId)?.Name.ToString()
             })
             .Where(x => !string.IsNullOrEmpty(x.Name))
             .ToDictionary(x => x.GatheringItemId, x => x.Name!);
 
         _gatheringPointsByExpansion = dataManager.GetExcelSheet<GatheringPoint>()!
-            .Where(x => x.GatheringPointBase.Row != 0)
-            .Where(x => x.GatheringPointBase.Row is < 653 or > 680) // exclude ishgard restoration phase 1
-            .DistinctBy(x => x.GatheringPointBase.Row)
+            .Where(x => x.GatheringPointBase.RowId != 0)
+            .Where(x => x.GatheringPointBase.RowId is < 653 or > 680) // exclude ishgard restoration phase 1
+            .DistinctBy(x => x.GatheringPointBase.RowId)
             .Select(x => new
             {
                 GatheringPointId = x.RowId,
-                Point = new DefaultGatheringPoint(new GatheringPointId((ushort)x.GatheringPointBase.Row),
-                    x.GatheringPointBase.Value!.GatheringType.Row switch
+                Point = new DefaultGatheringPoint(new GatheringPointId((ushort)x.GatheringPointBase.RowId),
+                    x.GatheringPointBase.Value!.GatheringType.RowId switch
                     {
                         0 or 1 => EClassJob.Miner,
                         2 or 3 => EClassJob.Botanist,
                         _ => EClassJob.Fisher
                     },
                     x.GatheringPointBase.Value.GatheringLevel,
-                    x.GatheringPointBase.Value.Item.Where(y => y != 0).Select(y => (ushort)y).ToList(),
-                    (EExpansionVersion?)x.TerritoryType.Value?.ExVersion.Row ?? (EExpansionVersion)byte.MaxValue,
-                    (ushort)x.TerritoryType.Row,
-                    x.TerritoryType.Value?.PlaceName.Value?.Name.ToString(),
-                    $"{x.GatheringPointBase.Row} - {x.PlaceName.Value?.Name}")
+                    x.GatheringPointBase.Value.Item.Where(y => y.RowId != 0).Select(y => (ushort)y.RowId).ToList(),
+                    (EExpansionVersion?)x.TerritoryType.ValueNullable?.ExVersion.RowId ?? (EExpansionVersion)byte.MaxValue,
+                    (ushort)x.TerritoryType.RowId,
+                    x.TerritoryType.ValueNullable?.PlaceName.ValueNullable?.Name.ToString(),
+                    $"{x.GatheringPointBase.RowId} - {x.PlaceName.ValueNullable?.Name}")
             })
             .Where(x => x.Point.ClassJob != EClassJob.Fisher)
             .Select(x =>
             {
-                if (gatheringPointToLeve.TryGetValue((int)x.GatheringPointId, out var leve))
+                if (gatheringPointToLeve.TryGetValue(x.GatheringPointId, out var leve))
                 {
                     // it's a leve
                     return x.Point with
@@ -161,9 +162,9 @@ internal sealed class GatheringJournalComponent
                     var territoryType = territoryTypeSheet.GetRow(gatheringRoot.Steps.Last().TerritoryId)!;
                     return x.Point with
                     {
-                        Expansion = (EExpansionVersion)territoryType.ExVersion.Row,
+                        Expansion = (EExpansionVersion)territoryType.ExVersion.RowId,
                         TerritoryType = (ushort)territoryType.RowId,
-                        TerritoryName = territoryType.PlaceName.Value?.Name.ToString(),
+                        TerritoryName = territoryType.PlaceName.ValueNullable?.Name.ToString(),
                     };
                 }
                 else
@@ -429,7 +430,7 @@ internal sealed class GatheringJournalComponent
         }
     }
 
-    public void ClearCounts()
+    public void ClearCounts(int type, int code)
     {
         foreach (var expansion in _gatheringPointsByExpansion)
         {
index f273b00dabbb98795c2cb80e8aeff767307a6803..36565fdf872252909313a21b43fba8ed74ae3190 100644 (file)
@@ -368,7 +368,7 @@ internal sealed class QuestJournalComponent
         }
     }
 
-    internal void ClearCounts()
+    internal void ClearCounts(int type, int code)
     {
         foreach (var genreCount in _genreCounts.ToList())
             _genreCounts[genreCount.Key] = genreCount.Value with { Completed = 0 };
index 1deaf934ca84dc8ce4729995231d08589ab5904a..4c100a1ba829b91b5a9173a93c42c4ed53c0d4ad 100644 (file)
@@ -67,7 +67,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
 #endif
         SizeConstraints = new WindowSizeConstraints
         {
-            MinimumSize = new Vector2(200, 30),
+            MinimumSize = new Vector2(230, 30),
             MaximumSize = default
         };
         RespectCloseHotkey = false;
index 147e12e95f2fb781f2c8ddac31d948700ed9051c..71ee09f7cc2230a73503b945422760da1368405c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 147e12e95f2fb781f2c8ddac31d948700ed9051c
+Subproject commit 71ee09f7cc2230a73503b945422760da1368405c