Compare commits
No commits in common. "bb098052133bd6f037d5dff88ffe4121fb3565d9" and "5791858984287c34a825cdd72972ca8ee492b7fe" have entirely different histories.
bb09805213
...
5791858984
18 changed files with 896 additions and 29496 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,9 @@ 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>
|
||||||
{
|
{
|
||||||
return dataManager.GetSeString<T>(key)?.WithCertainMacroCodeReplacements();
|
string text = 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>
|
||||||
|
|
@ -28,7 +30,9 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Regex(string.Join("", seString.Select((ReadOnlySePayload payload) => (payload.Type == ReadOnlySePayloadType.Text) ? Regex.Escape(payload.ToString()) : "(.*)")));
|
string text = 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>
|
||||||
|
|
@ -45,7 +49,9 @@ 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>
|
||||||
{
|
{
|
||||||
return dataManager.GetSeString(rowId, mapper)?.WithCertainMacroCodeReplacements();
|
string text = 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>
|
||||||
|
|
@ -55,7 +61,9 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return seString.ToRegex();
|
Regex regex = 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>
|
||||||
|
|
@ -66,7 +74,9 @@ public static class DataManagerExtensions
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return text.ToRegex();
|
Regex regex = 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)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Auto)]
|
|
||||||
[InlineArray(2)]
|
|
||||||
internal struct _003C_003Ey__InlineArray2<T>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -69,6 +69,7 @@ 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,6 +6,7 @@ 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;
|
||||||
|
|
@ -36,12 +37,10 @@ internal static class Dive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class DoDive(ICondition condition, ILogger<DoDive> logger) : AbstractDelayedTaskExecutor<Task>(TimeSpan.FromSeconds(5L)), IStoppableTaskExecutor, ITaskExecutor
|
internal sealed class DoDive(ICondition condition, ILogger<DoDive> logger) : AbstractDelayedTaskExecutor<Task>(TimeSpan.FromSeconds(5L))
|
||||||
{
|
{
|
||||||
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()
|
||||||
|
|
@ -68,30 +67,11 @@ 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;
|
||||||
|
|
@ -103,7 +83,7 @@ internal static class Dive
|
||||||
{
|
{
|
||||||
return ETaskResult.TaskComplete;
|
return ETaskResult.TaskComplete;
|
||||||
}
|
}
|
||||||
if (_attempts >= 5)
|
if (_attempts >= 3)
|
||||||
{
|
{
|
||||||
throw new TaskException("Please dive manually.");
|
throw new TaskException("Please dive manually.");
|
||||||
}
|
}
|
||||||
|
|
@ -114,25 +94,22 @@ internal static class Dive
|
||||||
|
|
||||||
private unsafe void Descend()
|
private unsafe void Descend()
|
||||||
{
|
{
|
||||||
Keybind* keybind = UIInputData.Instance()->GetKeybind(InputId.MOVE_DESCENT);
|
byte* ptr = stackalloc byte[16];
|
||||||
if (keybind == null)
|
Utf8String* name = Utf8String.FromString("MOVE_DESCENT");
|
||||||
{
|
UIInputData.Instance()->GetKeybindByName(name, (Keybind*)ptr);
|
||||||
throw new TaskException("Could not find descent keybind");
|
SeVirtualKey seVirtualKey = (SeVirtualKey)(*(uint*)ptr);
|
||||||
}
|
byte b = ptr[4];
|
||||||
Span<KeySetting> keySettings = keybind->KeySettings;
|
SeVirtualKey seVirtualKey2 = (SeVirtualKey)((uint*)ptr)[2];
|
||||||
SeVirtualKey key = keySettings[0].Key;
|
byte b2 = ptr[12];
|
||||||
KeyModifierFlag keyModifier = keySettings[0].KeyModifier;
|
logger.LogInformation("Dive keybind: {Key1} + {Modifier1}, {Key2} + {Modifier2}", seVirtualKey, b, seVirtualKey2, b2);
|
||||||
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(key, keyModifier);
|
span[num2] = GetKeysToPress(seVirtualKey, b);
|
||||||
num2++;
|
num2++;
|
||||||
span[num2] = GetKeysToPress(key2, keyModifier2);
|
span[num2] = GetKeysToPress(seVirtualKey2, b2);
|
||||||
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);
|
||||||
|
|
@ -143,12 +120,10 @@ internal static class Dive
|
||||||
foreach (nint item in list2)
|
foreach (nint item in list2)
|
||||||
{
|
{
|
||||||
_keysToPress.Enqueue((256u, item));
|
_keysToPress.Enqueue((256u, item));
|
||||||
for (int num3 = 0; num3 < 15; num3++)
|
_keysToPress.Enqueue((0u, 0));
|
||||||
{
|
_keysToPress.Enqueue((0u, 0));
|
||||||
_keysToPress.Enqueue((0u, 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int num4 = 0; num4 < 5; num4++)
|
for (int num3 = 0; num3 < 5; num3++)
|
||||||
{
|
{
|
||||||
_keysToPress.Enqueue((0u, 0));
|
_keysToPress.Enqueue((0u, 0));
|
||||||
}
|
}
|
||||||
|
|
@ -171,18 +146,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, KeyModifierFlag modifier)
|
private static List<nint>? GetKeysToPress(SeVirtualKey key, byte modifier)
|
||||||
{
|
{
|
||||||
List<nint> list = new List<nint>();
|
List<nint> list = new List<nint>();
|
||||||
if ((modifier & KeyModifierFlag.Ctrl) != KeyModifierFlag.None)
|
if ((modifier & 1) != 0)
|
||||||
{
|
{
|
||||||
list.Add(17);
|
list.Add(17);
|
||||||
}
|
}
|
||||||
if ((modifier & KeyModifierFlag.Shift) != KeyModifierFlag.None)
|
if ((modifier & 2) != 0)
|
||||||
{
|
{
|
||||||
list.Add(16);
|
list.Add(16);
|
||||||
}
|
}
|
||||||
if ((modifier & KeyModifierFlag.Alt) != KeyModifierFlag.None)
|
if ((modifier & 4) != 0)
|
||||||
{
|
{
|
||||||
list.Add(18);
|
list.Add(18);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,7 @@ 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");
|
||||||
IReadOnlyDictionary<ushort, GatheringRoot> locations = AssemblyGatheringLocationLoader.GetLocations();
|
foreach (var (value, value2) in 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;
|
||||||
}
|
}
|
||||||
|
|
@ -74,31 +72,27 @@ 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;
|
||||||
_logger.LogInformation("Looking for gathering paths in solution directory: {SolutionDirectory}", directoryInfo?.FullName ?? "(null)");
|
if (directoryInfo == null)
|
||||||
if (directoryInfo != null)
|
|
||||||
{
|
{
|
||||||
DirectoryInfo directoryInfo2 = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "GatheringPaths"));
|
return;
|
||||||
_logger.LogInformation("Gathering paths project directory: {PathProjectDirectory}, Exists: {Exists}", directoryInfo2.FullName, directoryInfo2.Exists);
|
}
|
||||||
if (!directoryInfo2.Exists)
|
DirectoryInfo directoryInfo2 = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "GatheringPaths"));
|
||||||
|
if (!directoryInfo2.Exists)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string value in ExpansionData.ExpansionFolders.Values)
|
||||||
{
|
{
|
||||||
return;
|
LoadFromDirectory(new DirectoryInfo(Path.Combine(directoryInfo2.FullName, value)));
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Could not determine solution directory from assembly location: {AssemblyLocation}", _pluginInterface.AssemblyLocation.FullName);
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_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_01ae;
|
goto IL_01c8;
|
||||||
}
|
}
|
||||||
if (elementId2 is UnlockLinkId unlockLinkId)
|
if (elementId2 is UnlockLinkId unlockLinkId)
|
||||||
{
|
{
|
||||||
|
|
@ -147,16 +147,18 @@ 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_01ae;
|
goto IL_01c8;
|
||||||
}
|
}
|
||||||
_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_01ae:
|
IL_01c8:
|
||||||
if (flag2 || flag3)
|
if (flag2 || flag3)
|
||||||
{
|
{
|
||||||
bool isSeasonal = flag ?? questInfo.IsSeasonalQuest;
|
bool flag4 = flag ?? questInfo.IsSeasonalQuest;
|
||||||
_questData.ApplySeasonalOverride(elementId2, isSeasonal, dateTime);
|
_questData.ApplySeasonalOverride(elementId2, flag4, 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,6 +109,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -120,6 +121,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -129,6 +131,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -168,19 +171,20 @@ internal sealed class JournalData
|
||||||
if (section != null)
|
if (section != null)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
foreach (Category category in section.Categories)
|
||||||
{
|
{
|
||||||
foreach (Category category in section.Categories)
|
foreach (Genre genre in category.Genres)
|
||||||
{
|
{
|
||||||
foreach (Genre genre in category.Genres)
|
genre.IsUnderOtherQuests = true;
|
||||||
{
|
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,7 +7,6 @@ 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;
|
||||||
|
|
@ -86,12 +85,11 @@ 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, questExSheet.GetRow(x.RowId), questChapters.GetValueOrDefault(x.RowId), startingCities.GetValueOrDefault(x.RowId), journalGenreOverrides));
|
select new QuestInfo(x, 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));
|
||||||
|
|
@ -1220,7 +1218,7 @@ internal sealed class QuestData
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ = value is UnlockLinkQuestInfo;
|
_logger.LogWarning("ApplySeasonalOverride: Quest {QuestId} not found in QuestData (could not apply seasonal override)", questId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1228,6 +1226,7 @@ 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 true;
|
return false;
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -1,420 +0,0 @@
|
||||||
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 ogquest, QuestEx quest, uint newGamePlusChapter, byte startingCity, JournalGenreOverrides journalGenreOverrides, bool isSeasonalEventQuest = false, DateTime? seasonalQuestExpiry = null)
|
public QuestInfo(Lumina.Excel.Sheets.Quest 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,6 +27,7 @@ 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,6 +265,7 @@ 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()
|
||||||
|
|
@ -276,6 +277,7 @@ 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,6 +492,7 @@ 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,6 +251,33 @@ 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))
|
||||||
|
|
@ -262,15 +289,15 @@ internal sealed class EventInfoComponent
|
||||||
{
|
{
|
||||||
if (questExpiry.HasValue)
|
if (questExpiry.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault = questExpiry.GetValueOrDefault();
|
DateTime valueOrDefault2 = questExpiry.GetValueOrDefault();
|
||||||
DateTime dateTime = NormalizeExpiry(valueOrDefault);
|
DateTime dateTime3 = NormalizeExpiry(valueOrDefault2);
|
||||||
if (dateTime > DateTime.UtcNow)
|
if (dateTime3 > 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, dateTime);
|
_logger.LogDebug("Skipping UnlockLink quest {QuestId} '{Name}': expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -280,24 +307,24 @@ internal sealed class EventInfoComponent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(questInfo is QuestInfo { SeasonalQuestExpiry: var seasonalQuestExpiry } questInfo2))
|
if (!(questInfo is QuestInfo { SeasonalQuestExpiry: var seasonalQuestExpiry } questInfo7))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (seasonalQuestExpiry.HasValue)
|
if (seasonalQuestExpiry.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault2 = seasonalQuestExpiry.GetValueOrDefault();
|
DateTime valueOrDefault3 = seasonalQuestExpiry.GetValueOrDefault();
|
||||||
DateTime dateTime2 = NormalizeExpiry(valueOrDefault2);
|
DateTime dateTime4 = NormalizeExpiry(valueOrDefault3);
|
||||||
if (dateTime2 > DateTime.UtcNow)
|
if (dateTime4 > 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, dateTime2);
|
_logger.LogDebug("Skipping quest {QuestId} '{Name}': seasonal expiry {Expiry:o} UTC is not in the future", questInfo.QuestId, questInfo.Name, dateTime4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (questInfo2.IsSeasonalQuest && !questInfo2.SeasonalQuestExpiry.HasValue)
|
else if (questInfo7.IsSeasonalQuest && !questInfo7.SeasonalQuestExpiry.HasValue)
|
||||||
{
|
{
|
||||||
yield return questInfo;
|
yield return questInfo;
|
||||||
}
|
}
|
||||||
|
|
@ -327,12 +354,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;
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
item.Select(delegate(IQuestInfo q)
|
DateTime dateTime = item.Select(delegate(IQuestInfo q)
|
||||||
{
|
{
|
||||||
DateTime? dateTime = (q as QuestInfo)?.SeasonalQuestExpiry ?? ((q is UnlockLinkQuestInfo unlockLinkQuestInfo) ? unlockLinkQuestInfo.QuestExpiry : ((DateTime?)null));
|
DateTime? dateTime2 = (q as QuestInfo)?.SeasonalQuestExpiry ?? ((q is UnlockLinkQuestInfo unlockLinkQuestInfo) ? unlockLinkQuestInfo.QuestExpiry : ((DateTime?)null));
|
||||||
if (dateTime.HasValue)
|
if (dateTime2.HasValue)
|
||||||
{
|
{
|
||||||
DateTime valueOrDefault = dateTime.GetValueOrDefault();
|
DateTime valueOrDefault = dateTime2.GetValueOrDefault();
|
||||||
return NormalizeExpiry(valueOrDefault);
|
return NormalizeExpiry(valueOrDefault);
|
||||||
}
|
}
|
||||||
return DateTime.MaxValue;
|
return DateTime.MaxValue;
|
||||||
|
|
@ -341,9 +368,14 @@ 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();
|
||||||
if (list.Count == 1)
|
string text = ((list.Count == 1) ? list[0] : null);
|
||||||
|
if (dateTime != DateTime.MaxValue)
|
||||||
{
|
{
|
||||||
_ = list[0];
|
_logger.LogInformation("Seasonal event '{Name}' ends at {Expiry:o} UTC (patch={Patch})", item.Key, dateTime, text ?? "n/a");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Seasonal event '{Name}' has no expiry (patch={Patch})", item.Key, text ?? "n/a");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ 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();
|
||||||
|
|
@ -70,12 +71,6 @@ 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