qstbak/Questionable/Questionable.Windows.ConfigComponents/SinglePlayerDutyConfigComponent.cs
2025-10-09 07:47:19 +10:00

916 lines
35 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using LLib.GameData;
using Lumina.Excel.Sheets;
using Microsoft.Extensions.Logging;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Model;
using Questionable.Model.Common;
using Questionable.Model.Questing;
namespace Questionable.Windows.ConfigComponents;
internal sealed class SinglePlayerDutyConfigComponent : ConfigComponent
{
private sealed record SinglePlayerDutyInfo(string Name, IQuestInfo QuestInfo, TerritoryData.ContentFinderConditionData ContentFinderConditionData, SinglePlayerDutyOptions Options, bool Enabled)
{
public EExpansionVersion Expansion => QuestInfo.Expansion;
public uint JournalGenreId => (uint)(((int?)QuestInfo.JournalGenre) ?? (-1));
public ushort SortKey => QuestInfo.SortKey;
public uint ContentFinderConditionId => ContentFinderConditionData.ContentFinderConditionId;
public uint TerritoryId => ContentFinderConditionData.TerritoryId;
public byte Index => Options.Index;
public bool EnabledByDefault => Options.Enabled;
public ReadOnlyCollection<string> Notes => Options.Notes.AsReadOnly();
public bool IsLimsaStart
{
get
{
uint contentFinderConditionId = ContentFinderConditionId;
if (contentFinderConditionId == 313 || contentFinderConditionId - 332 <= 2)
{
return true;
}
return false;
}
}
public bool IsGridaniaStart
{
get
{
uint contentFinderConditionId = ContentFinderConditionId;
if (contentFinderConditionId - 296 <= 3)
{
return true;
}
return false;
}
}
public bool IsUldahStart
{
get
{
uint contentFinderConditionId = ContentFinderConditionId;
if (contentFinderConditionId == 312 || contentFinderConditionId - 335 <= 2)
{
return true;
}
return false;
}
}
public bool IsOtherRoleQuest
{
get
{
uint contentFinderConditionId = ContentFinderConditionId;
if (contentFinderConditionId == 845 || contentFinderConditionId == 1016)
{
return true;
}
return false;
}
}
}
private const string SinglePlayerDutyClipboardPrefix = "qst:single:";
private static readonly List<(EClassJob ClassJob, string Name)> RoleQuestCategories;
private readonly TerritoryData _territoryData;
private readonly QuestRegistry _questRegistry;
private readonly QuestData _questData;
private readonly IDataManager _dataManager;
private readonly ClassJobUtils _classJobUtils;
private readonly ILogger<SinglePlayerDutyConfigComponent> _logger;
private ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>> _startingCityBattles = ImmutableDictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>>.Empty;
private ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>> _mainScenarioBattles = ImmutableDictionary<EExpansionVersion, List<SinglePlayerDutyInfo>>.Empty;
private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _jobQuestBattles = ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
private ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>> _roleQuestBattles = ImmutableDictionary<EClassJob, List<SinglePlayerDutyInfo>>.Empty;
private ImmutableList<SinglePlayerDutyInfo> _otherRoleQuestBattles = ImmutableList<SinglePlayerDutyInfo>.Empty;
private ImmutableList<(string Label, List<SinglePlayerDutyInfo>)> _otherQuestBattles = ImmutableList<(string, List<SinglePlayerDutyInfo>)>.Empty;
public SinglePlayerDutyConfigComponent(IDalamudPluginInterface pluginInterface, Configuration configuration, TerritoryData territoryData, QuestRegistry questRegistry, QuestData questData, IDataManager dataManager, ClassJobUtils classJobUtils, ILogger<SinglePlayerDutyConfigComponent> logger)
: base(pluginInterface, configuration)
{
_territoryData = territoryData;
_questRegistry = questRegistry;
_questData = questData;
_dataManager = dataManager;
_classJobUtils = classJobUtils;
_logger = logger;
}
public void Reload()
{
List<ElementId> list = (from x in _territoryData.GetAllQuestsWithQuestBattles()
group x by x.QuestId into x
where x.Count() > 1
select x.Key).ToList();
List<SinglePlayerDutyInfo> list2 = new List<SinglePlayerDutyInfo>();
Dictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>> dictionary = new Dictionary<EAetheryteLocation, List<SinglePlayerDutyInfo>>
{
{
EAetheryteLocation.Limsa,
new List<SinglePlayerDutyInfo>()
},
{
EAetheryteLocation.Gridania,
new List<SinglePlayerDutyInfo>()
},
{
EAetheryteLocation.Uldah,
new List<SinglePlayerDutyInfo>()
}
};
List<SinglePlayerDutyInfo> list3 = new List<SinglePlayerDutyInfo>();
Dictionary<ElementId, EClassJob> dictionary2 = (from x in Enum.GetValues<EClassJob>()
where x != EClassJob.Adventurer && !x.IsCrafter() && !x.IsGatherer()
where x.IsClass() || !x.HasBaseClass()
select x).SelectMany((EClassJob x) => from y in _questRegistry.GetKnownClassJobQuests(x, includeRoleQuests: false)
select (QuestId: y.QuestId, ClassJob: x)).ToDictionary<(ElementId, EClassJob), ElementId, EClassJob>(((ElementId QuestId, EClassJob ClassJob) x) => x.QuestId, ((ElementId QuestId, EClassJob ClassJob) x) => x.ClassJob);
Dictionary<EClassJob, List<SinglePlayerDutyInfo>> dictionary3 = dictionary2.Values.Distinct().ToDictionary((EClassJob x) => x, (EClassJob _) => new List<SinglePlayerDutyInfo>());
Dictionary<ElementId, List<EClassJob>> dictionary4 = (from x in RoleQuestCategories.SelectMany<(EClassJob, string), (ElementId, EClassJob)>(((EClassJob ClassJob, string Name) x) => from y in _questData.GetRoleQuests(x.ClassJob)
select (QuestId: y.QuestId, ClassJob: x.ClassJob))
group x by x.QuestId).ToDictionary((IGrouping<ElementId, (ElementId QuestId, EClassJob ClassJob)> x) => x.Key, (IGrouping<ElementId, (ElementId QuestId, EClassJob ClassJob)> x) => x.Select(((ElementId QuestId, EClassJob ClassJob) y) => y.ClassJob).ToList());
Dictionary<EClassJob, List<SinglePlayerDutyInfo>> dictionary5 = RoleQuestCategories.ToDictionary<(EClassJob, string), EClassJob, List<SinglePlayerDutyInfo>>(((EClassJob ClassJob, string Name) x) => x.ClassJob, ((EClassJob ClassJob, string Name) _) => new List<SinglePlayerDutyInfo>());
List<SinglePlayerDutyInfo> list4 = new List<SinglePlayerDutyInfo>();
foreach (var allQuestsWithQuestBattle in _territoryData.GetAllQuestsWithQuestBattles())
{
ElementId item = allQuestsWithQuestBattle.QuestId;
byte item2 = allQuestsWithQuestBattle.Index;
TerritoryData.ContentFinderConditionData item3 = allQuestsWithQuestBattle.Data;
IQuestInfo questInfo = _questData.GetQuestInfo(item);
(bool Enabled, SinglePlayerDutyOptions Options) tuple = FindDutyOptions(item, item2);
bool item4 = tuple.Enabled;
SinglePlayerDutyOptions item5 = tuple.Options;
string text = ConfigComponent.FormatLevel(questInfo.Level) + " " + questInfo.Name;
if (!string.IsNullOrEmpty(item3.Name) && !questInfo.Name.EndsWith(item3.Name, StringComparison.Ordinal))
{
text = text + " (" + item3.Name + ")";
}
if (list.Contains(item))
{
text += $" (Part {item5.Index + 1})";
}
else
{
uint contentFinderConditionId = item3.ContentFinderConditionId;
if ((contentFinderConditionId == 674 || contentFinderConditionId == 691) ? true : false)
{
text += " (Melee/Phys. Ranged)";
}
}
SinglePlayerDutyInfo singlePlayerDutyInfo = new SinglePlayerDutyInfo(text, questInfo, item3, item5, item4);
EClassJob value;
List<EClassJob> value2;
if (singlePlayerDutyInfo.IsLimsaStart)
{
dictionary[EAetheryteLocation.Limsa].Add(singlePlayerDutyInfo);
}
else if (singlePlayerDutyInfo.IsGridaniaStart)
{
dictionary[EAetheryteLocation.Gridania].Add(singlePlayerDutyInfo);
}
else if (singlePlayerDutyInfo.IsUldahStart)
{
dictionary[EAetheryteLocation.Uldah].Add(singlePlayerDutyInfo);
}
else if (questInfo.IsMainScenarioQuest)
{
list2.Add(singlePlayerDutyInfo);
}
else if (dictionary2.TryGetValue(item, out value))
{
dictionary3[value].Add(singlePlayerDutyInfo);
}
else if (dictionary4.TryGetValue(item, out value2))
{
foreach (EClassJob item6 in value2)
{
dictionary5[item6].Add(singlePlayerDutyInfo);
}
}
else if (singlePlayerDutyInfo.IsOtherRoleQuest)
{
list4.Add(singlePlayerDutyInfo);
}
else
{
list3.Add(singlePlayerDutyInfo);
}
}
_startingCityBattles = dictionary.ToImmutableDictionary((KeyValuePair<EAetheryteLocation, List<SinglePlayerDutyInfo>> x) => x.Key, (KeyValuePair<EAetheryteLocation, List<SinglePlayerDutyInfo>> x) => x.Value.OrderBy((SinglePlayerDutyInfo y) => y.SortKey).ToList());
_mainScenarioBattles = (from x in list2
group x by x.Expansion).ToImmutableDictionary((IGrouping<EExpansionVersion, SinglePlayerDutyInfo> x) => x.Key, (IGrouping<EExpansionVersion, SinglePlayerDutyInfo> x) => (from y in x
orderby y.JournalGenreId, y.SortKey, y.Index
select y).ToList());
_jobQuestBattles = dictionary3.Where((KeyValuePair<EClassJob, List<SinglePlayerDutyInfo>> x) => x.Value.Count > 0).ToImmutableDictionary((KeyValuePair<EClassJob, List<SinglePlayerDutyInfo>> x) => x.Key, (KeyValuePair<EClassJob, List<SinglePlayerDutyInfo>> x) => (from y in x.Value.DistinctBy((SinglePlayerDutyInfo y) => y.ContentFinderConditionId)
orderby y.JournalGenreId, y.SortKey, y.Index
select y).ToList());
_roleQuestBattles = dictionary5.ToImmutableDictionary((KeyValuePair<EClassJob, List<SinglePlayerDutyInfo>> x) => x.Key, (KeyValuePair<EClassJob, List<SinglePlayerDutyInfo>> x) => (from y in x.Value
orderby y.JournalGenreId, y.SortKey, y.Index
select y).ToList());
_otherRoleQuestBattles = list4.ToImmutableList();
_otherQuestBattles = (from x in list3
orderby x.JournalGenreId, x.SortKey, x.Index
group x by x.JournalGenreId into x
select (BuildJournalGenreLabel(x.Key), x.ToList())).ToImmutableList();
}
private (bool Enabled, SinglePlayerDutyOptions Options) FindDutyOptions(ElementId questId, byte index)
{
SinglePlayerDutyOptions singlePlayerDutyOptions = new SinglePlayerDutyOptions
{
Index = 0,
Enabled = false
};
if (_questRegistry.TryGetQuest(questId, out Questionable.Model.Quest quest))
{
if (quest.Root.Disabled)
{
_logger.LogDebug("Disabling quest battle for quest {QuestId}, quest is disabled", questId);
return (Enabled: false, Options: singlePlayerDutyOptions);
}
QuestStep questStep = (from x in quest.AllSteps()
select x.Step).FirstOrDefault((QuestStep x) => x.InteractionType == EInteractionType.SinglePlayerDuty && x.SinglePlayerDutyIndex == index);
if (questStep == null)
{
_logger.LogWarning("Disabling quest battle for quest {QuestId}, no battle with index {Index} found", questId, index);
return (Enabled: false, Options: singlePlayerDutyOptions);
}
return (Enabled: true, Options: questStep.SinglePlayerDutyOptions ?? singlePlayerDutyOptions);
}
_logger.LogDebug("Disabling quest battle for quest {QuestId}, unknown quest", questId);
return (Enabled: false, Options: singlePlayerDutyOptions);
}
private string BuildJournalGenreLabel(uint journalGenreId)
{
JournalGenre row = _dataManager.GetExcelSheet<JournalGenre>().GetRow(journalGenreId);
JournalCategory value = row.JournalCategory.Value;
string text = row.Name.ExtractText();
return value.Name.ExtractText() + " ※ " + text;
}
public override void DrawTab()
{
using ImRaii.IEndObject endObject = ImRaii.TabItem("Quest Battles###QuestBattles");
if (!endObject)
{
return;
}
bool v = base.Configuration.SinglePlayerDuties.RunSoloInstancesWithBossMod;
if (ImGui.Checkbox("Run quest battles with BossMod", ref v))
{
base.Configuration.SinglePlayerDuties.RunSoloInstancesWithBossMod = v;
Save();
}
using (ImRaii.PushIndent(ImGui.GetFrameHeight() + ImGui.GetStyle().ItemInnerSpacing.X))
{
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed))
{
ImGui.TextUnformatted("Work in Progress:");
ImGui.BulletText("Will always use BossMod for combat (ignoring the configured combat module).");
ImGui.BulletText("Only a small subset of quest battles have been tested - most of which are in the MSQ.");
ImGui.BulletText("When retrying a failed battle, it will always start at 'Normal' difficulty.");
ImGui.BulletText("Please don't enable this option when using a BossMod fork (such as Reborn);\nwith the missing combat module configuration, it is unlikely to be compatible.");
}
}
ImGui.Separator();
using (ImRaii.Disabled(!v))
{
ImGui.Text("Questionable includes a default list of quest battles that work if BossMod is installed.");
ImGui.Text("The included list of quest battles can change with each update.");
ImGui.Separator();
ImGui.Text("You can override the settings for each individual quest battle:");
using ImRaii.IEndObject endObject2 = ImRaii.TabBar("QuestionableConfigTabs");
if (endObject2)
{
DrawMainScenarioConfigTable();
DrawJobQuestConfigTable();
DrawRoleQuestConfigTable();
DrawOtherQuestConfigTable();
}
DrawEnableAllButton();
ImGui.SameLine();
DrawClipboardButtons();
ImGui.SameLine();
DrawResetButton();
}
}
private void DrawMainScenarioConfigTable()
{
(int enabledCount, int totalCount) mainScenarioQuestCounts = GetMainScenarioQuestCounts();
int item = mainScenarioQuestCounts.enabledCount;
int item2 = mainScenarioQuestCounts.totalCount;
ImU8String label = new ImU8String(30, 2);
label.AppendLiteral("Main Scenario Quests (");
label.AppendFormatted(item);
label.AppendLiteral("/");
label.AppendFormatted(item2);
label.AppendLiteral(")###MSQ");
using ImRaii.IEndObject endObject = ImRaii.TabItem(label);
if (!endObject)
{
return;
}
using ImRaii.IEndObject endObject2 = BeginChildArea();
if (!endObject2)
{
return;
}
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(_startingCityBattles[EAetheryteLocation.Limsa]);
int item3 = questBattleCounts.enabledCount;
int item4 = questBattleCounts.totalCount;
string obj = $"Limsa Lominsa ({ConfigComponent.FormatLevel(5)} - {ConfigComponent.FormatLevel(14)}) ({item3}/{item4})";
string key = "Limsa";
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = true;
Save();
}
DrawQuestTable("LimsaLominsa", _startingCityBattles[EAetheryteLocation.Limsa]);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = false;
Save();
}
(int enabledCount, int totalCount) questBattleCounts2 = GetQuestBattleCounts(_startingCityBattles[EAetheryteLocation.Gridania]);
int item5 = questBattleCounts2.enabledCount;
int item6 = questBattleCounts2.totalCount;
string obj2 = $"Gridania ({ConfigComponent.FormatLevel(5)} - {ConfigComponent.FormatLevel(14)}) ({item5}/{item6})";
string key2 = "Gridania";
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj2))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key2] = true;
Save();
}
DrawQuestTable("Gridania", _startingCityBattles[EAetheryteLocation.Gridania]);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key2] = false;
Save();
}
(int enabledCount, int totalCount) questBattleCounts3 = GetQuestBattleCounts(_startingCityBattles[EAetheryteLocation.Uldah]);
int item7 = questBattleCounts3.enabledCount;
int item8 = questBattleCounts3.totalCount;
string obj3 = $"Ul'dah ({ConfigComponent.FormatLevel(4)} - {ConfigComponent.FormatLevel(14)}) ({item7}/{item8})";
string key3 = "Uldah";
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key3, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj3))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key3, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key3] = true;
Save();
}
DrawQuestTable("Uldah", _startingCityBattles[EAetheryteLocation.Uldah]);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key3, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key3] = false;
Save();
}
EExpansionVersion[] values = Enum.GetValues<EExpansionVersion>();
for (int i = 0; i < values.Length; i++)
{
EExpansionVersion eExpansionVersion = values[i];
if (!_mainScenarioBattles.TryGetValue(eExpansionVersion, out List<SinglePlayerDutyInfo> value))
{
continue;
}
(int enabledCount, int totalCount) questBattleCounts4 = GetQuestBattleCounts(value);
int item9 = questBattleCounts4.enabledCount;
int item10 = questBattleCounts4.totalCount;
string obj4 = $"{eExpansionVersion.ToFriendlyString()} ({item9}/{item10})";
string key4 = eExpansionVersion.ToString();
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key4, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj4))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key4, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key4] = true;
Save();
}
DrawQuestTable($"Duties{eExpansionVersion}", value);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key4, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key4] = false;
Save();
}
}
}
private void DrawJobQuestConfigTable()
{
(int enabledCount, int totalCount) jobQuestCounts = GetJobQuestCounts();
int item = jobQuestCounts.enabledCount;
int item2 = jobQuestCounts.totalCount;
ImU8String label = new ImU8String(32, 2);
label.AppendLiteral("Class/Job Quests (");
label.AppendFormatted(item);
label.AppendLiteral("/");
label.AppendFormatted(item2);
label.AppendLiteral(")###JobQuests");
using ImRaii.IEndObject endObject = ImRaii.TabItem(label);
if (!endObject)
{
return;
}
using ImRaii.IEndObject endObject2 = BeginChildArea();
if (!endObject2)
{
return;
}
int num = 0;
foreach (var (eClassJob, num2) in _classJobUtils.SortedClassJobs)
{
if (eClassJob.IsCrafter() || eClassJob.IsGatherer() || !_jobQuestBattles.TryGetValue(eClassJob, out List<SinglePlayerDutyInfo> value))
{
continue;
}
if (num2 != num)
{
num = num2;
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
}
string text = eClassJob.ToFriendlyString();
if (eClassJob.IsClass())
{
text = text + " / " + eClassJob.AsJob().ToFriendlyString();
}
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(value);
int item3 = questBattleCounts.enabledCount;
int item4 = questBattleCounts.totalCount;
string obj = $"{text} ({item3}/{item4})";
string key = eClassJob.ToString();
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = true;
Save();
}
DrawQuestTable($"JobQuests{eClassJob}", value);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = false;
Save();
}
}
}
private void DrawRoleQuestConfigTable()
{
(int enabledCount, int totalCount) roleQuestCounts = GetRoleQuestCounts();
int item = roleQuestCounts.enabledCount;
int item2 = roleQuestCounts.totalCount;
ImU8String label = new ImU8String(28, 2);
label.AppendLiteral("Role Quests (");
label.AppendFormatted(item);
label.AppendLiteral("/");
label.AppendFormatted(item2);
label.AppendLiteral(")###RoleQuests");
using ImRaii.IEndObject endObject = ImRaii.TabItem(label);
if (!endObject)
{
return;
}
using ImRaii.IEndObject endObject2 = BeginChildArea();
if (!endObject2)
{
return;
}
foreach (var (eClassJob, value) in RoleQuestCategories)
{
if (!_roleQuestBattles.TryGetValue(eClassJob, out List<SinglePlayerDutyInfo> value2))
{
continue;
}
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(value2);
int item3 = questBattleCounts.enabledCount;
int item4 = questBattleCounts.totalCount;
string obj = $"{value} ({item3}/{item4})";
string key = $"Role_{eClassJob}";
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = true;
Save();
}
DrawQuestTable($"RoleQuests{eClassJob}", value2);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = false;
Save();
}
}
(int enabledCount, int totalCount) questBattleCounts2 = GetQuestBattleCounts(_otherRoleQuestBattles);
int item5 = questBattleCounts2.enabledCount;
int item6 = questBattleCounts2.totalCount;
string obj2 = $"General Role Quests ({item5}/{item6})";
string key2 = "Role_General";
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj2))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key2] = true;
Save();
}
DrawQuestTable("RoleQuestsGeneral", _otherRoleQuestBattles);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key2, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key2] = false;
Save();
}
}
private void DrawOtherQuestConfigTable()
{
(int enabledCount, int totalCount) otherQuestCounts = GetOtherQuestCounts();
int item = otherQuestCounts.enabledCount;
int item2 = otherQuestCounts.totalCount;
ImU8String label = new ImU8String(29, 2);
label.AppendLiteral("Other Quests (");
label.AppendFormatted(item);
label.AppendLiteral("/");
label.AppendFormatted(item2);
label.AppendLiteral(")###MiscQuests");
using ImRaii.IEndObject endObject = ImRaii.TabItem(label);
if (!endObject)
{
return;
}
using ImRaii.IEndObject endObject2 = BeginChildArea();
if (!endObject2)
{
return;
}
foreach (var otherQuestBattle in _otherQuestBattles)
{
string item3 = otherQuestBattle.Label;
List<SinglePlayerDutyInfo> item4 = otherQuestBattle.Item2;
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(item4);
int item5 = questBattleCounts.enabledCount;
int item6 = questBattleCounts.totalCount;
string obj = $"{item3} ({item5}/{item6})";
string key = "Other_" + item3;
ImGui.SetNextItemOpen(base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false), ImGuiCond.Always);
if (ImGui.CollapsingHeader(obj))
{
if (!base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = true;
Save();
}
DrawQuestTable("Other" + item3, item4);
}
else if (base.Configuration.SinglePlayerDuties.HeaderStates.GetValueOrDefault(key, defaultValue: false))
{
base.Configuration.SinglePlayerDuties.HeaderStates[key] = false;
Save();
}
}
}
private void DrawQuestTable(string label, IReadOnlyList<SinglePlayerDutyInfo> dutyInfos)
{
using ImRaii.IEndObject endObject = ImRaii.Table(label, 2, ImGuiTableFlags.SizingFixedFit);
if (!ImRaii.IEndObject.op_True(endObject))
{
return;
}
ImGui.TableSetupColumn("Quest", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableSetupColumn("Options", ImGuiTableColumnFlags.WidthFixed, 200f);
foreach (SinglePlayerDutyInfo dutyInfo in dutyInfos)
{
ImGui.TableNextRow();
string[] items = (dutyInfo.EnabledByDefault ? SupportedCfcOptions : UnsupportedCfcOptions);
int currentItem = 0;
if (base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(dutyInfo.ContentFinderConditionId))
{
currentItem = 1;
}
if (base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(dutyInfo.ContentFinderConditionId))
{
currentItem = 2;
}
ImU8String text;
if (ImGui.TableNextColumn())
{
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(dutyInfo.Name);
if (ImGui.IsItemHovered() && base.Configuration.Advanced.AdditionalStatusInformation)
{
using ImRaii.IEndObject endObject2 = ImRaii.Tooltip();
if (endObject2)
{
ImGui.TextUnformatted(dutyInfo.Name);
ImGui.Separator();
text = new ImU8String(13, 1);
text.AppendLiteral("TerritoryId: ");
text.AppendFormatted(dutyInfo.TerritoryId);
ImGui.BulletText(text);
text = new ImU8String(26, 1);
text.AppendLiteral("ContentFinderConditionId: ");
text.AppendFormatted(dutyInfo.ContentFinderConditionId);
ImGui.BulletText(text);
}
}
if (!dutyInfo.Enabled)
{
ImGuiComponents.HelpMarker("Questionable doesn't include support for this quest.", FontAwesomeIcon.Times, ImGuiColors.DalamudRed);
}
else if (dutyInfo.Notes.Count > 0)
{
ConfigComponent.DrawNotes(dutyInfo.EnabledByDefault, dutyInfo.Notes);
}
}
if (!ImGui.TableNextColumn())
{
continue;
}
text = new ImU8String(6, 1);
text.AppendLiteral("##Duty");
text.AppendFormatted(dutyInfo.ContentFinderConditionId);
using (ImRaii.PushId(text))
{
using (ImRaii.Disabled(!dutyInfo.Enabled))
{
ImGui.SetNextItemWidth(200f);
if (ImGui.Combo(string.Empty, ref currentItem, in items, items.Length))
{
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Remove(dutyInfo.ContentFinderConditionId);
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Remove(dutyInfo.ContentFinderConditionId);
switch (currentItem)
{
case 1:
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Add(dutyInfo.ContentFinderConditionId);
break;
case 2:
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Add(dutyInfo.ContentFinderConditionId);
break;
}
Save();
}
}
}
}
}
private static ImRaii.IEndObject BeginChildArea()
{
return ImRaii.Child("DutyConfiguration", new Vector2(675f, 400f), border: true);
}
private void DrawEnableAllButton()
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.CheckCircle, "Enable All"))
{
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Clear();
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Clear();
foreach (SinglePlayerDutyInfo allEnabledSinglePlayerDuty in GetAllEnabledSinglePlayerDuties())
{
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Add(allEnabledSinglePlayerDuty.ContentFinderConditionId);
}
Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Enable all of the quest battles, use at your own risk.");
}
}
private void DrawClipboardButtons()
{
using (ImRaii.Disabled(base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Count + base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Count == 0))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Copy, "Export to clipboard"))
{
IEnumerable<string> first = base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Select((uint x) => $"{"+"}{x}");
IEnumerable<string> second = base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Select((uint x) => $"{"-"}{x}");
ImGui.SetClipboardText("qst:single:" + Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Join(";", first.Concat(second)))));
}
}
ImGui.SameLine();
string text = ImGui.GetClipboardText().Trim();
using (ImRaii.Disabled(string.IsNullOrEmpty(text) || !text.StartsWith("qst:single:", StringComparison.InvariantCulture)))
{
if (!ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Paste, "Import from Clipboard"))
{
return;
}
text = text.Substring("qst:single:".Length);
string text2 = Encoding.UTF8.GetString(Convert.FromBase64String(text));
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Clear();
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Clear();
string[] array = text2.Split(";");
foreach (string text3 in array)
{
if (text3.StartsWith("+", StringComparison.InvariantCulture) && uint.TryParse(text3.AsSpan("+".Length), CultureInfo.InvariantCulture, out var result))
{
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Add(result);
}
if (text3.StartsWith("-", StringComparison.InvariantCulture) && uint.TryParse(text3.AsSpan("-".Length), CultureInfo.InvariantCulture, out var result2))
{
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Add(result2);
}
}
Save();
}
}
private void DrawResetButton()
{
using (ImRaii.Disabled(!ImGui.IsKeyDown(ImGuiKey.ModCtrl)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Undo, "Reset to default"))
{
base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Clear();
base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Clear();
Save();
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{
ImGui.SetTooltip("Hold CTRL to enable this button.");
}
}
private IEnumerable<SinglePlayerDutyInfo> GetAllEnabledSinglePlayerDuties()
{
return from x in _startingCityBattles.Values.SelectMany((List<SinglePlayerDutyInfo> x) => x).Concat(_mainScenarioBattles.Values.SelectMany((List<SinglePlayerDutyInfo> x) => x)).Concat(_jobQuestBattles.Values.SelectMany((List<SinglePlayerDutyInfo> x) => x))
.Concat(_roleQuestBattles.Values.SelectMany((List<SinglePlayerDutyInfo> x) => x))
.Concat(_otherRoleQuestBattles)
.Concat(_otherQuestBattles.SelectMany<(string, List<SinglePlayerDutyInfo>), SinglePlayerDutyInfo>(((string Label, List<SinglePlayerDutyInfo>) x) => x.Item2))
where x.Enabled
select x;
}
private (int enabledCount, int totalCount) GetQuestBattleCounts(IReadOnlyList<SinglePlayerDutyInfo> dutyInfos)
{
int num = 0;
int num2 = 0;
foreach (SinglePlayerDutyInfo dutyInfo in dutyInfos)
{
if (dutyInfo.Enabled)
{
num2++;
if (base.Configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(dutyInfo.ContentFinderConditionId) || (!base.Configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(dutyInfo.ContentFinderConditionId) && dutyInfo.EnabledByDefault))
{
num++;
}
}
}
return (enabledCount: num, totalCount: num2);
}
private (int enabledCount, int totalCount) GetMainScenarioQuestCounts()
{
int num = 0;
int num2 = 0;
foreach (List<SinglePlayerDutyInfo> value in _startingCityBattles.Values)
{
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(value);
int item = questBattleCounts.enabledCount;
int item2 = questBattleCounts.totalCount;
num += item;
num2 += item2;
}
foreach (List<SinglePlayerDutyInfo> value2 in _mainScenarioBattles.Values)
{
(int enabledCount, int totalCount) questBattleCounts2 = GetQuestBattleCounts(value2);
int item3 = questBattleCounts2.enabledCount;
int item4 = questBattleCounts2.totalCount;
num += item3;
num2 += item4;
}
return (enabledCount: num, totalCount: num2);
}
private (int enabledCount, int totalCount) GetJobQuestCounts()
{
int num = 0;
int num2 = 0;
foreach (List<SinglePlayerDutyInfo> value in _jobQuestBattles.Values)
{
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(value);
int item = questBattleCounts.enabledCount;
int item2 = questBattleCounts.totalCount;
num += item;
num2 += item2;
}
return (enabledCount: num, totalCount: num2);
}
private (int enabledCount, int totalCount) GetRoleQuestCounts()
{
int num = 0;
int num2 = 0;
foreach (List<SinglePlayerDutyInfo> value in _roleQuestBattles.Values)
{
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(value);
int item = questBattleCounts.enabledCount;
int item2 = questBattleCounts.totalCount;
num += item;
num2 += item2;
}
(int enabledCount, int totalCount) questBattleCounts2 = GetQuestBattleCounts(_otherRoleQuestBattles);
int item3 = questBattleCounts2.enabledCount;
int item4 = questBattleCounts2.totalCount;
num += item3;
num2 += item4;
return (enabledCount: num, totalCount: num2);
}
private (int enabledCount, int totalCount) GetOtherQuestCounts()
{
int num = 0;
int num2 = 0;
foreach (var otherQuestBattle in _otherQuestBattles)
{
List<SinglePlayerDutyInfo> item = otherQuestBattle.Item2;
(int enabledCount, int totalCount) questBattleCounts = GetQuestBattleCounts(item);
int item2 = questBattleCounts.enabledCount;
int item3 = questBattleCounts.totalCount;
num += item2;
num2 += item3;
}
return (enabledCount: num, totalCount: num2);
}
static SinglePlayerDutyConfigComponent()
{
int num = 5;
List<(EClassJob, string)> list = new List<(EClassJob, string)>(num);
CollectionsMarshal.SetCount(list, num);
Span<(EClassJob, string)> span = CollectionsMarshal.AsSpan(list);
int num2 = 0;
span[num2] = (EClassJob.Paladin, "Tank Role Quests");
num2++;
span[num2] = (EClassJob.WhiteMage, "Healer Role Quests");
num2++;
span[num2] = (EClassJob.Lancer, "Melee Role Quests");
num2++;
span[num2] = (EClassJob.Bard, "Physical Ranged Role Quests");
num2++;
span[num2] = (EClassJob.BlackMage, "Magical Ranged Role Quests");
RoleQuestCategories = list;
}
}