From dbf746f9ea3a50c7766204e98f6988a942a8a93e Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 8 Sep 2022 18:06:18 -0400 Subject: [PATCH] Core/Gossip: Drop OptionType for gossip_menu_option and rename OptionIcon to OptionNpc as it also determines functionality on client side Port From (https://github.com/TrinityCore/TrinityCore/commit/69e0249807f5a8f351e6be6f7350ebace3d2997a) --- Source/Framework/Constants/GossipConst.cs | 60 +++--- Source/Game/Entities/Creature/Gossip.cs | 28 +-- Source/Game/Entities/Player/Player.Talents.cs | 4 +- Source/Game/Entities/Player/Player.cs | 202 +++++++++++------- Source/Game/Globals/ObjectManager.cs | 48 +++-- Source/Game/Handlers/SkillHandler.cs | 6 - Source/Game/Networking/Packets/NPCPackets.cs | 4 +- Source/Game/Scripting/CoreScripts.cs | 8 +- Source/Game/Spells/SpellEffects.cs | 2 +- .../BlackrockDepths/TombOfSeven.cs | 8 +- Source/Scripts/World/GameObject.cs | 2 +- Source/Scripts/World/NpcSpecial.cs | 39 ---- .../world/master/2022_09_08_00_world.sql | 22 ++ 13 files changed, 224 insertions(+), 209 deletions(-) create mode 100644 sql/updates/world/master/2022_09_08_00_world.sql diff --git a/Source/Framework/Constants/GossipConst.cs b/Source/Framework/Constants/GossipConst.cs index dddc1d6f0..305ef8524 100644 --- a/Source/Framework/Constants/GossipConst.cs +++ b/Source/Framework/Constants/GossipConst.cs @@ -44,7 +44,7 @@ namespace Framework.Constants Max } - public enum GossipOptionIcon + public enum GossipOptionNpc { None = 0, // White chat bubble. Default Vendor = 1, // Brown bag @@ -59,39 +59,39 @@ namespace Framework.Constants Auctioneer = 10, // Stack of gold coins TalentMaster = 11, // White chat bubble StableMaster = 12, // White chat bubble - PetSpecializationMaster = 13, // White chat bubble - GuildBanker = 14, // White chat bubble - SpellClick = 15, // White chat bubble + PetSpecializationMaster = 13, /*DEPRECATED*/ // White chat bubble + GuildBanker = 14, /*NYI*/ // White chat bubble + SpellClick = 15, /*NYI*/ // White chat bubble DisableXPGain = 16, // White chat bubble EnableXPGain = 17, // White chat bubble Mailbox = 18, // White chat bubble - WorldPVPQueue = 19, // White chat bubble - DungeonFinder = 20, // White chat bubble - ArtifactRespec = 21, // White chat bubble - CemeterySelect = 22, // White chat bubble - SpecializationMaster = 23, // White chat bubble - GlyphMaster = 24, // White chat bubble - ScenarioQueue = 25, // White chat bubble - GarrisonArchitect = 26, // White chat bubble - GarrisonMission = 27, // White chat bubble - GarrisonShipment = 28, // Brown document - GarrisonTradeskill = 29, // White chat bubble - GarrisonRecruitment = 30, // White chat bubble - AdventureMap = 31, // White chat bubble - GarrisonTalent = 32, // White chat bubble - ContributionCollector = 33, // White chat bubble + WorldPVPQueue = 19, /*NYI*/ // White chat bubble + LFGDungeon = 20, /*NYI*/ // White chat bubble + ArtifactRespec = 21, /*NYI*/ // White chat bubble + CemeterySelect = 22, /*DEPRECATED*/ // White chat bubble + SpecializationMaster = 23, /*DEPRECATED*/ // White chat bubble + GlyphMaster = 24, /*DEPRECATED*/ // White chat bubble + QueueScenario = 25, /*NYI*/ // White chat bubble + GarrisonArchitect = 26, /*NYI*/ // White chat bubble + GarrisonMission = 27, /*NYI*/ // White chat bubble + ShipmentCrafter = 28, /*NYI*/ // Brown document + GarrisonTradeskill = 29, /*NYI*/ // White chat bubble + GarrisonRecruitment = 30, /*NYI*/ // White chat bubble + AdventureMap = 31, /*NYI*/ // White chat bubble + GarrisonTalent = 32, /*NYI*/ // White chat bubble + ContributionCollector = 33, /*NYI*/ // White chat bubble Transmogrify = 34, // Purple helm - AzeriteRespec = 35, // White chat bubble - IslandsQueue = 36, // White chat bubble - UIItemInteraction = 37, // White chat bubble - WorldMap = 38, // White chat bubble - Unk39 = 39, // - ChromieTime = 40, // White chat bubble - Unk41 = 41, // - RuneforgeCrafting = 42, // White chat bubble - GuideRecruiter = 43, // White chat bubble - RuneforgeUpgrading = 44, // White chat bubble - CovenantRenown = 45, // White chat bubble + AzeriteRespec = 35, /*NYI*/ // White chat bubble + IslandsMission = 36, /*NYI*/ // White chat bubble + UIItemInteraction = 37, /*NYI*/ // White chat bubble + WorldMap = 38, /*NYI*/ // White chat bubble + Soulbind = 39, /*NYI*/ // White chat bubble + ChromieTime = 40, /*NYI*/ // White chat bubble + CovenantPreview = 41, /*NYI*/ // White chat bubble + RuneforgeLegendaryCrafting = 42, /*NYI*/ // White chat bubble + NewPlayerGuide = 43, /*NYI*/ // White chat bubble + RuneforgeLegendaryUpgrade = 44, /*NYI*/ // White chat bubble + CovenantRenown = 45, /*NYI*/ // White chat bubble Max } diff --git a/Source/Game/Entities/Creature/Gossip.cs b/Source/Game/Entities/Creature/Gossip.cs index b21769505..7d16ca079 100644 --- a/Source/Game/Entities/Creature/Gossip.cs +++ b/Source/Game/Entities/Creature/Gossip.cs @@ -29,7 +29,7 @@ namespace Game.Misc { public class GossipMenu { - public uint AddMenuItem(int menuItemId, GossipOptionIcon icon, string message, uint sender, uint action, string boxMessage, uint boxMoney, bool coded = false) + public uint AddMenuItem(int menuItemId, GossipOptionNpc optionNpc, string message, uint sender, uint action, string boxMessage, uint boxMoney, bool coded = false) { Cypher.Assert(_menuItems.Count <= SharedConst.MaxGossipMenuItems); @@ -51,11 +51,11 @@ namespace Game.Misc GossipMenuItem menuItem = new(); - menuItem.MenuItemIcon = (byte)icon; + menuItem.OptionNpc = optionNpc; menuItem.Message = message; menuItem.IsCoded = coded; menuItem.Sender = sender; - menuItem.OptionType = action; + menuItem.Action = action; menuItem.BoxMessage = boxMessage; menuItem.BoxMoney = boxMoney; @@ -124,7 +124,7 @@ namespace Game.Misc } // Add menu item with existing method. Menu item id -1 is also used in ADD_GOSSIP_ITEM macro. - uint newOptionId = AddMenuItem(-1, item.OptionIcon, strOptionText, sender, action, strBoxText, item.BoxMoney, item.BoxCoded); + uint newOptionId = AddMenuItem(-1, item.OptionNpc, strOptionText, sender, action, strBoxText, item.BoxMoney, item.BoxCoded); AddGossipMenuItemData(newOptionId, item.ActionMenuId, item.ActionPoiId); } } @@ -150,7 +150,7 @@ namespace Game.Misc public uint GetMenuItemAction(uint menuItemId) { if (_menuItems.ContainsKey(menuItemId)) - return _menuItems.LookupByKey(menuItemId).OptionType; + return _menuItems.LookupByKey(menuItemId).Action; else return 0; } @@ -163,15 +163,6 @@ namespace Game.Misc return false; } - public bool HasMenuItemType(uint optionType) - { - foreach (var menuItemPair in _menuItems) - if (menuItemPair.Value.OptionType == optionType) - return true; - - return false; - } - public void ClearMenu() { _menuItems.Clear(); @@ -264,7 +255,7 @@ namespace Game.Misc ClientGossipOptions opt = new(); GossipMenuItem item = pair.Value; opt.ClientOption = (int)pair.Key; - opt.OptionNPC = item.MenuItemIcon; + opt.OptionNPC = item.OptionNpc; opt.OptionFlags = (byte)(item.IsCoded ? 1 : 0); // makes pop up box password opt.OptionCost = (int)item.BoxMoney; // money required to open menu, 2.0.3 opt.OptionLanguage = item.Language; @@ -701,11 +692,11 @@ namespace Game.Misc public class GossipMenuItem { - public byte MenuItemIcon; + public GossipOptionNpc OptionNpc; public bool IsCoded; public string Message; public uint Sender; - public uint OptionType; + public uint Action; public string BoxMessage; public uint BoxMoney; public uint Language; @@ -737,10 +728,9 @@ namespace Game.Misc { public uint MenuId; public uint OptionId; - public GossipOptionIcon OptionIcon; + public GossipOptionNpc OptionNpc; public string OptionText; public uint OptionBroadcastTextId; - public GossipOption OptionType; public NPCFlags OptionNpcFlag; public uint Language; public uint ActionMenuId; diff --git a/Source/Game/Entities/Player/Player.Talents.cs b/Source/Game/Entities/Player/Player.Talents.cs index f879f651d..68093a609 100644 --- a/Source/Game/Entities/Player/Player.Talents.cs +++ b/Source/Game/Entities/Player/Player.Talents.cs @@ -642,12 +642,12 @@ namespace Game.Entities SendPacket(packet); } - public void SendRespecWipeConfirm(ObjectGuid guid, uint cost) + public void SendRespecWipeConfirm(ObjectGuid guid, uint cost, SpecResetType respecType) { RespecWipeConfirm respecWipeConfirm = new(); respecWipeConfirm.RespecMaster = guid; respecWipeConfirm.Cost = cost; - respecWipeConfirm.RespecType = SpecResetType.Talents; + respecWipeConfirm.RespecType = respecType; SendPacket(respecWipeConfirm); } diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 16130a271..87e93274c 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2326,60 +2326,90 @@ namespace Game.Entities if (!menuItems.OptionNpcFlag.HasAnyFlag(npcflags)) continue; - switch (menuItems.OptionType) + switch (menuItems.OptionNpc) { - case GossipOption.Armorer: - canTalk = false; // added in special mode - break; - case GossipOption.Spirithealer: - if (!IsDead()) - canTalk = false; - break; - case GossipOption.Learndualspec: - canTalk = false; - break; - case GossipOption.Unlearntalents: - if (!creature.CanResetTalents(this)) - canTalk = false; - break; - case GossipOption.Taxivendor: + case GossipOptionNpc.TaxiNode: if (GetSession().SendLearnNewTaxiNode(creature)) return; break; - case GossipOption.Battlefield: + case GossipOptionNpc.SpiritHealer: + if (!IsDead()) + canTalk = false; + break; + case GossipOptionNpc.BattleMaster: if (!creature.CanInteractWithBattleMaster(this, false)) canTalk = false; break; - case GossipOption.Stablepet: + case GossipOptionNpc.TalentMaster: + case GossipOptionNpc.SpecializationMaster: + case GossipOptionNpc.GlyphMaster: + if (!creature.CanResetTalents(this)) + canTalk = false; + break; + case GossipOptionNpc.StableMaster: + case GossipOptionNpc.PetSpecializationMaster: if (GetClass() != Class.Hunter) canTalk = false; break; - case GossipOption.Questgiver: - canTalk = false; + case GossipOptionNpc.DisableXPGain: + if (HasPlayerFlag(PlayerFlags.NoXPGain)) + canTalk = false; break; - case GossipOption.Gossip: - case GossipOption.Vendor: - case GossipOption.Trainer: - case GossipOption.Spiritguide: - case GossipOption.Innkeeper: - case GossipOption.Banker: - case GossipOption.Petitioner: - case GossipOption.Tabarddesigner: - case GossipOption.Auctioneer: - case GossipOption.Transmogrifier: - case GossipOption.Mailbox: - break; // no checks + case GossipOptionNpc.EnableXPGain: + if (!HasPlayerFlag(PlayerFlags.NoXPGain)) + canTalk = false; + break; + case GossipOptionNpc.None: + case GossipOptionNpc.Vendor: + case GossipOptionNpc.Trainer: + case GossipOptionNpc.Binder: + case GossipOptionNpc.Banker: + case GossipOptionNpc.PetitionVendor: + case GossipOptionNpc.TabardVendor: + case GossipOptionNpc.Auctioneer: + case GossipOptionNpc.Mailbox: + case GossipOptionNpc.Transmogrify: + break; // No checks + case GossipOptionNpc.CemeterySelect: + canTalk = false; // Deprecated + break; + case GossipOptionNpc.GuildBanker: + case GossipOptionNpc.SpellClick: + case GossipOptionNpc.WorldPVPQueue: + case GossipOptionNpc.LFGDungeon: + case GossipOptionNpc.ArtifactRespec: + case GossipOptionNpc.QueueScenario: + case GossipOptionNpc.GarrisonArchitect: + case GossipOptionNpc.GarrisonMission: + case GossipOptionNpc.ShipmentCrafter: + case GossipOptionNpc.GarrisonTradeskill: + case GossipOptionNpc.GarrisonRecruitment: + case GossipOptionNpc.AdventureMap: + case GossipOptionNpc.GarrisonTalent: + case GossipOptionNpc.ContributionCollector: + case GossipOptionNpc.AzeriteRespec: + case GossipOptionNpc.IslandsMission: + case GossipOptionNpc.UIItemInteraction: + case GossipOptionNpc.WorldMap: + case GossipOptionNpc.Soulbind: + case GossipOptionNpc.ChromieTime: + case GossipOptionNpc.CovenantPreview: + case GossipOptionNpc.RuneforgeLegendaryCrafting: + case GossipOptionNpc.NewPlayerGuide: + case GossipOptionNpc.RuneforgeLegendaryUpgrade: + case GossipOptionNpc.CovenantRenown: + break; // NYI default: - Log.outError(LogFilter.Sql, "Creature entry {0} have unknown gossip option {1} for menu {2}", creature.GetEntry(), menuItems.OptionType, menuItems.MenuId); + Log.outError(LogFilter.Sql, $"Creature entry {creature.GetEntry()} has an unknown gossip option icon {menuItems.OptionNpc} for menu {menuItems.MenuId}."); canTalk = false; break; } } else if (go != null) { - switch (menuItems.OptionType) + switch (menuItems.OptionNpc) { - case GossipOption.Gossip: + case GossipOptionNpc.None: if (go.GetGoType() != GameObjectTypes.QuestGiver && go.GetGoType() != GameObjectTypes.Goober) canTalk = false; break; @@ -2426,7 +2456,7 @@ namespace Game.Entities } } - menu.GetGossipMenu().AddMenuItem((int)menuItems.OptionId, menuItems.OptionIcon, strOptionText, 0, (uint)menuItems.OptionType, strBoxText, menuItems.BoxMoney, menuItems.BoxCoded); + menu.GetGossipMenu().AddMenuItem((int)menuItems.OptionId, menuItems.OptionNpc, strOptionText, 0, (uint)menuItems.OptionNpc, strBoxText, menuItems.BoxMoney, menuItems.BoxCoded); menu.GetGossipMenu().AddGossipMenuItemData(menuItems.OptionId, menuItems.ActionMenuId, menuItems.ActionPoiId); } } @@ -2467,12 +2497,12 @@ namespace Game.Entities if (item == null) return; - uint gossipOptionType = item.OptionType; + GossipOptionNpc gossipOptionNpc = item.OptionNpc; ObjectGuid guid = source.GetGUID(); if (source.IsTypeId(TypeId.GameObject)) { - if (gossipOptionType > (int)GossipOption.Questgiver) + if (gossipOptionNpc != GossipOptionNpc.None) { Log.outError(LogFilter.Player, "Player guid {0} request invalid gossip option for GameObject entry {1}", GetGUID().ToString(), source.GetEntry()); return; @@ -2491,9 +2521,9 @@ namespace Game.Entities return; } - switch ((GossipOption)gossipOptionType) + switch (gossipOptionNpc) { - case GossipOption.Gossip: + case GossipOptionNpc.None: { if (menuItemData.GossipActionPoi != 0) PlayerTalkClass.SendPointOfInterest(menuItemData.GossipActionPoi); @@ -2506,56 +2536,36 @@ namespace Game.Entities break; } - case GossipOption.Spirithealer: - if (IsDead()) - source.ToCreature().CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCaster(GetGUID())); - break; - case GossipOption.Questgiver: - PrepareQuestMenu(guid); - SendPreparedQuest(source); - break; - case GossipOption.Vendor: - case GossipOption.Armorer: + case GossipOptionNpc.Vendor: GetSession().SendListInventory(guid); break; - case GossipOption.Stablepet: - GetSession().SendStablePet(guid); - break; - case GossipOption.Trainer: - GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, gossipListId)); - break; - case GossipOption.Learndualspec: - break; - case GossipOption.Unlearntalents: - PlayerTalkClass.SendCloseGossip(); - SendRespecWipeConfirm(guid, GetNextResetTalentsCost()); - break; - case GossipOption.Taxivendor: + case GossipOptionNpc.TaxiNode: GetSession().SendTaxiMenu(source.ToCreature()); break; - case GossipOption.Innkeeper: + case GossipOptionNpc.Trainer: + GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, gossipListId)); + break; + case GossipOptionNpc.SpiritHealer: + if (IsDead()) + source.ToCreature().CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask) + .SetOriginalCaster(GetGUID())); + break; + case GossipOptionNpc.Binder: PlayerTalkClass.SendCloseGossip(); SetBindPoint(guid); break; - case GossipOption.Banker: + case GossipOptionNpc.Banker: GetSession().SendShowBank(guid); break; - case GossipOption.Petitioner: + case GossipOptionNpc.PetitionVendor: PlayerTalkClass.SendCloseGossip(); GetSession().SendPetitionShowList(guid); break; - case GossipOption.Tabarddesigner: + case GossipOptionNpc.TabardVendor: PlayerTalkClass.SendCloseGossip(); GetSession().SendTabardVendorActivate(guid); break; - case GossipOption.Auctioneer: - GetSession().SendAuctionHello(guid, source.ToCreature()); - break; - case GossipOption.Spiritguide: - PrepareGossipMenu(source); - SendPreparedGossip(source); - break; - case GossipOption.Battlefield: + case GossipOptionNpc.BattleMaster: { BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.GetBattleMasterBG(source.GetEntry()); @@ -2568,11 +2578,43 @@ namespace Game.Entities Global.BattlegroundMgr.SendBattlegroundList(this, guid, bgTypeId); break; } - case GossipOption.Transmogrifier: + case GossipOptionNpc.Auctioneer: + GetSession().SendAuctionHello(guid, source.ToCreature()); + break; + case GossipOptionNpc.TalentMaster: + PlayerTalkClass.SendCloseGossip(); + SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents); + break; + case GossipOptionNpc.StableMaster: + GetSession().SendStablePet(guid); + break; + case GossipOptionNpc.PetSpecializationMaster: + PlayerTalkClass.SendCloseGossip(); + SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.PetTalents); + break; + case GossipOptionNpc.DisableXPGain: + PlayerTalkClass.SendCloseGossip(); + SetPlayerFlag(PlayerFlags.NoXPGain); + break; + case GossipOptionNpc.EnableXPGain: + PlayerTalkClass.SendCloseGossip(); + RemovePlayerFlag(PlayerFlags.NoXPGain); + break; + case GossipOptionNpc.Mailbox: + GetSession().SendShowMailBox(guid); + break; + case GossipOptionNpc.SpecializationMaster: + PlayerTalkClass.SendCloseGossip(); + SendRespecWipeConfirm(guid, 0, SpecResetType.Specialization); + break; + case GossipOptionNpc.GlyphMaster: + PlayerTalkClass.SendCloseGossip(); + SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs); + break; + case GossipOptionNpc.Transmogrify: GetSession().SendOpenTransmogrifier(guid); break; - case GossipOption.Mailbox: - GetSession().SendShowMailBox(guid); + default: break; } @@ -7345,9 +7387,9 @@ namespace Game.Entities } //Helpers - public void AddGossipItem(GossipOptionIcon icon, string message, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, "", 0); } + public void AddGossipItem(GossipOptionNpc icon, string message, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, "", 0); } public void AddGossipItem(uint menuId, uint menuItemId, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(menuId, menuItemId, sender, action); } - public void ADD_GOSSIP_ITEM_EXTENDED(GossipOptionIcon icon, string message, uint sender, uint action, string boxmessage, uint boxmoney, bool coded) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, boxmessage, boxmoney, coded); } + public void ADD_GOSSIP_ITEM_EXTENDED(GossipOptionNpc icon, string message, uint sender, uint action, string boxmessage, uint boxmoney, bool coded) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, boxmessage, boxmoney, coded); } // This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64) public void SendGossipMenu(uint titleId, ObjectGuid objGUID) { PlayerTalkClass.SendGossipMenu(titleId, objGUID); } diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 5ed2828c4..e7b959ff3 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -579,8 +579,8 @@ namespace Game gossipMenuItemsStorage.Clear(); - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 - SQLResult result = DB.World.Query("SELECT MenuID, OptionID, OptionIcon, OptionText, OptionBroadcastTextID, OptionType, OptionNpcFlag, Language, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID " + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + SQLResult result = DB.World.Query("SELECT MenuID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, OptionNpcFlag, Language, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID " + "FROM gossip_menu_option ORDER BY MenuID, OptionID"); if (result.IsEmpty()) @@ -595,23 +595,22 @@ namespace Game gMenuItem.MenuId = result.Read(0); gMenuItem.OptionId = result.Read(1); - gMenuItem.OptionIcon = (GossipOptionIcon)result.Read(2); + gMenuItem.OptionNpc = (GossipOptionNpc)result.Read(2); gMenuItem.OptionText = result.Read(3); gMenuItem.OptionBroadcastTextId = result.Read(4); - gMenuItem.OptionType = (GossipOption)result.Read(5); - gMenuItem.OptionNpcFlag = (NPCFlags)result.Read(6); - gMenuItem.Language = result.Read(7); - gMenuItem.ActionMenuId = result.Read(8); - gMenuItem.ActionPoiId = result.Read(9); - gMenuItem.BoxCoded = result.Read(10); - gMenuItem.BoxMoney = result.Read(11); - gMenuItem.BoxText = result.Read(12); - gMenuItem.BoxBroadcastTextId = result.Read(13); + gMenuItem.OptionNpcFlag = (NPCFlags)result.Read(5); + gMenuItem.Language = result.Read(6); + gMenuItem.ActionMenuId = result.Read(7); + gMenuItem.ActionPoiId = result.Read(8); + gMenuItem.BoxCoded = result.Read(9); + gMenuItem.BoxMoney = result.Read(10); + gMenuItem.BoxText = result.Read(11); + gMenuItem.BoxBroadcastTextId = result.Read(12); - if (gMenuItem.OptionIcon >= GossipOptionIcon.Max) + if (gMenuItem.OptionNpc >= GossipOptionNpc.Max) { - Log.outError(LogFilter.Sql, $"Table gossip_menu_option for MenuId {gMenuItem.MenuId}, OptionIndex {gMenuItem.OptionId} has unknown icon id {gMenuItem.OptionIcon}. Replacing with GossipOptionIcon.Chat"); - gMenuItem.OptionIcon = GossipOptionIcon.None; + Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} has unknown NPC option id {gMenuItem.OptionNpc}. Replacing with GossipOptionNpc.None"); + gMenuItem.OptionNpc = GossipOptionNpc.None; } if (gMenuItem.OptionBroadcastTextId != 0) @@ -623,18 +622,25 @@ namespace Game } } - if (gMenuItem.OptionType >= GossipOption.Max) - Log.outError(LogFilter.Sql, $"Table gossip_menu_option for MenuId {gMenuItem.MenuId}, OptionIndex {gMenuItem.OptionId} has unknown option id {gMenuItem.OptionType}. Option will not be used"); - if (gMenuItem.Language != 0 && !CliDB.LanguagesStorage.ContainsKey(gMenuItem.Language)) { Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} use non-existing Language {gMenuItem.Language}, ignoring"); gMenuItem.Language = 0; } - if (gMenuItem.ActionPoiId != 0 && GetPointOfInterest(gMenuItem.ActionPoiId) == null) + if (gMenuItem.ActionMenuId != 0 && gMenuItem.OptionNpc != GossipOptionNpc.None) { - Log.outError(LogFilter.Sql, $"Table gossip_menu_option for MenuId {gMenuItem.MenuId}, OptionIndex {gMenuItem.OptionId} use non-existing actionpoiid {gMenuItem.ActionPoiId}, ignoring"); + Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} can not use ActionMenuID for GossipOptionNpc different from GossipOptionNpc.None, ignoring"); + gMenuItem.ActionMenuId = 0; + } + + if (gMenuItem.ActionPoiId != 0) + { + if (gMenuItem.OptionNpc != GossipOptionNpc.None) + Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} can not use ActionPoiID for GossipOptionNpc different from GossipOptionNpc.None, ignoring"); + else if (GetPointOfInterest(gMenuItem.ActionPoiId) == null) + Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} use non-existing ActionPoiID {gMenuItem.ActionPoiId}, ignoring"); + gMenuItem.ActionPoiId = 0; } @@ -4493,7 +4499,7 @@ namespace Game stmt.AddValue(2, guid); DB.World.Execute(stmt); } - + // if not this is to be managed by GameEvent System if (gameEvent == 0) AddGameObjectToGrid(data); diff --git a/Source/Game/Handlers/SkillHandler.cs b/Source/Game/Handlers/SkillHandler.cs index cf34e5571..cd36c1f14 100644 --- a/Source/Game/Handlers/SkillHandler.cs +++ b/Source/Game/Handlers/SkillHandler.cs @@ -97,18 +97,12 @@ namespace Game if (!unit.CanResetTalents(_player)) return; - if (!_player.PlayerTalkClass.GetGossipMenu().HasMenuItemType((uint)GossipOption.Unlearntalents)) - return; - // remove fake death if (GetPlayer().HasUnitState(UnitState.Died)) GetPlayer().RemoveAurasByType(AuraType.FeignDeath); if (!GetPlayer().ResetTalents()) - { - GetPlayer().SendRespecWipeConfirm(ObjectGuid.Empty, 0); return; - } GetPlayer().SendTalentsInfoData(); unit.CastSpell(GetPlayer(), 14867, true); //spell: "Untalent Visual Effect" diff --git a/Source/Game/Networking/Packets/NPCPackets.cs b/Source/Game/Networking/Packets/NPCPackets.cs index b5bc6bfbc..9b8282dbd 100644 --- a/Source/Game/Networking/Packets/NPCPackets.cs +++ b/Source/Game/Networking/Packets/NPCPackets.cs @@ -60,7 +60,7 @@ namespace Game.Networking.Packets foreach (ClientGossipOptions options in GossipOptions) { _worldPacket.WriteInt32(options.ClientOption); - _worldPacket.WriteUInt8(options.OptionNPC); + _worldPacket.WriteUInt8((byte)options.OptionNPC); _worldPacket.WriteUInt8(options.OptionFlags); _worldPacket.WriteInt32(options.OptionCost); _worldPacket.WriteUInt32(options.OptionLanguage); @@ -345,7 +345,7 @@ namespace Game.Networking.Packets public class ClientGossipOptions { public int ClientOption; - public byte OptionNPC; + public GossipOptionNpc OptionNPC; public byte OptionFlags; public int OptionCost; public uint OptionLanguage; diff --git a/Source/Game/Scripting/CoreScripts.cs b/Source/Game/Scripting/CoreScripts.cs index dd8e38eef..f6997bdaf 100644 --- a/Source/Game/Scripting/CoreScripts.cs +++ b/Source/Game/Scripting/CoreScripts.cs @@ -57,14 +57,14 @@ namespace Game.Scripting public static void ClearGossipMenuFor(Player player) { player.PlayerTalkClass.ClearMenus(); } // Using provided text, not from DB - public static void AddGossipItemFor(Player player, GossipOptionIcon icon, string text, uint sender, uint action) + public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action) { - player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, text, sender, action, "", 0); + player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, optionNpc, text, sender, action, "", 0); } // Using provided texts, not from DB - public static void AddGossipItemFor(Player player, GossipOptionIcon icon, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded) + public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded) { - player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, text, sender, action, popupText, popupMoney, coded); + player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, optionNpc, text, sender, action, popupText, popupMoney, coded); } // Uses gossip item info from DB public static void AddGossipItemFor(Player player, uint gossipMenuID, uint gossipMenuItemID, uint sender, uint action) diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index c2ee2d153..b57c688e8 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -1956,7 +1956,7 @@ namespace Game.Spells ObjectGuid guid = m_caster.GetGUID(); if (!guid.IsEmpty()) // the trainer is the caster - unitTarget.ToPlayer().SendRespecWipeConfirm(guid, unitTarget.ToPlayer().GetNextResetTalentsCost()); + unitTarget.ToPlayer().SendRespecWipeConfirm(guid, unitTarget.ToPlayer().GetNextResetTalentsCost(), SpecResetType.Talents); } [SpellEffectHandler(SpellEffectName.TeleportUnitsFaceCaster)] diff --git a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/TombOfSeven.cs b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/TombOfSeven.cs index a732296cd..2bac63188 100644 --- a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/TombOfSeven.cs +++ b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/TombOfSeven.cs @@ -86,7 +86,7 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths.TombOfSeven switch (action) { case eTradeskill.GossipActionInfoDef + 1: - player.AddGossipItem(GossipOptionIcon.None, MiscConst.GossipItemTeach2, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 11); + player.AddGossipItem(GossipOptionNpc.None, MiscConst.GossipItemTeach2, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 11); player.SendGossipMenu(2606, me.GetGUID()); break; case eTradeskill.GossipActionInfoDef + 11: @@ -94,7 +94,7 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths.TombOfSeven player.CastSpell(player, SpellIds.LearnSmelt, false); break; case eTradeskill.GossipActionInfoDef + 2: - player.AddGossipItem(GossipOptionIcon.None, MiscConst.GossipItemTeach3, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 22); + player.AddGossipItem(GossipOptionNpc.None, MiscConst.GossipItemTeach3, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 22); player.SendGossipMenu(2604, me.GetGUID()); break; case eTradeskill.GossipActionInfoDef + 22: @@ -109,10 +109,10 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths.TombOfSeven public override bool OnGossipHello(Player player) { if (player.GetQuestRewardStatus(QuestIds.SpectralChalice) && player.GetSkillValue(SkillType.Mining) >= MiscConst.DataSkillpointMin && !player.HasSpell(SpellIds.SmeltDarkIron)) - player.AddGossipItem(GossipOptionIcon.None, MiscConst.GossipItemTeach1, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1); + player.AddGossipItem(GossipOptionNpc.None, MiscConst.GossipItemTeach1, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1); if (!player.GetQuestRewardStatus(QuestIds.SpectralChalice) && player.GetSkillValue(SkillType.Mining) >= MiscConst.DataSkillpointMin) - player.AddGossipItem(GossipOptionIcon.None, MiscConst.GossipItemTribute, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 2); + player.AddGossipItem(GossipOptionNpc.None, MiscConst.GossipItemTribute, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 2); player.SendGossipMenu(player.GetGossipTextId(me), me.GetGUID()); return true; diff --git a/Source/Scripts/World/GameObject.cs b/Source/Scripts/World/GameObject.cs index 7d63400c7..4b048c1fe 100644 --- a/Source/Scripts/World/GameObject.cs +++ b/Source/Scripts/World/GameObject.cs @@ -471,7 +471,7 @@ namespace Scripts.World.GameObjects QuestStatus status = player.GetQuestStatus(QuestIds.DoingYourDuty); if (status == QuestStatus.Incomplete || status == QuestStatus.Complete || status == QuestStatus.Rewarded) { - player.AddGossipItem(GossipOptionIcon.None, GossipConst.GossipUseOuthouse, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1); + player.AddGossipItem(GossipOptionNpc.None, GossipConst.GossipUseOuthouse, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1); player.SendGossipMenu(GossipConst.GossipOuthouseVacant, me.GetGUID()); } else diff --git a/Source/Scripts/World/NpcSpecial.cs b/Source/Scripts/World/NpcSpecial.cs index 6819e9dfe..ffeb9f97c 100644 --- a/Source/Scripts/World/NpcSpecial.cs +++ b/Source/Scripts/World/NpcSpecial.cs @@ -1475,45 +1475,6 @@ namespace Scripts.World.NpcSpecial bool _showUnderground; } - [Script] - class npc_experience : ScriptedAI - { - public npc_experience(Creature creature) : base(creature) { } - - public override bool OnGossipHello(Player player) - { - if (player.HasPlayerFlag(PlayerFlags.NoXPGain)) // not gaining XP - { - player.AddGossipItem(GossipMenus.MenuIdXpOnOff, GossipMenus.OptionIdXpOn, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1); - player.SendGossipMenu(TextIds.XpOnOff, me.GetGUID()); - } - else // currently gaining XP - { - player.AddGossipItem(GossipMenus.MenuIdXpOnOff, GossipMenus.OptionIdXpOff, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 2); - player.SendGossipMenu(TextIds.XpOnOff, me.GetGUID()); - } - return true; - } - - public override bool OnGossipSelect(Player player, uint menuId, uint gossipListId) - { - uint action = player.PlayerTalkClass.GetGossipOptionAction(gossipListId); - - switch (action) - { - case eTradeskill.GossipActionInfoDef + 1:// XP ON selected - player.RemovePlayerFlag(PlayerFlags.NoXPGain); // turn on XP gain - break; - case eTradeskill.GossipActionInfoDef + 2:// XP OFF selected - player.SetPlayerFlag(PlayerFlags.NoXPGain); // turn off XP gain - break; - } - - player.PlayerTalkClass.SendCloseGossip(); - return false; - } - } - [Script] class npc_spring_rabbit : ScriptedAI { diff --git a/sql/updates/world/master/2022_09_08_00_world.sql b/sql/updates/world/master/2022_09_08_00_world.sql new file mode 100644 index 000000000..fa06f668d --- /dev/null +++ b/sql/updates/world/master/2022_09_08_00_world.sql @@ -0,0 +1,22 @@ +-- Update table `gossip_menu_option` +ALTER TABLE `gossip_menu_option` DROP `OptionType`, RENAME COLUMN `OptionIcon` TO `OptionNpc`; + +-- Update default option +DELETE FROM `gossip_menu_option` WHERE `MenuID`=0; +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionNpc`, `OptionText`, `OptionBroadcastTextId`, `OptionNpcFlag`, `Language`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(0, 1 , 1 , 'I want to browse your goods.', 3370, 128, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 2 , 2 , 'I''d like to travel by air.', 53141, 8192, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 3 , 3 , 'Train me.', 3266, 16, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 4 , 4 , 'Return me to life.', 2547, 16384, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 5 , 5 , 'Make this inn your home.', 2822, 65536, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 6 , 6 , 'I would like to check my deposit box.', 3398, 131072, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 7 , 7 , 'How do I form a guild?', 3413, 262144, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 8 , 8 , 'I want to create a guild crest.', 3415, 524288, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 9, 9 , 'I would like to go to the battleground.', 10355, 1048576, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 10, 10, 'I''d like to browse the items up for auction.', 52635, 2097152, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 12, 12, 'I''d like to stable my pet here.', 30181, 4194304, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 18, 18, 'I''d like to check my mail.', 146045, 67108864, 0, 0, 0, 0, 0, NULL, 0, 0), +(0, 34, 34, 'I want to transmogrify my gear.', 130510, 268435456, 0, 0, 0, 0, 0, NULL, 0, 0); + +-- Drop "npc_experience" script use +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry` IN (35364, 35365);