Handle quests that are unlocked when a previous quest isn't complete yet

This commit is contained in:
Liza 2024-08-25 14:45:08 +02:00
parent abee323d2b
commit d310c9ff1b
Signed by: liza
GPG Key ID: 7199F8D727D55F67
6 changed files with 57 additions and 25 deletions

View File

@ -8,7 +8,8 @@ using LLib.GameData;
using Lumina.Excel.GeneratedSheets;
using Questionable.Model;
using Questionable.Model.Questing;
using Quest = Lumina.Excel.GeneratedSheets.Quest;
using Leve = Lumina.Excel.GeneratedSheets2.Leve;
using Quest = Lumina.Excel.GeneratedSheets2.Quest;
namespace Questionable.Data;
@ -62,7 +63,7 @@ internal sealed class QuestData
// workaround because the game doesn't require completion of the CT questline through normal means
QuestInfo aTimeToEveryPurpose = (QuestInfo)_quests[new QuestId(425)];
aTimeToEveryPurpose.AddPreviousQuest(new QuestId(495));
aTimeToEveryPurpose.AddPreviousQuest(new QuestInfo.PreviousQuestInfo(new QuestId(495)));
}
public IQuestInfo GetQuestInfo(ElementId elementId)

View File

@ -494,7 +494,8 @@ internal sealed unsafe class QuestFunctions
if (questInfo.PreviousQuests.Count == 0)
return true;
var completedQuests = questInfo.PreviousQuests.Count(x => IsQuestComplete(x) || x.Equals(extraCompletedQuest));
var completedQuests = questInfo.PreviousQuests.Count(x =>
HasEnoughProgressOnPreviousQuest(x) || x.QuestId.Equals(extraCompletedQuest));
if (questInfo.PreviousQuestJoin == QuestInfo.QuestJoin.All &&
questInfo.PreviousQuests.Count == completedQuests)
return true;
@ -504,6 +505,20 @@ internal sealed unsafe class QuestFunctions
return false;
}
private bool HasEnoughProgressOnPreviousQuest(QuestInfo.PreviousQuestInfo previousQuestInfo)
{
if (IsQuestComplete(previousQuestInfo.QuestId))
return true;
if (previousQuestInfo.Sequence != 0 && IsQuestAccepted(previousQuestInfo.QuestId))
{
var progress = GetQuestProgressInfo(previousQuestInfo.QuestId);
return progress != null && progress.Sequence >= previousQuestInfo.Sequence;
}
return false;
}
private static bool HasCompletedPreviousInstances(QuestInfo questInfo)
{
if (questInfo.PreviousInstanceContent.Count == 0)

View File

@ -1,6 +1,6 @@
using System.Collections.Generic;
using LLib.GameData;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.GeneratedSheets2;
using Questionable.Model.Questing;
namespace Questionable.Model;
@ -14,7 +14,7 @@ internal sealed class LeveInfo : IQuestInfo
Level = leve.ClassJobLevel;
JournalGenre = leve.JournalGenre.Row;
SortKey = QuestId.Value;
IssuerDataId = leve.LevelLevemete.Value!.Object;
IssuerDataId = leve.LevelLevemete.Value!.Object.Row;
ClassJobs = QuestInfoUtils.AsList(leve.ClassJobCategory.Value!);
Expansion = (EExpansionVersion)leve.LevelLevemete.Value.Territory.Value!.ExVersion.Row;
}

View File

