punish v6.8.18.0
This commit is contained in:
commit
cfb4dea47e
316 changed files with 554088 additions and 0 deletions
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Data;
|
||||
using Questionable.Functions;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
using Questionable.Windows.QuestComponents;
|
||||
|
||||
namespace Questionable.Windows.JournalComponents;
|
||||
|
||||
internal sealed class AlliedSocietyJournalComponent
|
||||
{
|
||||
private static readonly string[] RankNames = new string[8] { "Neutral", "Recognized", "Friendly", "Trusted", "Respected", "Honored", "Sworn", "Allied" };
|
||||
|
||||
private readonly AlliedSocietyQuestFunctions _alliedSocietyQuestFunctions;
|
||||
|
||||
private readonly QuestData _questData;
|
||||
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly QuestJournalUtils _questJournalUtils;
|
||||
|
||||
private readonly QuestTooltipComponent _questTooltipComponent;
|
||||
|
||||
private readonly UiUtils _uiUtils;
|
||||
|
||||
public AlliedSocietyJournalComponent(AlliedSocietyQuestFunctions alliedSocietyQuestFunctions, QuestData questData, QuestRegistry questRegistry, QuestJournalUtils questJournalUtils, QuestTooltipComponent questTooltipComponent, UiUtils uiUtils)
|
||||
{
|
||||
_alliedSocietyQuestFunctions = alliedSocietyQuestFunctions;
|
||||
_questData = questData;
|
||||
_questRegistry = questRegistry;
|
||||
_questJournalUtils = questJournalUtils;
|
||||
_questTooltipComponent = questTooltipComponent;
|
||||
_uiUtils = uiUtils;
|
||||
}
|
||||
|
||||
public void DrawAlliedSocietyQuests()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabItem("Allied Societies");
|
||||
if (!endObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (EAlliedSociety item in from x in Enum.GetValues<EAlliedSociety>()
|
||||
where x != EAlliedSociety.None
|
||||
select x)
|
||||
{
|
||||
List<QuestInfo> list = (from x in _alliedSocietyQuestFunctions.GetAvailableAlliedSocietyQuests(item)
|
||||
select (QuestInfo)_questData.GetQuestInfo(x)).ToList();
|
||||
if (list.Count == 0 || !ImGui.CollapsingHeader($"{item}###AlliedSociety{item}"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((int)item <= 5)
|
||||
{
|
||||
byte i = 1;
|
||||
while (i <= 8)
|
||||
{
|
||||
List<QuestInfo> list2 = list.Where((QuestInfo x) => x.AlliedSocietyRank == i).ToList();
|
||||
if (list2.Count != 0)
|
||||
{
|
||||
ImGui.Text(RankNames[i - 1]);
|
||||
foreach (QuestInfo item2 in list2)
|
||||
{
|
||||
DrawQuest(item2);
|
||||
}
|
||||
}
|
||||
byte b = (byte)(i + 1);
|
||||
i = b;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
foreach (QuestInfo item3 in list)
|
||||
{
|
||||
DrawQuest(item3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawQuest(QuestInfo questInfo)
|
||||
{
|
||||
var (color, icon, text) = _uiUtils.GetQuestStyle(questInfo.QuestId);
|
||||
if (!_questRegistry.TryGetQuest(questInfo.QuestId, out Quest quest) || quest.Root.Disabled)
|
||||
{
|
||||
color = ImGuiColors.DalamudGrey;
|
||||
}
|
||||
if (_uiUtils.ChecklistItem(questInfo.Name + " (" + text + ")", color, icon))
|
||||
{
|
||||
_questTooltipComponent.Draw(questInfo);
|
||||
}
|
||||
_questJournalUtils.ShowContextMenu(questInfo, quest, "AlliedSocietyJournalComponent");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,462 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using LLib.GameData;
|
||||
using Lumina.Excel;
|
||||
using Lumina.Excel.Sheets;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Gathering;
|
||||
|
||||
namespace Questionable.Windows.JournalComponents;
|
||||
|
||||
internal sealed class GatheringJournalComponent
|
||||
{
|
||||
private delegate byte GetIsGatheringItemGatheredDelegate(ushort item);
|
||||
|
||||
private sealed record ExpansionPoints(EExpansionVersion ExpansionVersion, List<TerritoryPoints> PointsByTerritories)
|
||||
{
|
||||
public int TotalItems { get; set; }
|
||||
|
||||
public int TotalPoints { get; set; }
|
||||
|
||||
public int CompletedItems { get; set; }
|
||||
|
||||
public int CompletedPoints { get; set; }
|
||||
}
|
||||
|
||||
private sealed record TerritoryPoints(ushort TerritoryType, string TerritoryName, List<DefaultGatheringPoint> Points)
|
||||
{
|
||||
public int TotalItems { get; set; }
|
||||
|
||||
public int TotalPoints => Points.Count;
|
||||
|
||||
public int CompletedItems { get; set; }
|
||||
|
||||
public int CompletedPoints { get; set; }
|
||||
|
||||
public string ToFriendlyString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(TerritoryName))
|
||||
{
|
||||
return $"??? ({TerritoryType})";
|
||||
}
|
||||
return TerritoryName;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record DefaultGatheringPoint(GatheringPointId Id, EClassJob ClassJob, byte Level, List<ushort> GatheringItemIds, EExpansionVersion Expansion, ushort TerritoryType, string? TerritoryName, string? PlaceName)
|
||||
{
|
||||
public int TotalItems { get; set; }
|
||||
|
||||
public int CompletedItems { get; set; }
|
||||
|
||||
public bool IsComplete { get; set; }
|
||||
}
|
||||
|
||||
private sealed record FilteredExpansion(ExpansionPoints Expansion, List<FilteredTerritory> Territories);
|
||||
|
||||
private sealed record FilteredTerritory(TerritoryPoints Territory, List<FilteredGatheringPoint> GatheringPoints);
|
||||
|
||||
private sealed record FilteredGatheringPoint(DefaultGatheringPoint Point, List<ushort> GatheringItemIds);
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private readonly UiUtils _uiUtils;
|
||||
|
||||
private readonly GatheringPointRegistry _gatheringPointRegistry;
|
||||
|
||||
private readonly Dictionary<int, string> _gatheringItems;
|
||||
|
||||
private readonly List<ExpansionPoints> _gatheringPointsByExpansion;
|
||||
|
||||
private readonly List<ushort> _gatheredItems = new List<ushort>();
|
||||
|
||||
private List<FilteredExpansion> _filteredExpansions = new List<FilteredExpansion>();
|
||||
|
||||
private string _searchText = string.Empty;
|
||||
|
||||
[Signature("48 89 5C 24 ?? 57 48 83 EC 20 8B D9 8B F9")]
|
||||
private GetIsGatheringItemGatheredDelegate _getIsGatheringItemGathered;
|
||||
|
||||
private bool IsGatheringItemGathered(uint item)
|
||||
{
|
||||
return _getIsGatheringItemGathered((ushort)item) != 0;
|
||||
}
|
||||
|
||||
public GatheringJournalComponent(IDataManager dataManager, IDalamudPluginInterface pluginInterface, UiUtils uiUtils, IGameInteropProvider gameInteropProvider, GatheringPointRegistry gatheringPointRegistry)
|
||||
{
|
||||
GatheringJournalComponent gatheringJournalComponent = this;
|
||||
_pluginInterface = pluginInterface;
|
||||
_uiUtils = uiUtils;
|
||||
_gatheringPointRegistry = gatheringPointRegistry;
|
||||
Dictionary<uint, List<uint>> routeToGatheringPoint = (from x in (from x in dataManager.GetExcelSheet<GatheringLeveRoute>()
|
||||
where x.GatheringPoint[0].RowId != 0
|
||||
select x).SelectMany((GatheringLeveRoute x) => from y in x.GatheringPoint
|
||||
where y.RowId != 0
|
||||
select new
|
||||
{
|
||||
RouteId = x.RowId,
|
||||
GatheringPointId = y.RowId
|
||||
})
|
||||
group x by x.RouteId).ToDictionary(x => x.Key, x => x.Select(y => y.GatheringPointId).ToList());
|
||||
ExcelSheet<GatheringLeve> gatheringLeveSheet = dataManager.GetExcelSheet<GatheringLeve>();
|
||||
ExcelSheet<TerritoryType> territoryTypeSheet = dataManager.GetExcelSheet<TerritoryType>();
|
||||
HashSet<uint> leveGatheringPoints = (from y in (from x in dataManager.GetExcelSheet<Leve>()
|
||||
where x.RowId != 0
|
||||
select gatheringLeveSheet.GetRowOrDefault(x.DataId.RowId) into x
|
||||
where x.HasValue
|
||||
select x).Cast<GatheringLeve>().SelectMany((GatheringLeve x) => x.Route)
|
||||
where y.RowId != 0
|
||||
select y).SelectMany((RowRef<GatheringLeveRoute> y) => routeToGatheringPoint[y.RowId]).Distinct().ToHashSet();
|
||||
ExcelSheet<Item> itemSheet = dataManager.GetExcelSheet<Item>();
|
||||
_gatheringItems = (from x in dataManager.GetExcelSheet<GatheringItem>()
|
||||
where x.RowId != 0 && x.GatheringItemLevel.RowId != 0
|
||||
select new
|
||||
{
|
||||
GatheringItemId = (int)x.RowId,
|
||||
Name = itemSheet.GetRowOrDefault(x.Item.RowId)?.Name.ToString()
|
||||
} into x
|
||||
where !string.IsNullOrEmpty(x.Name)
|
||||
select x).ToDictionary(x => x.GatheringItemId, x => x.Name);
|
||||
_gatheringPointsByExpansion = (from x in (from DefaultGatheringPoint x in from x in (from x in (from x in dataManager.GetExcelSheet<GatheringPoint>()
|
||||
where x.GatheringPointBase.RowId != 0
|
||||
select x).Where(delegate(GatheringPoint x)
|
||||
{
|
||||
uint rowId = x.GatheringPointBase.RowId;
|
||||
return (rowId < 653 || rowId > 680) ? true : false;
|
||||
}).DistinctBy((GatheringPoint x) => x.GatheringPointBase.RowId).Select(delegate(GatheringPoint x)
|
||||
{
|
||||
uint rowId = x.RowId;
|
||||
GatheringPointId id = new GatheringPointId((ushort)x.GatheringPointBase.RowId);
|
||||
EClassJob classJob;
|
||||
switch (x.GatheringPointBase.Value.GatheringType.RowId)
|
||||
{
|
||||
case 0u:
|
||||
case 1u:
|
||||
classJob = EClassJob.Miner;
|
||||
break;
|
||||
case 2u:
|
||||
case 3u:
|
||||
classJob = EClassJob.Botanist;
|
||||
break;
|
||||
default:
|
||||
classJob = EClassJob.Fisher;
|
||||
break;
|
||||
}
|
||||
return new
|
||||
{
|
||||
GatheringPointId = rowId,
|
||||
Point = new DefaultGatheringPoint(id, classJob, x.GatheringPointBase.Value.GatheringLevel, (from y in x.GatheringPointBase.Value.Item
|
||||
where y.RowId != 0
|
||||
select (ushort)y.RowId).ToList(), (EExpansionVersion)(((byte?)x.TerritoryType.ValueNullable?.ExVersion.RowId) ?? byte.MaxValue), (ushort)x.TerritoryType.RowId, x.TerritoryType.ValueNullable?.PlaceName.ValueNullable?.Name.ToString(), $"{x.GatheringPointBase.RowId} - {x.PlaceName.ValueNullable?.Name}")
|
||||
};
|
||||
})
|
||||
where x.Point.ClassJob != EClassJob.Fisher
|
||||
select x).Select(x =>
|
||||
{
|
||||
if (leveGatheringPoints.Contains(x.GatheringPointId))
|
||||
{
|
||||
return (DefaultGatheringPoint)null;
|
||||
}
|
||||
if (x.Point.TerritoryType == 1 && gatheringJournalComponent._gatheringPointRegistry.TryGetGatheringPoint(x.Point.Id, out GatheringRoot gatheringRoot))
|
||||
{
|
||||
TerritoryType row = territoryTypeSheet.GetRow(gatheringRoot.Steps.Last().TerritoryId);
|
||||
return x.Point with
|
||||
{
|
||||
Expansion = (EExpansionVersion)row.ExVersion.RowId,
|
||||
TerritoryType = (ushort)row.RowId,
|
||||
TerritoryName = row.PlaceName.ValueNullable?.Name.ToString()
|
||||
};
|
||||
}
|
||||
return x.Point;
|
||||
})
|
||||
where x != null
|
||||
select x
|
||||
where x.Expansion != (EExpansionVersion)255
|
||||
where x.GatheringItemIds.Count > 0
|
||||
select x).Where(delegate(DefaultGatheringPoint x)
|
||||
{
|
||||
ushort territoryType = x.TerritoryType;
|
||||
return territoryType != 901 && territoryType != 929;
|
||||
})
|
||||
group x by x.Expansion into x
|
||||
select new ExpansionPoints(x.Key, (from y in x
|
||||
group y by new
|
||||
{
|
||||
TerritoryType = y.TerritoryType,
|
||||
TerritoryName = $"{((!string.IsNullOrEmpty(y.TerritoryName)) ? y.TerritoryName : "???")} ({y.TerritoryType})"
|
||||
} into y
|
||||
select new TerritoryPoints(y.Key.TerritoryType, y.Key.TerritoryName, y.ToList()) into y
|
||||
where y.Points.Count > 0
|
||||
select y).ToList()) into x
|
||||
orderby x.ExpansionVersion
|
||||
select x).ToList();
|
||||
gameInteropProvider.InitializeFromAttributes(this);
|
||||
}
|
||||
|
||||
public void DrawGatheringItems()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabItem("Gathering Points");
|
||||
if (!endObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
if (ImGui.InputTextWithHint(string.Empty, "Search areas, gathering points and items", ref _searchText, 256))
|
||||
{
|
||||
UpdateFilter();
|
||||
}
|
||||
if (_filteredExpansions.Count > 0)
|
||||
{
|
||||
using (ImRaii.IEndObject endObject2 = ImRaii.Table("GatheringPoints", 3, ImGuiTableFlags.NoSavedSettings))
|
||||
{
|
||||
if (!endObject2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.NoHide);
|
||||
ImGui.TableSetupColumn("Supported", ImGuiTableColumnFlags.WidthFixed, 100f * ImGui.GetIO().FontGlobalScale);
|
||||
ImGui.TableSetupColumn("Collected", ImGuiTableColumnFlags.WidthFixed, 100f * ImGui.GetIO().FontGlobalScale);
|
||||
ImGui.TableHeadersRow();
|
||||
foreach (FilteredExpansion filteredExpansion in _filteredExpansions)
|
||||
{
|
||||
DrawExpansion(filteredExpansion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
ImGui.Text("No area, gathering point or item matches your search text.");
|
||||
}
|
||||
|
||||
private void DrawExpansion(FilteredExpansion expansion)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
bool num = ImGui.TreeNodeEx(expansion.Expansion.ExpansionVersion.ToFriendlyString(), ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(expansion.Expansion.CompletedPoints, expansion.Expansion.TotalPoints);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(expansion.Expansion.CompletedItems, expansion.Expansion.TotalItems);
|
||||
if (!num)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (FilteredTerritory territory in expansion.Territories)
|
||||
{
|
||||
DrawTerritory(territory);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawTerritory(FilteredTerritory territory)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
bool num = ImGui.TreeNodeEx(territory.Territory.ToFriendlyString(), ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(territory.Territory.CompletedPoints, territory.Territory.TotalPoints);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(territory.Territory.CompletedItems, territory.Territory.TotalItems);
|
||||
if (!num)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (FilteredGatheringPoint gatheringPoint in territory.GatheringPoints)
|
||||
{
|
||||
DrawPoint(gatheringPoint);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawPoint(FilteredGatheringPoint point)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImU8String id = new ImU8String(8, 3);
|
||||
id.AppendFormatted(point.Point.PlaceName);
|
||||
id.AppendLiteral(" (");
|
||||
id.AppendFormatted(point.Point.ClassJob);
|
||||
id.AppendLiteral(" Lv. ");
|
||||
id.AppendFormatted(point.Point.Level);
|
||||
id.AppendLiteral(")");
|
||||
bool flag = ImGui.TreeNodeEx(id, ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
float num;
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
num = ImGui.GetColumnWidth() / 2f - ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X;
|
||||
}
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + num);
|
||||
_uiUtils.ChecklistItem(string.Empty, point.Point.IsComplete);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(point.Point.CompletedItems, point.Point.TotalItems);
|
||||
if (!flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (ushort gatheringItemId in point.GatheringItemIds)
|
||||
{
|
||||
DrawItem(gatheringItemId);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawItem(ushort item)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TreeNodeEx(_gatheringItems.GetValueOrDefault(item, "???"), ImGuiTreeNodeFlags.NoTreePushOnOpen | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
float num;
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
num = ImGui.GetColumnWidth() / 2f - ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X;
|
||||
}
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + num);
|
||||
if (item < 10000)
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, _gatheredItems.Contains(item));
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, ImGuiColors.DalamudGrey, FontAwesomeIcon.Minus);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawCount(int count, int total)
|
||||
{
|
||||
string text = 999.ToString(CultureInfo.CurrentCulture);
|
||||
ImGui.PushFont(UiBuilder.MonoFont);
|
||||
string text2 = count.ToString(CultureInfo.CurrentCulture).PadLeft(text.Length) + " / " + total.ToString(CultureInfo.CurrentCulture).PadLeft(text.Length);
|
||||
if (count == total)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.ParsedGreen, text2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted(text2);
|
||||
}
|
||||
ImGui.PopFont();
|
||||
}
|
||||
|
||||
public void UpdateFilter()
|
||||
{
|
||||
Predicate<string> match;
|
||||
if (string.IsNullOrWhiteSpace(_searchText))
|
||||
{
|
||||
match = (string _) => true;
|
||||
}
|
||||
else
|
||||
{
|
||||
match = (string x) => x.Contains(_searchText, StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
_filteredExpansions = (from section in _gatheringPointsByExpansion
|
||||
select FilterExpansion(section, match) into x
|
||||
where x != null
|
||||
select x).Cast<FilteredExpansion>().ToList();
|
||||
}
|
||||
|
||||
private FilteredExpansion? FilterExpansion(ExpansionPoints expansion, Predicate<string> match)
|
||||
{
|
||||
List<FilteredTerritory> list = (from x in expansion.PointsByTerritories
|
||||
select FilterTerritory(x, match) into x
|
||||
where x != null
|
||||
select (x)).ToList();
|
||||
if (list.Count > 0)
|
||||
{
|
||||
return new FilteredExpansion(expansion, list);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private FilteredTerritory? FilterTerritory(TerritoryPoints territory, Predicate<string> match)
|
||||
{
|
||||
if (match(territory.TerritoryName))
|
||||
{
|
||||
return new FilteredTerritory(territory, territory.Points.Select((DefaultGatheringPoint x) => FilterGatheringPoint(x, (string _) => true)).ToList());
|
||||
}
|
||||
List<FilteredGatheringPoint> list = (from x in territory.Points
|
||||
select FilterGatheringPoint(x, match) into x
|
||||
where x != null
|
||||
select (x)).ToList();
|
||||
if (list.Count > 0)
|
||||
{
|
||||
return new FilteredTerritory(territory, list);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private FilteredGatheringPoint? FilterGatheringPoint(DefaultGatheringPoint gatheringPoint, Predicate<string> match)
|
||||
{
|
||||
if (match(gatheringPoint.PlaceName ?? string.Empty))
|
||||
{
|
||||
return new FilteredGatheringPoint(gatheringPoint, gatheringPoint.GatheringItemIds);
|
||||
}
|
||||
List<ushort> list = gatheringPoint.GatheringItemIds.Where((ushort x) => match(_gatheringItems.GetValueOrDefault(x, string.Empty))).ToList();
|
||||
if (list.Count > 0)
|
||||
{
|
||||
return new FilteredGatheringPoint(gatheringPoint, list);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal void RefreshCounts()
|
||||
{
|
||||
_gatheredItems.Clear();
|
||||
foreach (int key in _gatheringItems.Keys)
|
||||
{
|
||||
ushort item = (ushort)key;
|
||||
if (IsGatheringItemGathered(item))
|
||||
{
|
||||
_gatheredItems.Add(item);
|
||||
}
|
||||
}
|
||||
foreach (ExpansionPoints item2 in _gatheringPointsByExpansion)
|
||||
{
|
||||
foreach (TerritoryPoints pointsByTerritory in item2.PointsByTerritories)
|
||||
{
|
||||
foreach (DefaultGatheringPoint point in pointsByTerritory.Points)
|
||||
{
|
||||
point.TotalItems = point.GatheringItemIds.Count((ushort x) => x < 10000);
|
||||
point.CompletedItems = point.GatheringItemIds.Count(_gatheredItems.Contains);
|
||||
point.IsComplete = _gatheringPointRegistry.TryGetGatheringPoint(point.Id, out GatheringRoot _);
|
||||
}
|
||||
pointsByTerritory.TotalItems = pointsByTerritory.Points.Sum((DefaultGatheringPoint x) => x.TotalItems);
|
||||
pointsByTerritory.CompletedItems = pointsByTerritory.Points.Sum((DefaultGatheringPoint x) => x.CompletedItems);
|
||||
pointsByTerritory.CompletedPoints = pointsByTerritory.Points.Count((DefaultGatheringPoint x) => x.IsComplete);
|
||||
}
|
||||
item2.TotalItems = item2.PointsByTerritories.Sum((TerritoryPoints x) => x.TotalItems);
|
||||
item2.CompletedItems = item2.PointsByTerritories.Sum((TerritoryPoints x) => x.CompletedItems);
|
||||
item2.TotalPoints = item2.PointsByTerritories.Sum((TerritoryPoints x) => x.TotalPoints);
|
||||
item2.CompletedPoints = item2.PointsByTerritories.Sum((TerritoryPoints x) => x.CompletedPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCounts(int type, int code)
|
||||
{
|
||||
foreach (ExpansionPoints item in _gatheringPointsByExpansion)
|
||||
{
|
||||
item.CompletedItems = 0;
|
||||
item.CompletedPoints = 0;
|
||||
foreach (TerritoryPoints pointsByTerritory in item.PointsByTerritories)
|
||||
{
|
||||
pointsByTerritory.CompletedItems = 0;
|
||||
pointsByTerritory.CompletedPoints = 0;
|
||||
foreach (DefaultGatheringPoint point in pointsByTerritory.Points)
|
||||
{
|
||||
point.IsComplete = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,428 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Plugin;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Data;
|
||||
using Questionable.Functions;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
using Questionable.Validation;
|
||||
using Questionable.Windows.QuestComponents;
|
||||
|
||||
namespace Questionable.Windows.JournalComponents;
|
||||
|
||||
internal sealed class QuestJournalComponent
|
||||
{
|
||||
private sealed record FilteredSection(JournalData.Section Section, List<FilteredCategory> Categories);
|
||||
|
||||
private sealed record FilteredCategory(JournalData.Category Category, List<FilteredGenre> Genres);
|
||||
|
||||
private sealed record FilteredGenre(JournalData.Genre Genre, List<IQuestInfo> Quests);
|
||||
|
||||
private sealed record JournalCounts(int Available, int Total, int Obtainable, int Completed)
|
||||
{
|
||||
public JournalCounts()
|
||||
: this(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class FilterConfiguration
|
||||
{
|
||||
public string SearchText = string.Empty;
|
||||
|
||||
public bool AvailableOnly;
|
||||
|
||||
public bool HideNoPaths;
|
||||
|
||||
public bool AdvancedFiltersActive
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!AvailableOnly)
|
||||
{
|
||||
return HideNoPaths;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public FilterConfiguration WithoutName()
|
||||
{
|
||||
return new FilterConfiguration
|
||||
{
|
||||
AvailableOnly = AvailableOnly,
|
||||
HideNoPaths = HideNoPaths
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<JournalData.Genre, JournalCounts> _genreCounts = new Dictionary<JournalData.Genre, JournalCounts>();
|
||||
|
||||
private readonly Dictionary<JournalData.Category, JournalCounts> _categoryCounts = new Dictionary<JournalData.Category, JournalCounts>();
|
||||
|
||||
private readonly Dictionary<JournalData.Section, JournalCounts> _sectionCounts = new Dictionary<JournalData.Section, JournalCounts>();
|
||||
|
||||
private readonly JournalData _journalData;
|
||||
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly QuestFunctions _questFunctions;
|
||||
|
||||
private readonly UiUtils _uiUtils;
|
||||
|
||||
private readonly QuestTooltipComponent _questTooltipComponent;
|
||||
|
||||
private readonly IDalamudPluginInterface _pluginInterface;
|
||||
|
||||
private readonly QuestJournalUtils _questJournalUtils;
|
||||
|
||||
private readonly QuestValidator _questValidator;
|
||||
|
||||
private List<FilteredSection> _filteredSections = new List<FilteredSection>();
|
||||
|
||||
internal FilterConfiguration Filter { get; } = new FilterConfiguration();
|
||||
|
||||
public QuestJournalComponent(JournalData journalData, QuestRegistry questRegistry, QuestFunctions questFunctions, UiUtils uiUtils, QuestTooltipComponent questTooltipComponent, IDalamudPluginInterface pluginInterface, QuestJournalUtils questJournalUtils, QuestValidator questValidator)
|
||||
{
|
||||
_journalData = journalData;
|
||||
_questRegistry = questRegistry;
|
||||
_questFunctions = questFunctions;
|
||||
_uiUtils = uiUtils;
|
||||
_questTooltipComponent = questTooltipComponent;
|
||||
_pluginInterface = pluginInterface;
|
||||
_questJournalUtils = questJournalUtils;
|
||||
_questValidator = questValidator;
|
||||
}
|
||||
|
||||
public void DrawQuests()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabItem("Quests");
|
||||
if (!endObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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.Spacing();
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
}
|
||||
QuestJournalUtils.ShowFilterContextMenu(this);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
if (ImGui.InputTextWithHint(string.Empty, "Search quests and categories", ref Filter.SearchText, 256))
|
||||
{
|
||||
UpdateFilter();
|
||||
}
|
||||
if (_filteredSections.Count > 0)
|
||||
{
|
||||
using (ImRaii.IEndObject endObject2 = ImRaii.Table("Quests", 3, ImGuiTableFlags.NoSavedSettings))
|
||||
{
|
||||
if (!endObject2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.NoHide);
|
||||
ImGui.TableSetupColumn("Supported", ImGuiTableColumnFlags.WidthFixed, 120f * ImGui.GetIO().FontGlobalScale);
|
||||
ImGui.TableSetupColumn("Completed", ImGuiTableColumnFlags.WidthFixed, 120f * ImGui.GetIO().FontGlobalScale);
|
||||
ImGui.TableHeadersRow();
|
||||
foreach (FilteredSection filteredSection in _filteredSections)
|
||||
{
|
||||
DrawSection(filteredSection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
ImGui.Text("No quest or category matches your search.");
|
||||
}
|
||||
|
||||
private void DrawSection(FilteredSection filter)
|
||||
{
|
||||
var (count, num5, total, count2) = _sectionCounts.GetValueOrDefault(filter.Section, new JournalCounts());
|
||||
if (num5 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
bool num6 = ImGui.TreeNodeEx(filter.Section.Name, ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count, num5);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count2, total);
|
||||
if (!num6)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (FilteredCategory category in filter.Categories)
|
||||
{
|
||||
DrawCategory(category);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawCategory(FilteredCategory filter)
|
||||
{
|
||||
var (count, num5, total, count2) = _categoryCounts.GetValueOrDefault(filter.Category, new JournalCounts());
|
||||
if (num5 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
bool num6 = ImGui.TreeNodeEx(filter.Category.Name, ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count, num5);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count2, total);
|
||||
if (!num6)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (FilteredGenre genre in filter.Genres)
|
||||
{
|
||||
DrawGenre(genre);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawGenre(FilteredGenre filter)
|
||||
{
|
||||
var (count, num5, total, count2) = _genreCounts.GetValueOrDefault(filter.Genre, new JournalCounts());
|
||||
if (num5 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
bool num6 = ImGui.TreeNodeEx(filter.Genre.Name, ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count, num5);
|
||||
ImGui.TableNextColumn();
|
||||
DrawCount(count2, total);
|
||||
if (!num6)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (IQuestInfo quest in filter.Quests)
|
||||
{
|
||||
DrawQuest(quest);
|
||||
}
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
private void DrawQuest(IQuestInfo questInfo)
|
||||
{
|
||||
_questRegistry.TryGetQuest(questInfo.QuestId, out Quest quest);
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImU8String id = new ImU8String(3, 2);
|
||||
id.AppendFormatted(questInfo.Name);
|
||||
id.AppendLiteral(" (");
|
||||
id.AppendFormatted(questInfo.QuestId);
|
||||
id.AppendLiteral(")");
|
||||
ImGui.TreeNodeEx(id, ImGuiTreeNodeFlags.NoTreePushOnOpen | ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
_questTooltipComponent.Draw(questInfo);
|
||||
}
|
||||
_questJournalUtils.ShowContextMenu(questInfo, quest, "QuestJournalComponent");
|
||||
ImGui.TableNextColumn();
|
||||
float num;
|
||||
using (_pluginInterface.UiBuilder.IconFontFixedWidthHandle.Push())
|
||||
{
|
||||
num = ImGui.GetColumnWidth() / 2f - ImGui.CalcTextSize(FontAwesomeIcon.Check.ToIconString()).X;
|
||||
}
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + num);
|
||||
if (_questFunctions.IsQuestRemoved(questInfo.QuestId))
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, ImGuiColors.DalamudGrey, FontAwesomeIcon.Minus);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quest != null)
|
||||
{
|
||||
QuestRoot root = quest.Root;
|
||||
if (root != null && !root.Disabled)
|
||||
{
|
||||
List<ValidationIssue> issues = _questValidator.GetIssues(quest.Id);
|
||||
if (issues.Any((ValidationIssue x) => x.Severity == EIssueSeverity.Error))
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, ImGuiColors.DalamudRed, FontAwesomeIcon.ExclamationTriangle);
|
||||
}
|
||||
else if (issues.Count > 0)
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, ImGuiColors.ParsedBlue, FontAwesomeIcon.InfoCircle);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiUtils.ChecklistItem(string.Empty, complete: true);
|
||||
}
|
||||
goto IL_0215;
|
||||
}
|
||||
}
|
||||
_uiUtils.ChecklistItem(string.Empty, complete: false);
|
||||
}
|
||||
goto IL_0215;
|
||||
IL_0215:
|
||||
ImGui.TableNextColumn();
|
||||
var (color, icon, text) = _uiUtils.GetQuestStyle(questInfo.QuestId);
|
||||
_uiUtils.ChecklistItem(text, color, icon);
|
||||
}
|
||||
|
||||
private static void DrawCount(int count, int total)
|
||||
{
|
||||
string text = 9999.ToString(CultureInfo.CurrentCulture);
|
||||
ImGui.PushFont(UiBuilder.MonoFont);
|
||||
if (total == 0)
|
||||
{
|
||||
Vector4 col = ImGuiColors.DalamudGrey;
|
||||
ImU8String text2 = new ImU8String(3, 2);
|
||||
text2.AppendFormatted("-".PadLeft(text.Length));
|
||||
text2.AppendLiteral(" / ");
|
||||
text2.AppendFormatted("-".PadLeft(text.Length));
|
||||
ImGui.TextColored(in col, text2);
|
||||
}
|
||||
else
|
||||
{
|
||||
string text3 = count.ToString(CultureInfo.CurrentCulture).PadLeft(text.Length) + " / " + total.ToString(CultureInfo.CurrentCulture).PadLeft(text.Length);
|
||||
if (count == total)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.ParsedGreen, text3);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted(text3);
|
||||
}
|
||||
}
|
||||
ImGui.PopFont();
|
||||
}
|
||||
|
||||
public void UpdateFilter()
|
||||
{
|
||||
_filteredSections = (from x in _journalData.Sections
|
||||
select FilterSection(x, Filter) into x
|
||||
where x.Categories.Count > 0
|
||||
select x).ToList();
|
||||
RefreshCounts();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
private FilteredCategory FilterCategory(JournalData.Category category, FilterConfiguration filter)
|
||||
{
|
||||
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())));
|
||||
return new FilteredCategory(category, source.Where((FilteredGenre x) => x.Quests.Count > 0).ToList());
|
||||
}
|
||||
|
||||
private FilteredGenre FilterGenre(JournalData.Genre genre, FilterConfiguration filter)
|
||||
{
|
||||
IEnumerable<IQuestInfo> source = ((!IsCategorySectionGenreMatch(filter, genre.Name)) ? genre.Quests.Where((IQuestInfo x) => IsQuestMatch(filter, x)) : genre.Quests.Where((IQuestInfo x) => IsQuestMatch(filter.WithoutName(), x)));
|
||||
return new FilteredGenre(genre, source.ToList());
|
||||
}
|
||||
|
||||
internal void RefreshCounts()
|
||||
{
|
||||
_genreCounts.Clear();
|
||||
_categoryCounts.Clear();
|
||||
_sectionCounts.Clear();
|
||||
foreach (JournalData.Genre genre in _journalData.Genres)
|
||||
{
|
||||
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));
|
||||
_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);
|
||||
}
|
||||
foreach (JournalData.Section section in _journalData.Sections)
|
||||
{
|
||||
List<JournalCounts> source2 = (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);
|
||||
_sectionCounts[section] = new JournalCounts(available3, total3, obtainable3, completed3);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearCounts(int type, int code)
|
||||
{
|
||||
foreach (KeyValuePair<JournalData.Genre, JournalCounts> item in _genreCounts.ToList())
|
||||
{
|
||||
_genreCounts[item.Key] = item.Value with
|
||||
{
|
||||
Completed = 0
|
||||
};
|
||||
}
|
||||
foreach (KeyValuePair<JournalData.Category, JournalCounts> item2 in _categoryCounts.ToList())
|
||||
{
|
||||
_categoryCounts[item2.Key] = item2.Value with
|
||||
{
|
||||
Completed = 0
|
||||
};
|
||||
}
|
||||
foreach (KeyValuePair<JournalData.Section, JournalCounts> item3 in _sectionCounts.ToList())
|
||||
{
|
||||
_sectionCounts[item3.Key] = item3.Value with
|
||||
{
|
||||
Completed = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCategorySectionGenreMatch(FilterConfiguration filter, string name)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filter.SearchText))
|
||||
{
|
||||
return name.Contains(filter.SearchText, StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsQuestMatch(FilterConfiguration filter, IQuestInfo questInfo)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filter.SearchText) && !questInfo.Name.Contains(filter.SearchText, StringComparison.CurrentCultureIgnoreCase) && !(questInfo.QuestId.ToString() == filter.SearchText))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (filter.AvailableOnly && !_questFunctions.IsReadyToAcceptQuest(questInfo.QuestId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (filter.HideNoPaths && (!_questRegistry.TryGetQuest(questInfo.QuestId, out Quest quest) || quest.Root.Disabled))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Functions;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Windows.JournalComponents;
|
||||
|
||||
internal sealed class QuestJournalUtils
|
||||
{
|
||||
private readonly QuestController _questController;
|
||||
|
||||
private readonly QuestFunctions _questFunctions;
|
||||
|
||||
private readonly ICommandManager _commandManager;
|
||||
|
||||
public QuestJournalUtils(QuestController questController, QuestFunctions questFunctions, ICommandManager commandManager)
|
||||
{
|
||||
_questController = questController;
|
||||
_questFunctions = questFunctions;
|
||||
_commandManager = commandManager;
|
||||
}
|
||||
|
||||
public void ShowContextMenu(IQuestInfo questInfo, Quest? quest, string label)
|
||||
{
|
||||
ImU8String strId;
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
strId = new ImU8String(12, 1);
|
||||
strId.AppendLiteral("##QuestPopup");
|
||||
strId.AppendFormatted(questInfo.QuestId);
|
||||
ImGui.OpenPopup(strId);
|
||||
}
|
||||
strId = new ImU8String(12, 1);
|
||||
strId.AppendLiteral("##QuestPopup");
|
||||
strId.AppendFormatted(questInfo.QuestId);
|
||||
using ImRaii.IEndObject endObject = ImRaii.Popup(strId);
|
||||
if (!endObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (ImRaii.Disabled(!_questFunctions.IsReadyToAcceptQuest(questInfo.QuestId)))
|
||||
{
|
||||
if (ImGui.MenuItem("Start as next quest"))
|
||||
{
|
||||
_questController.SetNextQuest(quest);
|
||||
_questController.Start(label);
|
||||
}
|
||||
}
|
||||
bool flag = _commandManager.Commands.ContainsKey("/questinfo");
|
||||
using (ImRaii.Disabled(!(questInfo.QuestId is QuestId) || !flag))
|
||||
{
|
||||
if (ImGui.MenuItem("View in Quest Map"))
|
||||
{
|
||||
_commandManager.ProcessCommand($"/questinfo {questInfo.QuestId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ShowFilterContextMenu(QuestJournalComponent journalUi)
|
||||
{
|
||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Filter, "Filter"))
|
||||
{
|
||||
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)))
|
||||
{
|
||||
journalUi.UpdateFilter();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
using Questionable.Controller;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model;
|
||||
using Questionable.Windows.QuestComponents;
|
||||
|
||||
namespace Questionable.Windows.JournalComponents;
|
||||
|
||||
internal sealed class QuestRewardComponent
|
||||
{
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly QuestData _questData;
|
||||
|
||||
private readonly QuestTooltipComponent _questTooltipComponent;
|
||||
|
||||
private readonly UiUtils _uiUtils;
|
||||
|
||||
private bool _showEventRewards;
|
||||
|
||||
public QuestRewardComponent(QuestRegistry questRegistry, QuestData questData, QuestTooltipComponent questTooltipComponent, UiUtils uiUtils)
|
||||
{
|
||||
_questRegistry = questRegistry;
|
||||
_questData = questData;
|
||||
_questTooltipComponent = questTooltipComponent;
|
||||
_uiUtils = uiUtils;
|
||||
}
|
||||
|
||||
public void DrawItemRewards()
|
||||
{
|
||||
using ImRaii.IEndObject endObject = ImRaii.TabItem("Item Rewards");
|
||||
if (!(!endObject))
|
||||
{
|
||||
ImGui.Checkbox("Show rewards from seasonal event quests", ref _showEventRewards);
|
||||
ImGui.Spacing();
|
||||
ImGui.BulletText("Only untradeable items are listed (e.g. the Wind-up Airship can be sold on the market board).");
|
||||
DrawGroup("Mounts", EItemRewardType.Mount);
|
||||
DrawGroup("Minions", EItemRewardType.Minion);
|
||||
DrawGroup("Orchestrion Rolls", EItemRewardType.OrchestrionRoll);
|
||||
DrawGroup("Triple Triad Cards", EItemRewardType.TripleTriadCard);
|
||||
DrawGroup("Fashion Accessories", EItemRewardType.FashionAccessory);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGroup(string label, EItemRewardType type)
|
||||
{
|
||||
ImU8String label2 = new ImU8String(9, 2);
|
||||
label2.AppendFormatted(label);
|
||||
label2.AppendLiteral("###Reward");
|
||||
label2.AppendFormatted(type);
|
||||
if (!ImGui.CollapsingHeader(label2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (ItemReward item in _questData.RedeemableItems.Where((ItemReward x) => x.Type == type).OrderBy<ItemReward, string>((ItemReward x) => x.Name, StringComparer.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (!_questData.TryGetQuestInfo(item.ElementId, out IQuestInfo questInfo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = questInfo is QuestInfo questInfo2 && questInfo2.IsSeasonalEvent;
|
||||
if (!_showEventRewards && flag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string text = item.Name;
|
||||
if (flag)
|
||||
{
|
||||
text = text + " " + SeIconChar.Clock.ToIconString();
|
||||
}
|
||||
bool flag2 = item.IsUnlocked();
|
||||
Vector4 color = ((!_questRegistry.IsKnownQuest(item.ElementId)) ? ImGuiColors.DalamudGrey : (flag2 ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed));
|
||||
FontAwesomeIcon icon = (flag2 ? FontAwesomeIcon.Check : FontAwesomeIcon.Times);
|
||||
if (!_uiUtils.ChecklistItem(text, color, icon))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
using ImRaii.IEndObject endObject = ImRaii.Tooltip();
|
||||
if (!(!endObject))
|
||||
{
|
||||
label2 = new ImU8String(15, 1);
|
||||
label2.AppendLiteral("Obtained from: ");
|
||||
label2.AppendFormatted(questInfo.Name);
|
||||
ImGui.Text(label2);
|
||||
using (ImRaii.PushIndent())
|
||||
{
|
||||
_questTooltipComponent.DrawInner(questInfo, showItemRewards: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue