diff --git a/WowPacketParser/App.config b/WowPacketParser/App.config
index b29c08f6af..29cf2ef9da 100644
--- a/WowPacketParser/App.config
+++ b/WowPacketParser/App.config
@@ -93,7 +93,7 @@
20: Classic
21: WotlkClassic
- 22: CataClassic
+ 22: CataClassic
-->
diff --git a/WowPacketParser/DBC/DBC.cs b/WowPacketParser/DBC/DBC.cs
index 41761e333f..a53772deba 100644
--- a/WowPacketParser/DBC/DBC.cs
+++ b/WowPacketParser/DBC/DBC.cs
@@ -29,6 +29,7 @@ public static class DBC
public static Storage ItemSparse { get; set; }
public static Storage Map { get; set; }
public static Storage MapDifficulty { get; set; }
+ public static Storage QuestLineXQuest { get; set; }
public static Storage Phase { get; set; }
public static Storage PhaseXPhaseGroup { get; set; }
public static Storage SpellEffect { get; set; }
diff --git a/WowPacketParser/DBC/Structures/TheWarWithin/QuestLineXQuestEntry.cs b/WowPacketParser/DBC/Structures/TheWarWithin/QuestLineXQuestEntry.cs
new file mode 100644
index 0000000000..7ebdedc19a
--- /dev/null
+++ b/WowPacketParser/DBC/Structures/TheWarWithin/QuestLineXQuestEntry.cs
@@ -0,0 +1,15 @@
+using DBFileReaderLib.Attributes;
+
+namespace WowPacketParser.DBC.Structures.TheWarWithin
+{
+ [DBFile("QuestLineXQuest")]
+ public sealed class QuestLineXQuestEntry
+ {
+ [Index(true)]
+ public int ID;
+ public uint QuestLineID;
+ public uint QuestID;
+ public uint OrderIndex;
+ public int Flags;
+ }
+}
diff --git a/WowPacketParser/SQL/Builders/QuestMisc.cs b/WowPacketParser/SQL/Builders/QuestMisc.cs
index 1aafcafdc8..3ad6fb6fa5 100644
--- a/WowPacketParser/SQL/Builders/QuestMisc.cs
+++ b/WowPacketParser/SQL/Builders/QuestMisc.cs
@@ -182,6 +182,37 @@ public static string QuestRequestItemsConditional()
return SQLUtil.Compare(Storage.QuestRequestItemsConditional, templatesDb, StoreNameType.Quest);
}
+ [BuilderMethod]
+ public static string UIMapQuestLines()
+ {
+ if (!Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.quest_template))
+ return string.Empty;
+
+ if (Storage.UIMapQuestLines.IsEmpty())
+ return string.Empty;
+
+ var templatesDb = SQLDatabase.Get(Storage.UIMapQuestLines);
+
+ return SQLUtil.Compare(Storage.UIMapQuestLines, templatesDb, StoreNameType.None);
+ }
+
+ [BuilderMethod]
+ public static string UIMapQuests()
+ {
+ if (!Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.quest_template))
+ return string.Empty;
+
+ if (Storage.UIMapQuests.IsEmpty())
+ return string.Empty;
+
+ var templatesDb = SQLDatabase.Get(Storage.UIMapQuests);
+
+ return SQLUtil.Compare(Storage.UIMapQuests, templatesDb, x =>
+ {
+ return $"{StoreGetters.GetName(StoreNameType.Quest, (int)x.QuestId, false)}";
+ });
+ }
+
[BuilderMethod]
public static string CreatureQuestStarters()
{
diff --git a/WowPacketParser/Store/Objects/UIMapQuest.cs b/WowPacketParser/Store/Objects/UIMapQuest.cs
new file mode 100644
index 0000000000..354ef3785c
--- /dev/null
+++ b/WowPacketParser/Store/Objects/UIMapQuest.cs
@@ -0,0 +1,19 @@
+using WowPacketParser.Enums;
+using WowPacketParser.Misc;
+using WowPacketParser.SQL;
+
+namespace WowPacketParser.Store.Objects
+{
+ [DBTableName("ui_map_quest", TargetedDatabaseFlag.SinceTheWarWithin)]
+ public sealed record UIMapQuest : IDataModel
+ {
+ [DBFieldName("UIMapId", true)]
+ public uint? UIMapId;
+
+ [DBFieldName("QuestId", true)]
+ public uint? QuestId;
+
+ [DBFieldName("VerifiedBuild")]
+ public int? VerifiedBuild = ClientVersion.BuildInt;
+ }
+}
diff --git a/WowPacketParser/Store/Objects/UIMapQuestLine.cs b/WowPacketParser/Store/Objects/UIMapQuestLine.cs
new file mode 100644
index 0000000000..8eeec57791
--- /dev/null
+++ b/WowPacketParser/Store/Objects/UIMapQuestLine.cs
@@ -0,0 +1,19 @@
+using WowPacketParser.Enums;
+using WowPacketParser.Misc;
+using WowPacketParser.SQL;
+
+namespace WowPacketParser.Store.Objects
+{
+ [DBTableName("ui_map_quest_line", TargetedDatabaseFlag.SinceTheWarWithin)]
+ public sealed record UIMapQuestLine : IDataModel
+ {
+ [DBFieldName("UIMapId", true)]
+ public uint? UIMapId;
+
+ [DBFieldName("QuestLineId", true)]
+ public uint? QuestLineId;
+
+ [DBFieldName("VerifiedBuild")]
+ public int? VerifiedBuild = ClientVersion.BuildInt;
+ }
+}
diff --git a/WowPacketParser/Store/Storage.cs b/WowPacketParser/Store/Storage.cs
index 499fb8704f..6513020d5f 100644
--- a/WowPacketParser/Store/Storage.cs
+++ b/WowPacketParser/Store/Storage.cs
@@ -105,6 +105,8 @@ public static class Storage
public static readonly DataBag QuestCompletionLogConditional = new DataBag(new List { SQLOutput.quest_template });
public static readonly DataBag QuestOfferRewardConditional = new DataBag(new List { SQLOutput.quest_template });
public static readonly DataBag QuestRequestItemsConditional = new DataBag(new List { SQLOutput.quest_template });
+ public static readonly DataBag UIMapQuestLines = new DataBag(new List { SQLOutput.quest_template });
+ public static readonly DataBag UIMapQuests = new DataBag(new List { SQLOutput.quest_template });
// Names
public static readonly DataBag ObjectNames = new DataBag();
@@ -1654,6 +1656,8 @@ public static void ClearContainers()
QuestCompletionLogConditional.Clear();
QuestOfferRewardConditional.Clear();
QuestRequestItemsConditional.Clear();
+ UIMapQuestLines.Clear();
+ UIMapQuests.Clear();
ObjectNames.Clear();
diff --git a/WowPacketParserModule.V10_0_0_46181/Parsers/QuestHandler.cs b/WowPacketParserModule.V10_0_0_46181/Parsers/QuestHandler.cs
index a9289775e4..dd0e880c1b 100644
--- a/WowPacketParserModule.V10_0_0_46181/Parsers/QuestHandler.cs
+++ b/WowPacketParserModule.V10_0_0_46181/Parsers/QuestHandler.cs
@@ -1,4 +1,4 @@
-
+using WowPacketParser.DBC;
using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.Parsing;
@@ -349,5 +349,50 @@ public static void QueryQuestItemUsability(Packet packet)
for (var i = 0; i < itemGuidCount; ++i)
packet.ReadPackedGuid128("ItemGUID", i);
}
+
+ [Parser(Opcode.SMSG_UI_MAP_QUEST_LINES_RESPONSE)]
+ public static void HandleUiMapQuestLinesResponse(Packet packet)
+ {
+ var uiMap = packet.ReadInt32("UiMapID");
+ var questLineXQuestCount = packet.ReadUInt32();
+ var questCount = packet.ReadUInt32();
+
+ for (int i = 0; i < questLineXQuestCount; i++)
+ {
+ var questLineXQuestId = packet.ReadUInt32();
+
+ if (Settings.UseDBC && DBC.QuestLineXQuest.ContainsKey((int)questLineXQuestId))
+ {
+ if (DBC.QuestLineXQuest.TryGetValue((int)questLineXQuestId, out var questLineXQuest))
+ {
+ var questLineId = questLineXQuest.QuestLineID;
+ var questId = questLineXQuest.QuestID;
+
+ UIMapQuestLine uiMapQuestLine = new()
+ {
+ UIMapId = (uint)uiMap,
+ QuestLineId = questLineId
+ };
+ Storage.UIMapQuestLines.Add(uiMapQuestLine, packet.TimeSpan);
+
+ packet.WriteLine($"[{i}] QuestLineXQuestID: {questLineXQuestId} (QuestID: {questId} QuestLineID: {questLineId})");
+ }
+ }
+ else
+ packet.AddValue($"QuestLineXQuestID", questLineXQuestId, i);
+ }
+
+ for (int i = 0; i < questCount; i++)
+ {
+ var questId = packet.ReadUInt32("QuestID", i);
+
+ UIMapQuest uiMapQuest = new UIMapQuest
+ {
+ UIMapId = (uint)uiMap,
+ QuestId = questId
+ };
+ Storage.UIMapQuests.Add(uiMapQuest, packet.TimeSpan);
+ }
+ }
}
}
diff --git a/WowPacketParserModule.V11_0_0_55666/Parsers/QuestHandler.cs b/WowPacketParserModule.V11_0_0_55666/Parsers/QuestHandler.cs
index 54ead6ce12..173ef5e8eb 100644
--- a/WowPacketParserModule.V11_0_0_55666/Parsers/QuestHandler.cs
+++ b/WowPacketParserModule.V11_0_0_55666/Parsers/QuestHandler.cs
@@ -1,4 +1,5 @@
-using WowPacketParser.Enums;
+using WowPacketParser.DBC;
+using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.Parsing;
using WowPacketParser.Store;
@@ -282,5 +283,63 @@ public static void QuestGiverOfferReward(Packet packet)
Storage.LocalesQuestOfferRewards.Add(localesQuestOfferReward, packet.TimeSpan);
}
}
+
+ [Parser(Opcode.SMSG_UI_MAP_QUEST_LINES_RESPONSE)]
+ public static void HandleUiMapQuestLinesResponse(Packet packet)
+ {
+ var uiMap = packet.ReadInt32("UiMapID");
+ var questLineXQuestCount = packet.ReadUInt32();
+ var questCount = packet.ReadUInt32();
+ var questLineCount = packet.ReadUInt32();
+
+ for (int i = 0; i < questLineXQuestCount; i++)
+ {
+ var questLineXQuestId = packet.ReadUInt32();
+
+ if (Settings.UseDBC && DBC.QuestLineXQuest.ContainsKey((int)questLineXQuestId))
+ {
+ if (DBC.QuestLineXQuest.TryGetValue((int)questLineXQuestId, out var questLineXQuest))
+ {
+ var questLineId = questLineXQuest.QuestLineID;
+ var questId = questLineXQuest.QuestID;
+
+ UIMapQuestLine uiMapQuestLine = new()
+ {
+ UIMapId = (uint)uiMap,
+ QuestLineId = questLineId
+ };
+ Storage.UIMapQuestLines.Add(uiMapQuestLine, packet.TimeSpan);
+
+ packet.WriteLine($"[{i}] QuestLineXQuestID: {questLineXQuestId} (QuestID: {questId} QuestLineID: {questLineId})");
+ }
+ }
+ else
+ packet.AddValue($"QuestLineXQuestID", questLineXQuestId, i);
+ }
+
+ for (int i = 0; i < questCount; i++)
+ {
+ var questId = packet.ReadUInt32("QuestID", i);
+
+ UIMapQuest uiMapQuest = new UIMapQuest
+ {
+ UIMapId = (uint)uiMap,
+ QuestId = questId
+ };
+ Storage.UIMapQuests.Add(uiMapQuest, packet.TimeSpan);
+ }
+
+ for (int i = 0; i < questLineCount; i++)
+ {
+ var questLineId = packet.ReadUInt32("QuestLineID", i);
+
+ UIMapQuestLine uiMapQuestLine = new()
+ {
+ UIMapId = (uint)uiMap,
+ QuestLineId = questLineId
+ };
+ Storage.UIMapQuestLines.Add(uiMapQuestLine, packet.TimeSpan);
+ }
+ }
}
}