@ -5,7 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using JetBrains.Annotations;
using LLib.GameData;
using Questionable.Model.Questing;
using ExcelQuest = Lumina.Excel.GeneratedSheets.Quest;
using ExcelQuest = Lumina.Excel.GeneratedSheets2.Quest;
namespace Questionable.Model;
@ -31,13 +31,18 @@ internal sealed class QuestInfo : IQuestInfo
};
Name = $"{quest.Name}{suffix}";
Level = quest.ClassJobLevel0;
IssuerDataId = quest.IssuerStart;
Level = quest.ClassJobLevel[0];
IssuerDataId = quest.IssuerStart.Row;
IsRepeatable = quest.IsRepeatable;
PreviousQuests = quest.PreviousQuest
.Select(x => new QuestId((ushort)(x.Row & 0xFFFF)))
.Where(x => x.Value != 0)
.ToImmutableList();
PreviousQuests =
new List<PreviousQuestInfo>
{
new(new QuestId((ushort)(quest.PreviousQuest[0].Row & 0xFFFF)), quest.Unknown7),
new(new QuestId((ushort)(quest.PreviousQuest[1].Row & 0xFFFF))),
new(new QuestId((ushort)(quest.PreviousQuest[1].Row & 0xFFFF)))
}
.Where(x => x.QuestId.Value != 0)
.ToImmutableList();
PreviousQuestJoin = (QuestJoin)quest.PreviousQuestJoin;
QuestLocks = quest.QuestLock
.Select(x => new QuestId((ushort)(x.Row & 0xFFFFF)))
@ -47,7 +52,7 @@ internal sealed class QuestInfo : IQuestInfo
JournalGenre = quest.JournalGenre?.Row;
SortKey = quest.SortKey;
IsMainScenarioQuest = quest.JournalGenre?.Value?.JournalCategory?.Value?.JournalSection?.Row is 0 or 1;
CompletesInstantly = quest.ToDoCompleteSeq[0] == 0;
CompletesInstantly = quest.TodoParams[0].ToDoCompleteSeq == 0;
PreviousInstanceContent = quest.InstanceContent.Select(x => (ushort)x.Row).Where(x => x != 0).ToList();
PreviousInstanceContentJoin = (QuestJoin)quest.InstanceContentJoin;
GrandCompany = (GrandCompany)quest.GrandCompany.Row;
@ -64,7 +69,7 @@ internal sealed class QuestInfo : IQuestInfo
public ushort Level { get; }
public uint IssuerDataId { get; }
public bool IsRepeatable { get; }
public ImmutableList<QuestId> PreviousQuests { get; set; }
public ImmutableList<PreviousQuestInfo> PreviousQuests { get; set; }
public QuestJoin PreviousQuestJoin { get; }
public ImmutableList<QuestId> QuestLocks { get; }
public QuestJoin QuestLockJoin { get; }
@ -89,8 +94,10 @@ internal sealed class QuestInfo : IQuestInfo
AtLeastOne = 2,
}
public void AddPreviousQuest(QuestId questId)
public void AddPreviousQuest(PreviousQuestInfo questId)
{
PreviousQuests = [..PreviousQuests, questId];
}
public sealed record PreviousQuestInfo(QuestId QuestId, byte Sequence = 0);
}

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using LLib.GameData;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.GeneratedSheets2;
namespace Questionable.Model;
@ -57,8 +57,8 @@ internal static class QuestInfoUtils
{ EClassJob.Dancer, classJobCategory.DNC },
{ EClassJob.Reaper, classJobCategory.RPR },
{ EClassJob.Sage, classJobCategory.SGE },
{ EClassJob.Viper, classJobCategory.VPR },
{ EClassJob.Pictomancer, classJobCategory.PCT }
{ EClassJob.Viper, classJobCategory.Unknown1 },
{ EClassJob.Pictomancer, classJobCategory.Unknown2 }
}
.Where(y => y.Value)
.Select(y => y.Key)

View File

@ -19,19 +19,22 @@ internal sealed class QuestTooltipComponent
private readonly TerritoryData _territoryData;
private readonly QuestFunctions _questFunctions;
private readonly UiUtils _uiUtils;
private readonly Configuration _configuration;
public QuestTooltipComponent(
QuestRegistry questRegistry,
QuestData questData,
TerritoryData territoryData,
QuestFunctions questFunctions,
UiUtils uiUtils)
UiUtils uiUtils,
Configuration configuration)
{
_questRegistry = questRegistry;
_questData = questData;
_territoryData = territoryData;
_questFunctions = questFunctions;
_uiUtils = uiUtils;
_configuration = configuration;
}
public void Draw(IQuestInfo quest)
@ -105,13 +108,13 @@ internal sealed class QuestTooltipComponent
foreach (var q in quest.PreviousQuests)
{
if (_questData.TryGetQuestInfo(q, out var qInfo))
if (_questData.TryGetQuestInfo(q.QuestId, out var qInfo))
{
var (iconColor, icon, _) = _uiUtils.GetQuestStyle(q);
var (iconColor, icon, _) = _uiUtils.GetQuestStyle(q.QuestId);
if (!_questRegistry.IsKnownQuest(qInfo.QuestId))
iconColor = ImGuiColors.DalamudGrey;
_uiUtils.ChecklistItem(FormatQuestUnlockName(qInfo), iconColor, icon);
_uiUtils.ChecklistItem(FormatQuestUnlockName(qInfo, _questFunctions.IsQuestComplete(q.QuestId) ? byte.MinValue : q.Sequence), iconColor, icon);
if (qInfo is QuestInfo qstInfo && (counter <= 2 || icon != FontAwesomeIcon.Check))
DrawQuestUnlocks(qstInfo, counter + 1);
@ -188,11 +191,17 @@ internal sealed class QuestTooltipComponent
ImGui.Unindent();
}
private static string FormatQuestUnlockName(IQuestInfo questInfo)
private string FormatQuestUnlockName(IQuestInfo questInfo, byte sequence = 0)
{
string name = questInfo.Name;
if (_configuration.Advanced.AdditionalStatusInformation && sequence != 0)
name += $" {SeIconChar.ItemLevel.ToIconString()}";
if (questInfo.IsMainScenarioQuest)
return $"{questInfo.Name} ({questInfo.QuestId}, MSQ)";
name += $" ({questInfo.QuestId}, MSQ)";
else
return $"{questInfo.Name} ({questInfo.QuestId})";
name += $" {questInfo.Name} ({questInfo.QuestId})";
return name;
}
}