Merge pull request 'Quest Window Filters' (#122) from Taurenkey/Questionable:filters into master

Reviewed-on: liza/Questionable#122
This commit is contained in:
Liza 2024-12-27 16:49:00 +00:00
commit cad6c30b80
4 changed files with 94 additions and 32 deletions

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Fate;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.Questing; using Questionable.Model.Questing;
@ -9,30 +10,44 @@ namespace Questionable.Data;
internal sealed class JournalData internal sealed class JournalData
{ {
private readonly IDataManager _dataManager;
private readonly QuestData _questData;
public JournalData(IDataManager dataManager, QuestData questData) public JournalData(IDataManager dataManager, QuestData questData)
{ {
var genres = dataManager.GetExcelSheet<JournalGenre>() _dataManager = dataManager;
.Where(x => x.RowId > 0 && x.Icon > 0) _questData = questData;
.Select(x => new Genre(x, questData.GetAllByJournalGenre(x.RowId)))
.ToList();
var limsaStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(1); Reload();
var gridaniaStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(2); }
var uldahStart = dataManager.GetExcelSheet<QuestRedo>().GetRow(3);
public List<Genre> Genres { get; set; }
public List<Category> Categories { get; set; }
public List<Section> Sections { get; set; }
public void Reload()
{
var genres = _dataManager.GetExcelSheet<JournalGenre>()
.Where(x => x.RowId > 0 && x.Icon > 0)
.Select(x => new Genre(x, _questData.GetAllByJournalGenre(x.RowId)))
.ToList();
var limsaStart = _dataManager.GetExcelSheet<QuestRedo>().GetRow(1);
var gridaniaStart = _dataManager.GetExcelSheet<QuestRedo>().GetRow(2);
var uldahStart = _dataManager.GetExcelSheet<QuestRedo>().GetRow(3);
var genreLimsa = new Genre(uint.MaxValue - 3, "Starting in Limsa Lominsa", 1, var genreLimsa = new Genre(uint.MaxValue - 3, "Starting in Limsa Lominsa", 1,
new uint[] { 108, 109 }.Concat(limsaStart.QuestRedoParam.Select(x => x.Quest.RowId)) new uint[] { 108, 109 }.Concat(limsaStart.QuestRedoParam.Select(x => x.Quest.RowId))
.Where(x => x != 0) .Where(x => x != 0)
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF)))) .Select(x => _questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList()); .ToList());
var genreGridania = new Genre(uint.MaxValue - 2, "Starting in Gridania", 1, var genreGridania = new Genre(uint.MaxValue - 2, "Starting in Gridania", 1,
new uint[] { 85, 123, 124 }.Concat(gridaniaStart.QuestRedoParam.Select(x => x.Quest.RowId)) new uint[] { 85, 123, 124 }.Concat(gridaniaStart.QuestRedoParam.Select(x => x.Quest.RowId))
.Where(x => x != 0) .Where(x => x != 0)
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF)))) .Select(x => _questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList()); .ToList());
var genreUldah = new Genre(uint.MaxValue - 1, "Starting in Ul'dah", 1, var genreUldah = new Genre(uint.MaxValue - 1, "Starting in Ul'dah", 1,
new uint[] { 568, 569, 570 }.Concat(uldahStart.QuestRedoParam.Select(x => x.Quest.RowId)) new uint[] { 568, 569, 570 }.Concat(uldahStart.QuestRedoParam.Select(x => x.Quest.RowId))
.Where(x => x != 0) .Where(x => x != 0)
.Select(x => questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF)))) .Select(x => _questData.GetQuestInfo(new QuestId((ushort)(x & 0xFFFF))))
.ToList()); .ToList());
genres.InsertRange(0, [genreLimsa, genreGridania, genreUldah]); genres.InsertRange(0, [genreLimsa, genreGridania, genreUldah]);
genres.Single(x => x.Id == 1) genres.Single(x => x.Id == 1)
@ -40,21 +55,16 @@ internal sealed class JournalData
.RemoveAll(x => .RemoveAll(x =>
genreLimsa.Quests.Contains(x) || genreGridania.Quests.Contains(x) || genreUldah.Quests.Contains(x)); genreLimsa.Quests.Contains(x) || genreGridania.Quests.Contains(x) || genreUldah.Quests.Contains(x));
Genres = genres.AsReadOnly(); Genres = genres.ToList();
Categories = dataManager.GetExcelSheet<JournalCategory>() Categories = _dataManager.GetExcelSheet<JournalCategory>()
.Where(x => x.RowId > 0) .Where(x => x.RowId > 0)
.Select(x => new Category(x, Genres.Where(y => y.CategoryId == x.RowId).ToList())) .Select(x => new Category(x, Genres.Where(y => y.CategoryId == x.RowId).ToList()))
.ToList() .ToList();
.AsReadOnly(); Sections = _dataManager.GetExcelSheet<JournalSection>()
Sections = dataManager.GetExcelSheet<JournalSection>()
.Select(x => new Section(x, Categories.Where(y => y.SectionId == x.RowId).ToList())) .Select(x => new Section(x, Categories.Where(y => y.SectionId == x.RowId).ToList()))
.ToList(); .ToList();
} }
public IReadOnlyList<Genre> Genres { get; }
public IReadOnlyList<Category> Categories { get; }
public List<Section> Sections { get; set; }
internal sealed class Genre internal sealed class Genre
{ {
public Genre(JournalGenre journalGenre, List<IQuestInfo> quests) public Genre(JournalGenre journalGenre, List<IQuestInfo> quests)

View File

@ -455,6 +455,9 @@ internal sealed unsafe class QuestFunctions
if (QuestManager.Instance()->IsDailyQuestCompleted(questId.Value)) if (QuestManager.Instance()->IsDailyQuestCompleted(questId.Value))
return false; return false;
} }
if (IsQuestComplete(questId))
return false;
} }
else else
{ {

View File

@ -1,8 +1,4 @@
using System; using Dalamud.Interface;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Dalamud.Interface;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin; using Dalamud.Plugin;
@ -12,9 +8,12 @@ using Questionable.Controller;
using Questionable.Data; using Questionable.Data;
using Questionable.Functions; using Questionable.Functions;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.Questing;
using Questionable.Validation; using Questionable.Validation;
using Questionable.Windows.QuestComponents; using Questionable.Windows.QuestComponents;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Questionable.Windows.JournalComponents; namespace Questionable.Windows.JournalComponents;
@ -32,13 +31,14 @@ internal sealed class QuestJournalComponent
private readonly IDalamudPluginInterface _pluginInterface; private readonly IDalamudPluginInterface _pluginInterface;
private readonly QuestJournalUtils _questJournalUtils; private readonly QuestJournalUtils _questJournalUtils;
private readonly QuestValidator _questValidator; private readonly QuestValidator _questValidator;
private readonly IPluginLog _log;
private List<FilteredSection> _filteredSections = []; private List<FilteredSection> _filteredSections = [];
private string _searchText = string.Empty; private string _searchText = string.Empty;
public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions, public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions,
UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface,
QuestJournalUtils questJournalUtils, QuestValidator questValidator) QuestJournalUtils questJournalUtils, QuestValidator questValidator, IPluginLog log)
{ {
_journalData = journalData; _journalData = journalData;
_questRegistry = questRegistry; _questRegistry = questRegistry;
@ -48,6 +48,7 @@ internal sealed class QuestJournalComponent
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_questJournalUtils = questJournalUtils; _questJournalUtils = questJournalUtils;
_questValidator = questValidator; _questValidator = questValidator;
_log = log;
} }
public void DrawQuests() public void DrawQuests()
@ -69,6 +70,9 @@ internal sealed class QuestJournalComponent
ImGui.Spacing(); ImGui.Spacing();
} }
QuestJournalUtils.ShowFilterContextMenu(this);
ImGui.SameLine();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
if (ImGui.InputTextWithHint(string.Empty, "Search quests and categories", ref _searchText, 256)) if (ImGui.InputTextWithHint(string.Empty, "Search quests and categories", ref _searchText, 256))
UpdateFilter(); UpdateFilter();
@ -235,17 +239,41 @@ internal sealed class QuestJournalComponent
public void UpdateFilter() public void UpdateFilter()
{ {
Predicate<string> match; _journalData.Reload();
if (string.IsNullOrWhiteSpace(_searchText)) Predicate<string> match = string.IsNullOrWhiteSpace(_searchText) ? x => true : x => x.Contains(_searchText, StringComparison.CurrentCultureIgnoreCase);
match = _ => true;
else
match = x => x.Contains(_searchText, StringComparison.CurrentCultureIgnoreCase);
_filteredSections = _journalData.Sections _filteredSections = _journalData.Sections
.Select(section => FilterSection(section, match)) .Select(section => FilterSection(section, match))
.Where(x => x != null) .Where(x => x != null)
.Cast<FilteredSection>() .Cast<FilteredSection>()
.ToList(); .ToList();
for (int i = 0; i < _filteredSections.Count; i++)
{
var section = _filteredSections[i];
for (int s = 0; s < section.Categories.Count; s++)
{
var category = section.Categories[s];
for (int c = 0; c < category.Genres.Count; c++)
{
var genre = category.Genres[c];
for (int g = 0; g < genre.Quests.Count; g++)
{
var quest = genre.Quests[g];
//All Quest Filter conditions checked here, cause we just love IEnumerable
if (QuestJournalUtils.AvailableOnly && !_questFunctions.IsReadyToAcceptQuest(quest.QuestId) ||
QuestJournalUtils.HideNoPaths && !_questRegistry.TryGetQuest(quest.QuestId, out _))
{
genre.Quests.Remove(quest);
g--;
}
}
}
}
}
RefreshCounts();
} }
private static FilteredSection? FilterSection(JournalData.Section section, Predicate<string> match) private static FilteredSection? FilterSection(JournalData.Section section, Predicate<string> match)

