qstbak/Questionable/Questionable.Model/QuestInfo.cs
2025-10-09 07:53:51 +10:00

225 lines
6.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using LLib.GameData;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Questionable.Model.Questing;
namespace Questionable.Model;
internal sealed class QuestInfo : IQuestInfo
{
public ElementId QuestId { get; }
public string Name { get; }
public ushort Level { get; }
public uint IssuerDataId { get; }
public bool IsRepeatable { get; }
public ImmutableList<PreviousQuestInfo> PreviousQuests { get; private set; }
public EQuestJoin PreviousQuestJoin { get; }
public ImmutableList<QuestId> QuestLocks { get; private set; }
public EQuestJoin QuestLockJoin { get; private set; }
public List<ushort> PreviousInstanceContent { get; }
public EQuestJoin PreviousInstanceContentJoin { get; }
public uint? JournalGenre { get; set; }
public ushort SortKey { get; set; }
public bool IsMainScenarioQuest { get; }
public bool CompletesInstantly { get; }
public FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany GrandCompany { get; }
public EAlliedSociety AlliedSociety { get; }
public byte AlliedSocietyQuestGroup { get; }
public int AlliedSocietyRank { get; }
public IReadOnlyList<EClassJob> ClassJobs { get; }
public bool IsSeasonalEvent { get; }
public uint NewGamePlusChapter { get; }
public byte StartingCity { get; set; }
public byte MoogleDeliveryLevel { get; }
public bool IsMoogleDeliveryQuest => JournalGenre == 87;
public IReadOnlyList<ItemReward> ItemRewards { get; }
public EExpansionVersion Expansion { get; }
public DateTime? SeasonalQuestExpiry { 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)
{
QuestId = Questionable.Model.Questing.QuestId.FromRowId(quest.RowId);
string value = QuestId.Value switch
{
85 => " (Lancer)",
108 => " (Marauder)",
109 => " (Arcanist)",
123 => " (Archer)",
124 => " (Conjurer)",
568 => " (Gladiator)",
569 => " (Pugilist)",
570 => " (Thaumaturge)",
673 => " (Ul'dah)",
674 => " (Limsa/Gridania)",
1432 => " (Gridania)",
1433 => " (Limsa)",
1434 => " (Ul'dah)",
_ => "",
};
Name = $"{quest.Name}{value}";
Level = quest.ClassJobLevel[0];
IssuerDataId = quest.IssuerStart.RowId;
IsRepeatable = quest.IsRepeatable;
PreviousQuests = new List<PreviousQuestInfo>
{
new PreviousQuestInfo(ReplaceOldQuestIds(Questionable.Model.Questing.QuestId.FromRowId(quest.PreviousQuest[0].RowId)), quest.Unknown7),
new PreviousQuestInfo(ReplaceOldQuestIds(Questionable.Model.Questing.QuestId.FromRowId(quest.PreviousQuest[1].RowId)), 0),
new PreviousQuestInfo(ReplaceOldQuestIds(Questionable.Model.Questing.QuestId.FromRowId(quest.PreviousQuest[2].RowId)), 0)
}.Where((PreviousQuestInfo x) => x.QuestId.Value != 0).ToImmutableList();
PreviousQuestJoin = (EQuestJoin)quest.PreviousQuestJoin;
QuestLocks = (from x in quest.QuestLock
select Questionable.Model.Questing.QuestId.FromRowId(x.RowId) into x
where x.Value != 0
select x).ToImmutableList();
QuestLockJoin = (EQuestJoin)quest.QuestLockJoin;
(uint?, ushort?) tuple;
switch (QuestId.Value)
{
case 1119:
case 1120:
case 1121:
case 1122:
case 1123:
case 1124:
case 1125:
case 1126:
case 1127:
case 1579:
tuple = (journalGenreOverrides.ARelicRebornQuests, (ushort)0);
break;
case 4196:
case 4197:
case 4198:
case 4199:
case 4200:
case 4201:
case 4202:
case 4203:
case 4204:
case 4205:
case 4206:
case 4207:
case 4208:
case 4209:
tuple = (journalGenreOverrides.ThavnairSideQuests, null);
break;
case 4173:
tuple = (journalGenreOverrides.RadzAtHanSideQuests, null);
break;
default:
tuple = (quest.JournalGenre.ValueNullable?.RowId, null);
break;
}
(uint?, ushort?) tuple2 = tuple;
JournalGenre = tuple2.Item1;
SortKey = tuple2.Item2 ?? quest.SortKey;
JournalGenre? valueNullable = quest.JournalGenre.ValueNullable;
IsMainScenarioQuest = valueNullable.HasValue && valueNullable.GetValueOrDefault().Icon == 61412;
CompletesInstantly = quest.TodoParams[0].ToDoCompleteSeq == 0;
PreviousInstanceContent = (from x in quest.InstanceContent
select (ushort)x.RowId into x
where x != 0
select x).ToList();
PreviousInstanceContentJoin = (EQuestJoin)quest.InstanceContentJoin;
GrandCompany = (FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany)quest.GrandCompany.RowId;
AlliedSociety = (EAlliedSociety)quest.BeastTribe.RowId;
AlliedSocietyQuestGroup = quest.DailyQuestPool;
AlliedSocietyRank = (int)quest.BeastReputationRank.RowId;
ClassJobs = QuestInfoUtils.AsList(quest.ClassJobCategory0.ValueNullable);
IsSeasonalEvent = quest.Festival.RowId != 0;
IsSeasonalQuest = isSeasonalEventQuest;
SeasonalQuestExpiry = (IsSeasonalQuest ? seasonalQuestExpiry : ((DateTime?)null));
SeasonalQuestExpiry = seasonalQuestExpiry;
NewGamePlusChapter = newGamePlusChapter;
StartingCity = startingCity;
MoogleDeliveryLevel = (byte)quest.DeliveryQuest.RowId;
ItemRewards = (from Item x in from x in quest.Reward
where x.RowId != 0 && x.Is<Item>()
select x.GetValueOrDefault<Item>() into x
where x.HasValue
select x
where x.IsUntradable
select ItemReward.CreateFromItem(x, QuestId) into x
where x != null
select x).Cast<ItemReward>().ToList();
Expansion = (EExpansionVersion)quest.Expansion.RowId;
}
private static QuestId ReplaceOldQuestIds(QuestId questId)
{
if (questId.Value == 524)
{
return new QuestId(4522);
}
return questId;
}
public void AddPreviousQuest(PreviousQuestInfo questId)
{
ImmutableList<PreviousQuestInfo> previousQuests = PreviousQuests;
int num = 0;
PreviousQuestInfo[] array = new PreviousQuestInfo[1 + previousQuests.Count];
foreach (PreviousQuestInfo item in previousQuests)
{
array[num] = item;
num++;
}
array[num] = questId;
PreviousQuests = ImmutableList.Create(new ReadOnlySpan<PreviousQuestInfo>(array));
}
public void AddQuestLocks(EQuestJoin questJoin, params QuestId[] questId)
{
if (QuestLocks.Count > 0 && QuestLockJoin != questJoin)
{
throw new InvalidOperationException();
}
QuestLockJoin = questJoin;
ImmutableList<QuestId> questLocks = QuestLocks;
int num = 0;
QuestId[] array = new QuestId[questLocks.Count + questId.Length];
foreach (QuestId item in questLocks)
{
array[num] = item;
num++;
}
ReadOnlySpan<QuestId> readOnlySpan = new ReadOnlySpan<QuestId>(questId);
readOnlySpan.CopyTo(new Span<QuestId>(array).Slice(num, readOnlySpan.Length));
num += readOnlySpan.Length;
QuestLocks = ImmutableList.Create(new ReadOnlySpan<QuestId>(array));
}
}