muffin v7.4.7

This commit is contained in:
alydev 2025-12-28 12:35:39 +10:00
parent 1cc65e495d
commit 63f975ff4f
16 changed files with 1659 additions and 939 deletions

View file

@ -72,6 +72,10 @@ internal sealed class QuestFunctions
private ElementId? _lastLoggedAcceptedHiddenMsq;
private bool _loggedNoClassQuestsAvailable;
private bool _loggedAdventurerClass;
public QuestFunctions(QuestRegistry questRegistry, QuestData questData, JournalData journalData, AetheryteFunctions aetheryteFunctions, AlliedSocietyQuestFunctions alliedSocietyQuestFunctions, AlliedSocietyData alliedSocietyData, AetheryteData aetheryteData, Configuration configuration, IDataManager dataManager, IObjectTable objectTable, IClientState clientState, IGameGui gameGui, IAetheryteList aetheryteList, ILogger<QuestFunctions> logger)
{
_questRegistry = questRegistry;
@ -195,6 +199,8 @@ internal sealed class QuestFunctions
{
_logger.LogInformation("MSQ {MsqId} requires level {RequiredLevel}, current level {CurrentLevel}. Checking for early class quests to level up.", questReference.CurrentQuest, quest.Info.Level, currentLevel);
_lastLoggedLevelLockedMsq = questReference.CurrentQuest;
_loggedNoClassQuestsAvailable = false;
_loggedAdventurerClass = false;
}
if (valueOrDefault != EClassJob.Adventurer)
{
@ -222,10 +228,10 @@ internal sealed class QuestFunctions
return new QuestReference(questId2, QuestManager.GetQuestSequence(questId2.Value), questReference.State);
}
}
else if (_lastLoggedLevelLockedMsq == questReference.CurrentQuest && _lastLoggedForcedClassQuest == null)
else if (!_loggedNoClassQuestsAvailable)
{
_logger.LogWarning("No class quests passed the filter for {ClassJob} at level {CurrentLevel}", valueOrDefault, currentLevel);
_lastLoggedLevelLockedMsq = null;
_loggedNoClassQuestsAvailable = true;
}
List<QuestInfo> list2 = (from x in _questRegistry.GetKnownClassJobQuests(valueOrDefault, includeRoleQuests: false)
where x.Level <= currentLevel && x.Level <= 5 && !IsQuestAcceptedOrComplete(x.QuestId) && IsReadyToAcceptQuest(x.QuestId)
@ -237,11 +243,16 @@ internal sealed class QuestFunctions
_logger.LogInformation("MSQ level locked. Prioritizing class quest {ClassQuestId} for {ClassJob} (level {QuestLevel}) from registry", questId3, valueOrDefault, list2.First().Level);
return new QuestReference(questId3, QuestManager.GetQuestSequence(questId3.Value), questReference.State);
}
_logger.LogWarning("MSQ level locked but no available early class quests found for {ClassJob} at level {CurrentLevel}", valueOrDefault, currentLevel);
if (!_loggedNoClassQuestsAvailable)
{
_logger.LogWarning("MSQ level locked but no available early class quests found for {ClassJob} at level {CurrentLevel}", valueOrDefault, currentLevel);
_loggedNoClassQuestsAvailable = true;
}
}
else
else if (!_loggedAdventurerClass)
{
_logger.LogWarning("Current class is Adventurer, cannot find class quests");
_loggedAdventurerClass = true;
}
Questionable.Model.Quest quest2;
ElementId elementId = (from x in GetNextPriorityQuestsThatCanBeAccepted()
@ -253,11 +264,17 @@ internal sealed class QuestFunctions
_logger.LogInformation("MSQ {MsqId} requires level {RequiredLevel}, current level {CurrentLevel}. Prioritizing early class quest {ClassQuestId} (from priority list)", questReference.CurrentQuest, quest.Info.Level, currentLevel, elementId);
return new QuestReference(elementId, QuestManager.GetQuestSequence(elementId.Value), questReference.State);
}
_logger.LogWarning("MSQ {MsqId} is level locked (requires {RequiredLevel}, current {CurrentLevel}) and no early class quests available. Cannot proceed.", questReference.CurrentQuest, quest.Info.Level, currentLevel);
if (!_loggedNoClassQuestsAvailable)
{
_logger.LogWarning("MSQ {MsqId} is level locked (requires {RequiredLevel}, current {CurrentLevel}) and no early class quests available. Cannot proceed.", questReference.CurrentQuest, quest.Info.Level, currentLevel);
_loggedNoClassQuestsAvailable = true;
}
return QuestReference.NoQuest(MainScenarioQuestState.Unavailable);
}
_lastLoggedLevelLockedMsq = null;
_lastLoggedForcedClassQuest = null;
_loggedNoClassQuestsAvailable = false;
_loggedAdventurerClass = false;
}
if (questReference.CurrentQuest != null && !IsQuestAccepted(questReference.CurrentQuest))
{
@ -931,7 +948,7 @@ internal sealed class QuestFunctions
private static bool IsQuestLocked(UnlockLinkId unlockLinkId)
{
return IsQuestUnobtainable(unlockLinkId);
return IsQuestUnobtainableStatic(unlockLinkId);
}
private bool IsQuestLocked(AethernetId aethernetId)
@ -995,11 +1012,24 @@ internal sealed class QuestFunctions
}
if (elementId is UnlockLinkId unlockLinkId)
{
return IsQuestUnobtainable(unlockLinkId);
return IsQuestUnobtainableStatic(unlockLinkId);
}
return false;
}
private static bool IsQuestUnobtainableStatic(UnlockLinkId unlockLinkId)
{
if (unlockLinkId.Value == 506)
{
return !IsFestivalActive(160, (ushort)2);
}
if (unlockLinkId.Value == 568)
{
return !IsFestivalActive(160, (ushort)3);
}
return true;
}
public unsafe bool IsQuestUnobtainable(QuestId questId, ElementId? extraCompletedQuest = null)
{
IQuestInfo questInfo = _questData.GetQuestInfo(questId);
@ -1024,10 +1054,6 @@ internal sealed class QuestFunctions
}
if (DateTime.UtcNow > dateTime)
{
if (_alreadyLoggedUnobtainableQuestsDetailed.Add(questId.Value))
{
_logger.LogDebug("UnlockLink quest {QuestId} unobtainable: expiry {ExpiryUtc} (UTC) is before now {NowUtc}", questId, dateTime.ToString("o"), DateTime.UtcNow.ToString("o"));
}
return true;
}
}
@ -1043,7 +1069,7 @@ internal sealed class QuestFunctions
List<QuestSequence> list = quest?.Root?.QuestSequence;
if (list != null && list.Count > 0)
{
goto IL_027a;
goto IL_0228;
}
}
if (_alreadyLoggedUnobtainableQuestsDetailed.Add(questId.Value))
@ -1053,8 +1079,8 @@ internal sealed class QuestFunctions
}
return true;
}
goto IL_027a;
IL_027a:
goto IL_0228;
IL_0228:
if (questInfo2.QuestLocks.Count > 0)
{
int num = questInfo2.QuestLocks.Count((QuestId x) => IsQuestComplete(x) || x.Equals(extraCompletedQuest));
@ -1073,41 +1099,15 @@ internal sealed class QuestFunctions
DateTime valueOrDefault = seasonalQuestExpiry.GetValueOrDefault();
TimeSpan timeOfDay2 = valueOrDefault.TimeOfDay;
TimeSpan timeSpan2 = new TimeSpan(23, 59, 59);
bool flag2 = false;
DateTime dateTime2;
if (timeOfDay2 == TimeSpan.Zero || timeOfDay2 == timeSpan2)
{
dateTime2 = EventInfoComponent.AtDailyReset(DateOnly.FromDateTime(valueOrDefault));
flag2 = true;
}
else
{
dateTime2 = ((valueOrDefault.Kind == DateTimeKind.Utc) ? valueOrDefault : valueOrDefault.ToUniversalTime());
}
if (_alreadyLoggedUnobtainableQuestsDetailed.Add(questId.Value))
{
_logger.LogDebug("Quest {QuestId} seasonal expiry raw={ExpiryRaw} Kind={Kind} TimeOfDay={TimeOfDay} treatedAsDailyReset={TreatedAsDailyReset}", questId, valueOrDefault.ToString("o"), valueOrDefault.Kind, valueOrDefault.TimeOfDay, flag2);
_logger.LogDebug("Quest {QuestId} expiry check: nowUtc={Now:o}, expiryUtc={Expiry:o}, expired={Expired}", questId, DateTime.UtcNow, dateTime2, DateTime.UtcNow > dateTime2);
}
DateTime dateTime2 = ((!(timeOfDay2 == TimeSpan.Zero) && !(timeOfDay2 == timeSpan2)) ? ((valueOrDefault.Kind == DateTimeKind.Utc) ? valueOrDefault : valueOrDefault.ToUniversalTime()) : EventInfoComponent.AtDailyReset(DateOnly.FromDateTime(valueOrDefault)));
if (DateTime.UtcNow > dateTime2)
{
if (_alreadyLoggedUnobtainableQuestsDetailed.Add(questId.Value))
{
_logger.LogDebug("Quest {QuestId} unobtainable: seasonal expiry {ExpiryUtc} (UTC) is before now {NowUtc}", questId, dateTime2.ToString("o"), DateTime.UtcNow.ToString("o"));
}
return true;
}
}
if ((questInfo2.IsSeasonalEvent || questInfo2.IsSeasonalQuest) && !(questInfo2.SeasonalQuestExpiry is DateTime))
if ((questInfo2.IsSeasonalEvent || questInfo2.IsSeasonalQuest) && !questInfo2.SeasonalQuestExpiry.HasValue && !_configuration.General.ShowIncompleteSeasonalEvents)
{
if (_alreadyLoggedUnobtainableQuestsDetailed.Add(questId.Value))
{
_logger.LogDebug("Quest {QuestId} is seasonal/event with no expiry; ShowIncompleteSeasonalEvents={ShowIncomplete}", questId, _configuration.General.ShowIncompleteSeasonalEvents);
}
if (!_configuration.General.ShowIncompleteSeasonalEvents)
{
return true;
}
return true;
}
if (_questData.GetLockedClassQuests().Contains(questId))
{
@ -1172,19 +1172,6 @@ internal sealed class QuestFunctions
return false;
}
private static bool IsQuestUnobtainable(UnlockLinkId unlockLinkId)
{
if (unlockLinkId.Value == 506)
{
return !IsFestivalActive(160, (ushort)2);
}
if (unlockLinkId.Value == 568)
{
return !IsFestivalActive(160, (ushort)3);
}
return true;
}
private unsafe static bool IsFestivalActive(ushort id, ushort? phase = null)
{
for (int i = 0; i < GameMain.Instance()->ActiveFestivals.Length; i++)
@ -1310,4 +1297,43 @@ internal sealed class QuestFunctions
{
return IsQuestComplete(_questData.LastMainScenarioQuestId);
}
public (bool isLevelLocked, int levelsNeeded, int requiredLevel, string? questName) GetMsqLevelLockInfo()
{
byte b = _objectTable.LocalPlayer?.Level ?? 0;
if (b == 0)
{
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: 0, questName: null);
}
QuestReference item = GetMainScenarioQuest().Item1;
if (item.CurrentQuest == null)
{
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: 0, questName: null);
}
if (IsQuestAccepted(item.CurrentQuest))
{
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: 0, questName: null);
}
if (_questRegistry.TryGetQuest(item.CurrentQuest, out Questionable.Model.Quest quest))
{
int level = quest.Info.Level;
if (level <= b)
{
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: level, questName: null);
}
int item2 = level - b;
return (isLevelLocked: true, levelsNeeded: item2, requiredLevel: level, questName: quest.Info.Name);
}
if (item.CurrentQuest is QuestId elementId && _questData.TryGetQuestInfo(elementId, out IQuestInfo questInfo) && questInfo is QuestInfo questInfo2)
{
int level2 = questInfo2.Level;
if (level2 <= b)
{
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: level2, questName: null);
}
int item3 = level2 - b;
return (isLevelLocked: true, levelsNeeded: item3, requiredLevel: level2, questName: questInfo2.Name);
}
return (isLevelLocked: false, levelsNeeded: 0, requiredLevel: 0, questName: null);
}
}