From 068c3c7ce5a7d243b34ea99fd9e505d3463c2f3a Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Tue, 19 Aug 2025 21:29:25 -0400 Subject: [PATCH] Core/Gossip: Track started interaction types and reset only questgiver on quest accept Port From (https://github.com/TrinityCore/TrinityCore/commit/c02e311eef9e635738b9e48559d5455ef016d8b4) --- .../Game/BattleGrounds/BattleGroundManager.cs | 2 + Source/Game/DataStorage/DB2Manager.cs | 1 - Source/Game/Entities/Creature/Gossip.cs | 53 ++++-- Source/Game/Entities/Player/Player.Talents.cs | 12 ++ Source/Game/Entities/Player/Player.cs | 66 ++++---- Source/Game/Handlers/AuctionHandler.cs | 2 + Source/Game/Handlers/BankHandler.cs | 4 +- Source/Game/Handlers/GuildHandler.cs | 2 + Source/Game/Handlers/MailHandler.cs | 3 +- Source/Game/Handlers/NPCHandler.cs | 13 +- Source/Game/Handlers/PetitionsHandler.cs | 3 +- Source/Game/Handlers/QuestHandler.cs | 154 ++++++++---------- Source/Game/Handlers/TaxiHandler.cs | 2 + 13 files changed, 176 insertions(+), 141 deletions(-) diff --git a/Source/Game/BattleGrounds/BattleGroundManager.cs b/Source/Game/BattleGrounds/BattleGroundManager.cs index 9501fbf74..74c72410b 100644 --- a/Source/Game/BattleGrounds/BattleGroundManager.cs +++ b/Source/Game/BattleGrounds/BattleGroundManager.cs @@ -398,6 +398,8 @@ namespace Game.BattleGrounds if (bgTemplate == null) return; + player.PlayerTalkClass.GetInteractionData().StartInteraction(guid, PlayerInteractionType.BattleMaster); + BattlefieldList battlefieldList = new(); battlefieldList.BattlemasterGuid = guid; battlefieldList.BattlemasterListID = (int)bgTypeId; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index a15adfe63..311bc5807 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -275,7 +275,6 @@ namespace Game.DataStorage _curvePoints.AddRange(curveId, curvePoints.Select(p => p.Pos)); } - foreach (EmotesTextSoundRecord emoteTextSound in EmotesTextSoundStorage.Values) _emoteTextSounds[Tuple.Create(emoteTextSound.EmotesTextId, emoteTextSound.RaceId, emoteTextSound.SexId, emoteTextSound.ClassId)] = emoteTextSound; diff --git a/Source/Game/Entities/Creature/Gossip.cs b/Source/Game/Entities/Creature/Gossip.cs index 07bd1ddcf..8e516bd58 100644 --- a/Source/Game/Entities/Creature/Gossip.cs +++ b/Source/Game/Entities/Creature/Gossip.cs @@ -207,24 +207,45 @@ namespace Game.Misc public class InteractionData { public ObjectGuid SourceGuid; + public PlayerInteractionType InteractionType; public bool IsLaunchedByQuest; ushort _playerChoiceResponseIdentifierGenerator = 0; // not reset between interactions - uint trainerId; + TrainerData trainerData; PlayerChoiceData playerChoiceData; + public void StartInteraction(ObjectGuid target, PlayerInteractionType type) + { + SourceGuid = target; + InteractionType = type; + IsLaunchedByQuest = false; + switch (type) + { + case PlayerInteractionType.Trainer: + trainerData = new(); + break; + case PlayerInteractionType.PlayerChoice: + playerChoiceData = new(); + break; + default: + break; + } + } + + public bool IsInteractingWith(ObjectGuid target, PlayerInteractionType type) { return SourceGuid == target && InteractionType == type; } + public void Reset() { SourceGuid.Clear(); + InteractionType = PlayerInteractionType.None; IsLaunchedByQuest = false; - trainerId = 0; + trainerData = null; + playerChoiceData = null; } - public uint? GetTrainerId() { return trainerId; } - public void SetTrainerId(uint _trainerId) { trainerId = _trainerId; } + public TrainerData GetTrainer() { return trainerData; } public PlayerChoiceData GetPlayerChoice() { return playerChoiceData; } - public void SetPlayerChoice(uint choiceId) { playerChoiceData = new PlayerChoiceData(choiceId); } public ushort AddPlayerChoiceResponse(uint responseId) { @@ -250,8 +271,7 @@ namespace Game.Misc public void SendGossipMenu(uint titleTextId, ObjectGuid objectGUID) { - _interactionData.Reset(); - _interactionData.SourceGuid = objectGUID; + _interactionData.StartInteraction(objectGUID, PlayerInteractionType.Gossip); GossipMessagePkt packet = new(); packet.GossipGUID = objectGUID; @@ -362,6 +382,9 @@ namespace Game.Misc public void SendQuestGiverQuestListMessage(WorldObject questgiver) { ObjectGuid guid = questgiver.GetGUID(); + + GetInteractionData().StartInteraction(guid, PlayerInteractionType.QuestGiver); + Locale localeConstant = _session.GetSessionDbLocaleIndex(); QuestGiverQuestListMessage questList = new(); @@ -429,6 +452,8 @@ namespace Game.Misc public void SendQuestGiverQuestDetails(Quest quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup) { + GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType.QuestGiver); + QuestGiverQuestDetails packet = new(); packet.QuestTitle = quest.LogTitle; @@ -532,6 +557,8 @@ namespace Game.Misc public void SendQuestGiverOfferReward(Quest quest, ObjectGuid npcGUID, bool autoLaunched) { + GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType.QuestGiver); + QuestGiverOfferRewardMessage packet = new(); packet.QuestTitle = quest.LogTitle; @@ -616,6 +643,8 @@ namespace Game.Misc return; } + GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType.QuestGiver); + QuestGiverRequestItems packet = new(); packet.QuestTitle = quest.LogTitle; @@ -852,17 +881,17 @@ namespace Game.Misc public ConditionsReference Conditions; } + public class TrainerData + { + public uint Id; + } + public class PlayerChoiceData { uint _choiceId; List _responses = new(); DateTime? _expireTime; - public PlayerChoiceData(uint choiceId) - { - _choiceId = choiceId; - } - public uint? FindIdByClientIdentifier(ushort clientIdentifier) { var itr = _responses.Find(p => p.ClientIdentifier == clientIdentifier); diff --git a/Source/Game/Entities/Player/Player.Talents.cs b/Source/Game/Entities/Player/Player.Talents.cs index a9a540373..50cd11d72 100644 --- a/Source/Game/Entities/Player/Player.Talents.cs +++ b/Source/Game/Entities/Player/Player.Talents.cs @@ -688,6 +688,18 @@ namespace Game.Entities public void SendRespecWipeConfirm(ObjectGuid guid, uint cost, SpecResetType respecType) { + switch (respecType) + { + case SpecResetType.Talents: + PlayerTalkClass.GetInteractionData().StartInteraction(guid, PlayerInteractionType.TalentMaster); + break; + case SpecResetType.Specialization: + PlayerTalkClass.GetInteractionData().StartInteraction(guid, PlayerInteractionType.SpecializationMaster); + break; + default: + break; + } + RespecWipeConfirm respecWipeConfirm = new(); respecWipeConfirm.RespecMaster = guid; respecWipeConfirm.Cost = cost; diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 2166af3c3..a471ad6d0 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -2787,6 +2787,7 @@ namespace Game.Entities PlayerTalkClass.SendGossipMenu(textId, source.GetGUID()); } + public void OnGossipSelect(WorldObject source, int gossipOptionId, uint menuId) { GossipMenu gossipMenu = PlayerTalkClass.GetGossipMenu(); @@ -2882,7 +2883,10 @@ namespace Game.Entities case GossipOptionNpc.GuildBanker: Guild guild = GetGuild(); if (guild != null) + { + PlayerTalkClass.GetInteractionData().StartInteraction(source.GetGUID(), PlayerInteractionType.GuildBanker); guild.SendBankList(GetSession(), 0, true); + } else Guild.SendCommandResult(GetSession(), GuildCommandType.ViewTab, GuildCommandError.PlayerNotInGuild); break; @@ -2931,6 +2935,36 @@ namespace Game.Entities if (!handled) { + PlayerInteractionType[] GossipOptionNpcToInteractionType = + [ + PlayerInteractionType.None, PlayerInteractionType.Vendor, PlayerInteractionType.TaxiNode, + PlayerInteractionType.Trainer, PlayerInteractionType.SpiritHealer, PlayerInteractionType.Binder, + PlayerInteractionType.Banker, PlayerInteractionType.PetitionVendor, PlayerInteractionType.GuildTabardVendor, + PlayerInteractionType.BattleMaster, PlayerInteractionType.Auctioneer, PlayerInteractionType.TalentMaster, + PlayerInteractionType.StableMaster, PlayerInteractionType.None, PlayerInteractionType.GuildBanker, + PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.None, + PlayerInteractionType.MailInfo, PlayerInteractionType.None, PlayerInteractionType.LFGDungeon, + PlayerInteractionType.ArtifactForge, PlayerInteractionType.None, PlayerInteractionType.SpecializationMaster, + PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.GarrArchitect, + PlayerInteractionType.GarrMission, PlayerInteractionType.ShipmentCrafter, PlayerInteractionType.GarrTradeskill, + PlayerInteractionType.GarrRecruitment, PlayerInteractionType.AdventureMap, PlayerInteractionType.GarrTalent, + PlayerInteractionType.ContributionCollector, PlayerInteractionType.Transmogrifier, PlayerInteractionType.AzeriteRespec, + PlayerInteractionType.IslandQueue, PlayerInteractionType.ItemInteraction, PlayerInteractionType.WorldMap, + PlayerInteractionType.Soulbind, PlayerInteractionType.ChromieTime, PlayerInteractionType.CovenantPreview, + PlayerInteractionType.LegendaryCrafting, PlayerInteractionType.NewPlayerGuide, PlayerInteractionType.LegendaryCrafting, + PlayerInteractionType.Renown, PlayerInteractionType.BlackMarketAuctioneer, PlayerInteractionType.PerksProgramVendor, + PlayerInteractionType.ProfessionsCraftingOrder, PlayerInteractionType.Professions, PlayerInteractionType.ProfessionsCustomerOrder, + PlayerInteractionType.TraitSystem, PlayerInteractionType.BarbersChoice, PlayerInteractionType.MajorFactionRenown, + PlayerInteractionType.PersonalTabardVendor, PlayerInteractionType.ForgeMaster, PlayerInteractionType.CharacterBanker, + PlayerInteractionType.AccountBanker, PlayerInteractionType.ProfessionRespec, PlayerInteractionType.PlaceholderType72, + PlayerInteractionType.PlaceholderType75, PlayerInteractionType.PlaceholderType76, PlayerInteractionType.GuildRename, + PlayerInteractionType.PlaceholderType77, PlayerInteractionType.ItemUpgrade + ]; + + PlayerInteractionType interactionType = GossipOptionNpcToInteractionType[(int)gossipOptionNpc]; + if (interactionType != PlayerInteractionType.None) + PlayerTalkClass.GetInteractionData().StartInteraction(source.GetGUID(), interactionType); + if (item.GossipNpcOptionID.HasValue) { GossipMenuAddon addon = ObjectMgr.GetGossipMenuAddon(menuId); @@ -2945,33 +2979,6 @@ namespace Game.Entities } else { - PlayerInteractionType[] GossipOptionNpcToInteractionType = - { - PlayerInteractionType.None, PlayerInteractionType.Vendor, PlayerInteractionType.TaxiNode, - PlayerInteractionType.Trainer, PlayerInteractionType.SpiritHealer, PlayerInteractionType.Binder, - PlayerInteractionType.Banker, PlayerInteractionType.PetitionVendor, PlayerInteractionType.GuildTabardVendor, - PlayerInteractionType.BattleMaster, PlayerInteractionType.Auctioneer, PlayerInteractionType.TalentMaster, - PlayerInteractionType.StableMaster, PlayerInteractionType.None, PlayerInteractionType.GuildBanker, - PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.None, - PlayerInteractionType.MailInfo, PlayerInteractionType.None, PlayerInteractionType.LFGDungeon, - PlayerInteractionType.ArtifactForge, PlayerInteractionType.None, PlayerInteractionType.SpecializationMaster, - PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.GarrArchitect, - PlayerInteractionType.GarrMission, PlayerInteractionType.ShipmentCrafter, PlayerInteractionType.GarrTradeskill, - PlayerInteractionType.GarrRecruitment, PlayerInteractionType.AdventureMap, PlayerInteractionType.GarrTalent, - PlayerInteractionType.ContributionCollector, PlayerInteractionType.Transmogrifier, PlayerInteractionType.AzeriteRespec, - PlayerInteractionType.IslandQueue, PlayerInteractionType.ItemInteraction, PlayerInteractionType.WorldMap, - PlayerInteractionType.Soulbind, PlayerInteractionType.ChromieTime, PlayerInteractionType.CovenantPreview, - PlayerInteractionType.LegendaryCrafting, PlayerInteractionType.NewPlayerGuide, PlayerInteractionType.LegendaryCrafting, - PlayerInteractionType.Renown, PlayerInteractionType.BlackMarketAuctioneer, PlayerInteractionType.PerksProgramVendor, - PlayerInteractionType.ProfessionsCraftingOrder, PlayerInteractionType.Professions, PlayerInteractionType.ProfessionsCustomerOrder, - PlayerInteractionType.TraitSystem, PlayerInteractionType.BarbersChoice, PlayerInteractionType.MajorFactionRenown, - PlayerInteractionType.PersonalTabardVendor, PlayerInteractionType.ForgeMaster, PlayerInteractionType.CharacterBanker, - PlayerInteractionType.AccountBanker, PlayerInteractionType.ProfessionRespec,PlayerInteractionType.PlaceholderType72, - PlayerInteractionType.PlaceholderType75, PlayerInteractionType.PlaceholderType76, PlayerInteractionType.GuildRename, - PlayerInteractionType.PlaceholderType77, PlayerInteractionType.ItemUpgrade - }; - - PlayerInteractionType interactionType = GossipOptionNpcToInteractionType[(int)gossipOptionNpc]; if (interactionType != PlayerInteractionType.None) { NPCInteractionOpenResult npcInteraction = new(); @@ -4953,9 +4960,8 @@ namespace Game.Entities Locale locale = GetSession().GetSessionDbLocaleIndex(); PlayerChoiceLocale playerChoiceLocale = locale != Locale.enUS ? ObjectMgr.GetPlayerChoiceLocale(choiceId) : null; - PlayerTalkClass.GetInteractionData().Reset(); - PlayerTalkClass.GetInteractionData().SourceGuid = sender; - PlayerTalkClass.GetInteractionData().SetPlayerChoice((uint)choiceId); + PlayerTalkClass.GetInteractionData().StartInteraction(sender, PlayerInteractionType.PlayerChoice); + PlayerTalkClass.GetInteractionData().GetPlayerChoice().SetChoiceId((uint)choiceId); DisplayPlayerChoice displayPlayerChoice = new(); displayPlayerChoice.SenderGUID = sender; diff --git a/Source/Game/Handlers/AuctionHandler.cs b/Source/Game/Handlers/AuctionHandler.cs index d1d2003d6..853de15b5 100644 --- a/Source/Game/Handlers/AuctionHandler.cs +++ b/Source/Game/Handlers/AuctionHandler.cs @@ -993,6 +993,8 @@ namespace Game if (ahEntry == null) return; + GetPlayer().PlayerTalkClass.GetInteractionData().StartInteraction(guid, PlayerInteractionType.Auctioneer); + AuctionHelloResponse auctionHelloResponse = new(); auctionHelloResponse.Auctioneer = guid; auctionHelloResponse.AuctionHouseID = ahEntry.Id; diff --git a/Source/Game/Handlers/BankHandler.cs b/Source/Game/Handlers/BankHandler.cs index 4197d4e86..0bc314c30 100644 --- a/Source/Game/Handlers/BankHandler.cs +++ b/Source/Game/Handlers/BankHandler.cs @@ -307,8 +307,8 @@ namespace Game public void SendShowBank(ObjectGuid guid, PlayerInteractionType interactionType) { - _player.PlayerTalkClass.GetInteractionData().Reset(); - _player.PlayerTalkClass.GetInteractionData().SourceGuid = guid; + _player.PlayerTalkClass.GetInteractionData().StartInteraction(guid, interactionType); + NPCInteractionOpenResult npcInteraction = new(); npcInteraction.Npc = guid; npcInteraction.InteractionType = interactionType; diff --git a/Source/Game/Handlers/GuildHandler.cs b/Source/Game/Handlers/GuildHandler.cs index 2d8a4980a..f57724a7c 100644 --- a/Source/Game/Handlers/GuildHandler.cs +++ b/Source/Game/Handlers/GuildHandler.cs @@ -265,6 +265,8 @@ namespace Game return; } + GetPlayer().PlayerTalkClass.GetInteractionData().StartInteraction(packet.Banker, PlayerInteractionType.GuildBanker); + guild.SendBankList(this, 0, packet.FullUpdate); } diff --git a/Source/Game/Handlers/MailHandler.cs b/Source/Game/Handlers/MailHandler.cs index 142806a53..cba2c7bbb 100644 --- a/Source/Game/Handlers/MailHandler.cs +++ b/Source/Game/Handlers/MailHandler.cs @@ -562,8 +562,7 @@ namespace Game response.Mails.Add(new MailListEntry(m, player)); } - player.PlayerTalkClass.GetInteractionData().Reset(); - player.PlayerTalkClass.GetInteractionData().SourceGuid = getList.Mailbox; + player.PlayerTalkClass.GetInteractionData().StartInteraction(getList.Mailbox, PlayerInteractionType.MailInfo); SendPacket(response); // recalculate m_nextMailDelivereTime and unReadMails diff --git a/Source/Game/Handlers/NPCHandler.cs b/Source/Game/Handlers/NPCHandler.cs index 223a46b05..081ebc9a2 100644 --- a/Source/Game/Handlers/NPCHandler.cs +++ b/Source/Game/Handlers/NPCHandler.cs @@ -89,9 +89,8 @@ namespace Game return; } - _player.PlayerTalkClass.GetInteractionData().Reset(); - _player.PlayerTalkClass.GetInteractionData().SourceGuid = npc.GetGUID(); - _player.PlayerTalkClass.GetInteractionData().SetTrainerId(trainerId); + _player.PlayerTalkClass.GetInteractionData().StartInteraction(npc.GetGUID(), PlayerInteractionType.Trainer); + _player.PlayerTalkClass.GetInteractionData().GetTrainer().Id = trainerId; trainer.SendSpells(npc, _player, GetSessionDbLocaleIndex()); } @@ -109,10 +108,10 @@ namespace Game if (_player.HasUnitState(UnitState.Died)) _player.RemoveAurasByType(AuraType.FeignDeath); - if (_player.PlayerTalkClass.GetInteractionData().SourceGuid != packet.TrainerGUID) + if (!_player.PlayerTalkClass.GetInteractionData().IsInteractingWith(packet.TrainerGUID, PlayerInteractionType.Trainer)) return; - if (_player.PlayerTalkClass.GetInteractionData().GetTrainerId() != packet.TrainerID) + if (_player.PlayerTalkClass.GetInteractionData().GetTrainer().Id != packet.TrainerID) return; // check present spell in trainer spell list @@ -177,7 +176,7 @@ namespace Game return; // Prevent cheating on C# scripted menus - if (GetPlayer().PlayerTalkClass.GetInteractionData().SourceGuid != packet.GossipUnit) + if (!_player.PlayerTalkClass.GetInteractionData().IsInteractingWith(packet.GossipUnit, PlayerInteractionType.Gossip)) return; Creature unit = null; @@ -424,6 +423,8 @@ namespace Game if (GetPlayer().HasUnitState(UnitState.Died)) GetPlayer().RemoveAurasByType(AuraType.FeignDeath); + GetPlayer().PlayerTalkClass.GetInteractionData().StartInteraction(vendorGuid, PlayerInteractionType.Vendor); + // Stop the npc if moving uint pause = vendor.GetMovementTemplate().GetInteractionPauseTimer(); if (pause != 0) diff --git a/Source/Game/Handlers/PetitionsHandler.cs b/Source/Game/Handlers/PetitionsHandler.cs index 59cd9e913..d83f07353 100644 --- a/Source/Game/Handlers/PetitionsHandler.cs +++ b/Source/Game/Handlers/PetitionsHandler.cs @@ -425,8 +425,7 @@ namespace Game return; } - WorldPacket data = new(ServerOpcodes.PetitionShowList); - data.WritePackedGuid(guid); // npc guid + GetPlayer().PlayerTalkClass.GetInteractionData().StartInteraction(guid, PlayerInteractionType.PetitionVendor); ServerPetitionShowList packet = new(); packet.Unit = guid; diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index 2b277b2a5..470496237 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -77,118 +77,100 @@ namespace Game // no or incorrect quest giver if (obj == null) - { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; - } Player playerQuestObject = obj.ToPlayer(); if (playerQuestObject != null) { if ((_player.GetPlayerSharingQuest().IsEmpty() && _player.GetPlayerSharingQuest() != packet.QuestGiverGUID) || !playerQuestObject.CanShareQuest(packet.QuestID)) - { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; - } + if (!_player.IsInSameRaidWith(playerQuestObject)) - { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; - } } else { if (!obj.HasQuest(packet.QuestID)) - { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; - } } // some kind of WPE protection if (!_player.CanInteractWithQuestGiver(obj)) - { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; - } Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID); - if (quest != null) + if (quest == null) + return; + + // prevent cheating + if (!GetPlayer().CanTakeQuest(quest, true)) + return; + + if (!_player.GetPlayerSharingQuest().IsEmpty()) { - // prevent cheating - if (!GetPlayer().CanTakeQuest(quest, true)) + Player player = Global.ObjAccessor.FindPlayer(_player.GetPlayerSharingQuest()); + if (player != null) { - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); - return; - } - - if (!_player.GetPlayerSharingQuest().IsEmpty()) - { - Player player = Global.ObjAccessor.FindPlayer(_player.GetPlayerSharingQuest()); - if (player != null) - { - player.SendPushToPartyResponse(_player, QuestPushReason.Accepted); - _player.ClearQuestSharingInfo(); - } - } - - if (_player.CanAddQuest(quest, true)) - { - _player.AddQuestAndCheckCompletion(quest, obj); - - if (quest.IsPushedToPartyOnAccept()) - { - var group = _player.GetGroup(); - if (group != null) - { - for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) - { - Player player = refe.GetSource(); - - if (player == null || player == _player || !player.IsInMap(_player)) // not self and in same map - continue; - - if (player.CanTakeQuest(quest, true)) - { - player.SetQuestSharingInfo(_player.GetGUID(), quest.Id); - - //need confirmation that any gossip window will close - player.PlayerTalkClass.SendCloseGossip(); - - _player.SendQuestConfirmAccept(quest, player); - } - } - } - } - - if (quest.HasFlag(QuestFlags.LaunchGossipAccept) && !quest.HasFlagEx(QuestFlagsEx.SuppressGossipAccept)) - { - void launchGossip(WorldObject worldObject) - { - _player.PlayerTalkClass.ClearMenus(); - _player.PrepareGossipMenu(worldObject, _player.GetGossipMenuForSource(worldObject), true); - _player.SendPreparedGossip(worldObject); - _player.PlayerTalkClass.GetInteractionData().IsLaunchedByQuest = true; - } - - Creature creature = obj.ToCreature(); - if (creature != null) - launchGossip(creature); - else - { - GameObject go = obj.ToGameObject(); - if (go != null) - launchGossip(go); - } - } - else - _player.PlayerTalkClass.SendCloseGossip(); - - return; + player.SendPushToPartyResponse(_player, QuestPushReason.Accepted); + _player.ClearQuestSharingInfo(); } } - CLOSE_GOSSIP_CLEAR_SHARING_INFO(); + if (!_player.CanAddQuest(quest, true)) + return; + + _player.AddQuestAndCheckCompletion(quest, obj); + + if (quest.IsPushedToPartyOnAccept()) + { + var group = _player.GetGroup(); + if (group != null) + { + for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) + { + Player player = refe.GetSource(); + + if (player == null || player == _player || !player.IsInMap(_player)) // not self and in same map + continue; + + if (player.CanTakeQuest(quest, true)) + { + player.SetQuestSharingInfo(_player.GetGUID(), quest.Id); + + //need confirmation that any gossip window will close + player.PlayerTalkClass.SendCloseGossip(); + + _player.SendQuestConfirmAccept(quest, player); + } + } + } + } + + if (quest.HasFlag(QuestFlags.LaunchGossipAccept) && !quest.HasFlagEx(QuestFlagsEx.SuppressGossipAccept)) + { + void launchGossip(WorldObject worldObject) + { + _player.PlayerTalkClass.ClearMenus(); + _player.PrepareGossipMenu(worldObject, _player.GetGossipMenuForSource(worldObject), true); + _player.SendPreparedGossip(worldObject); + _player.PlayerTalkClass.GetInteractionData().IsLaunchedByQuest = true; + } + + Creature creature = obj.ToCreature(); + if (creature != null) + launchGossip(creature); + else + { + GameObject go = obj.ToGameObject(); + if (go != null) + launchGossip(go); + } + } + // do not close gossip if quest accept script started a new interaction + else if (!_player.PlayerTalkClass.GetInteractionData().IsInteractingWith(obj.GetGUID(), PlayerInteractionType.QuestGiver)) + _player.PlayerTalkClass.GetInteractionData().IsLaunchedByQuest = true; + else + _player.PlayerTalkClass.SendCloseGossip(); } [WorldPacketHandler(ClientOpcodes.QuestGiverQueryQuest, Processing = PacketProcessing.Inplace)] diff --git a/Source/Game/Handlers/TaxiHandler.cs b/Source/Game/Handlers/TaxiHandler.cs index dc75fe654..67fbea2ce 100644 --- a/Source/Game/Handlers/TaxiHandler.cs +++ b/Source/Game/Handlers/TaxiHandler.cs @@ -85,6 +85,8 @@ namespace Game if (curloc == 0) return; + GetPlayer().PlayerTalkClass.GetInteractionData().StartInteraction(unit.GetGUID(), PlayerInteractionType.TaxiNode); + bool lastTaxiCheaterState = GetPlayer().IsTaxiCheater(); if (unit.GetEntry() == 29480) GetPlayer().SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.