diff --git a/Quest Map/Commands.cs b/Quest Map/Commands.cs
index 073a777..bbd9859 100644
--- a/Quest Map/Commands.cs
+++ b/Quest Map/Commands.cs
@@ -8,13 +8,13 @@ namespace QuestMap {
internal Commands(Plugin plugin) {
this.Plugin = plugin;
- this.Plugin.Interface.CommandManager.AddHandler("/quests", new CommandInfo(this.OnCommand) {
+ this.Plugin.CommandManager.AddHandler("/quests", new CommandInfo(this.OnCommand) {
HelpMessage = "Show Quest Map",
});
}
public void Dispose() {
- this.Plugin.Interface.CommandManager.RemoveHandler("/quests");
+ this.Plugin.CommandManager.RemoveHandler("/quests");
}
private void OnCommand(string command, string args) {
diff --git a/Quest Map/DalamudPlugin.cs b/Quest Map/DalamudPlugin.cs
deleted file mode 100644
index 0dfaf40..0000000
--- a/Quest Map/DalamudPlugin.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Dalamud.Plugin;
-
-namespace QuestMap {
- // ReSharper disable once UnusedType.Global
- public class DalamudPlugin : IDalamudPlugin {
- internal const string PluginName = "Quest Map";
-
- public string Name => PluginName;
-
- private Plugin? Plugin { get; set; }
-
- public void Initialize(DalamudPluginInterface pluginInterface) {
- this.Plugin = new Plugin(pluginInterface);
- }
-
- public void Dispose() {
- this.Plugin?.Dispose();
- }
- }
-}
diff --git a/Quest Map/FodyWeavers.xml b/Quest Map/FodyWeavers.xml
deleted file mode 100644
index e5727bf..0000000
--- a/Quest Map/FodyWeavers.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/Quest Map/Node.cs b/Quest Map/Node.cs
index 62606b2..344a24a 100644
--- a/Quest Map/Node.cs
+++ b/Quest Map/Node.cs
@@ -152,15 +152,15 @@ namespace QuestMap {
internal static IEnumerable PreviousQuests(this Quest quest) {
if (quest.PreviousQuest0.Row != 0) {
- yield return quest.PreviousQuest0.Value;
+ yield return quest.PreviousQuest0.Value!;
}
if (quest.PreviousQuest1.Row != 0) {
- yield return quest.PreviousQuest1.Value;
+ yield return quest.PreviousQuest1.Value!;
}
if (quest.PreviousQuest2.Row != 0) {
- yield return quest.PreviousQuest2.Value;
+ yield return quest.PreviousQuest2.Value!;
}
}
}
diff --git a/Quest Map/Plugin.cs b/Quest Map/Plugin.cs
index f35b386..8dfbbef 100644
--- a/Quest Map/Plugin.cs
+++ b/Quest Map/Plugin.cs
@@ -1,21 +1,44 @@
-using System;
-using System.Threading.Channels;
+using System.Threading.Channels;
+using Dalamud.Data;
+using Dalamud.Game.ClientState;
+using Dalamud.Game.Command;
+using Dalamud.Game.Gui;
+using Dalamud.Game.Text.SeStringHandling;
+using Dalamud.IoC;
using Dalamud.Plugin;
-using Microsoft.Msagl.Core.Layout;
using XivCommon;
namespace QuestMap {
- internal class Plugin : IDisposable {
- internal DalamudPluginInterface Interface { get; }
+ // ReSharper disable once ClassNeverInstantiated.Global
+ internal class Plugin : IDalamudPlugin {
+ public string Name => "Quest Map";
+
+ [PluginService]
+ internal DalamudPluginInterface Interface { get; init; } = null!;
+
+ [PluginService]
+ internal ClientState ClientState { get; init; } = null!;
+
+ [PluginService]
+ internal CommandManager CommandManager { get; init; } = null!;
+
+ [PluginService]
+ internal DataManager DataManager { get; init; } = null!;
+
+ [PluginService]
+ internal GameGui GameGui { get; init; } = null!;
+
+ [PluginService]
+ internal SeStringManager SeStringManager { get; init; } = null!;
+
internal XivCommonBase Common { get; }
internal Configuration Config { get; }
internal Quests Quests { get; }
internal PluginUi Ui { get; }
private Commands Commands { get; }
- internal Plugin(DalamudPluginInterface pluginInterface) {
- this.Interface = pluginInterface;
- this.Common = new XivCommonBase(pluginInterface);
+ public Plugin() {
+ this.Common = new XivCommonBase();
this.Config = this.Interface.GetPluginConfig() as Configuration ?? new Configuration();
var graphChannel = Channel.CreateUnbounded();
diff --git a/Quest Map/PluginUi.cs b/Quest Map/PluginUi.cs
index 3159c6d..a3da52a 100644
--- a/Quest Map/PluginUi.cs
+++ b/Quest Map/PluginUi.cs
@@ -60,20 +60,20 @@ namespace QuestMap {
this.Refilter();
- this.Plugin.Interface.UiBuilder.OnBuildUi += this.Draw;
- this.Plugin.Interface.UiBuilder.OnOpenConfigUi += this.OpenConfig;
+ this.Plugin.Interface.UiBuilder.Draw += this.Draw;
+ this.Plugin.Interface.UiBuilder.OpenConfigUi += this.OpenConfig;
}
public void Dispose() {
- this.Plugin.Interface.UiBuilder.OnOpenConfigUi -= this.OpenConfig;
- this.Plugin.Interface.UiBuilder.OnBuildUi -= this.Draw;
+ this.Plugin.Interface.UiBuilder.OpenConfigUi -= this.OpenConfig;
+ this.Plugin.Interface.UiBuilder.Draw -= this.Draw;
foreach (var icon in this.Icons.Values) {
icon.Dispose();
}
}
- private void OpenConfig(object sender, EventArgs e) {
+ private void OpenConfig() {
this.Show = true;
}
@@ -81,7 +81,7 @@ namespace QuestMap {
this.FilteredQuests.Clear();
var filterLower = this._filter.ToLowerInvariant();
- var filtered = this.Plugin.Interface.Data.GetExcelSheet()
+ var filtered = this.Plugin.DataManager.GetExcelSheet()!
.Where(quest => {
if (quest.Name.ToString().Length == 0) {
return false;
@@ -198,7 +198,7 @@ namespace QuestMap {
ImGui.SetNextWindowSize(new Vector2(675, 600), ImGuiCond.FirstUseEver);
- if (!ImGui.Begin(DalamudPlugin.PluginName, ref this.Show, ImGuiWindowFlags.MenuBar)) {
+ if (!ImGui.Begin(this.Plugin.Name, ref this.Show, ImGuiWindowFlags.MenuBar)) {
ImGui.End();
return;
}
@@ -357,7 +357,7 @@ namespace QuestMap {
var remove = 0u;
foreach (var id in this.InfoWindows) {
- var quest = this.Plugin.Interface.Data.GetExcelSheet().GetRow(id);
+ var quest = this.Plugin.DataManager.GetExcelSheet()!.GetRow(id);
if (quest == null) {
continue;
}
@@ -393,13 +393,15 @@ namespace QuestMap {
ImGui.PopFont();
}
- TextureWrap GetIcon(uint id) {
+ TextureWrap? GetIcon(uint id) {
if (this.Icons.TryGetValue(id, out var wrap)) {
return wrap;
}
- wrap = this.Plugin.Interface.Data.GetImGuiTextureIcon(this.Plugin.Interface.ClientState.ClientLanguage, (int) id);
- this.Icons[id] = wrap;
+ wrap = this.Plugin.DataManager.GetImGuiTextureIcon(this.Plugin.ClientState.ClientLanguage, id);
+ if (wrap != null) {
+ this.Icons[id] = wrap;
+ }
return wrap;
}
@@ -408,13 +410,19 @@ namespace QuestMap {
if (quest.Icon != 0) {
var header = GetIcon(quest.Icon);
- textWrap = header.Width;
- ImGui.Image(header.ImGuiHandle, new Vector2(header.Width, header.Height));
+ if (header != null) {
+ textWrap = header.Width;
+ ImGui.Image(header.ImGuiHandle, new Vector2(header.Width, header.Height));
+ }
}
var rewards = new List();
- var paramGrow = this.Plugin.Interface.Data.GetExcelSheet().GetRow(quest.ClassJobLevel0);
- var xp = quest.ExpFactor * paramGrow.ScaledQuestXP * paramGrow.QuestExpModifier / 100;
+ var paramGrow = this.Plugin.DataManager.GetExcelSheet()!.GetRow(quest.ClassJobLevel0);
+ var xp = 0;
+ if (paramGrow != null) {
+ xp = quest.ExpFactor * paramGrow.ScaledQuestXP * paramGrow.QuestExpModifier / 100;
+ }
+
if (xp > 0) {
rewards.Add($"Exp: {xp:N0}");
}
@@ -437,17 +445,23 @@ namespace QuestMap {
ImGui.TextUnformatted(label);
- var maxHeight = items.Select(entry => GetIcon(entry.icon)).Max(image => image.Height);
+ var maxHeight = items
+ .Select(entry => GetIcon(entry.icon))
+ .Where(image => image != null)
+ .Max(image => image!.Height);
var originalY = ImGui.GetCursorPosY();
foreach (var (name, icon, qty) in items) {
var image = GetIcon(icon);
- if (image.Height < maxHeight) {
- ImGui.SetCursorPosY(originalY + (maxHeight - image.Height) / 2f);
+ if (image != null) {
+ if (image.Height < maxHeight) {
+ ImGui.SetCursorPosY(originalY + (maxHeight - image.Height) / 2f);
+ }
+
+ ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
+ Util.Tooltip(name.ToString());
}
- ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
- Util.Tooltip(name.ToString());
if (qty > 1) {
var oldSpacing = ImGui.GetStyle().ItemSpacing;
ImGui.GetStyle().ItemSpacing = new Vector2(2, 0);
@@ -478,12 +492,12 @@ namespace QuestMap {
var amount = quest.ItemCountCatalyst[i];
if (catalyst.Row != 0) {
- additionalRewards.Add((this.Convert(catalyst.Value.Name), catalyst.Value.Icon, amount));
+ additionalRewards.Add((this.Convert(catalyst.Value!.Name), catalyst.Value.Icon, amount));
}
}
foreach (var generalAction in quest.GeneralActionReward.Where(row => row.Row != 0)) {
- additionalRewards.Add((this.Convert(generalAction.Value.Name), (uint) generalAction.Value.Icon, 1));
+ additionalRewards.Add((this.Convert(generalAction.Value!.Name), (uint) generalAction.Value.Icon, 1));
}
if (this.Plugin.Quests.ActionRewards.TryGetValue(quest.RowId, out var action)) {
@@ -495,7 +509,7 @@ namespace QuestMap {
}
if (quest.OtherReward.Row != 0) {
- additionalRewards.Add((this.Convert(quest.OtherReward.Value.Name), quest.OtherReward.Value.Icon, 1));
+ additionalRewards.Add((this.Convert(quest.OtherReward.Value!.Name), quest.OtherReward.Value.Icon, 1));
}
if (quest.ReputationReward > 0) {
@@ -506,7 +520,7 @@ namespace QuestMap {
}
if (quest.TomestoneReward > 0) {
- var tomestone = this.Plugin.Interface.Data.GetExcelSheet().First(row => row.Tomestones.Row == quest.TomestoneReward);
+ var tomestone = this.Plugin.DataManager.GetExcelSheet()!.FirstOrDefault(row => row.Tomestones.Row == quest.TomestoneReward);
var item = tomestone?.Item?.Value;
if (item != null) {
additionalRewards.Add((this.Convert(item.Name), item.Icon, quest.TomestoneCountReward));
@@ -519,9 +533,9 @@ namespace QuestMap {
quest.ItemReward0
.Zip(quest.ItemCountReward0, (id, qty) => (id, qty))
.Where(entry => entry.id != 0)
- .Select(entry => (item: this.Plugin.Interface.Data.GetExcelSheet- ().GetRow(entry.id), entry.qty))
+ .Select(entry => (item: this.Plugin.DataManager.GetExcelSheet
- ()!.GetRow(entry.id), entry.qty))
.Where(entry => entry.item != null)
- .Select(entry => (this.Convert(entry.item.Name), (uint) entry.item.Icon, entry.qty))
+ .Select(entry => (this.Convert(entry.item!.Name), (uint) entry.item.Icon, entry.qty))
.Concat(additionalRewards)
);
@@ -532,7 +546,7 @@ namespace QuestMap {
.Where(entry => entry.row.Row != 0)
.Select(entry => (item: entry.row.Value, entry.qty))
.Where(entry => entry.item != null)
- .Select(entry => (this.Convert(entry.item.Name), (uint) entry.item.Icon, entry.qty))
+ .Select(entry => (this.Convert(entry.item!.Name), (uint) entry.item.Icon, entry.qty))
);
}
@@ -543,8 +557,10 @@ namespace QuestMap {
var icon = instance.ContentType.Value?.Icon ?? 0;
if (icon > 0) {
var image = GetIcon(icon);
- ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
- Util.Tooltip(this.Convert(instance.Name).ToString());
+ if (image != null) {
+ ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
+ Util.Tooltip(this.Convert(instance.Name).ToString());
+ }
} else {
ImGui.TextUnformatted(this.Convert(instance.Name).ToString());
}
@@ -557,34 +573,37 @@ namespace QuestMap {
ImGui.TextUnformatted("Beast tribe");
var image = GetIcon(tribe.Icon);
- ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
- Util.Tooltip(this.Convert(tribe.Name).ToString());
+ if (image != null) {
+ ImGui.Image(image.ImGuiHandle, new Vector2(image.Width, image.Height));
+ Util.Tooltip(this.Convert(tribe.Name).ToString());
+ }
ImGui.Separator();
}
var id = quest.RowId & 0xFFFF;
- var lang = this.Plugin.Interface.ClientState.ClientLanguage switch {
+ var lang = this.Plugin.ClientState.ClientLanguage switch {
ClientLanguage.English => Language.English,
ClientLanguage.Japanese => Language.Japanese,
ClientLanguage.German => Language.German,
ClientLanguage.French => Language.French,
_ => Language.English,
};
- var path = $"quest/{id.ToString("00000").Substring(0, 3)}/{quest.Id.RawString.ToLowerInvariant()}";
+ var path = $"quest/{id.ToString("00000")[..3]}/{quest.Id.RawString.ToLowerInvariant()}";
// FIXME: this is gross, but lumina caches incorrectly
- this.Plugin.Interface.Data.Excel.RemoveSheetFromCache();
- var sheet = this.Plugin.Interface.Data.Excel.GetType()
- .GetMethod("GetSheet", BindingFlags.Instance | BindingFlags.NonPublic)
- ?.MakeGenericMethod(typeof(QuestData))
+ this.Plugin.DataManager.Excel.RemoveSheetFromCache();
+ var sheet = this.Plugin.DataManager.Excel.GetType()
+ .GetMethod("GetSheet", BindingFlags.Instance | BindingFlags.NonPublic)?
// ReSharper disable once ConstantConditionalAccessQualifier
- ?.Invoke(this.Plugin.Interface.Data.Excel, new object?[] {
+ .MakeGenericMethod(typeof(QuestData))?
+ // ReSharper disable once ConstantConditionalAccessQualifier
+ .Invoke(this.Plugin.DataManager.Excel, new object?[] {
path,
lang,
null,
}) as ExcelSheet;
// default to english if reflection failed
- sheet ??= this.Plugin.Interface.Data.Excel.GetSheet(path);
+ sheet ??= this.Plugin.DataManager.Excel.GetSheet(path);
var firstData = sheet?.GetRow(0);
if (firstData != null) {
ImGui.PushTextWrapPos(textWrap);
@@ -600,18 +619,17 @@ namespace QuestMap {
}
var mapLink = new MapLinkPayload(
- this.Plugin.Interface.Data,
level.Territory.Row,
level.Map.Row,
(int) (level.X * 1_000f),
(int) (level.Z * 1_000f)
);
- this.Plugin.Interface.Framework.Gui.OpenMapWithMapLink(mapLink);
+ this.Plugin.GameGui.OpenMapWithMapLink(mapLink);
}
- var issuer = this.Plugin.Interface.Data.GetExcelSheet().GetRow(quest.IssuerStart)?.Singular ?? "Unknown";
- var target = this.Plugin.Interface.Data.GetExcelSheet().GetRow(quest.TargetEnd)?.Singular ?? "Unknown";
+ var issuer = this.Plugin.DataManager.GetExcelSheet()!.GetRow(quest.IssuerStart)?.Singular ?? "Unknown";
+ var target = this.Plugin.DataManager.GetExcelSheet()!.GetRow(quest.TargetEnd)?.Singular ?? "Unknown";
ImGui.TextUnformatted(issuer);
ImGui.PushFont(UiBuilder.IconFont);
ImGui.SameLine();
@@ -877,7 +895,7 @@ namespace QuestMap {
private static readonly byte[] NewLinePayload = { 0x02, 0x10, 0x01, 0x03 };
private SeString Convert(Lumina.Text.SeString lumina) {
- var se = this.Plugin.Interface.SeStringManager.Parse(lumina.RawData.ToArray());
+ var se = this.Plugin.SeStringManager.Parse(lumina.RawData.ToArray());
for (var i = 0; i < se.Payloads.Count; i++) {
switch (se.Payloads[i].Type) {
case PayloadType.Unknown:
diff --git a/Quest Map/Quest Map.csproj b/Quest Map/Quest Map.csproj
old mode 100644
new mode 100755
index 4c9758c..f77a4f5
--- a/Quest Map/Quest Map.csproj
+++ b/Quest Map/Quest Map.csproj
@@ -1,12 +1,14 @@
- net48
+ net5-windows
QuestMap
1.3.0
enable
latest
true
+ true
+ false
@@ -30,22 +32,17 @@
$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll
False
-
- $(AppData)\XIVLauncher\addon\Hooks\dev\System.Memory.dll
- False
-
-
- D:\code\XivCommon\XivCommon\bin\Release\net48\XivCommon.dll
-
-
-
-
+
-
+
+
+
+
+
diff --git a/Quest Map/Quest Map.yaml b/Quest Map/Quest Map.yaml
index b4b7313..e2da8fd 100644
--- a/Quest Map/Quest Map.yaml
+++ b/Quest Map/Quest Map.yaml
@@ -1,5 +1,6 @@
name: Quest Map
author: ascclemens
+punchline: Explore quests and their rewards.
description: |-
Explore quests and their rewards.
- Search for quest names or their rewards, including instances,
@@ -7,3 +8,7 @@ description: |-
- See an interactive map of quest requirements and unlocks.
- Open a quest info window even for quests you haven't completed.
- Open quest starting locations on the map or open quests in the journal.
+
+ Icons: treasure map by Anthony Ledoux from the Noun Project and
+ locked book by Anthony Ledoux from the Noun Project
+repo_url: https://git.sr.ht/~jkcclemens/QuestMap
diff --git a/Quest Map/QuestData.cs b/Quest Map/QuestData.cs
index 1719fc0..c6ea11b 100644
--- a/Quest Map/QuestData.cs
+++ b/Quest Map/QuestData.cs
@@ -17,8 +17,8 @@ namespace QuestMap {
public override void PopulateData(RowParser parser, GameData gameData, Language language) {
base.PopulateData(parser, gameData, language);
- this.Id = parser.ReadColumn(0);
- this.Text = parser.ReadColumn(1);
+ this.Id = parser.ReadColumn(0)!;
+ this.Text = parser.ReadColumn(1)!;
}
}
}
diff --git a/Quest Map/Quests.cs b/Quest Map/Quests.cs
index 6edd1f7..c2fd1cc 100644
--- a/Quest Map/Quests.cs
+++ b/Quest Map/Quests.cs
@@ -41,7 +41,7 @@ namespace QuestMap {
var linkedInstances = new HashSet();
var allQuests = new Dictionary();
- foreach (var quest in this.Plugin.Interface.Data.GetExcelSheet()) {
+ foreach (var quest in this.Plugin.DataManager.GetExcelSheet()!) {
if (quest.Name.RawString.Length == 0 || quest.RowId == 65536) {
continue;
}
@@ -49,11 +49,11 @@ namespace QuestMap {
allQuests[quest.RowId] = quest;
if (quest.EmoteReward.Row != 0) {
- emoteRewards[quest.RowId] = quest.EmoteReward.Value;
+ emoteRewards[quest.RowId] = quest.EmoteReward.Value!;
}
foreach (var row in quest.ItemReward0.Where(item => item != 0)) {
- var item = this.Plugin.Interface.Data.GetExcelSheet
- ().GetRow(row);
+ var item = this.Plugin.DataManager.GetExcelSheet
- ()!.GetRow(row);
if (item == null) {
continue;
}
@@ -80,11 +80,11 @@ namespace QuestMap {
itemRewards[quest.RowId] = rewards;
}
- rewards.Add(item);
+ rewards.Add(item!);
}
if (quest.ActionReward.Row != 0) {
- actionRewards[quest.RowId] = quest.ActionReward.Value;
+ actionRewards[quest.RowId] = quest.ActionReward.Value!;
}
var instances = this.InstanceUnlocks(quest, linkedInstances);
@@ -96,7 +96,7 @@ namespace QuestMap {
}
if (quest.BeastTribe.Row != 0 && !quest.IsRepeatable && quest.BeastReputationRank.Row == 0) {
- beastRewards[quest.RowId] = quest.BeastTribe.Value;
+ beastRewards[quest.RowId] = quest.BeastTribe.Value!;
}
var jobReward = this.JobUnlocks(quest);
@@ -259,7 +259,7 @@ namespace QuestMap {
var unlocks = new HashSet();
if (quest.InstanceContentUnlock.Row != 0) {
- var cfc = this.Plugin.Interface.Data.GetExcelSheet().FirstOrDefault(cfc => cfc.Content == quest.InstanceContentUnlock.Row && cfc.ContentLinkType == 1);
+ var cfc = this.Plugin.DataManager.GetExcelSheet()!.FirstOrDefault(cfc => cfc.Content == quest.InstanceContentUnlock.Row && cfc.ContentLinkType == 1);
if (cfc != null && cfc.UnlockQuest.Row == 0) {
unlocks.Add(cfc);
}
@@ -274,7 +274,7 @@ namespace QuestMap {
// var content = this.Plugin.Interface.Data.GetExcelSheet().GetRow(key);
- var cfc = this.Plugin.Interface.Data.GetExcelSheet().FirstOrDefault(cfc => cfc.Content == key && cfc.ContentLinkType == 1);
+ var cfc = this.Plugin.DataManager.GetExcelSheet()!.FirstOrDefault(cfc => cfc.Content == key && cfc.ContentLinkType == 1);
if (cfc == null || cfc.UnlockQuest.Row != 0 || others.Contains(cfc)) {
continue;
}
@@ -306,7 +306,7 @@ namespace QuestMap {
.arg;
return jobId == 0
? null
- : this.Plugin.Interface.Data.GetExcelSheet().GetRow(jobId);
+ : this.Plugin.DataManager.GetExcelSheet()!.GetRow(jobId);
}
}
}
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..3bf4f3c
Binary files /dev/null and b/icon.png differ
diff --git a/icon.svg b/icon.svg
new file mode 100755
index 0000000..6282ff8
--- /dev/null
+++ b/icon.svg
@@ -0,0 +1,217 @@
+
+