From f441175665003357294424025185baeb6df9a495 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Tue, 11 Oct 2022 20:27:05 -0400 Subject: [PATCH] Core/Garrisons: Implement SMSG_GARRISON_OPEN_TALENT_NPC opcode Port From (https://github.com/TrinityCore/TrinityCore/commit/4772c4817f1b34553f1c697e2aedc0372af9aea2) --- Source/Framework/Constants/GossipConst.cs | 2 +- .../Database/Databases/HotfixDatabase.cs | 8 ++++ Source/Game/DataStorage/CliDB.cs | 2 + Source/Game/DataStorage/Structs/G_Records.cs | 17 ++++++++ Source/Game/Entities/Creature/Gossip.cs | 5 +++ Source/Game/Entities/Player/Player.Quest.cs | 9 ++++ Source/Game/Entities/Player/Player.cs | 7 +++ Source/Game/Globals/ObjectManager.cs | 43 ++++++++++++++++++- .../Networking/Packets/GarrisonPackets.cs | 16 +++++++ Source/Game/World/WorldManager.cs | 7 ++- 10 files changed, 112 insertions(+), 4 deletions(-) diff --git a/Source/Framework/Constants/GossipConst.cs b/Source/Framework/Constants/GossipConst.cs index 305ef8524..699b078e2 100644 --- a/Source/Framework/Constants/GossipConst.cs +++ b/Source/Framework/Constants/GossipConst.cs @@ -78,7 +78,7 @@ namespace Framework.Constants GarrisonTradeskill = 29, /*NYI*/ // White chat bubble GarrisonRecruitment = 30, /*NYI*/ // White chat bubble AdventureMap = 31, /*NYI*/ // White chat bubble - GarrisonTalent = 32, /*NYI*/ // White chat bubble + GarrisonTalent = 32, // White chat bubble ContributionCollector = 33, /*NYI*/ // White chat bubble Transmogrify = 34, // Purple helm AzeriteRespec = 35, /*NYI*/ // White chat bubble diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index c98aa51dc..e285791bc 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -497,6 +497,11 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_GARR_SITE_LEVEL_PLOT_INST, "SELECT ID, UiMarkerPosX, UiMarkerPosY, GarrSiteLevelID, GarrPlotInstanceID, UiMarkerSize" + " FROM garr_site_level_plot_inst"); + // GarrTalentTree.db2 + PrepareStatement(HotfixStatements.SEL_GARR_TALENT_TREE, "SELECT ID, Name, GarrTypeID, ClassID, MaxTiers, UiOrder, Flags, UiTextureKitID, " + + "GarrTalentTreeType, PlayerConditionID, FeatureTypeIndex, FeatureSubtypeIndex, CurrencyID FROM garr_talent_tree"); + PrepareStatement(HotfixStatements.SEL_GARR_TALENT_TREE_LOCALE, "SELECT ID, Name_lang FROM garr_talent_tree_locale WHERE locale = ?"); + // GemProperties.db2 PrepareStatement(HotfixStatements.SEL_GEM_PROPERTIES, "SELECT ID, EnchantId, Type FROM gem_properties"); @@ -1533,6 +1538,9 @@ namespace Framework.Database SEL_GARR_SITE_LEVEL_PLOT_INST, + SEL_GARR_TALENT_TREE, + SEL_GARR_TALENT_TREE_LOCALE, + SEL_GEM_PROPERTIES, SEL_GLOBAL_CURVE, diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index 7bd3c197b..661a6f71e 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -158,6 +158,7 @@ namespace Game.DataStorage GarrPlotInstanceStorage = ReadDB2("GarrPlotInstance.db2", HotfixStatements.SEL_GARR_PLOT_INSTANCE); GarrSiteLevelStorage = ReadDB2("GarrSiteLevel.db2", HotfixStatements.SEL_GARR_SITE_LEVEL); GarrSiteLevelPlotInstStorage = ReadDB2("GarrSiteLevelPlotInst.db2", HotfixStatements.SEL_GARR_SITE_LEVEL_PLOT_INST); + GarrTalentTreeStorage = ReadDB2("GarrTalentTree.db2", HotfixStatements.SEL_GARR_TALENT_TREE, HotfixStatements.SEL_GARR_TALENT_TREE_LOCALE); GemPropertiesStorage = ReadDB2("GemProperties.db2", HotfixStatements.SEL_GEM_PROPERTIES); GlobalCurveStorage = ReadDB2("GlobalCurve.db2", HotfixStatements.SEL_GLOBAL_CURVE); GlyphBindableSpellStorage = ReadDB2("GlyphBindableSpell.db2", HotfixStatements.SEL_GLYPH_BINDABLE_SPELL); @@ -555,6 +556,7 @@ namespace Game.DataStorage public static DB6Storage GarrPlotInstanceStorage; public static DB6Storage GarrSiteLevelStorage; public static DB6Storage GarrSiteLevelPlotInstStorage; + public static DB6Storage GarrTalentTreeStorage; public static DB6Storage GemPropertiesStorage; public static DB6Storage GlobalCurveStorage; public static DB6Storage GlyphBindableSpellStorage; diff --git a/Source/Game/DataStorage/Structs/G_Records.cs b/Source/Game/DataStorage/Structs/G_Records.cs index f2353091e..039a0705a 100644 --- a/Source/Game/DataStorage/Structs/G_Records.cs +++ b/Source/Game/DataStorage/Structs/G_Records.cs @@ -258,6 +258,23 @@ namespace Game.DataStorage public byte UiMarkerSize; } + public sealed class GarrTalentTreeRecord + { + public uint Id; + public string Name; + public byte GarrTypeID; + public int ClassID; + public sbyte MaxTiers; + public sbyte UiOrder; + public int Flags; + public ushort UiTextureKitID; + public int GarrTalentTreeType; + public int PlayerConditionID; + public sbyte FeatureTypeIndex; + public sbyte FeatureSubtypeIndex; + public int CurrencyID; + } + public sealed class GemPropertiesRecord { public uint Id; diff --git a/Source/Game/Entities/Creature/Gossip.cs b/Source/Game/Entities/Creature/Gossip.cs index 24d019517..16df7a212 100644 --- a/Source/Game/Entities/Creature/Gossip.cs +++ b/Source/Game/Entities/Creature/Gossip.cs @@ -746,6 +746,11 @@ namespace Game.Misc public int FriendshipFactionID; } + public class GossipMenuItemAddon + { + public int? GarrTalentTreeID; + } + public class PointOfInterest { public uint Id; diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 59c282b7f..66c9dc6cc 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -3111,5 +3111,14 @@ namespace Game.Entities SendPacket(displayToast); } + + void SendGarrisonOpenTalentNpc(ObjectGuid guid, int garrTalentTreeId, int friendshipFactionId) + { + GarrisonOpenTalentNpc openTalentNpc = new(); + openTalentNpc.NpcGUID = guid; + openTalentNpc.GarrTalentTreeID = garrTalentTreeId; + openTalentNpc.FriendshipFactionID = friendshipFactionId; + SendPacket(openTalentNpc); + } } } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index cde97b953..a61b5b3ee 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2612,6 +2612,13 @@ namespace Game.Entities PlayerTalkClass.SendCloseGossip(); SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs); break; + case GossipOptionNpc.GarrisonTalent: + { + GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId); + GossipMenuItemAddon itemAddon = Global.ObjectMgr.GetGossipMenuItemAddon(menuId, gossipListId); + SendGarrisonOpenTalentNpc(guid, itemAddon != null ? itemAddon.GarrTalentTreeID.GetValueOrDefault(0) : 0, addon != null ? addon.FriendshipFactionID : 0); + break; + } case GossipOptionNpc.Transmogrify: GetSession().SendOpenTransmogrifier(guid); break; diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 5a71ab8c0..160928048 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -661,7 +661,7 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, $"Loaded {gossipMenuItemsStorage.Count} gossip_menu_option entries in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); } - public void LoadGossipMenuFriendshipFactions() + public void LoadGossipMenuAddon() { uint oldMSTime = Time.GetMSTime(); @@ -701,6 +701,42 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, $"Loaded {_gossipMenuAddonStorage.Count} gossip_menu_addon IDs in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); } + public void LoadGossipMenuItemAddon() + { + uint oldMSTime = Time.GetMSTime(); + + _gossipMenuItemAddonStorage.Clear(); + + // 0 1 2 + SQLResult result = DB.World.Query("SELECT MenuID, OptionId, GarrTalentTreeID FROM gossip_menu_option_addon"); + if (result.IsEmpty()) + { + Log.outInfo(LogFilter.ServerLoading, "Loaded 0 gossip_menu_option_addon IDs. DB table `gossip_menu_option_addon` is empty!"); + return; + } + + do + { + uint menuId = result.Read(0); + uint optionId = result.Read(1); + GossipMenuItemAddon addon = new(); + if (!result.IsNull(2)) + { + addon.GarrTalentTreeID = result.Read(2); + + if (!CliDB.GarrTalentTreeStorage.ContainsKey(addon.GarrTalentTreeID.Value)) + { + Log.outError(LogFilter.Sql, $"Table gossip_menu_option_addon: MenuID {menuId} OptionID {optionId} is using non-existing GarrTalentTree {addon.GarrTalentTreeID.Value}"); + addon.GarrTalentTreeID = null; + } + } + + _gossipMenuItemAddonStorage[Tuple.Create(menuId, optionId)] = addon; + + } while (result.NextRow()); + + Log.outInfo(LogFilter.ServerLoading, $"Loaded {_gossipMenuItemAddonStorage.Count} gossip_menu_option_addon IDs in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); + } public void LoadPointsOfInterest() { @@ -756,6 +792,10 @@ namespace Game { return _gossipMenuAddonStorage.LookupByKey(menuId); } + public GossipMenuItemAddon GetGossipMenuItemAddon(uint menuId, uint optionId) + { + return _gossipMenuItemAddonStorage.LookupByKey(Tuple.Create(menuId, optionId)); + } public PointOfInterest GetPointOfInterest(uint id) { return pointsOfInterestStorage.LookupByKey(id); @@ -10863,6 +10903,7 @@ namespace Game MultiMap gossipMenusStorage = new(); MultiMap gossipMenuItemsStorage = new(); Dictionary _gossipMenuAddonStorage = new(); + Dictionary, GossipMenuItemAddon> _gossipMenuItemAddonStorage = new(); Dictionary pointsOfInterestStorage = new(); //Creature diff --git a/Source/Game/Networking/Packets/GarrisonPackets.cs b/Source/Game/Networking/Packets/GarrisonPackets.cs index 5104e1469..d28d24636 100644 --- a/Source/Game/Networking/Packets/GarrisonPackets.cs +++ b/Source/Game/Networking/Packets/GarrisonPackets.cs @@ -317,6 +317,22 @@ namespace Game.Networking.Packets public uint GarrPlotInstanceID; } + class GarrisonOpenTalentNpc : ServerPacket + { + public GarrisonOpenTalentNpc() : base(ServerOpcodes.GarrisonOpenTalentNpc, ConnectionType.Instance) { } + + public override void Write() + { + _worldPacket.WritePackedGuid(NpcGUID); + _worldPacket.WriteInt32(GarrTalentTreeID); + _worldPacket.WriteInt32(FriendshipFactionID); + } + + public ObjectGuid NpcGUID; + public int GarrTalentTreeID; + public int FriendshipFactionID; // Always 0 except on The Deaths of Chromie Scenario + } + //Structs public struct GarrisonPlotInfo { diff --git a/Source/Game/World/WorldManager.cs b/Source/Game/World/WorldManager.cs index b79dab43f..27d31a204 100644 --- a/Source/Game/World/WorldManager.cs +++ b/Source/Game/World/WorldManager.cs @@ -887,8 +887,11 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu options..."); Global.ObjectMgr.LoadGossipMenuItems(); - Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu friendship factions..."); - Global.ObjectMgr.LoadGossipMenuFriendshipFactions(); + Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu addon..."); + Global.ObjectMgr.LoadGossipMenuAddon(); + + Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu item addon..."); + Global.ObjectMgr.LoadGossipMenuItemAddon(); Log.outInfo(LogFilter.ServerLoading, "Loading Creature trainers..."); Global.ObjectMgr.LoadCreatureTrainers(); // must be after LoadGossipMenuItems