muffin v6.12
This commit is contained in:
parent
060278c1b7
commit
155fbee291
59 changed files with 40083 additions and 58104 deletions
|
@ -6,8 +6,11 @@ using System.Numerics;
|
|||
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.Utility;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Data;
|
||||
using Questionable.Functions;
|
||||
|
@ -42,13 +45,15 @@ internal sealed class QuestJournalComponent
|
|||
|
||||
public bool HideNoPaths;
|
||||
|
||||
public bool HideUnobtainable;
|
||||
|
||||
public bool AdvancedFiltersActive
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!AvailableOnly)
|
||||
if (!AvailableOnly && !HideNoPaths)
|
||||
{
|
||||
return HideNoPaths;
|
||||
return HideUnobtainable;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -59,7 +64,8 @@ internal sealed class QuestJournalComponent
|
|||
return new FilterConfiguration
|
||||
{
|
||||
AvailableOnly = AvailableOnly,
|
||||
HideNoPaths = HideNoPaths
|
||||
HideNoPaths = HideNoPaths,
|
||||
HideUnobtainable = HideUnobtainable
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -86,11 +92,19 @@ internal sealed class QuestJournalComponent
|
|||
|
||||
private readonly QuestValidator _questValidator;
|
||||
|
||||
private readonly Configuration _configuration;
|
||||
|
||||
private readonly ILogger<QuestJournalComponent> _logger;
|
||||
|
||||
private const uint SeasonalJournalCategoryRowId = 96u;
|
||||
|
||||
private List<FilteredSection> _filteredSections = new List<FilteredSection>();
|
||||
|
||||
private bool _lastHideSeasonalGlobally;
|
||||
|
||||
internal FilterConfiguration Filter { get; } = new FilterConfiguration();
|
||||
|
||||
public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface, QuestJournalUtils questJournalUtils, QuestValidator questValidator)
|
||||
public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface, QuestJournalUtils questJournalUtils, QuestValidator questValidator, Configuration configuration, ILogger<QuestJournalComponent> logger)
|
||||
{
|
||||
_journalData = journalData;
|
||||
_questRegistry = questRegistry;
|
||||
|
@ -100,6 +114,9 @@ internal sealed class QuestJournalComponent
|
|||
_pluginInterface = pluginInterface;
|
||||
_questJournalUtils = questJournalUtils;
|
||||
_questValidator = questValidator;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_lastHideSeasonalGlobally = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
||||
}
|
||||
|
||||
public void DrawQuests()
|
||||
|
@ -109,18 +126,34 @@ internal sealed class QuestJournalComponent
|
|||
{
|
||||
return;
|
||||
}
|
||||
bool hideSeasonalEventsFromJournalProgress = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
||||
if (hideSeasonalEventsFromJournalProgress != _lastHideSeasonalGlobally)
|
||||
{
|
||||
_lastHideSeasonalGlobally = hideSeasonalEventsFromJournalProgress;
|
||||
_logger.LogDebug("Configuration change detected: HideSeasonalEventsFromJournalProgress={Hide} - refreshing journal", hideSeasonalEventsFromJournalProgress);
|
||||
UpdateFilter();
|
||||
}
|
||||
if (ImGui.CollapsingHeader("Explanation", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
{
|
||||
ImGui.Text("The list below contains all quests that appear in your journal.");
|
||||
ImGui.BulletText("'Supported' lists quests that Questionable can do for you");
|
||||
ImGui.BulletText("'Completed' lists quests your current character has completed.");
|
||||
ImGui.BulletText("Not all quests can be completed even if they're listed as available, e.g. starting city quest chains.");
|
||||
ImGui.BulletText("Not all quests can be completed even if they're listed as available, e.g. starting city quest chains or past seasonal events.");
|
||||
ImGui.Spacing();
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
}
|
||||
QuestJournalUtils.ShowFilterContextMenu(this);
|
||||
ImGui.SameLine();
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.GlobeEurope))
|
||||
{
|
||||
Util.OpenLink("https://wigglymuffin.github.io/FFXIV-Tools/");
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip("View All Quest Paths Online");
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
if (ImGui.InputTextWithHint(string.Empty, "Search quests and categories", ref Filter.SearchText, 256))
|
||||
{
|
||||
|
@ -270,16 +303,57 @@ internal sealed class QuestJournalComponent
|
|||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, complete: true);
|
||||
}
|
||||
goto IL_0215;
|
||||
goto IL_0210;
|
||||
}
|
||||
}
|
||||
_uiUtils.ChecklistItem(string.Empty, complete: false);
|
||||
}
|
||||
goto IL_0215;
|
||||
IL_0215:
|
||||
goto IL_0210;
|
||||
IL_0210:
|
||||
ImGui.TableNextColumn();
|
||||
var (color, icon, text) = _uiUtils.GetQuestStyle(questInfo.QuestId);
|
||||
_uiUtils.ChecklistItem(text, color, icon);
|
||||
if (_questFunctions.IsQuestComplete(questInfo.QuestId))
|
||||
{
|
||||
if (questInfo.IsRepeatable && _questFunctions.IsReadyToAcceptQuest(questInfo.QuestId))
|
||||
{
|
||||
_uiUtils.ChecklistItem("Complete", ImGuiColors.ParsedBlue, FontAwesomeIcon.Check);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiUtils.ChecklistItem("Complete", ImGuiColors.ParsedGreen, FontAwesomeIcon.Check);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_questFunctions.IsQuestAccepted(questInfo.QuestId))
|
||||
{
|
||||
_uiUtils.ChecklistItem("Active", ImGuiColors.DalamudYellow, FontAwesomeIcon.PersonWalkingArrowRight);
|
||||
return;
|
||||
}
|
||||
bool flag = false;
|
||||
bool flag2 = _questFunctions.IsQuestUnobtainable(questInfo.QuestId);
|
||||
bool flag3 = _questFunctions.IsQuestLocked(questInfo.QuestId);
|
||||
bool flag4 = _questFunctions.IsReadyToAcceptQuest(questInfo.QuestId);
|
||||
DateTime? seasonalQuestExpiry = questInfo.SeasonalQuestExpiry;
|
||||
if (seasonalQuestExpiry.HasValue)
|
||||
{
|
||||
DateTime valueOrDefault = seasonalQuestExpiry.GetValueOrDefault();
|
||||
DateTime dateTime = ((valueOrDefault.Kind == DateTimeKind.Utc) ? valueOrDefault : valueOrDefault.ToUniversalTime());
|
||||
if (DateTime.UtcNow > dateTime)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag || flag2)
|
||||
{
|
||||
_uiUtils.ChecklistItem("Unobtainable", ImGuiColors.DalamudGrey, FontAwesomeIcon.Minus);
|
||||
}
|
||||
else if (flag3 || !flag4 || !_questRegistry.IsKnownQuest(questInfo.QuestId))
|
||||
{
|
||||
_uiUtils.ChecklistItem("Locked", ImGuiColors.DalamudRed, FontAwesomeIcon.Times);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiUtils.ChecklistItem("Available", ImGuiColors.DalamudYellow, FontAwesomeIcon.Running);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawCount(int count, int total)
|
||||
|
@ -321,19 +395,34 @@ internal sealed class QuestJournalComponent
|
|||
|
||||
private FilteredSection FilterSection(JournalData.Section section, FilterConfiguration filter)
|
||||
{
|
||||
IEnumerable<FilteredCategory> source = ((!IsCategorySectionGenreMatch(filter, section.Name)) ? section.Categories.Select((JournalData.Category category) => FilterCategory(category, filter)) : section.Categories.Select((JournalData.Category x) => FilterCategory(x, filter.WithoutName())));
|
||||
return new FilteredSection(section, source.Where((FilteredCategory x) => x.Genres.Count > 0).ToList());
|
||||
IEnumerable<JournalData.Category> enumerable;
|
||||
if (!_configuration.General.HideSeasonalEventsFromJournalProgress)
|
||||
{
|
||||
IEnumerable<JournalData.Category> categories = section.Categories;
|
||||
enumerable = categories;
|
||||
}
|
||||
else
|
||||
{
|
||||
enumerable = section.Categories.Where((JournalData.Category c) => c.Id != 96);
|
||||
}
|
||||
IEnumerable<JournalData.Category> source = enumerable;
|
||||
return new FilteredSection(Categories: ((!IsCategorySectionGenreMatch(filter, section.Name)) ? source.Select((JournalData.Category category) => FilterCategory(category, filter, section)) : source.Select((JournalData.Category x) => FilterCategory(x, filter.WithoutName(), section))).Where((FilteredCategory x) => x.Genres.Count > 0).ToList(), Section: section);
|
||||
}
|
||||
|
||||
private FilteredCategory FilterCategory(JournalData.Category category, FilterConfiguration filter)
|
||||
private FilteredCategory FilterCategory(JournalData.Category category, FilterConfiguration filter, JournalData.Section? parentSection = null)
|
||||
{
|
||||
IEnumerable<FilteredGenre> source = ((!IsCategorySectionGenreMatch(filter, category.Name)) ? category.Genres.Select((JournalData.Genre genre) => FilterGenre(genre, filter)) : category.Genres.Select((JournalData.Genre x) => FilterGenre(x, filter.WithoutName())));
|
||||
IEnumerable<FilteredGenre> source = ((!IsCategorySectionGenreMatch(filter, category.Name)) ? category.Genres.Select((JournalData.Genre genre) => FilterGenre(genre, filter, parentSection)) : category.Genres.Select((JournalData.Genre x) => FilterGenre(x, filter.WithoutName(), parentSection)));
|
||||
return new FilteredCategory(category, source.Where((FilteredGenre x) => x.Quests.Count > 0).ToList());
|
||||
}
|
||||
|
||||
private FilteredGenre FilterGenre(JournalData.Genre genre, FilterConfiguration filter)
|
||||
private FilteredGenre FilterGenre(JournalData.Genre genre, FilterConfiguration filter, JournalData.Section? parentSection = null)
|
||||
{
|
||||
bool hideSeasonalEventsFromJournalProgress = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
||||
IEnumerable<IQuestInfo> source = ((!IsCategorySectionGenreMatch(filter, genre.Name)) ? genre.Quests.Where((IQuestInfo x) => IsQuestMatch(filter, x)) : genre.Quests.Where((IQuestInfo x) => IsQuestMatch(filter.WithoutName(), x)));
|
||||
if (hideSeasonalEventsFromJournalProgress && genre.CategoryId == 96)
|
||||
{
|
||||
source = source.Where((IQuestInfo q) => !IsSeasonal(q));
|
||||
}
|
||||
return new FilteredGenre(genre, source.ToList());
|
||||
}
|
||||
|
||||
|
@ -342,37 +431,50 @@ internal sealed class QuestJournalComponent
|
|||
_genreCounts.Clear();
|
||||
_categoryCounts.Clear();
|
||||
_sectionCounts.Clear();
|
||||
bool hideSeasonalEventsFromJournalProgress = _configuration.General.HideSeasonalEventsFromJournalProgress;
|
||||
_logger.LogInformation("Refreshing journal counts. HideSeasonalEventsFromJournalProgress={Hide}", hideSeasonalEventsFromJournalProgress);
|
||||
foreach (JournalData.Genre genre in _journalData.Genres)
|
||||
{
|
||||
List<IQuestInfo> source = ((hideSeasonalEventsFromJournalProgress && genre.CategoryId == 96) ? genre.Quests.Where((IQuestInfo q) => !IsSeasonal(q)).ToList() : genre.Quests.ToList());
|
||||
Quest quest;
|
||||
int available = genre.Quests.Count((IQuestInfo x) => _questRegistry.TryGetQuest(x.QuestId, out quest) && !quest.Root.Disabled && !_questFunctions.IsQuestRemoved(x.QuestId));
|
||||
int total = genre.Quests.Count((IQuestInfo x) => !_questFunctions.IsQuestRemoved(x.QuestId));
|
||||
int obtainable = genre.Quests.Count((IQuestInfo x) => !_questFunctions.IsQuestUnobtainable(x.QuestId));
|
||||
int completed = genre.Quests.Count((IQuestInfo x) => _questFunctions.IsQuestComplete(x.QuestId));
|
||||
int available = source.Count((IQuestInfo x) => _questRegistry.TryGetQuest(x.QuestId, out quest) && !quest.Root.Disabled && !_questFunctions.IsQuestRemoved(x.QuestId));
|
||||
int total = source.Count((IQuestInfo x) => !_questFunctions.IsQuestRemoved(x.QuestId));
|
||||
int obtainable = source.Count((IQuestInfo x) => !_questFunctions.IsQuestUnobtainable(x.QuestId));
|
||||
int completed = source.Count((IQuestInfo x) => _questFunctions.IsQuestComplete(x.QuestId));
|
||||
_genreCounts[genre] = new JournalCounts(available, total, obtainable, completed);
|
||||
}
|
||||
foreach (JournalData.Category category in _journalData.Categories)
|
||||
{
|
||||
List<JournalCounts> source = (from x in _genreCounts
|
||||
where category.Genres.Contains(x.Key)
|
||||
select x.Value).ToList();
|
||||
int available2 = source.Sum((JournalCounts x) => x.Available);
|
||||
int total2 = source.Sum((JournalCounts x) => x.Total);
|
||||
int obtainable2 = source.Sum((JournalCounts x) => x.Obtainable);
|
||||
int completed2 = source.Sum((JournalCounts x) => x.Completed);
|
||||
_categoryCounts[category] = new JournalCounts(available2, total2, obtainable2, completed2);
|
||||
if (!hideSeasonalEventsFromJournalProgress || category.Id != 96)
|
||||
{
|
||||
List<JournalCounts> source2 = _genre_counts_or_default(category);
|
||||
int available2 = source2.Sum((JournalCounts x) => x.Available);
|
||||
int total2 = source2.Sum((JournalCounts x) => x.Total);
|
||||
int obtainable2 = source2.Sum((JournalCounts x) => x.Obtainable);
|
||||
int completed2 = source2.Sum((JournalCounts x) => x.Completed);
|
||||
_categoryCounts[category] = new JournalCounts(available2, total2, obtainable2, completed2);
|
||||
}
|
||||
}
|
||||
foreach (JournalData.Section section in _journalData.Sections)
|
||||
{
|
||||
List<JournalCounts> source2 = (from x in _categoryCounts
|
||||
List<JournalCounts> source3 = (from x in _categoryCounts
|
||||
where section.Categories.Contains(x.Key)
|
||||
select x.Value).ToList();
|
||||
int available3 = source2.Sum((JournalCounts x) => x.Available);
|
||||
int total3 = source2.Sum((JournalCounts x) => x.Total);
|
||||
int obtainable3 = source2.Sum((JournalCounts x) => x.Obtainable);
|
||||
int completed3 = source2.Sum((JournalCounts x) => x.Completed);
|
||||
int available3 = source3.Sum((JournalCounts x) => x.Available);
|
||||
int total3 = source3.Sum((JournalCounts x) => x.Total);
|
||||
int obtainable3 = source3.Sum((JournalCounts x) => x.Obtainable);
|
||||
int completed3 = source3.Sum((JournalCounts x) => x.Completed);
|
||||
_sectionCounts[section] = new JournalCounts(available3, total3, obtainable3, completed3);
|
||||
}
|
||||
int num = _sectionCounts.Values.Sum((JournalCounts x) => x.Total);
|
||||
_logger.LogDebug("RefreshCounts complete. Sections={Sections}, Categories={Categories}, Genres={Genres}, TotalQuests={Total}", _sectionCounts.Count, _categoryCounts.Count, _genreCounts.Count, num);
|
||||
}
|
||||
|
||||
private List<JournalCounts> _genre_counts_or_default(JournalData.Category category)
|
||||
{
|
||||
return (from x in _genreCounts
|
||||
where category.Genres.Contains(x.Key)
|
||||
select x.Value).ToList();
|
||||
}
|
||||
|
||||
internal void ClearCounts(int type, int code)
|
||||
|
@ -423,6 +525,31 @@ internal sealed class QuestJournalComponent
|
|||
{
|
||||
return false;
|
||||
}
|
||||
if (filter.HideUnobtainable && _questFunctions.IsQuestUnobtainable(questInfo.QuestId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsSeasonal(IQuestInfo q)
|
||||
{
|
||||
if (q == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (q.IsSeasonalQuest)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (q.SeasonalQuestExpiry.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (q is UnlockLinkQuestInfo { QuestExpiry: not null })
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,12 +43,28 @@ internal sealed class QuestJournalUtils
|
|||
{
|
||||
return;
|
||||
}
|
||||
using (ImRaii.Disabled(!_questFunctions.IsReadyToAcceptQuest(questInfo.QuestId)))
|
||||
using (ImRaii.Disabled(quest == null || (!_questFunctions.IsReadyToAcceptQuest(questInfo.QuestId) && !_questFunctions.IsQuestAccepted(questInfo.QuestId))))
|
||||
{
|
||||
if (ImGui.MenuItem("Start as next quest"))
|
||||
{
|
||||
_questController.SetNextQuest(quest);
|
||||
_questController.Start(label);
|
||||
if (quest == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_questFunctions.IsQuestAccepted(questInfo.QuestId))
|
||||
{
|
||||
QuestProgressInfo questProgressInfo = _questFunctions.GetQuestProgressInfo(questInfo.QuestId);
|
||||
if (questProgressInfo != null)
|
||||
{
|
||||
_questController.SetStartedQuest(quest, questProgressInfo.Sequence);
|
||||
_questController.Start(label);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_questController.SetNextQuest(quest);
|
||||
_questController.Start(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool flag = _commandManager.Commands.ContainsKey("/questinfo");
|
||||
|
@ -68,7 +84,7 @@ internal sealed class QuestJournalUtils
|
|||
ImGui.OpenPopup("##QuestFilters");
|
||||
}
|
||||
using ImRaii.IEndObject endObject = ImRaii.Popup("##QuestFilters");
|
||||
if (!(!endObject) && (ImGui.Checkbox("Show only Available Quests", ref journalUi.Filter.AvailableOnly) || ImGui.Checkbox("Hide Quests Without Path", ref journalUi.Filter.HideNoPaths)))
|
||||
if (!(!endObject) && (ImGui.Checkbox("Show only Available Quests", ref journalUi.Filter.AvailableOnly) || ImGui.Checkbox("Hide Quests Without Path", ref journalUi.Filter.HideNoPaths) || ImGui.Checkbox("Hide Unobtainable Quests", ref journalUi.Filter.HideUnobtainable)))
|
||||
{
|
||||
journalUi.UpdateFilter();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue