Compare commits
2 commits
5791858984
...
bb09805213
| Author | SHA1 | Date | |
|---|---|---|---|
| bb09805213 | |||
| 8461a561d3 |
18 changed files with 29488 additions and 888 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -18,9 +18,7 @@ public static class DataManagerExtensions
|
||||||
|
|
||||||
public static string? GetString<T>(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow<T>
|
public static string? GetString<T>(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow<T>
|
||||||
{
|
{
|
||||||
string text = dataManager.GetSeString<T>(key)?.WithCertainMacroCodeReplacements();
|
return dataManager.GetSeString<T>(key)?.WithCertainMacroCodeReplacements();
|
||||||
pluginLog?.Verbose($"{typeof(T).Name}.{key} => {text}");
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Regex? GetRegex<T>(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow<T>
|
public static Regex? GetRegex<T>(this IDataManager dataManager, string key, IPluginLog? pluginLog) where T : struct, IQuestDialogueText, IExcelRow<T>
|
||||||
|
|
@ -30,9 +28,7 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
string text = string.Join("", seString.Select((ReadOnlySePayload payload) => (payload.Type == ReadOnlySePayloadType.Text) ? Regex.Escape(payload.ToString()) : "(.*)"));
|
return new Regex(string.Join("", seString.Select((ReadOnlySePayload payload) => (payload.Type == ReadOnlySePayloadType.Text) ? Regex.Escape(payload.ToString()) : "(.*)")));
|
||||||
pluginLog?.Verbose($"{typeof(T).Name}.{key} => /{text}/");
|
|
||||||
return new Regex(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlySeString? GetSeString<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper) where T : struct, IExcelRow<T>
|
public static ReadOnlySeString? GetSeString<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper) where T : struct, IExcelRow<T>
|
||||||
|
|
@ -49,9 +45,7 @@ public static class DataManagerExtensions
|
||||||
|
|
||||||
public static string? GetString<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow<T>
|
public static string? GetString<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow<T>
|
||||||
{
|
{
|
||||||
string text = dataManager.GetSeString(rowId, mapper)?.WithCertainMacroCodeReplacements();
|
return dataManager.GetSeString(rowId, mapper)?.WithCertainMacroCodeReplacements();
|
||||||
pluginLog?.Verbose($"{typeof(T).Name}.{rowId} => {text}");
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Regex? GetRegex<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow<T>
|
public static Regex? GetRegex<T>(this IDataManager dataManager, uint rowId, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog = null) where T : struct, IExcelRow<T>
|
||||||
|
|
@ -61,9 +55,7 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Regex regex = seString.ToRegex();
|
return seString.ToRegex();
|
||||||
pluginLog?.Verbose($"{typeof(T).Name}.{rowId} => /{regex}/");
|
|
||||||
return regex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Regex? GetRegex<T>(this T excelRow, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog) where T : struct, IExcelRow<T>
|
public static Regex? GetRegex<T>(this T excelRow, Func<T, ReadOnlySeString?> mapper, IPluginLog? pluginLog) where T : struct, IExcelRow<T>
|
||||||
|
|
@ -74,9 +66,7 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Regex regex = text.ToRegex();
|
return text.ToRegex();
|
||||||
pluginLog?.Verbose($"{typeof(T).Name}.regex => /{regex}/");
|
|
||||||
return regex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Regex ToRegex(this ReadOnlySeString? text)
|
public static Regex ToRegex(this ReadOnlySeString? text)
|
||||||
|
|
|
||||||
8
Questionable/--y__InlineArray2.cs
Normal file
8
Questionable/--y__InlineArray2.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
[InlineArray(2)]
|
||||||
|
internal struct _003C_003Ey__InlineArray2<T>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -69,7 +69,6 @@ internal sealed class CreditsController : IDisposable
|
||||||
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditScrollArray, _creditScrollHandler);
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditScrollArray, _creditScrollHandler);
|
||||||
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditArray, _creditHandler);
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditArray, _creditHandler);
|
||||||
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditPlayerArray, _creditPlayerHandler);
|
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, CreditPlayerArray, _creditPlayerHandler);
|
||||||
_logger.LogDebug("CreditsController: registered listeners and ready to skip up to {MaxSkips} successive cutscenes.", _maxConsecutiveSkips);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Input;
|
using FFXIVClientStructs.FFXIV.Client.System.Input;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Controller.Steps.Common;
|
using Questionable.Controller.Steps.Common;
|
||||||
|
|
@ -37,10 +36,12 @@ internal static class Dive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class DoDive(ICondition condition, ILogger<DoDive> logger) : AbstractDelayedTaskExecutor<Task>(TimeSpan.FromSeconds(5L))
|
internal sealed class DoDive(ICondition condition, ILogger<DoDive> logger) : AbstractDelayedTaskExecutor<Task>(TimeSpan.FromSeconds(5L)), IStoppableTaskExecutor, ITaskExecutor
|
||||||
{
|
{
|
||||||
private readonly Queue<(uint Type, nint Key)> _keysToPress = new Queue<(uint, nint)>();
|
private readonly Queue<(uint Type, nint Key)> _keysToPress = new Queue<(uint, nint)>();
|
||||||
|
|
||||||
|
private readonly HashSet<nint> _pressedKeys = new HashSet<nint>();
|
||||||
|
|
||||||
private int _attempts;
|
private int _attempts;
|
||||||
|
|
||||||
protected override bool StartInternal()
|
protected override bool StartInternal()
|
||||||
|
|
@ -67,11 +68,30 @@ internal static class Dive
|
||||||
}
|
}
|
||||||
logger.LogDebug("{Action} key {KeyCode:X2}", (result.Item1 == 256) ? "Pressing" : "Releasing", result.Item2);
|
logger.LogDebug("{Action} key {KeyCode:X2}", (result.Item1 == 256) ? "Pressing" : "Releasing", result.Item2);
|
||||||
NativeMethods.SendMessage((nint)Device.Instance()->hWnd, result.Item1, result.Item2, IntPtr.Zero);
|
NativeMethods.SendMessage((nint)Device.Instance()->hWnd, result.Item1, result.Item2, IntPtr.Zero);
|
||||||
|
if (result.Item1 == 256)
|
||||||
|
{
|
||||||
|
_pressedKeys.Add(result.Item2);
|
||||||
|
}
|
||||||
|
else if (result.Item1 == 257)
|
||||||
|
{
|
||||||
|
_pressedKeys.Remove(result.Item2);
|
||||||
|
}
|
||||||
return ETaskResult.StillRunning;
|
return ETaskResult.StillRunning;
|
||||||
}
|
}
|
||||||
return base.Update();
|
return base.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe void StopNow()
|
||||||
|
{
|
||||||
|
foreach (nint pressedKey in _pressedKeys)
|
||||||
|
{
|
||||||
|
logger.LogDebug("Releasing stuck key {KeyCode:X2} on stop", pressedKey);
|
||||||
|
NativeMethods.SendMessage((nint)Device.Instance()->hWnd, 257u, pressedKey, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
_pressedKeys.Clear();
|
||||||
|
_keysToPress.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public override bool ShouldInterruptOnDamage()
|
public override bool ShouldInterruptOnDamage()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -83,7 +103,7 @@ internal static class Dive
|
||||||
{
|
{
|
||||||
return ETaskResult.TaskComplete;
|
return ETaskResult.TaskComplete;
|
||||||
}
|
}
|
||||||
if (_attempts >= 3)
|
if (_attempts >= 5)
|
||||||
{
|
{
|
||||||
throw new TaskException("Please dive manually.");
|
throw new TaskException("Please dive manually.");
|
||||||
}
|
}
|
||||||
|
|
@ -94,22 +114,25 @@ internal static class Dive
|
||||||
|
|
||||||
private unsafe void Descend()
|
private unsafe void Descend()
|
||||||
{
|
{
|
||||||
byte* ptr = stackalloc byte[16];
|
Keybind* keybind = UIInputData.Instance()->GetKeybind(InputId.MOVE_DESCENT);
|
||||||
Utf8String* name = Utf8String.FromString("MOVE_DESCENT");
|
if (keybind == null)
|
||||||
UIInputData.Instance()->GetKeybindByName(name, (Keybind*)ptr);
|
{
|
||||||
SeVirtualKey seVirtualKey = (SeVirtualKey)(*(uint*)ptr);
|
throw new TaskException("Could not find descent keybind");
|
||||||
byte b = ptr[4];
|
}
|
||||||
SeVirtualKey seVirtualKey2 = (SeVirtualKey)((uint*)ptr)[2];
|
Span<KeySetting> keySettings = keybind->KeySettings;
|
||||||
byte b2 = ptr[12];
|
SeVirtualKey key = keySettings[0].Key;
|
||||||
logger.LogInformation("Dive keybind: {Key1} + {Modifier1}, {Key2} + {Modifier2}", seVirtualKey, b, seVirtualKey2, b2);
|
KeyModifierFlag keyModifier = keySettings[0].KeyModifier;
|
||||||
|
SeVirtualKey key2 = keySettings[1].Key;
|
||||||
|
KeyModifierFlag keyModifier2 = keySettings[1].KeyModifier;
|
||||||
|
logger.LogInformation("Dive keybind: {Key1} + {Modifier1}, {Key2} + {Modifier2}", key, keyModifier, key2, keyModifier2);
|
||||||
int num = 2;
|
int num = 2;
|
||||||
List<List<nint>> list = new List<List<nint>>(num);
|
List<List<nint>> list = new List<List<nint>>(num);
|
||||||
CollectionsMarshal.SetCount(list, num);
|
CollectionsMarshal.SetCount(list, num);
|
||||||
Span<List<nint>> span = CollectionsMarshal.AsSpan(list);
|
Span<List<nint>> span = CollectionsMarshal.AsSpan(list);
|
||||||
int num2 = 0;
|
int num2 = 0;
|
||||||
span[num2] = GetKeysToPress(seVirtualKey, b);
|
span[num2] = GetKeysToPress(key, keyModifier);
|
||||||
num2++;
|
num2++;
|
||||||
span[num2] = GetKeysToPress(seVirtualKey2, b2);
|
span[num2] = GetKeysToPress(key2, keyModifier2);
|
||||||
List<nint> list2 = (from x in list
|
List<nint> list2 = (from x in list
|
||||||
where x != null
|
where x != null
|
||||||
select (x)).MinBy((List<nint> x) => x.Count);
|
select (x)).MinBy((List<nint> x) => x.Count);
|
||||||
|
|
@ -120,10 +143,12 @@ internal static class Dive
|
||||||
foreach (nint item in list2)
|
foreach (nint item in list2)
|
||||||
{
|
{
|
||||||
_keysToPress.Enqueue((256u, item));
|
_keysToPress.Enqueue((256u, item));
|
||||||
_keysToPress.Enqueue((0u, 0));
|
for (int num3 = 0; num3 < 15; num3++)
|
||||||
_keysToPress.Enqueue((0u, 0));
|
{
|
||||||
|
_keysToPress.Enqueue((0u, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int num3 = 0; num3 < 5; num3++)
|
for (int num4 = 0; num4 < 5; num4++)
|
||||||
{
|
{
|
||||||
_keysToPress.Enqueue((0u, 0));
|
_keysToPress.Enqueue((0u, 0));
|
||||||
}
|
}
|
||||||
|
|
@ -146,18 +171,18 @@ internal static class Dive
|
||||||
public static extern nint SendMessage(nint hWnd, uint Msg, nint wParam, nint lParam);
|
public static extern nint SendMessage(nint hWnd, uint Msg, nint wParam, nint lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<nint>? GetKeysToPress(SeVirtualKey key, byte modifier)
|
private static List<nint>? GetKeysToPress(SeVirtualKey key, KeyModifierFlag modifier)
|
||||||
{
|
{
|
||||||
List<nint> list = new List<nint>();
|
List<nint> list = new List<nint>();
|
||||||
if ((modifier & 1) != 0)
|
if ((modifier & KeyModifierFlag.Ctrl) != KeyModifierFlag.None)
|
||||||
{
|
{
|
||||||
list.Add(17);
|
list.Add(17);
|
||||||
}
|
}
|
||||||
if ((modifier & 2) != 0)
|
if ((modifier & KeyModifierFlag.Shift) != KeyModifierFlag.None)
|
||||||
{
|
{
|
||||||
list.Add(16);
|
list.Add(16);
|
||||||
}
|
}
|
||||||
if ((modifier & 4) != 0)
|
if ((modifier & KeyModifierFlag.Alt) != KeyModifierFlag.None)
|
||||||
{
|
{
|
||||||
list.Add(18);
|
list.Add(18);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,9 @@ internal sealed class GatheringPointRegistry : IDisposable
|
||||||
private void LoadGatheringPointsFromAssembly()
|
private void LoadGatheringPointsFromAssembly()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Loading gathering points from assembly");
|
_logger.LogInformation("Loading gathering points from assembly");
|
||||||
foreach (var (value, value2) in AssemblyGatheringLocationLoader.GetLocations())
|
IReadOnlyDictionary<ushort, GatheringRoot> locations = AssemblyGatheringLocationLoader.GetLocations();
|
||||||
|
_logger.LogInformation("AssemblyGatheringLocationLoader returned {Count} locations", locations.Count);
|
||||||
|
foreach (var (value, value2) in locations)
|
||||||
{
|
{
|
||||||
_gatheringPoints[new GatheringPointId(value)] = value2;
|
_gatheringPoints[new GatheringPointId(value)] = value2;
|
||||||
}
|
}
|
||||||
|
|
@ -72,27 +74,31 @@ internal sealed class GatheringPointRegistry : IDisposable
|
||||||
private void LoadGatheringPointsFromProjectDirectory()
|
private void LoadGatheringPointsFromProjectDirectory()
|
||||||
{
|
{
|
||||||
DirectoryInfo directoryInfo = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent;
|
DirectoryInfo directoryInfo = _pluginInterface.AssemblyLocation.Directory?.Parent?.Parent;
|
||||||
if (directoryInfo == null)
|
_logger.LogInformation("Looking for gathering paths in solution directory: {SolutionDirectory}", directoryInfo?.FullName ?? "(null)");
|
||||||
|
if (directoryInfo != null)
|
||||||
{
|
{
|
||||||
return;
|
DirectoryInfo directoryInfo2 = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "GatheringPaths"));
|
||||||
}
|
_logger.LogInformation("Gathering paths project directory: {PathProjectDirectory}, Exists: {Exists}", directoryInfo2.FullName, directoryInfo2.Exists);
|
||||||
DirectoryInfo directoryInfo2 = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "GatheringPaths"));
|
if (!directoryInfo2.Exists)
|
||||||
if (!directoryInfo2.Exists)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (string value in ExpansionData.ExpansionFolders.Values)
|
|
||||||
{
|
{
|
||||||
LoadFromDirectory(new DirectoryInfo(Path.Combine(directoryInfo2.FullName, value)));
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string value in ExpansionData.ExpansionFolders.Values)
|
||||||
|
{
|
||||||
|
LoadFromDirectory(new DirectoryInfo(Path.Combine(directoryInfo2.FullName, value)));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_gatheringPoints.Clear();
|
||||||
|
_logger.LogError(exception, "Failed to load gathering points from project directory");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
_logger.LogWarning("Could not determine solution directory from assembly location: {AssemblyLocation}", _pluginInterface.AssemblyLocation.FullName);
|
||||||
{
|
|
||||||
_gatheringPoints.Clear();
|
|
||||||
_logger.LogError(exception, "Failed to load gathering points from project directory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadGatheringPointFromStream(string fileName, Stream stream)
|
private void LoadGatheringPointFromStream(string fileName, Stream stream)
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ internal sealed class QuestRegistry
|
||||||
}
|
}
|
||||||
if (_questData.TryGetQuestInfo(elementId2, out IQuestInfo questInfo))
|
if (_questData.TryGetQuestInfo(elementId2, out IQuestInfo questInfo))
|
||||||
{
|
{
|
||||||
goto IL_01c8;
|
goto IL_01ae;
|
||||||
}
|
}
|
||||||
if (elementId2 is UnlockLinkId unlockLinkId)
|
if (elementId2 is UnlockLinkId unlockLinkId)
|
||||||
{
|
{
|
||||||
|
|
@ -147,18 +147,16 @@ internal sealed class QuestRegistry
|
||||||
text = $"Unlock Link {unlockLinkId.Value}";
|
text = $"Unlock Link {unlockLinkId.Value}";
|
||||||
}
|
}
|
||||||
questInfo = new UnlockLinkQuestInfo(unlockLinkId, text, 0u, dateTime);
|
questInfo = new UnlockLinkQuestInfo(unlockLinkId, text, 0u, dateTime);
|
||||||
_logger.LogDebug("Created UnlockLinkQuestInfo for {QuestId} from assembly", elementId2);
|
|
||||||
_questData.AddOrReplaceQuestInfo(questInfo);
|
_questData.AddOrReplaceQuestInfo(questInfo);
|
||||||
goto IL_01c8;
|
goto IL_01ae;
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Not loading unknown quest {QuestId} from assembly: Quest not found in quest data", elementId2);
|
_logger.LogWarning("Not loading unknown quest {QuestId} from assembly: Quest not found in quest data", elementId2);
|
||||||
goto end_IL_003d;
|
goto end_IL_003d;
|
||||||
IL_01c8:
|
IL_01ae:
|
||||||
if (flag2 || flag3)
|
if (flag2 || flag3)
|
||||||
{
|
{
|
||||||
bool flag4 = flag ?? questInfo.IsSeasonalQuest;
|
bool isSeasonal = flag ?? questInfo.IsSeasonalQuest;
|
||||||
_questData.ApplySeasonalOverride(elementId2, flag4, dateTime);
|
_questData.ApplySeasonalOverride(elementId2, isSeasonal, dateTime);
|
||||||
_logger.LogDebug("Applied seasonal override for quest {QuestId} from assembly: IsSeasonal={IsSeasonal}, Expiry={Expiry}", elementId2, flag4, dateTime?.ToString("o") ?? "(null)");
|
|
||||||
}
|
}
|
||||||
IQuestInfo questInfo2 = _questData.GetQuestInfo(elementId2);
|
IQuestInfo questInfo2 = _questData.GetQuestInfo(elementId2);
|
||||||
Quest quest = new Quest
|
Quest quest = new Quest
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -109,7 +109,6 @@ internal sealed class JournalData
|
||||||
if (journalCategory.RowId != 0)
|
if (journalCategory.RowId != 0)
|
||||||
{
|
{
|
||||||
SeasonalEventsCategoryId = journalCategory.RowId;
|
SeasonalEventsCategoryId = journalCategory.RowId;
|
||||||
_logger.LogInformation("Resolved 'Seasonal Events' JournalCategory ID: {CategoryId}", SeasonalEventsCategoryId);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -121,7 +120,6 @@ internal sealed class JournalData
|
||||||
SeasonalEventGenreIds = (from x in excelSheet
|
SeasonalEventGenreIds = (from x in excelSheet
|
||||||
where x.RowId != 0 && x.JournalCategory.RowId == journalData.SeasonalEventsCategoryId.Value
|
where x.RowId != 0 && x.JournalCategory.RowId == journalData.SeasonalEventsCategoryId.Value
|
||||||
select x.RowId).ToHashSet();
|
select x.RowId).ToHashSet();
|
||||||
_logger.LogInformation("Resolved {Count} seasonal event JournalGenre IDs from JournalCategory {CategoryId}: [{Ids}]", SeasonalEventGenreIds.Count, SeasonalEventsCategoryId.Value, string.Join(", ", SeasonalEventGenreIds.OrderBy((uint x) => x)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -131,7 +129,6 @@ internal sealed class JournalData
|
||||||
if (journalGenre.RowId != 0)
|
if (journalGenre.RowId != 0)
|
||||||
{
|
{
|
||||||
MoogleDeliveryGenreId = journalGenre.RowId;
|
MoogleDeliveryGenreId = journalGenre.RowId;
|
||||||
_logger.LogInformation("Resolved 'Delivery Moogle Quests' JournalGenre ID: {GenreId}", MoogleDeliveryGenreId);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -171,20 +168,19 @@ internal sealed class JournalData
|
||||||
if (section != null)
|
if (section != null)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
foreach (Category category in section.Categories)
|
|
||||||
{
|
{
|
||||||
foreach (Genre genre in category.Genres)
|
foreach (Category category in section.Categories)
|
||||||
{
|
{
|
||||||
genre.IsUnderOtherQuests = true;
|
foreach (Genre genre in category.Genres)
|
||||||
num++;
|
{
|
||||||
|
genre.IsUnderOtherQuests = true;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_logger.LogInformation("Marked {Count} genres as under 'Other Quests' (OtherQuestsSectionRowId={Id})", num, valueOrDefault);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogWarning("OtherQuestsSectionRowId = {Id} found, but matching Section not present in constructed Sections", valueOrDefault);
|
|
||||||
}
|
}
|
||||||
|
_logger.LogWarning("OtherQuestsSectionRowId = {Id} found, but matching Section not present in constructed Sections", valueOrDefault);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||||
using LLib.GameData;
|
using LLib.GameData;
|
||||||
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Questionable.Model;
|
using Questionable.Model;
|
||||||
|
|
@ -85,11 +86,12 @@ internal sealed class QuestData
|
||||||
startingCities[item.Quest.RowId] = b;
|
startingCities[item.Quest.RowId] = b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExcelSheet<QuestEx> questExSheet = dataManager.GetExcelSheet<QuestEx>();
|
||||||
List<IQuestInfo> list = new List<IQuestInfo>();
|
List<IQuestInfo> list = new List<IQuestInfo>();
|
||||||
list.AddRange(from x in dataManager.GetExcelSheet<Lumina.Excel.Sheets.Quest>()
|
list.AddRange(from x in dataManager.GetExcelSheet<Lumina.Excel.Sheets.Quest>()
|
||||||
where x.RowId != 0
|
where x.RowId != 0
|
||||||
where x.IssuerLocation.RowId != 0
|
where x.IssuerLocation.RowId != 0
|
||||||
select new QuestInfo(x, questChapters.GetValueOrDefault(x.RowId), startingCities.GetValueOrDefault(x.RowId), journalGenreOverrides));
|
select new QuestInfo(x, questExSheet.GetRow(x.RowId), questChapters.GetValueOrDefault(x.RowId), startingCities.GetValueOrDefault(x.RowId), journalGenreOverrides));
|
||||||
list.AddRange(from x in dataManager.GetExcelSheet<SatisfactionNpc>()
|
list.AddRange(from x in dataManager.GetExcelSheet<SatisfactionNpc>()
|
||||||
where x.RowId != 0 && x.Npc.RowId != 0
|
where x.RowId != 0 && x.Npc.RowId != 0
|
||||||
select new SatisfactionSupplyInfo(x));
|
select new SatisfactionSupplyInfo(x));
|
||||||
|
|
@ -1218,7 +1220,7 @@ internal sealed class QuestData
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogWarning("ApplySeasonalOverride: Quest {QuestId} not found in QuestData (could not apply seasonal override)", questId);
|
_ = value is UnlockLinkQuestInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1226,7 +1228,6 @@ internal sealed class QuestData
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(info, "info");
|
ArgumentNullException.ThrowIfNull(info, "info");
|
||||||
_quests[info.QuestId] = info;
|
_quests[info.QuestId] = info;
|
||||||
_logger.LogDebug("Added or replaced QuestInfo for {QuestId} in QuestData", info.QuestId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QuestData()
|
static QuestData()
|
||||||
|
|
|
||||||
|
|
@ -873,7 +873,7 @@ internal sealed class QuestFunctions
|
||||||
{
|
{
|
||||||
if (IsQuestUnobtainable(questId, extraCompletedQuest))
|
if (IsQuestUnobtainable(questId, extraCompletedQuest))
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
QuestInfo questInfo = (QuestInfo)_questData.GetQuestInfo(questId);
|
QuestInfo questInfo = (QuestInfo)_questData.GetQuestInfo(questId);
|
||||||
if (questInfo.GrandCompany != FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany.None)
|
if (questInfo.GrandCompany != FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany.None)
|
||||||
|
|
|
||||||
420
Questionable/Questionable.Model/QuestEx.cs
Normal file
420
Questionable/Questionable.Model/QuestEx.cs
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
using Lumina.Excel;
|
||||||
|
using Lumina.Excel.Sheets;
|
||||||
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
|
namespace Questionable.Model;
|
||||||
|
|
||||||
|
[GeneratedCode("Lumina.Excel.Generator", "2.0.0")]
|
||||||
|
[Sheet("Quest", 179568153u)]
|
||||||
|
public readonly struct QuestEx : IExcelRow<QuestEx>
|
||||||
|
{
|
||||||
|
public readonly struct QuestParamsStruct
|
||||||
|
{
|
||||||
|
public ReadOnlySeString ScriptInstruction => _003Cpage_003EP.ReadString(_003Coffset_003EP, _003CparentOffset_003EP);
|
||||||
|
|
||||||
|
public uint ScriptArg => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 4);
|
||||||
|
|
||||||
|
public QuestParamsStruct(ExcelPage page, uint parentOffset, uint offset)
|
||||||
|
{
|
||||||
|
_003Cpage_003EP = page;
|
||||||
|
_003CparentOffset_003EP = parentOffset;
|
||||||
|
_003Coffset_003EP = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct QuestListenerParamsStruct
|
||||||
|
{
|
||||||
|
public uint Listener => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP);
|
||||||
|
|
||||||
|
public uint ConditionValue => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 4);
|
||||||
|
|
||||||
|
public ushort Behavior => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 8);
|
||||||
|
|
||||||
|
public byte ActorSpawnSeq => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 10);
|
||||||
|
|
||||||
|
public byte ActorDespawnSeq => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 11);
|
||||||
|
|
||||||
|
public byte Unknown0 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 12);
|
||||||
|
|
||||||
|
public byte Unknown1 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 13);
|
||||||
|
|
||||||
|
public byte QuestUInt8A => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 14);
|
||||||
|
|
||||||
|
public byte ConditionType => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 15);
|
||||||
|
|
||||||
|
public byte ConditionOperator => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 16);
|
||||||
|
|
||||||
|
public bool VisibleBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 0);
|
||||||
|
|
||||||
|
public bool ConditionBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 1);
|
||||||
|
|
||||||
|
public bool ItemBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 2);
|
||||||
|
|
||||||
|
public bool AnnounceBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 3);
|
||||||
|
|
||||||
|
public bool BehaviorBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 4);
|
||||||
|
|
||||||
|
public bool AcceptBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 5);
|
||||||
|
|
||||||
|
public bool QualifiedBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 6);
|
||||||
|
|
||||||
|
public bool CanTargetBool => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 17, 7);
|
||||||
|
|
||||||
|
public QuestListenerParamsStruct(ExcelPage page, uint parentOffset, uint offset)
|
||||||
|
{
|
||||||
|
_003Cpage_003EP = page;
|
||||||
|
_003Coffset_003EP = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct TodoParamsStruct
|
||||||
|
{
|
||||||
|
public unsafe Collection<RowRef<Level>> ToDoLocation => new Collection<RowRef<Level>>(_003Cpage_003EP, _003CparentOffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<Level>>)(&ToDoLocationCtor), 8);
|
||||||
|
|
||||||
|
public byte ToDoCompleteSeq => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 32);
|
||||||
|
|
||||||
|
public byte ToDoQty => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 33);
|
||||||
|
|
||||||
|
public byte CountableNum => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 34);
|
||||||
|
|
||||||
|
public TodoParamsStruct(ExcelPage page, uint parentOffset, uint offset)
|
||||||
|
{
|
||||||
|
_003Cpage_003EP = page;
|
||||||
|
_003CparentOffset_003EP = parentOffset;
|
||||||
|
_003Coffset_003EP = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<Level> ToDoLocationCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<Level>(page.Module, page.ReadUInt32(offset + i * 4), page.Language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExcelPage ExcelPage => _003Cpage_003EP;
|
||||||
|
|
||||||
|
public uint RowOffset => _003Coffset_003EP;
|
||||||
|
|
||||||
|
public uint RowId => _003Crow_003EP;
|
||||||
|
|
||||||
|
public ReadOnlySeString Name => _003Cpage_003EP.ReadString(_003Coffset_003EP, _003Coffset_003EP);
|
||||||
|
|
||||||
|
public unsafe Collection<QuestParamsStruct> QuestParams => new Collection<QuestParamsStruct>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, QuestParamsStruct>)(&QuestParamsCtor), 50);
|
||||||
|
|
||||||
|
public unsafe Collection<QuestListenerParamsStruct> QuestListenerParams => new Collection<QuestListenerParamsStruct>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, QuestListenerParamsStruct>)(&QuestListenerParamsCtor), 64);
|
||||||
|
|
||||||
|
public unsafe Collection<TodoParamsStruct> TodoParams => new Collection<TodoParamsStruct>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, TodoParamsStruct>)(&TodoParamsCtor), 24);
|
||||||
|
|
||||||
|
public uint GilReward => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2548);
|
||||||
|
|
||||||
|
public RowRef<Item> CurrencyReward => new RowRef<Item>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2552), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public uint CurrencyRewardCount => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2556);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef> Reward => new Collection<RowRef>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef>)(&RewardCtor), 7);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<Item>> OptionalItemReward => new Collection<RowRef<Item>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<Item>>)(&OptionalItemRewardCtor), 5);
|
||||||
|
|
||||||
|
public RowRef<InstanceContent> InstanceContentUnlock => new RowRef<InstanceContent>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2608), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public ushort ExpFactor => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2612);
|
||||||
|
|
||||||
|
public RowRef<Emote> EmoteReward => new RowRef<Emote>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2614), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<Lumina.Excel.Sheets.Action> ActionReward => new RowRef<Lumina.Excel.Sheets.Action>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2616), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public unsafe Collection<ushort> SystemReward => new Collection<ushort>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, ushort>)(&SystemRewardCtor), 2);
|
||||||
|
|
||||||
|
public ushort GCTypeReward => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2622);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<Item>> ItemCatalyst => new Collection<RowRef<Item>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<Item>>)(&ItemCatalystCtor), 3);
|
||||||
|
|
||||||
|
public unsafe Collection<byte> ItemCountCatalyst => new Collection<byte>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, byte>)(&ItemCountCatalystCtor), 3);
|
||||||
|
|
||||||
|
public byte ItemRewardType => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2630);
|
||||||
|
|
||||||
|
public unsafe Collection<byte> ItemCountReward => new Collection<byte>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, byte>)(&ItemCountRewardCtor), 7);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<Stain>> RewardStain => new Collection<RowRef<Stain>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<Stain>>)(&RewardStainCtor), 7);
|
||||||
|
|
||||||
|
public unsafe Collection<byte> OptionalItemCountReward => new Collection<byte>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, byte>)(&OptionalItemCountRewardCtor), 5);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<Stain>> OptionalItemStainReward => new Collection<RowRef<Stain>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<Stain>>)(&OptionalItemStainRewardCtor), 5);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<GeneralAction>> GeneralActionReward => new Collection<RowRef<GeneralAction>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<GeneralAction>>)(&GeneralActionRewardCtor), 2);
|
||||||
|
|
||||||
|
public RowRef<QuestRewardOther> OtherReward => new RowRef<QuestRewardOther>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2657), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte Tomestone => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2658);
|
||||||
|
|
||||||
|
public byte TomestoneReward => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2659);
|
||||||
|
|
||||||
|
public byte TomestoneCountReward => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2660);
|
||||||
|
|
||||||
|
public byte ReputationReward => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2661);
|
||||||
|
|
||||||
|
public bool Unknown0 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2662);
|
||||||
|
|
||||||
|
public bool Unknown1 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2663);
|
||||||
|
|
||||||
|
public bool Unknown2 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2664);
|
||||||
|
|
||||||
|
public bool Unknown3 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2665);
|
||||||
|
|
||||||
|
public bool Unknown4 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2666);
|
||||||
|
|
||||||
|
public bool Unknown5 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2667);
|
||||||
|
|
||||||
|
public bool Unknown6 => _003Cpage_003EP.ReadBool(_003Coffset_003EP + 2668);
|
||||||
|
|
||||||
|
public unsafe Collection<bool> OptionalItemIsHQReward => new Collection<bool>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, bool>)(&OptionalItemIsHQRewardCtor), 5);
|
||||||
|
|
||||||
|
public ReadOnlySeString Id => _003Cpage_003EP.ReadString(_003Coffset_003EP + 2676, _003Coffset_003EP);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<QuestEx>> PreviousQuest => new Collection<RowRef<QuestEx>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<QuestEx>>)(&PreviousQuestCtor), 3);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<QuestEx>> QuestLock => new Collection<RowRef<QuestEx>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<QuestEx>>)(&QuestLockCtor), 2);
|
||||||
|
|
||||||
|
public unsafe Collection<RowRef<InstanceContent>> InstanceContent => new Collection<RowRef<InstanceContent>>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, RowRef<InstanceContent>>)(&InstanceContentCtor), 3);
|
||||||
|
|
||||||
|
public RowRef IssuerStart
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ExcelModule module = _003Cpage_003EP.Module;
|
||||||
|
uint rowId = _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2712);
|
||||||
|
global::_003C_003Ey__InlineArray2<Type> buffer = default(global::_003C_003Ey__InlineArray2<Type>);
|
||||||
|
global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef<global::_003C_003Ey__InlineArray2<Type>, Type>(ref buffer, 0) = typeof(EObjName);
|
||||||
|
global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef<global::_003C_003Ey__InlineArray2<Type>, Type>(ref buffer, 1) = typeof(ENpcResident);
|
||||||
|
return RowRef.GetFirstValidRowOrUntyped(module, rowId, global::_003CPrivateImplementationDetails_003E.InlineArrayAsReadOnlySpan<global::_003C_003Ey__InlineArray2<Type>, Type>(in buffer, 2), -965341264, _003Cpage_003EP.Language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RowRef<Level> IssuerLocation => new RowRef<Level>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2716), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef TargetEnd
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ExcelModule module = _003Cpage_003EP.Module;
|
||||||
|
uint rowId = _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2720);
|
||||||
|
global::_003C_003Ey__InlineArray2<Type> buffer = default(global::_003C_003Ey__InlineArray2<Type>);
|
||||||
|
global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef<global::_003C_003Ey__InlineArray2<Type>, Type>(ref buffer, 0) = typeof(EObjName);
|
||||||
|
global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef<global::_003C_003Ey__InlineArray2<Type>, Type>(ref buffer, 1) = typeof(ENpcResident);
|
||||||
|
return RowRef.GetFirstValidRowOrUntyped(module, rowId, global::_003CPrivateImplementationDetails_003E.InlineArrayAsReadOnlySpan<global::_003C_003Ey__InlineArray2<Type>, Type>(in buffer, 2), -965341264, _003Cpage_003EP.Language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RowRef<JournalGenre> JournalGenre => new RowRef<JournalGenre>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2724), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public uint Icon => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2728);
|
||||||
|
|
||||||
|
public uint IconSpecial => _003Cpage_003EP.ReadUInt32(_003Coffset_003EP + 2732);
|
||||||
|
|
||||||
|
public RowRef<Mount> MountRequired => new RowRef<Mount>(_003Cpage_003EP.Module, (uint)_003Cpage_003EP.ReadInt32(_003Coffset_003EP + 2736), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public unsafe Collection<ushort> ClassJobLevel => new Collection<ushort>(_003Cpage_003EP, _003Coffset_003EP, _003Coffset_003EP, (delegate*<ExcelPage, uint, uint, uint, ushort>)(&ClassJobLevelCtor), 2);
|
||||||
|
|
||||||
|
public ushort Header => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2744);
|
||||||
|
|
||||||
|
public RowRef<Festival> Festival => new RowRef<Festival>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2746), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public ushort BellStart => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2748);
|
||||||
|
|
||||||
|
public ushort BellEnd => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2750);
|
||||||
|
|
||||||
|
public ushort BeastReputationValue => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2752);
|
||||||
|
|
||||||
|
public SubrowRef<Behavior> ClientBehavior => new SubrowRef<Behavior>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2754), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public SubrowRef<QuestClassJobSupply> QuestClassJobSupply => new SubrowRef<QuestClassJobSupply>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2756), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<PlaceName> PlaceName => new RowRef<PlaceName>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2758), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public ushort SortKey => _003Cpage_003EP.ReadUInt16(_003Coffset_003EP + 2760);
|
||||||
|
|
||||||
|
public RowRef<ExVersion> Expansion => new RowRef<ExVersion>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2762), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<ClassJobCategory> ClassJobCategory0 => new RowRef<ClassJobCategory>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2763), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte QuestLevelOffset => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2764);
|
||||||
|
|
||||||
|
public RowRef<ClassJobCategory> ClassJobCategory1 => new RowRef<ClassJobCategory>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2765), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte PreviousQuestJoin => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2766);
|
||||||
|
|
||||||
|
public byte Unknown7 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2767);
|
||||||
|
|
||||||
|
public byte QuestLockJoin => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2768);
|
||||||
|
|
||||||
|
public byte Unknown8 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2769);
|
||||||
|
|
||||||
|
public byte Unknown9 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2770);
|
||||||
|
|
||||||
|
public RowRef<ClassJob> ClassJobUnlock => new RowRef<ClassJob>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2771), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<GrandCompany> GrandCompany => new RowRef<GrandCompany>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2772), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<GrandCompanyRank> GrandCompanyRank => new RowRef<GrandCompanyRank>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2773), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte InstanceContentJoin => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2774);
|
||||||
|
|
||||||
|
public byte FestivalBegin => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2775);
|
||||||
|
|
||||||
|
public byte FestivalEnd => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2776);
|
||||||
|
|
||||||
|
public RowRef<BeastTribe> BeastTribe => new RowRef<BeastTribe>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2777), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<BeastReputationRank> BeastReputationRank => new RowRef<BeastReputationRank>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2778), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<SatisfactionNpc> SatisfactionNpc => new RowRef<SatisfactionNpc>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2779), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte SatisfactionLevel => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2780);
|
||||||
|
|
||||||
|
public RowRef<DeliveryQuest> DeliveryQuest => new RowRef<DeliveryQuest>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2781), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte RepeatIntervalType => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2782);
|
||||||
|
|
||||||
|
public RowRef<QuestRepeatFlag> QuestRepeatFlag => new RowRef<QuestRepeatFlag>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2783), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte Type => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2784);
|
||||||
|
|
||||||
|
public byte Unknown_70 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2785);
|
||||||
|
|
||||||
|
public byte LevelMax => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2786);
|
||||||
|
|
||||||
|
public RowRef<ClassJob> ClassJobRequired => new RowRef<ClassJob>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2787), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public RowRef<QuestRewardOther> QuestRewardOtherDisplay => new RowRef<QuestRewardOther>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2788), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte Unknown10 => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2789);
|
||||||
|
|
||||||
|
public RowRef<EventIconType> EventIconType => new RowRef<EventIconType>(_003Cpage_003EP.Module, _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2790), _003Cpage_003EP.Language);
|
||||||
|
|
||||||
|
public byte DailyQuestPool => _003Cpage_003EP.ReadUInt8(_003Coffset_003EP + 2791);
|
||||||
|
|
||||||
|
public bool IsHouseRequired => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 0);
|
||||||
|
|
||||||
|
public bool IsRepeatable => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 1);
|
||||||
|
|
||||||
|
public bool CanCancel => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 2);
|
||||||
|
|
||||||
|
public bool Introduction => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 3);
|
||||||
|
|
||||||
|
public bool HideOfferIcon => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 4);
|
||||||
|
|
||||||
|
public bool Unknown12 => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 5);
|
||||||
|
|
||||||
|
public bool Unknown13 => _003Cpage_003EP.ReadPackedBool(_003Coffset_003EP + 2792, 6);
|
||||||
|
|
||||||
|
public QuestEx(ExcelPage page, uint offset, uint row)
|
||||||
|
{
|
||||||
|
_003Cpage_003EP = page;
|
||||||
|
_003Coffset_003EP = offset;
|
||||||
|
_003Crow_003EP = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static QuestParamsStruct QuestParamsCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new QuestParamsStruct(page, parentOffset, offset + 4 + i * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static QuestListenerParamsStruct QuestListenerParamsCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new QuestListenerParamsStruct(page, parentOffset, offset + 404 + i * 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TodoParamsStruct TodoParamsCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new TodoParamsStruct(page, parentOffset, offset + 1684 + i * 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef RewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt8(offset + 2630) switch
|
||||||
|
{
|
||||||
|
1 => RowRef.Create<Item>(page.Module, page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
3 => RowRef.Create<Item>(page.Module, page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
5 => RowRef.Create<Item>(page.Module, page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
6 => RowRef.CreateSubrow<QuestClassJobReward>(page.Module, page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
7 => RowRef.Create<BeastRankBonus>(page.Module, page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
_ => RowRef.CreateUntyped(page.ReadUInt32(offset + 2560 + i * 4), page.Language),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<Item> OptionalItemRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<Item>(page.Module, page.ReadUInt32(offset + 2588 + i * 4), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ushort SystemRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt16(offset + 2618 + i * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<Item> ItemCatalystCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<Item>(page.Module, page.ReadUInt8(offset + 2624 + i), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte ItemCountCatalystCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt8(offset + 2627 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte ItemCountRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt8(offset + 2631 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<Stain> RewardStainCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<Stain>(page.Module, page.ReadUInt8(offset + 2638 + i), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte OptionalItemCountRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt8(offset + 2645 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<Stain> OptionalItemStainRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<Stain>(page.Module, page.ReadUInt8(offset + 2650 + i), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<GeneralAction> GeneralActionRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<GeneralAction>(page.Module, page.ReadUInt8(offset + 2655 + i), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool OptionalItemIsHQRewardCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadBool(offset + 2669 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<QuestEx> PreviousQuestCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<QuestEx>(page.Module, page.ReadUInt32(offset + 2680 + i * 4), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<QuestEx> QuestLockCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<QuestEx>(page.Module, page.ReadUInt32(offset + 2692 + i * 4), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowRef<InstanceContent> InstanceContentCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return new RowRef<InstanceContent>(page.Module, page.ReadUInt32(offset + 2700 + i * 4), page.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ushort ClassJobLevelCtor(ExcelPage page, uint parentOffset, uint offset, uint i)
|
||||||
|
{
|
||||||
|
return page.ReadUInt16(offset + 2740 + i * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QuestEx IExcelRow<QuestEx>.Create(ExcelPage page, uint offset, uint row)
|
||||||
|
{
|
||||||
|
return new QuestEx(page, offset, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -68,7 +68,7 @@ internal sealed class QuestInfo : IQuestInfo
|
||||||
|
|
||||||
public bool IsSeasonalQuest { get; internal set; }
|
public bool IsSeasonalQuest { get; internal set; }
|
||||||
|
|
||||||
public QuestInfo(Lumina.Excel.Sheets.Quest quest, uint newGamePlusChapter, byte startingCity, JournalGenreOverrides journalGenreOverrides, bool isSeasonalEventQuest = false, DateTime? seasonalQuestExpiry = null)
|
public QuestInfo(Lumina.Excel.Sheets.Quest ogquest, QuestEx quest, uint newGamePlusChapter, byte startingCity, JournalGenreOverrides journalGenreOverrides, bool isSeasonalEventQuest = false, DateTime? seasonalQuestExpiry = null)
|
||||||
{
|
{
|
||||||
QuestId = Questionable.Model.Questing.QuestId.FromRowId(quest.RowId);
|
QuestId = Questionable.Model.Questing.QuestId.FromRowId(quest.RowId);
|
||||||
string value = QuestId.Value switch
|
string value = QuestId.Value switch
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ internal sealed class QuestValidator
|
||||||
{
|
{
|
||||||
_validators = validators.ToList();
|
_validators = validators.ToList();
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_logger.LogInformation("Validators: {Validators}", string.Join(", ", _validators.Select((IQuestValidator x) => x.GetType().Name)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,6 @@ internal sealed class SinglePlayerDutyConfigComponent : ConfigComponent
|
||||||
{
|
{
|
||||||
if (quest.Root.Disabled)
|
if (quest.Root.Disabled)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Disabling quest battle for quest {QuestId}, quest is disabled", questId);
|
|
||||||
return (Enabled: false, Options: singlePlayerDutyOptions);
|
return (Enabled: false, Options: singlePlayerDutyOptions);
|
||||||
}
|
}
|
||||||
QuestStep questStep = (from x in quest.AllSteps()
|
QuestStep questStep = (from x in quest.AllSteps()
|
||||||
|
|
@ -277,7 +276,6 @@ internal sealed class SinglePlayerDutyConfigComponent : ConfigComponent
|
||||||
}
|
}
|
||||||
return (Enabled: true, Options: questStep.SinglePlayerDutyOptions ?? singlePlayerDutyOptions);
|
return (Enabled: true, Options: questStep.SinglePlayerDutyOptions ?? singlePlayerDutyOptions);
|
||||||
}
|
}
|
||||||
_logger.LogDebug("Disabling quest battle for quest {QuestId}, unknown quest", questId);
|
|
||||||
return (Enabled: false, Options: singlePlayerDutyOptions);
|
return (Enabled: false, Options: singlePlayerDutyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,6 @@ internal sealed class QuestJournalComponent
|
||||||
_categoryCounts.Clear();
|
_categoryCounts.Clear();
|
||||||
_sectionCounts.Clear();
|
_sectionCounts.Clear();
|
||||||
bool hideSeasonalEventsFromJournalProgress = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
bool hideSeasonalEventsFromJournalProgress = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
||||||
_logger.LogInformation("Refreshing journal counts. HideSeasonalEventsFromJournalProgress={Hide}", hideSeasonalEventsFromJournalProgress);
|
|
||||||
foreach (JournalData.Genre genre in _journalData.Genres)
|
foreach (JournalData.Genre genre in _journalData.Genres)
|
||||||
{
|
{
|
||||||
List<IQuestInfo> source = ((hideSeasonalEventsFromJournalProgress && _journalData.SeasonalEventsCategoryId.HasValue && genre.CategoryId == _journalData.SeasonalEventsCategoryId.Value) ? genre.Quests.Where((IQuestInfo q) => !IsSeasonal(q)).ToList() : genre.Quests.ToList());
|
List<IQuestInfo> source = ((hideSeasonalEventsFromJournalProgress && _journalData.SeasonalEventsCategoryId.HasValue && genre.CategoryId == _journalData.SeasonalEventsCategoryId.Value) ? genre.Quests.Where((IQuestInfo q) => !IsSeasonal(q)).ToList() : genre.Quests.ToList());
|
||||||
|
|
|
||||||
|
|
@ -251,33 +251,6 @@ internal sealed class EventInfoComponent
|
||||||
}
|
}
|
||||||
questInfo = quest.Info;
|
questInfo = quest.Info;
|
||||||
}
|
}
|
||||||
try
|
|
||||||
{
|
|
||||||
bool flag = false;
|
|
||||||
DateTime? dateTime = null;
|
|
||||||
if (questInfo is QuestInfo questInfo2)
|
|
||||||
{
|
|
||||||
flag = questInfo2.IsSeasonalQuest || questInfo2.IsSeasonalEvent || questInfo2.SeasonalQuestExpiry is DateTime || (questInfo2.JournalGenre.HasValue && _journalData.SeasonalEventGenreIds.Contains(questInfo2.JournalGenre.Value));
|
|
||||||
dateTime = questInfo2.SeasonalQuestExpiry;
|
|
||||||
}
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
if (dateTime.HasValue)
|
|
||||||
{
|
|
||||||
DateTime valueOrDefault = dateTime.GetValueOrDefault();
|
|
||||||
DateTime dateTime2 = NormalizeExpiry(valueOrDefault);
|
|
||||||
_logger.LogInformation("Seasonal details: Quest {QuestId} '{Name}' rawExpiry={Raw:o} Kind={Kind} TimeOfDay={TimeOfDay} normalizedUtc={Normalized:o}", questInfo.QuestId, questInfo.Name, valueOrDefault, valueOrDefault.Kind, valueOrDefault.TimeOfDay, dateTime2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Seasonal details: Quest {QuestId} '{Name}' has no expiry (seasonal flag present). IsSeasonalEvent={IsSeasonalEvent} IsSeasonalQuest={IsSeasonalQuest} JournalGenre={JournalGenre} SeasonalQuestExpiry={SeasonalQuestExpiry}", questInfo.QuestId, questInfo.Name, questInfo is QuestInfo questInfo3 && questInfo3.IsSeasonalEvent, questInfo is QuestInfo questInfo4 && questInfo4.IsSeasonalQuest, (questInfo is QuestInfo questInfo5) ? questInfo5.JournalGenre : ((uint?)null), (questInfo is QuestInfo questInfo6) ? questInfo6.SeasonalQuestExpiry : ((DateTime?)null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
_logger.LogDebug(exception, "Failed to log seasonal details for {QuestId}", questInfo.QuestId);
|
|
||||||
}
|
|
||||||
if (_questFunctions.IsQuestUnobtainable(questInfo.QuestId))
|
if (_questFunctions.IsQuestUnobtainable(questInfo.QuestId))
|
||||||
{
|
{
|
||||||
if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
||||||
|
|
@ -289,15 +262,15 @@ internal sealed class EventInfoComponent
|
||||||
{
|
{
|
||||||
if (questExpiry.HasValue)
|
if (questExpiry.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault2 = questExpiry.GetValueOrDefault();
|
DateTime valueOrDefault = questExpiry.GetValueOrDefault();
|
||||||
DateTime dateTime3 = NormalizeExpiry(valueOrDefault2);
|
DateTime dateTime = NormalizeExpiry(valueOrDefault);
|
||||||
if (dateTime3 > DateTime.UtcNow)
|
if (dateTime > DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
yield return questInfo;
|
yield return questInfo;
|
||||||
}
|
}
|
||||||
else if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
else if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Skipping UnlockLink quest {QuestId} '{Name}': expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime3);
|
_logger.LogDebug("Skipping UnlockLink quest {QuestId} '{Name}': expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -307,24 +280,24 @@ internal sealed class EventInfoComponent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(questInfo is QuestInfo { SeasonalQuestExpiry: var seasonalQuestExpiry } questInfo7))
|
if (!(questInfo is QuestInfo { SeasonalQuestExpiry: var seasonalQuestExpiry } questInfo2))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (seasonalQuestExpiry.HasValue)
|
if (seasonalQuestExpiry.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault3 = seasonalQuestExpiry.GetValueOrDefault();
|
DateTime valueOrDefault2 = seasonalQuestExpiry.GetValueOrDefault();
|
||||||
DateTime dateTime4 = NormalizeExpiry(valueOrDefault3);
|
DateTime dateTime2 = NormalizeExpiry(valueOrDefault2);
|
||||||
if (dateTime4 > DateTime.UtcNow)
|
if (dateTime2 > DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
yield return questInfo;
|
yield return questInfo;
|
||||||
}
|
}
|
||||||
else if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
else if (_alreadyLoggedActiveSeasonalSkip.Add(questInfo.QuestId.Value))
|
||||||
{
|
{
|
||||||
_logger.LogDebug("Skipping quest {QuestId} '{Name}': seasonal expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime4);
|
_logger.LogDebug("Skipping quest {QuestId} '{Name}': seasonal expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (questInfo7.IsSeasonalQuest && !questInfo7.SeasonalQuestExpiry.HasValue)
|
else if (questInfo2.IsSeasonalQuest && !questInfo2.SeasonalQuestExpiry.HasValue)
|
||||||
{
|
{
|
||||||
yield return questInfo;
|
yield return questInfo;
|
||||||
}
|
}
|
||||||
|
|
@ -354,12 +327,12 @@ internal sealed class EventInfoComponent
|
||||||
return q.JournalGenre.HasValue ? GetJournalGenreName(q.JournalGenre.Value) : q.Name;
|
return q.JournalGenre.HasValue ? GetJournalGenreName(q.JournalGenre.Value) : q.Name;
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
DateTime dateTime = item.Select(delegate(IQuestInfo q)
|
item.Select(delegate(IQuestInfo q)
|
||||||
{
|
{
|
||||||
DateTime? dateTime2 = (q as QuestInfo)?.SeasonalQuestExpiry ?? ((q is UnlockLinkQuestInfo unlockLinkQuestInfo) ? unlockLinkQuestInfo.QuestExpiry : ((DateTime?)null));
|
DateTime? dateTime = (q as QuestInfo)?.SeasonalQuestExpiry ?? ((q is UnlockLinkQuestInfo unlockLinkQuestInfo) ? unlockLinkQuestInfo.QuestExpiry : ((DateTime?)null));
|
||||||
if (dateTime2.HasValue)
|
if (dateTime.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault = dateTime2.GetValueOrDefault();
|
DateTime valueOrDefault = dateTime.GetValueOrDefault();
|
||||||
return NormalizeExpiry(valueOrDefault);
|
return NormalizeExpiry(valueOrDefault);
|
||||||
}
|
}
|
||||||
return DateTime.MaxValue;
|
return DateTime.MaxValue;
|
||||||
|
|
@ -368,14 +341,9 @@ internal sealed class EventInfoComponent
|
||||||
select (q as UnlockLinkQuestInfo)?.Patch into p
|
select (q as UnlockLinkQuestInfo)?.Patch into p
|
||||||
where !string.IsNullOrEmpty(p)
|
where !string.IsNullOrEmpty(p)
|
||||||
select p).Distinct().ToList();
|
select p).Distinct().ToList();
|
||||||
string text = ((list.Count == 1) ? list[0] : null);
|
if (list.Count == 1)
|
||||||
if (dateTime != DateTime.MaxValue)
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Seasonal event '{Name}' ends at {Expiry:o} UTC (patch={Patch})", item.Key, dateTime, text ?? "n/a");
|
_ = list[0];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Seasonal event '{Name}' has no expiry (patch={Patch})", item.Key, text ?? "n/a");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ internal sealed class ChangelogWindow : LWindow
|
||||||
DrawChangelogEntries();
|
DrawChangelogEntries();
|
||||||
ChangelogFooterComponent.Draw(delegate
|
ChangelogFooterComponent.Draw(delegate
|
||||||
{
|
{
|
||||||
MarkAllAsRead();
|
|
||||||
base.IsOpen = false;
|
base.IsOpen = false;
|
||||||
});
|
});
|
||||||
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
|
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
|
||||||
|
|
@ -71,6 +70,12 @@ internal sealed class ChangelogWindow : LWindow
|
||||||
_headerComponent.Reset();
|
_headerComponent.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnClose()
|
||||||
|
{
|
||||||
|
base.OnClose();
|
||||||
|
MarkAllAsRead();
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawChangelogEntries()
|
private void DrawChangelogEntries()
|
||||||
{
|
{
|
||||||
_headerAnimationTime += ImGui.GetIO().DeltaTime;
|
_headerAnimationTime += ImGui.GetIO().DeltaTime;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue