Seasonal event info panel

master v2.11
Liza 2024-08-19 15:19:15 +02:00
parent 57712b1c0c
commit 3ba342aa48
Signed by: liza
GPG Key ID: 7199F8D727D55F67
7 changed files with 160 additions and 3 deletions

View File

@ -18,6 +18,7 @@ internal sealed class Configuration : IPluginConfiguration
public GrandCompany GrandCompany { get; set; } = GrandCompany.None;
public bool HideInAllInstances { get; set; } = true;
public bool UseEscToCancelQuesting { get; set; } = true;
public bool ShowIncompleteSeasonalEvents { get; set; } = true;
}
internal sealed class AdvancedConfiguration

View File

@ -208,6 +208,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
serviceCollection.AddSingleton<ActiveQuestComponent>();
serviceCollection.AddSingleton<ARealmRebornComponent>();
serviceCollection.AddSingleton<CreationUtilsComponent>();
serviceCollection.AddSingleton<EventInfoComponent>();
serviceCollection.AddSingleton<QuestTooltipComponent>();
serviceCollection.AddSingleton<QuickAccessButtonsComponent>();
serviceCollection.AddSingleton<RemainingTasksComponent>();

View File

@ -83,6 +83,13 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
Save();
}
bool showIncompleteSeasonalEvents = _configuration.General.ShowIncompleteSeasonalEvents;
if (ImGui.Checkbox("Show details for incomplete seasonal events", ref showIncompleteSeasonalEvents))
{
_configuration.General.ShowIncompleteSeasonalEvents = showIncompleteSeasonalEvents;
Save();
}
ImGui.EndTabItem();
}

View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Plugin;
using Humanizer;
using Humanizer.Localisation;
using ImGuiNET;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Windows.QuestComponents;
internal sealed class EventInfoComponent
{
private readonly List<EventQuest> _eventQuests =
[
new EventQuest("Moonfire Faire", [new(5182), new(5183)],
new DateTime(new DateOnly(2024, 8, 26), new TimeOnly(14, 59), DateTimeKind.Utc)),
];
private readonly QuestData _questData;
private readonly QuestRegistry _questRegistry;
private readonly QuestFunctions _questFunctions;
private readonly UiUtils _uiUtils;
private readonly QuestController _questController;
private readonly QuestTooltipComponent _questTooltipComponent;
private readonly Configuration _configuration;
private readonly IDalamudPluginInterface _pluginInterface;
public EventInfoComponent(QuestData questData, QuestRegistry questRegistry, QuestFunctions questFunctions,
UiUtils uiUtils, QuestController questController, QuestTooltipComponent questTooltipComponent,
Configuration configuration, IDalamudPluginInterface pluginInterface)
{
_questData = questData;
_questRegistry = questRegistry;
_questFunctions = questFunctions;
_uiUtils = uiUtils;
_questController = questController;
_questTooltipComponent = questTooltipComponent;
_configuration = configuration;
_pluginInterface = pluginInterface;
}
public bool ShouldDraw => _configuration.General.ShowIncompleteSeasonalEvents && _eventQuests.Any(IsIncomplete);
public void Draw()
{
foreach (var eventQuest in _eventQuests)
{
if (IsIncomplete(eventQuest))
DrawEventQuest(eventQuest);
}
}
private void DrawEventQuest(EventQuest eventQuest)
{
string time = (eventQuest.EndsAtUtc - DateTime.UtcNow).Humanize(
precision: 1,
culture: CultureInfo.InvariantCulture,
minUnit: TimeUnit.Minute,
maxUnit: TimeUnit.Day);
ImGui.Text($"{eventQuest.Name} ({time})");
float width;
using (var _ = _pluginInterface.UiBuilder.IconFontHandle.Push())
width = ImGui.CalcTextSize(FontAwesomeIcon.Play.ToIconString()).X + ImGui.GetStyle().FramePadding.X;
using (var _ = _pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
width -= ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X;
List<QuestId> startableQuests = eventQuest.QuestIds.Where(x =>
_questRegistry.IsKnownQuest(x) &&
_questFunctions.IsReadyToAcceptQuest(x) &&
x != _questController.StartedQuest?.Quest.Id &&
x != _questController.NextQuest?.Quest.Id)
.ToList();
if (startableQuests.Count == 0)
width = 0;
foreach (var questId in eventQuest.QuestIds)
{
if (_questFunctions.IsQuestComplete(questId))
continue;
string questName = _questData.GetQuestInfo(questId).Name;
if (startableQuests.Contains(questId) &&
_questRegistry.TryGetQuest(questId, out Quest? quest))
{
ImGuiComponents.IconButton(FontAwesomeIcon.Play);
if (ImGui.IsItemClicked())
{
_questController.SetNextQuest(quest);
_questController.Start("SeasonalEventSelection");
}
bool hovered = ImGui.IsItemHovered();
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGui.Text(questName);
hovered |= ImGui.IsItemHovered();
if (hovered)
_questTooltipComponent.Draw(quest.Info);
}
else
{
if (width > 0)
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + width);
var style = _uiUtils.GetQuestStyle(questId);
if (_uiUtils.ChecklistItem(questName, style.Color, style.Icon, ImGui.GetStyle().FramePadding.X))
_questTooltipComponent.Draw(_questData.GetQuestInfo(questId));
}
}
}
private bool IsIncomplete(EventQuest eventQuest)
{
if (eventQuest.EndsAtUtc <= DateTime.UtcNow)
return false;
return !eventQuest.QuestIds.All(x => _questFunctions.IsQuestComplete(x));
}
private sealed record EventQuest(string Name, List<QuestId> QuestIds, DateTime EndsAtUtc);
}

