punish v6.8.18.0
This commit is contained in:
commit
cfb4dea47e
316 changed files with 554088 additions and 0 deletions
91
Questionable/Questionable.Model/AlliedSocietyDailyInfo.cs
Normal file
91
Questionable/Questionable.Model/AlliedSocietyDailyInfo.cs
Normal file
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using LLib.GameData;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class AlliedSocietyDailyInfo : IQuestInfo
|
||||
{
|
||||
public ElementId QuestId { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public uint IssuerDataId => 0u;
|
||||
|
||||
public ImmutableList<PreviousQuestInfo> PreviousQuests { get; } = ImmutableList.Create(default(ReadOnlySpan<PreviousQuestInfo>));
|
||||
|
||||
public EQuestJoin PreviousQuestJoin => EQuestJoin.All;
|
||||
|
||||
public bool IsRepeatable => true;
|
||||
|
||||
public ushort Level => 1;
|
||||
|
||||
public EAlliedSociety AlliedSociety => EAlliedSociety.None;
|
||||
|
||||
public uint? JournalGenre => null;
|
||||
|
||||
public ushort SortKey => 0;
|
||||
|
||||
public bool IsMainScenarioQuest => false;
|
||||
|
||||
public IReadOnlyList<EClassJob> ClassJobs { get; }
|
||||
|
||||
public EExpansionVersion Expansion { get; }
|
||||
|
||||
public AlliedSocietyDailyInfo(BeastTribe beastTribe, byte rank, ClassJobUtils classJobUtils)
|
||||
{
|
||||
QuestId = new AlliedSocietyDailyId((byte)beastTribe.RowId, rank);
|
||||
Name = beastTribe.Name.ToString();
|
||||
List<EClassJob> list2;
|
||||
switch ((EAlliedSociety)(byte)beastTribe.RowId)
|
||||
{
|
||||
case EAlliedSociety.Amaljaa:
|
||||
case EAlliedSociety.Sylphs:
|
||||
case EAlliedSociety.Kobolds:
|
||||
case EAlliedSociety.Sahagin:
|
||||
case EAlliedSociety.VanuVanu:
|
||||
case EAlliedSociety.Vath:
|
||||
case EAlliedSociety.Kojin:
|
||||
case EAlliedSociety.Ananta:
|
||||
case EAlliedSociety.Pixies:
|
||||
case EAlliedSociety.Arkasodara:
|
||||
case EAlliedSociety.Pelupelu:
|
||||
{
|
||||
List<EClassJob> list3 = new List<EClassJob>();
|
||||
list3.AddRange(classJobUtils.AsIndividualJobs(EExtendedClassJob.DoW, null));
|
||||
list3.AddRange(classJobUtils.AsIndividualJobs(EExtendedClassJob.DoM, null));
|
||||
list2 = list3;
|
||||
break;
|
||||
}
|
||||
case EAlliedSociety.Ixal:
|
||||
case EAlliedSociety.Moogles:
|
||||
case EAlliedSociety.Dwarves:
|
||||
case EAlliedSociety.Loporrits:
|
||||
case EAlliedSociety.YokHuy:
|
||||
list2 = classJobUtils.AsIndividualJobs(EExtendedClassJob.DoH, null).ToList();
|
||||
break;
|
||||
case EAlliedSociety.Qitari:
|
||||
case EAlliedSociety.Omicrons:
|
||||
case EAlliedSociety.MamoolJa:
|
||||
list2 = classJobUtils.AsIndividualJobs(EExtendedClassJob.DoL, null).ToList();
|
||||
break;
|
||||
case EAlliedSociety.Namazu:
|
||||
{
|
||||
List<EClassJob> list = new List<EClassJob>();
|
||||
list.AddRange(classJobUtils.AsIndividualJobs(EExtendedClassJob.DoH, null));
|
||||
list.AddRange(classJobUtils.AsIndividualJobs(EExtendedClassJob.DoL, null));
|
||||
list2 = list;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("beastTribe");
|
||||
}
|
||||
ClassJobs = list2;
|
||||
Expansion = (EExpansionVersion)beastTribe.Expansion.RowId;
|
||||
}
|
||||
}
|
26
Questionable/Questionable.Model/EAlliedSociety.cs
Normal file
26
Questionable/Questionable.Model/EAlliedSociety.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
namespace Questionable.Model;
|
||||
|
||||
public enum EAlliedSociety : byte
|
||||
{
|
||||
None,
|
||||
Amaljaa,
|
||||
Sylphs,
|
||||
Kobolds,
|
||||
Sahagin,
|
||||
Ixal,
|
||||
VanuVanu,
|
||||
Vath,
|
||||
Moogles,
|
||||
Kojin,
|
||||
Ananta,
|
||||
Namazu,
|
||||
Pixies,
|
||||
Qitari,
|
||||
Dwarves,
|
||||
Arkasodara,
|
||||
Omicrons,
|
||||
Loporrits,
|
||||
Pelupelu,
|
||||
MamoolJa,
|
||||
YokHuy
|
||||
}
|
10
Questionable/Questionable.Model/EItemRewardType.cs
Normal file
10
Questionable/Questionable.Model/EItemRewardType.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Questionable.Model;
|
||||
|
||||
public enum EItemRewardType
|
||||
{
|
||||
Mount,
|
||||
Minion,
|
||||
OrchestrionRoll,
|
||||
TripleTriadCard,
|
||||
FashionAccessory
|
||||
}
|
11
Questionable/Questionable.Model/EMovementType.cs
Normal file
11
Questionable/Questionable.Model/EMovementType.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Questionable.Model;
|
||||
|
||||
public enum EMovementType
|
||||
{
|
||||
None,
|
||||
Quest,
|
||||
DebugWindow,
|
||||
Shortcut,
|
||||
Landing,
|
||||
Combat
|
||||
}
|
8
Questionable/Questionable.Model/EQuestJoin.cs
Normal file
8
Questionable/Questionable.Model/EQuestJoin.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Questionable.Model;
|
||||
|
||||
internal enum EQuestJoin : byte
|
||||
{
|
||||
None,
|
||||
All,
|
||||
AtLeastOne
|
||||
}
|
29
Questionable/Questionable.Model/FashionAccessoryReward.cs
Normal file
29
Questionable/Questionable.Model/FashionAccessoryReward.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed record FashionAccessoryReward : ItemReward
|
||||
{
|
||||
public uint AccessoryId { get; init; }
|
||||
|
||||
public override EItemRewardType Type => EItemRewardType.FashionAccessory;
|
||||
|
||||
public FashionAccessoryReward(ItemRewardDetails Item, uint AccessoryId)
|
||||
{
|
||||
this.AccessoryId = AccessoryId;
|
||||
base._002Ector(Item);
|
||||
}
|
||||
|
||||
public unsafe override bool IsUnlocked()
|
||||
{
|
||||
return PlayerState.Instance()->IsOrnamentUnlocked(AccessoryId);
|
||||
}
|
||||
|
||||
[CompilerGenerated]
|
||||
public void Deconstruct(out ItemRewardDetails Item, out uint AccessoryId)
|
||||
{
|
||||
Item = base.Item;
|
||||
AccessoryId = this.AccessoryId;
|
||||
}
|
||||
}
|
47
Questionable/Questionable.Model/IQuestInfo.cs
Normal file
47
Questionable/Questionable.Model/IQuestInfo.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Dalamud.Game.Text;
|
||||
using LLib.GameData;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal interface IQuestInfo
|
||||
{
|
||||
ElementId QuestId { get; }
|
||||
|
||||
string Name { get; }
|
||||
|
||||
uint IssuerDataId { get; }
|
||||
|
||||
bool IsRepeatable { get; }
|
||||
|
||||
ImmutableList<PreviousQuestInfo> PreviousQuests { get; }
|
||||
|
||||
EQuestJoin PreviousQuestJoin { get; }
|
||||
|
||||
ushort Level { get; }
|
||||
|
||||
EAlliedSociety AlliedSociety { get; }
|
||||
|
||||
uint? JournalGenre { get; }
|
||||
|
||||
ushort SortKey { get; }
|
||||
|
||||
bool IsMainScenarioQuest { get; }
|
||||
|
||||
IReadOnlyList<EClassJob> ClassJobs { get; }
|
||||
|
||||
EExpansionVersion Expansion { get; }
|
||||
|
||||
string SimplifiedName => Name.Replace(".", "", StringComparison.Ordinal).Replace("*", "", StringComparison.Ordinal).Replace("\"", "", StringComparison.Ordinal)
|
||||
.Replace("/", "", StringComparison.Ordinal)
|
||||
.Replace("\\", "", StringComparison.Ordinal)
|
||||
.Replace("<", "", StringComparison.Ordinal)
|
||||
.Replace(">", "", StringComparison.Ordinal)
|
||||
.Replace("|", "", StringComparison.Ordinal)
|
||||
.Replace(":", "", StringComparison.Ordinal)
|
||||
.Replace("?", "", StringComparison.Ordinal)
|
||||
.TrimStart(SeIconChar.QuestSync.ToIconChar(), SeIconChar.QuestRepeatable.ToIconChar(), ' ');
|
||||
}
|
52
Questionable/Questionable.Model/ItemReward.cs
Normal file
52
Questionable/Questionable.Model/ItemReward.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public abstract record ItemReward(ItemRewardDetails Item)
|
||||
{
|
||||
public uint ItemId => Item.ItemId;
|
||||
|
||||
public string Name => Item.Name;
|
||||
|
||||
public ElementId ElementId => Item.ElementId;
|
||||
|
||||
public TimeSpan CastTime => Item.CastTime;
|
||||
|
||||
public abstract EItemRewardType Type { get; }
|
||||
|
||||
internal static ItemReward? CreateFromItem(Item item, ElementId elementId)
|
||||
{
|
||||
ushort? num = item.ItemAction.ValueNullable?.Type;
|
||||
if (num.HasValue && num == 1322)
|
||||
{
|
||||
return new MountReward(new ItemRewardDetails(item, elementId), item.ItemAction.Value.Data[0]);
|
||||
}
|
||||
num = item.ItemAction.ValueNullable?.Type;
|
||||
if (num.HasValue && num == 853)
|
||||
{
|
||||
return new MinionReward(new ItemRewardDetails(item, elementId), item.ItemAction.Value.Data[0]);
|
||||
}
|
||||
Orchestrion? valueOrDefault = item.AdditionalData.GetValueOrDefault<Orchestrion>();
|
||||
if (valueOrDefault.HasValue)
|
||||
{
|
||||
Orchestrion valueOrDefault2 = valueOrDefault.GetValueOrDefault();
|
||||
return new OrchestrionRollReward(new ItemRewardDetails(item, elementId), valueOrDefault2.RowId);
|
||||
}
|
||||
TripleTriadCard? valueOrDefault3 = item.AdditionalData.GetValueOrDefault<TripleTriadCard>();
|
||||
if (valueOrDefault3.HasValue)
|
||||
{
|
||||
TripleTriadCard valueOrDefault4 = valueOrDefault3.GetValueOrDefault();
|
||||
return new TripleTriadCardReward(new ItemRewardDetails(item, elementId), (ushort)valueOrDefault4.RowId);
|
||||
}
|
||||
num = item.ItemAction.ValueNullable?.Type;
|
||||
if (num.HasValue && num == 20086)
|
||||
{
|
||||
return new FashionAccessoryReward(new ItemRewardDetails(item, elementId), item.ItemAction.Value.Data[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract bool IsUnlocked();
|
||||
}
|
23
Questionable/Questionable.Model/ItemRewardDetails.cs
Normal file
23
Questionable/Questionable.Model/ItemRewardDetails.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using Dalamud.Utility;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed class ItemRewardDetails
|
||||
{
|
||||
public uint ItemId { get; } = item.RowId;
|
||||
|
||||
public string Name { get; } = item.Name.ToDalamudString().ToString();
|
||||
|
||||
public TimeSpan CastTime { get; } = TimeSpan.FromSeconds(item.CastTimeSeconds);
|
||||
|
||||
public ElementId ElementId { get; }
|
||||
|
||||
public ItemRewardDetails(Item item, ElementId elementId)
|
||||
{
|
||||
ElementId = elementId;
|
||||
base._002Ector();
|
||||
}
|
||||
}
|
10
Questionable/Questionable.Model/JournalGenreOverrides.cs
Normal file
10
Questionable/Questionable.Model/JournalGenreOverrides.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class JournalGenreOverrides
|
||||
{
|
||||
public required uint ARelicRebornQuests { get; init; }
|
||||
|
||||
public required uint ThavnairSideQuests { get; init; }
|
||||
|
||||
public required uint RadzAtHanSideQuests { get; init; }
|
||||
}
|
29
Questionable/Questionable.Model/MinionReward.cs
Normal file
29
Questionable/Questionable.Model/MinionReward.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed record MinionReward : ItemReward
|
||||
{
|
||||
public uint MinionId { get; init; }
|
||||
|
||||
public override EItemRewardType Type => EItemRewardType.Minion;
|
||||
|
||||
public MinionReward(ItemRewardDetails Item, uint MinionId)
|
||||
{
|
||||
this.MinionId = MinionId;
|
||||
base._002Ector(Item);
|
||||
}
|
||||
|
||||
public unsafe override bool IsUnlocked()
|
||||
{
|
||||
return UIState.Instance()->IsCompanionUnlocked(MinionId);
|
||||
}
|
||||
|
||||
[CompilerGenerated]
|
||||
public void Deconstruct(out ItemRewardDetails Item, out uint MinionId)
|
||||
{
|
||||
Item = base.Item;
|
||||
MinionId = this.MinionId;
|
||||
}
|
||||
}
|
29
Questionable/Questionable.Model/MountReward.cs
Normal file
29
Questionable/Questionable.Model/MountReward.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed record MountReward : ItemReward
|
||||
{
|
||||
public uint MountId { get; init; }
|
||||
|
||||
public override EItemRewardType Type => EItemRewardType.Mount;
|
||||
|
||||
public MountReward(ItemRewardDetails Item, uint MountId)
|
||||
{
|
||||
this.MountId = MountId;
|
||||
base._002Ector(Item);
|
||||
}
|
||||
|
||||
public unsafe override bool IsUnlocked()
|
||||
{
|
||||
return PlayerState.Instance()->IsMountUnlocked(MountId);
|
||||
}
|
||||
|
||||
[CompilerGenerated]
|
||||
public void Deconstruct(out ItemRewardDetails Item, out uint MountId)
|
||||
{
|
||||
Item = base.Item;
|
||||
MountId = this.MountId;
|
||||
}
|
||||
}
|
29
Questionable/Questionable.Model/OrchestrionRollReward.cs
Normal file
29
Questionable/Questionable.Model/OrchestrionRollReward.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed record OrchestrionRollReward : ItemReward
|
||||
{
|
||||
public uint OrchestrionRollId { get; init; }
|
||||
|
||||
public override EItemRewardType Type => EItemRewardType.OrchestrionRoll;
|
||||
|
||||
public OrchestrionRollReward(ItemRewardDetails Item, uint OrchestrionRollId)
|
||||
{
|
||||
this.OrchestrionRollId = OrchestrionRollId;
|
||||
base._002Ector(Item);
|
||||
}
|
||||
|
||||
public unsafe override bool IsUnlocked()
|
||||
{
|
||||
return PlayerState.Instance()->IsOrchestrionRollUnlocked(OrchestrionRollId);
|
||||
}
|
||||
|
||||
[CompilerGenerated]
|
||||
public void Deconstruct(out ItemRewardDetails Item, out uint OrchestrionRollId)
|
||||
{
|
||||
Item = base.Item;
|
||||
OrchestrionRollId = this.OrchestrionRollId;
|
||||
}
|
||||
}
|
5
Questionable/Questionable.Model/PreviousQuestInfo.cs
Normal file
5
Questionable/Questionable.Model/PreviousQuestInfo.cs
Normal file
|
@ -0,0 +1,5 @@
|
|||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed record PreviousQuestInfo(QuestId QuestId, byte Sequence = 0);
|
48
Questionable/Questionable.Model/Quest.cs
Normal file
48
Questionable/Questionable.Model/Quest.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class Quest
|
||||
{
|
||||
public enum ESource
|
||||
{
|
||||
Assembly,
|
||||
ProjectDirectory,
|
||||
UserDirectory
|
||||
}
|
||||
|
||||
public required ElementId Id { get; init; }
|
||||
|
||||
public required QuestRoot Root { get; init; }
|
||||
|
||||
public required IQuestInfo Info { get; init; }
|
||||
|
||||
public required ESource Source { get; init; }
|
||||
|
||||
public QuestSequence? FindSequence(byte currentSequence)
|
||||
{
|
||||
return Root.QuestSequence.SingleOrDefault((QuestSequence seq) => seq.Sequence == currentSequence);
|
||||
}
|
||||
|
||||
public IEnumerable<QuestSequence> AllSequences()
|
||||
{
|
||||
return Root.QuestSequence;
|
||||
}
|
||||
|
||||
public IEnumerable<(QuestSequence Sequence, int StepId, QuestStep Step)> AllSteps()
|
||||
{
|
||||
foreach (QuestSequence sequence in Root.QuestSequence)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < sequence.Steps.Count)
|
||||
{
|
||||
QuestStep item = sequence.Steps[i];
|
||||
yield return (Sequence: sequence, StepId: i, Step: item);
|
||||
int num = i + 1;
|
||||
i = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
218
Questionable/Questionable.Model/QuestInfo.cs
Normal file
218
Questionable/Questionable.Model/QuestInfo.cs
Normal file
|
@ -0,0 +1,218 @@
|
|||
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 QuestInfo(Lumina.Excel.Sheets.Quest quest, uint newGamePlusChapter, byte startingCity, JournalGenreOverrides journalGenreOverrides)
|
||||
{
|
||||
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;
|
||||
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));
|
||||
}
|
||||
}
|
204
Questionable/Questionable.Model/QuestInfoUtils.cs
Normal file
204
Questionable/Questionable.Model/QuestInfoUtils.cs
Normal file
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LLib.GameData;
|
||||
using Lumina.Excel.Sheets;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal static class QuestInfoUtils
|
||||
{
|
||||
private static readonly Dictionary<uint, IReadOnlyList<EClassJob>> CachedClassJobs = new Dictionary<uint, IReadOnlyList<EClassJob>>();
|
||||
|
||||
internal static IReadOnlyList<EClassJob> AsList(ClassJobCategory? optionalClassJobCategory)
|
||||
{
|
||||
if (!optionalClassJobCategory.HasValue)
|
||||
{
|
||||
return Enum.GetValues<EClassJob>();
|
||||
}
|
||||
ClassJobCategory value = optionalClassJobCategory.Value;
|
||||
if (CachedClassJobs.TryGetValue(value.RowId, out IReadOnlyList<EClassJob> value2))
|
||||
{
|
||||
return value2;
|
||||
}
|
||||
value2 = (from y in new Dictionary<EClassJob, bool>
|
||||
{
|
||||
{
|
||||
EClassJob.Adventurer,
|
||||
value.ADV
|
||||
},
|
||||
{
|
||||
EClassJob.Gladiator,
|
||||
value.GLA
|
||||
},
|
||||
{
|
||||
EClassJob.Pugilist,
|
||||
value.PGL
|
||||
},
|
||||
{
|
||||
EClassJob.Marauder,
|
||||
value.MRD
|
||||
},
|
||||
{
|
||||
EClassJob.Lancer,
|
||||
value.LNC
|
||||
},
|
||||
{
|
||||
EClassJob.Archer,
|
||||
value.ARC
|
||||
},
|
||||
{
|
||||
EClassJob.Conjurer,
|
||||
value.CNJ
|
||||
},
|
||||
{
|
||||
EClassJob.Thaumaturge,
|
||||
value.THM
|
||||
},
|
||||
{
|
||||
EClassJob.Carpenter,
|
||||
value.CRP
|
||||
},
|
||||
{
|
||||
EClassJob.Blacksmith,
|
||||
value.BSM
|
||||
},
|
||||
{
|
||||
EClassJob.Armorer,
|
||||
value.ARM
|
||||
},
|
||||
{
|
||||
EClassJob.Goldsmith,
|
||||
value.GSM
|
||||
},
|
||||
{
|
||||
EClassJob.Leatherworker,
|
||||
value.LTW
|
||||
},
|
||||
{
|
||||
EClassJob.Weaver,
|
||||
value.WVR
|
||||
},
|
||||
{
|
||||
EClassJob.Alchemist,
|
||||
value.ALC
|
||||
},
|
||||
{
|
||||
EClassJob.Culinarian,
|
||||
value.CUL
|
||||
},
|
||||
{
|
||||
EClassJob.Miner,
|
||||
value.MIN
|
||||
},
|
||||
{
|
||||
EClassJob.Botanist,
|
||||
value.BTN
|
||||
},
|
||||
{
|
||||
EClassJob.Fisher,
|
||||
value.FSH
|
||||
},
|
||||
{
|
||||
EClassJob.Paladin,
|
||||
value.PLD
|
||||
},
|
||||
{
|
||||
EClassJob.Monk,
|
||||
value.MNK
|
||||
},
|
||||
{
|
||||
EClassJob.Warrior,
|
||||
value.WAR
|
||||
},
|
||||
{
|
||||
EClassJob.Dragoon,
|
||||
value.DRG
|
||||
},
|
||||
{
|
||||
EClassJob.Bard,
|
||||
value.BRD
|
||||
},
|
||||
{
|
||||
EClassJob.WhiteMage,
|
||||
value.WHM
|
||||
},
|
||||
{
|
||||
EClassJob.BlackMage,
|
||||
value.BLM
|
||||
},
|
||||
{
|
||||
EClassJob.Arcanist,
|
||||
value.ACN
|
||||
},
|
||||
{
|
||||
EClassJob.Summoner,
|
||||
value.SMN
|
||||
},
|
||||
{
|
||||
EClassJob.Scholar,
|
||||
value.SCH
|
||||
},
|
||||
{
|
||||
EClassJob.Rogue,
|
||||
value.ROG
|
||||
},
|
||||
{
|
||||
EClassJob.Ninja,
|
||||
value.NIN
|
||||
},
|
||||
{
|
||||
EClassJob.Machinist,
|
||||
value.MCH
|
||||
},
|
||||
{
|
||||
EClassJob.DarkKnight,
|
||||
value.DRK
|
||||
},
|
||||
{
|
||||
EClassJob.Astrologian,
|
||||
value.AST
|
||||
},
|
||||
{
|
||||
EClassJob.Samurai,
|
||||
value.SAM
|
||||
},
|
||||
{
|
||||
EClassJob.RedMage,
|
||||
value.RDM
|
||||
},
|
||||
{
|
||||
EClassJob.BlueMage,
|
||||
value.BLU
|
||||
},
|
||||
{
|
||||
EClassJob.Gunbreaker,
|
||||
value.GNB
|
||||
},
|
||||
{
|
||||
EClassJob.Dancer,
|
||||
value.DNC
|
||||
},
|
||||
{
|
||||
EClassJob.Reaper,
|
||||
value.RPR
|
||||
},
|
||||
{
|
||||
EClassJob.Sage,
|
||||
value.SGE
|
||||
},
|
||||
{
|
||||
EClassJob.Viper,
|
||||
value.VPR
|
||||
},
|
||||
{
|
||||
EClassJob.Pictomancer,
|
||||
value.PCT
|
||||
}
|
||||
}
|
||||
where y.Value
|
||||
select y.Key).ToList().AsReadOnly();
|
||||
CachedClassJobs[value.RowId] = value2;
|
||||
return value2;
|
||||
}
|
||||
}
|
62
Questionable/Questionable.Model/QuestProgressInfo.cs
Normal file
62
Questionable/Questionable.Model/QuestProgressInfo.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
|
||||
using LLib.GameData;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class QuestProgressInfo
|
||||
{
|
||||
private readonly string _asString;
|
||||
|
||||
public ElementId Id { get; }
|
||||
|
||||
public byte Sequence { get; }
|
||||
|
||||
public ushort Flags { get; init; }
|
||||
|
||||
public List<byte> Variables { get; }
|
||||
|
||||
public bool IsHidden { get; }
|
||||
|
||||
public EClassJob ClassJob { get; }
|
||||
|
||||
public string Tooltip { get; }
|
||||
|
||||
public QuestProgressInfo(QuestWork questWork)
|
||||
{
|
||||
Id = new QuestId(questWork.QuestId);
|
||||
Sequence = questWork.Sequence;
|
||||
Flags = questWork.Flags;
|
||||
Variables = questWork.Variables.ToArray().ToList();
|
||||
IsHidden = questWork.IsHidden;
|
||||
ClassJob = (EClassJob)questWork.AcceptClassJob;
|
||||
Tooltip = "";
|
||||
Span<byte> variables = questWork.Variables;
|
||||
string text = "";
|
||||
for (int i = 0; i < variables.Length; i++)
|
||||
{
|
||||
byte b = variables[i];
|
||||
Tooltip = Tooltip + Convert.ToString(b, 2).PadLeft(8).Replace(" ", "0") + "\n";
|
||||
int num = b & 0xF;
|
||||
text += b;
|
||||
if (num != 0)
|
||||
{
|
||||
text += $"({num})";
|
||||
}
|
||||
text += " ";
|
||||
if (i % 2 == 1)
|
||||
{
|
||||
text += " ";
|
||||
}
|
||||
}
|
||||
_asString = "QW: " + text.Trim();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _asString;
|
||||
}
|
||||
}
|
53
Questionable/Questionable.Model/SatisfactionSupplyInfo.cs
Normal file
53
Questionable/Questionable.Model/SatisfactionSupplyInfo.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using LLib.GameData;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class SatisfactionSupplyInfo : IQuestInfo
|
||||
{
|
||||
public ElementId QuestId { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public uint IssuerDataId { get; }
|
||||
|
||||
public bool IsRepeatable => true;
|
||||
|
||||
public ImmutableList<PreviousQuestInfo> PreviousQuests { get; }
|
||||
|
||||
public EQuestJoin PreviousQuestJoin => EQuestJoin.All;
|
||||
|
||||
public ushort Level { get; }
|
||||
|
||||
public EAlliedSociety AlliedSociety => EAlliedSociety.None;
|
||||
|
||||
public uint? JournalGenre => null;
|
||||
|
||||
public ushort SortKey { get; }
|
||||
|
||||
public bool IsMainScenarioQuest => false;
|
||||
|
||||
public EExpansionVersion Expansion { get; }
|
||||
|
||||
public IReadOnlyList<EClassJob> ClassJobs { get; } = new global::_003C_003Ez__ReadOnlyArray<EClassJob>(new EClassJob[2]
|
||||
{
|
||||
EClassJob.Miner,
|
||||
EClassJob.Botanist
|
||||
});
|
||||
|
||||
public SatisfactionSupplyInfo(SatisfactionNpc npc)
|
||||
{
|
||||
QuestId = new SatisfactionSupplyNpcId((ushort)npc.RowId);
|
||||
Name = npc.Npc.Value.Singular.ToString();
|
||||
IssuerDataId = npc.Npc.RowId;
|
||||
Level = npc.LevelUnlock;
|
||||
SortKey = QuestId.Value;
|
||||
Expansion = (EExpansionVersion)npc.QuestRequired.Value.Expansion.RowId;
|
||||
PreviousQuestInfo reference = new PreviousQuestInfo(Questionable.Model.Questing.QuestId.FromRowId(npc.QuestRequired.RowId), 0);
|
||||
PreviousQuests = ImmutableList.Create(new ReadOnlySpan<PreviousQuestInfo>(in reference));
|
||||
}
|
||||
}
|
49
Questionable/Questionable.Model/StringOrRegex.cs
Normal file
49
Questionable/Questionable.Model/StringOrRegex.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Questionable.Functions;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class StringOrRegex
|
||||
{
|
||||
private readonly Regex? _regex;
|
||||
|
||||
private readonly string? _stringValue;
|
||||
|
||||
public StringOrRegex(Regex? regex)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(regex, "regex");
|
||||
_regex = regex;
|
||||
_stringValue = null;
|
||||
}
|
||||
|
||||
public StringOrRegex(string? str)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(str, "str");
|
||||
_regex = null;
|
||||
_stringValue = str;
|
||||
}
|
||||
|
||||
public bool IsMatch(string other)
|
||||
{
|
||||
if (_regex != null)
|
||||
{
|
||||
return _regex.IsMatch(other);
|
||||
}
|
||||
return GameFunctions.GameStringEquals(_stringValue, other);
|
||||
}
|
||||
|
||||
public string? GetString()
|
||||
{
|
||||
if (_stringValue == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
return _stringValue;
|
||||
}
|
||||
|
||||
public override string? ToString()
|
||||
{
|
||||
return _regex?.ToString() ?? _stringValue;
|
||||
}
|
||||
}
|
29
Questionable/Questionable.Model/TripleTriadCardReward.cs
Normal file
29
Questionable/Questionable.Model/TripleTriadCardReward.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
public sealed record TripleTriadCardReward : ItemReward
|
||||
{
|
||||
public ushort TripleTriadCardId { get; init; }
|
||||
|
||||
public override EItemRewardType Type => EItemRewardType.TripleTriadCard;
|
||||
|
||||
public TripleTriadCardReward(ItemRewardDetails Item, ushort TripleTriadCardId)
|
||||
{
|
||||
this.TripleTriadCardId = TripleTriadCardId;
|
||||
base._002Ector(Item);
|
||||
}
|
||||
|
||||
public unsafe override bool IsUnlocked()
|
||||
{
|
||||
return UIState.Instance()->IsTripleTriadCardUnlocked(TripleTriadCardId);
|
||||
}
|
||||
|
||||
[CompilerGenerated]
|
||||
public void Deconstruct(out ItemRewardDetails Item, out ushort TripleTriadCardId)
|
||||
{
|
||||
Item = base.Item;
|
||||
TripleTriadCardId = this.TripleTriadCardId;
|
||||
}
|
||||
}
|
43
Questionable/Questionable.Model/UnlockLinkQuestInfo.cs
Normal file
43
Questionable/Questionable.Model/UnlockLinkQuestInfo.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using LLib.GameData;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Model;
|
||||
|
||||
internal sealed class UnlockLinkQuestInfo : IQuestInfo
|
||||
{
|
||||
public ElementId QuestId { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public uint IssuerDataId { get; }
|
||||
|
||||
public bool IsRepeatable => false;
|
||||
|
||||
public ImmutableList<PreviousQuestInfo> PreviousQuests => ImmutableList.Create(default(ReadOnlySpan<PreviousQuestInfo>));
|
||||
|
||||
public EQuestJoin PreviousQuestJoin => EQuestJoin.All;
|
||||
|
||||
public ushort Level => 1;
|
||||
|
||||
public EAlliedSociety AlliedSociety => EAlliedSociety.None;
|
||||
|
||||
public uint? JournalGenre => null;
|
||||
|
||||
public ushort SortKey => 0;
|
||||
|
||||
public bool IsMainScenarioQuest => false;
|
||||
|
||||
public IReadOnlyList<EClassJob> ClassJobs => Array.Empty<EClassJob>();
|
||||
|
||||
public EExpansionVersion Expansion => EExpansionVersion.ARealmReborn;
|
||||
|
||||
public UnlockLinkQuestInfo(UnlockLinkId unlockLinkId, string name, uint issuerDataId)
|
||||
{
|
||||
QuestId = unlockLinkId;
|
||||
Name = name;
|
||||
IssuerDataId = issuerDataId;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue