225 lines
6.8 KiB
C#
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));
|
|
}
|
|
}
|