View File

@ -1,4 +1,5 @@
using Dalamud.Interface;
using Dalamud.Game.Text;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility.Raii;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
@ -44,6 +45,9 @@ internal sealed class QuestTooltipComponent
using var tooltip = ImRaii.Tooltip();
if (tooltip)
{
ImGui.Text($"{SeIconChar.LevelEn.ToIconString()}{quest.Level}");
ImGui.SameLine();
var (color, _, tooltipText) = _uiUtils.GetQuestStyle(quest.QuestId);
ImGui.TextColored(color, tooltipText);
if (quest.IsRepeatable)

View File

@ -25,6 +25,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
private readonly ActiveQuestComponent _activeQuestComponent;
private readonly ARealmRebornComponent _aRealmRebornComponent;
private readonly CreationUtilsComponent _creationUtilsComponent;
private readonly EventInfoComponent _eventInfoComponent;
private readonly QuickAccessButtonsComponent _quickAccessButtonsComponent;
private readonly RemainingTasksComponent _remainingTasksComponent;
private readonly IFramework _framework;
@ -38,6 +39,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
TerritoryData territoryData,
ActiveQuestComponent activeQuestComponent,
ARealmRebornComponent aRealmRebornComponent,
EventInfoComponent eventInfoComponent,
CreationUtilsComponent creationUtilsComponent,
QuickAccessButtonsComponent quickAccessButtonsComponent,
RemainingTasksComponent remainingTasksComponent,
@ -53,6 +55,7 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
_territoryData = territoryData;
_activeQuestComponent = activeQuestComponent;
_aRealmRebornComponent = aRealmRebornComponent;
_eventInfoComponent = eventInfoComponent;
_creationUtilsComponent = creationUtilsComponent;
_quickAccessButtonsComponent = quickAccessButtonsComponent;
_remainingTasksComponent = remainingTasksComponent;
@ -135,6 +138,12 @@ internal sealed class QuestWindow : LWindow, IPersistableWindowConfig
ImGui.Separator();
}
if (_eventInfoComponent.ShouldDraw)
{
_eventInfoComponent.Draw();
ImGui.Separator();
}
_creationUtilsComponent.Draw();
ImGui.Separator();

View File

@ -20,7 +20,7 @@ internal sealed class UiUtils
_pluginInterface = pluginInterface;
}
public (Vector4 color, FontAwesomeIcon icon, string status) GetQuestStyle(ElementId elementId)
public (Vector4 Color, FontAwesomeIcon Icon, string Status) GetQuestStyle(ElementId elementId)
{
if (_questFunctions.IsQuestAccepted(elementId))
return (ImGuiColors.DalamudYellow, FontAwesomeIcon.PersonWalkingArrowRight, "Active");
@ -42,7 +42,7 @@ internal sealed class UiUtils
return (ImGuiColors.DalamudRed, FontAwesomeIcon.Times);
}
public bool ChecklistItem(string text, Vector4 color, FontAwesomeIcon icon)
public bool ChecklistItem(string text, Vector4 color, FontAwesomeIcon icon, float extraPadding = 0)
{
// ReSharper disable once UnusedVariable
using (var font = _pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
@ -53,6 +53,8 @@ internal sealed class UiUtils
bool hover = ImGui.IsItemHovered();
ImGui.SameLine();
if (extraPadding > 0)
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + extraPadding);
ImGui.TextUnformatted(text);
return hover;
}