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); + } + } } }