View File

@ -1,10 +1,12 @@
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using ImGuiNET; using ImGuiNET;
using Questionable.Controller; using Questionable.Controller;
using Questionable.Functions; using Questionable.Functions;
using Questionable.Model; using Questionable.Model;
using Questionable.Model.Questing; using Questionable.Model.Questing;
using System;
namespace Questionable.Windows.JournalComponents; namespace Questionable.Windows.JournalComponents;
@ -14,6 +16,9 @@ internal sealed class QuestJournalUtils
private readonly QuestFunctions _questFunctions; private readonly QuestFunctions _questFunctions;
private readonly ICommandManager _commandManager; private readonly ICommandManager _commandManager;
public static bool AvailableOnly;
public static bool HideNoPaths;
public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions, public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions,
ICommandManager commandManager) ICommandManager commandManager)
{ {
@ -44,4 +49,20 @@ internal sealed class QuestJournalUtils
commandInfo!); commandInfo!);
} }
} }
internal static void ShowFilterContextMenu(QuestJournalComponent journalUI)
{
if (ImGuiComponents.IconButton(Dalamud.Interface.FontAwesomeIcon.Filter))
ImGui.OpenPopup($"##QuestFilters");
using var popup = ImRaii.Popup($"##QuestFilters");
if (!popup)
return;
if (ImGui.Checkbox("Show only Available Quests", ref AvailableOnly) ||
ImGui.Checkbox("Hide Quests Without Path", ref HideNoPaths))
journalUI.UpdateFilter();
}
} }