aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-07-05 22:34:45 +0200
committerShauren <shauren.trinity@gmail.com>2025-07-05 22:34:45 +0200
commitc02e311eef9e635738b9e48559d5455ef016d8b4 (patch)
treef89eca0ae0bd057575690d9e6a7a6d72bb2c3e58 /src/server
parent2a2e09e8f431209c00b162f9e6c736d732b24114 (diff)
Core/Gossip: Track started interaction types and reset only questgiver on quest accept
Closes #31120
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp3
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp51
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h30
-rw-r--r--src/server/game/Entities/Player/Player.cpp77
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp3
-rw-r--r--src/server/game/Handlers/BankHandler.cpp4
-rw-r--r--src/server/game/Handlers/GuildHandler.cpp3
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp2
-rw-r--r--src/server/game/Handlers/MailHandler.cpp3
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp11
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp5
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp130
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp3
13 files changed, 193 insertions, 132 deletions
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index ca21d466b37..1f5392f2dae 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -23,6 +23,7 @@
#include "DatabaseEnv.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
+#include "GossipDef.h"
#include "Language.h"
#include "Log.h"
#include "MapManager.h"
@@ -452,6 +453,8 @@ void BattlegroundMgr::SendBattlegroundList(Player* player, ObjectGuid const& gui
if (!bgTemplate)
return;
+ player->PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::BattleMaster);
+
WorldPackets::Battleground::BattlefieldList battlefieldList;
battlefieldList.BattlemasterGuid = guid;
battlefieldList.BattlemasterListID = bgTypeId;
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 75fc7f8ce87..c1a359b0fff 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -219,8 +219,7 @@ void PlayerMenu::ClearMenus()
void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID)
{
- _interactionData.Reset();
- _interactionData.SourceGuid = objectGUID;
+ _interactionData.StartInteraction(objectGUID, PlayerInteractionType::Gossip);
WorldPackets::NPC::GossipMessage packet;
packet.GossipGUID = objectGUID;
@@ -364,6 +363,39 @@ void PlayerChoiceData::AddResponse(uint32 id, uint16 clientIdentifier)
_responses.push_back({ .Id = id, .ClientIdentifier = clientIdentifier });
}
+InteractionData::InteractionData() = default;
+InteractionData::InteractionData(InteractionData const& other) = default;
+InteractionData::InteractionData(InteractionData&& other) noexcept = default;
+InteractionData& InteractionData::operator=(InteractionData const& other) = default;
+InteractionData& InteractionData::operator=(InteractionData&& other) noexcept = default;
+InteractionData::~InteractionData() = default;
+
+void InteractionData::StartInteraction(ObjectGuid target, PlayerInteractionType type)
+{
+ SourceGuid = target;
+ Type = type;
+ IsLaunchedByQuest = false;
+ switch (type)
+ {
+ case PlayerInteractionType::Trainer:
+ _data.emplace<TrainerData>();
+ break;
+ case PlayerInteractionType::PlayerChoice:
+ _data.emplace<PlayerChoiceData>();
+ break;
+ default:
+ break;
+ }
+}
+
+void InteractionData::Reset()
+{
+ SourceGuid.Clear();
+ Type = PlayerInteractionType::None;
+ IsLaunchedByQuest = false;
+ _data.emplace<std::monostate>();
+}
+
void QuestMenu::ClearMenu()
{
_questMenuItems.clear();
@@ -372,6 +404,9 @@ void QuestMenu::ClearMenu()
void PlayerMenu::SendQuestGiverQuestListMessage(Object* questgiver)
{
ObjectGuid guid = questgiver->GetGUID();
+
+ GetInteractionData().StartInteraction(guid, PlayerInteractionType::QuestGiver);
+
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
WorldPackets::Quest::QuestGiverQuestListMessage questList;
@@ -432,8 +467,10 @@ void PlayerMenu::SendQuestGiverStatus(QuestGiverStatus questStatus, ObjectGuid n
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC={}, status={}", npcGUID.ToString(), AsUnderlyingType(questStatus));
}
-void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup) const
+void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup)
{
+ GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType::QuestGiver);
+
WorldPackets::Quest::QuestGiverQuestDetails packet;
packet.QuestTitle = quest->GetLogTitle();
@@ -532,8 +569,10 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid={}", quest->GetQuestId());
}
-void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched) const
+void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched)
{
+ GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType::QuestGiver);
+
WorldPackets::Quest::QuestGiverOfferRewardMessage packet;
packet.QuestTitle = quest->GetLogTitle();
@@ -602,7 +641,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPC={}, questid={}", npcGUID.ToString(), quest->GetQuestId());
}
-void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGUID, bool canComplete, bool autoLaunched) const
+void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGUID, bool canComplete, bool autoLaunched)
{
// We can always call to RequestItems, but this packet only goes out if there are actually
// items. Otherwise, we'll skip straight to the OfferReward
@@ -613,6 +652,8 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU
return;
}
+ GetInteractionData().StartInteraction(npcGUID, PlayerInteractionType::QuestGiver);
+
WorldPackets::Quest::QuestGiverRequestItems packet;
packet.QuestTitle = quest->GetLogTitle();
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index da83b064300..4a9c06f8e81 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -28,6 +28,7 @@ class Object;
class Quest;
class WorldSession;
struct GossipMenuItems;
+enum class PlayerInteractionType : int32;
enum class QuestGiverStatus : uint64;
#define GOSSIP_MAX_MENU_ITEMS 32
@@ -260,7 +261,7 @@ private:
Optional<SystemTimePoint> _expireTime;
};
-class InteractionData
+class TC_GAME_API InteractionData
{
template <typename>
struct TaggedId
@@ -275,20 +276,23 @@ class InteractionData
using TrainerData = TaggedId<TrainerTag>;
public:
- void Reset()
- {
- SourceGuid.Clear();
- IsLaunchedByQuest = false;
- _data.emplace<std::monostate>();
- }
+ InteractionData();
+ InteractionData(InteractionData const& other);
+ InteractionData(InteractionData&& other) noexcept;
+ InteractionData& operator=(InteractionData const& other);
+ InteractionData& operator=(InteractionData&& other) noexcept;
+ ~InteractionData();
+
+ void StartInteraction(ObjectGuid target, PlayerInteractionType type);
+ bool IsInteractingWith(ObjectGuid target, PlayerInteractionType type) const { return SourceGuid == target && Type == type; }
+ void Reset();
ObjectGuid SourceGuid;
+ PlayerInteractionType Type = { };
- Optional<uint32> GetTrainerId() const { return std::holds_alternative<TrainerData>(_data) ? std::get<TrainerData>(_data).Id : Optional<uint32>(); }
- void SetTrainerId(uint32 trainerId) { _data.emplace<TrainerData>(trainerId); }
+ TrainerData* GetTrainer() { return std::holds_alternative<TrainerData>(_data) ? &std::get<TrainerData>(_data) : nullptr; }
PlayerChoiceData* GetPlayerChoice() { return std::holds_alternative<PlayerChoiceData>(_data) ? &std::get<PlayerChoiceData>(_data) : nullptr; }
- void SetPlayerChoice(uint32 choiceId) { _data.emplace<PlayerChoiceData>(choiceId); }
uint16 AddPlayerChoiceResponse(uint32 responseId)
{
@@ -336,10 +340,10 @@ class TC_GAME_API PlayerMenu
void SendQuestGiverQuestListMessage(Object* questgiver);
void SendQuestQueryResponse(Quest const* quest) const;
- void SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup) const;
+ void SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup);
- void SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched) const;
- void SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGUID, bool canComplete, bool autoLaunched) const;
+ void SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched);
+ void SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGUID, bool canComplete, bool autoLaunched);
private:
GossipMenu _gossipMenu;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f33d76ee8d4..be44c7a9898 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9237,6 +9237,18 @@ void Player::SetBindPoint(ObjectGuid guid) const
void Player::SendRespecWipeConfirm(ObjectGuid const& guid, uint32 cost, SpecResetType respecType) const
{
+ switch (respecType)
+ {
+ case SPEC_RESET_TALENTS:
+ PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::TalentMaster);
+ break;
+ case SPEC_RESET_SPECIALIZATION:
+ PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::SpecializationMaster);
+ break;
+ default:
+ break;
+ }
+
WorldPackets::Talent::RespecWipeConfirm respecWipeConfirm;
respecWipeConfirm.RespecMaster = guid;
respecWipeConfirm.Cost = cost;
@@ -14148,7 +14160,10 @@ void Player::OnGossipSelect(WorldObject* source, int32 gossipOptionId, uint32 me
break;
case GossipOptionNpc::GuildBanker:
if (Guild* const guild = GetGuild())
+ {
+ PlayerTalkClass->GetInteractionData().StartInteraction(source->GetGUID(), PlayerInteractionType::GuildBanker);
guild->SendBankList(GetSession(), 0, true);
+ }
else
Guild::SendCommandResult(GetSession(), GUILD_COMMAND_VIEW_TAB, ERR_GUILD_PLAYER_NOT_IN_GUILD);
break;
@@ -14197,6 +14212,36 @@ void Player::OnGossipSelect(WorldObject* source, int32 gossipOptionId, uint32 me
if (!handled)
{
+ static constexpr std::array<PlayerInteractionType, AsUnderlyingType(GossipOptionNpc::Count)> 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[AsUnderlyingType(gossipOptionNpc)];
+ if (interactionType != PlayerInteractionType::None)
+ PlayerTalkClass->GetInteractionData().StartInteraction(source->GetGUID(), interactionType);
+
if (item->GossipNpcOptionID)
{
GossipMenuAddon const* addon = sObjectMgr->GetGossipMenuAddon(menuId);
@@ -14211,33 +14256,6 @@ void Player::OnGossipSelect(WorldObject* source, int32 gossipOptionId, uint32 me
}
else
{
- static constexpr std::array<PlayerInteractionType, AsUnderlyingType(GossipOptionNpc::Count)> 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[AsUnderlyingType(gossipOptionNpc)];
if (interactionType != PlayerInteractionType::None)
{
WorldPackets::NPC::NPCInteractionOpenResult npcInteraction;
@@ -29978,9 +29996,8 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
LocaleConstant locale = GetSession()->GetSessionDbLocaleIndex();
PlayerChoiceLocale const* playerChoiceLocale = locale != DEFAULT_LOCALE ? sObjectMgr->GetPlayerChoiceLocale(choiceId) : nullptr;
- PlayerTalkClass->GetInteractionData().Reset();
- PlayerTalkClass->GetInteractionData().SourceGuid = sender;
- PlayerTalkClass->GetInteractionData().SetPlayerChoice(choiceId);
+ PlayerTalkClass->GetInteractionData().StartInteraction(sender, PlayerInteractionType::PlayerChoice);
+ PlayerTalkClass->GetInteractionData().GetPlayerChoice()->SetChoiceId(choiceId);
WorldPackets::Quest::DisplayPlayerChoice displayPlayerChoice;
displayPlayerChoice.SenderGUID = sender;
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 6d74c1621cd..41936528511 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -23,6 +23,7 @@
#include "Creature.h"
#include "DatabaseEnv.h"
#include "GameTime.h"
+#include "GossipDef.h"
#include "Item.h"
#include "Language.h"
#include "Log.h"
@@ -1004,6 +1005,8 @@ void WorldSession::SendAuctionHello(ObjectGuid guid, Unit const* unit)
if (!ahEntry)
return;
+ GetPlayer()->PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::Auctioneer);
+
WorldPackets::AuctionHouse::AuctionHelloResponse auctionHelloResponse;
auctionHelloResponse.Auctioneer = guid;
auctionHelloResponse.AuctionHouseID = ahEntry->ID;
diff --git a/src/server/game/Handlers/BankHandler.cpp b/src/server/game/Handlers/BankHandler.cpp
index bf8b3a92ff4..91a65dfb58b 100644
--- a/src/server/game/Handlers/BankHandler.cpp
+++ b/src/server/game/Handlers/BankHandler.cpp
@@ -324,8 +324,8 @@ void WorldSession::HandleAutoStoreBankReagentOpcode(WorldPackets::Bank::AutoStor
void WorldSession::SendShowBank(ObjectGuid guid, PlayerInteractionType interactionType)
{
- _player->PlayerTalkClass->GetInteractionData().Reset();
- _player->PlayerTalkClass->GetInteractionData().SourceGuid = guid;
+ _player->PlayerTalkClass->GetInteractionData().StartInteraction(guid, interactionType);
+
WorldPackets::NPC::NPCInteractionOpenResult npcInteraction;
npcInteraction.Npc = guid;
npcInteraction.InteractionType = interactionType;
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index c778ca97ca8..2dbc1c5e02a 100644
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -19,6 +19,7 @@
#include "AchievementPackets.h"
#include "Common.h"
#include "GameTime.h"
+#include "GossipDef.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "GuildPackets.h"
@@ -249,6 +250,8 @@ void WorldSession::HandleGuildBankActivate(WorldPackets::Guild::GuildBankActivat
return;
}
+ GetPlayer()->PlayerTalkClass->GetInteractionData().StartInteraction(packet.Banker, PlayerInteractionType::GuildBanker);
+
guild->SendBankList(this, 0, packet.FullUpdate);
}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index c3bbf6c1fa7..e63ed58e7e4 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -606,6 +606,8 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
+ GetPlayer()->PlayerTalkClass->GetInteractionData().StartInteraction(vendorGuid, PlayerInteractionType::Vendor);
+
// Stop the npc if moving
if (uint32 pause = vendor->GetMovementTemplate().GetInteractionPauseTimer())
vendor->PauseMovement(pause);
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index e6df9fa28d1..fbe5e3ea090 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -576,8 +576,7 @@ void WorldSession::HandleGetMailList(WorldPackets::Mail::MailGetList& getList)
++response.TotalNumRecords;
}
- player->PlayerTalkClass->GetInteractionData().Reset();
- player->PlayerTalkClass->GetInteractionData().SourceGuid = getList.Mailbox;
+ player->PlayerTalkClass->GetInteractionData().StartInteraction(getList.Mailbox, PlayerInteractionType::MailInfo);
SendPacket(response.Write());
// recalculate m_nextMailDelivereTime and unReadMails
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 3505651926b..06fd9155c29 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -122,9 +122,8 @@ void WorldSession::SendTrainerList(Creature* npc, uint32 trainerId)
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());
}
@@ -143,10 +142,10 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpel
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- if (_player->PlayerTalkClass->GetInteractionData().SourceGuid != packet.TrainerGUID)
+ if (!_player->PlayerTalkClass->GetInteractionData().IsInteractingWith(packet.TrainerGUID, PlayerInteractionType::Trainer))
return;
- if (_player->PlayerTalkClass->GetInteractionData().GetTrainerId() != uint32(packet.TrainerID))
+ if (_player->PlayerTalkClass->GetInteractionData().GetTrainer()->Id != uint32(packet.TrainerID))
return;
Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(packet.TrainerID);
@@ -198,7 +197,7 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelec
return;
// Prevent cheating on C++ scripted menus
- if (_player->PlayerTalkClass->GetInteractionData().SourceGuid != packet.GossipUnit)
+ if (!_player->PlayerTalkClass->GetInteractionData().IsInteractingWith(packet.GossipUnit, PlayerInteractionType::Gossip))
return;
Creature* unit = nullptr;
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index 7cade43cddc..acbd1db23b1 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -19,6 +19,7 @@
#include "Common.h"
#include "CharacterCache.h"
#include "DatabaseEnv.h"
+#include "GossipDef.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "Item.h"
@@ -455,10 +456,10 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid)
return;
}
+ GetPlayer()->PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::PetitionVendor);
+
WorldPackets::Petition::ServerPetitionShowList packet;
packet.Unit = guid;
packet.Price = uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD));
SendPacket(packet.Write());
-
- TC_LOG_DEBUG("network", "Sent SMSG_PETITION_SHOW_LIST");
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 1fe2dbc32b9..d86bbf17cb1 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -28,6 +28,7 @@
#include "GossipDef.h"
#include "Group.h"
#include "Log.h"
+#include "Memory.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -94,118 +95,103 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
else
object = ObjectAccessor::FindPlayer(packet.QuestGiverGUID);
- auto CLOSE_GOSSIP_CLEAR_SHARING_INFO = ([this]()
+ auto CLOSE_GOSSIP_CLEAR_SHARING_INFO = Trinity::make_unique_ptr_with_deleter(_player, [](Player* player)
{
- _player->PlayerTalkClass->SendCloseGossip();
- _player->ClearQuestSharingInfo();
+ player->PlayerTalkClass->SendCloseGossip();
+ player->ClearQuestSharingInfo();
});
// no or incorrect quest giver
if (!object)
- {
- CLOSE_GOSSIP_CLEAR_SHARING_INFO();
return;
- }
if (Player* playerQuestObject = object->ToPlayer())
{
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 (!object->hasQuest(packet.QuestID))
- {
- CLOSE_GOSSIP_CLEAR_SHARING_INFO();
return;
- }
}
// some kind of WPE protection
if (!_player->CanInteractWithQuestGiver(object))
- {
- CLOSE_GOSSIP_CLEAR_SHARING_INFO();
return;
- }
- if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID))
+ Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
+ if (!quest)
+ return;
+
+ // prevent cheating
+ if (!GetPlayer()->CanTakeQuest(quest, true))
+ return;
+
+ if (!_player->GetPlayerSharingQuest().IsEmpty())
{
- // prevent cheating
- if (!GetPlayer()->CanTakeQuest(quest, true))
+ Player* player = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
+ if (player)
{
- CLOSE_GOSSIP_CLEAR_SHARING_INFO();
- return;
+ player->SendPushToPartyResponse(_player, QuestPushReason::Accepted);
+ _player->ClearQuestSharingInfo();
}
+ }
- if (!_player->GetPlayerSharingQuest().IsEmpty())
- {
- Player* player = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
- if (player)
- {
- player->SendPushToPartyResponse(_player, QuestPushReason::Accepted);
- _player->ClearQuestSharingInfo();
- }
- }
+ if (!_player->CanAddQuest(quest, true))
+ return;
- if (_player->CanAddQuest(quest, true))
- {
- _player->AddQuestAndCheckCompletion(quest, object);
+ (void)CLOSE_GOSSIP_CLEAR_SHARING_INFO.release();
+
+ _player->AddQuestAndCheckCompletion(quest, object);
- if (quest->IsPushedToPartyOnAccept())
+ if (quest->IsPushedToPartyOnAccept())
+ {
+ if (Group* group = _player->GetGroup())
+ {
+ for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
- if (Group* group = _player->GetGroup())
- {
- for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
- {
- Player* player = itr->GetSource();
+ Player* player = itr->GetSource();
- if (!player || player == _player || !player->IsInMap(_player)) // not self and in same map
- continue;
+ if (!player || player == _player || !player->IsInMap(_player)) // not self and in same map
+ continue;
- if (player->CanTakeQuest(quest, true))
- {
- player->SetQuestSharingInfo(_player->GetGUID(), quest->GetQuestId());
+ if (player->CanTakeQuest(quest, true))
+ {
+ player->SetQuestSharingInfo(_player->GetGUID(), quest->GetQuestId());
- // need confirmation that any gossip window will close
- player->PlayerTalkClass->SendCloseGossip();
+ // need confirmation that any gossip window will close
+ player->PlayerTalkClass->SendCloseGossip();
- _player->SendQuestConfirmAccept(quest, player);
- }
- }
+ _player->SendQuestConfirmAccept(quest, player);
}
}
-
- if (quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT) && !quest->HasFlagEx(QUEST_FLAGS_EX_SUPPRESS_GOSSIP_ACCEPT))
- {
- auto launchGossip = [&](WorldObject* worldObject)
- {
- _player->PlayerTalkClass->ClearMenus();
- _player->PrepareGossipMenu(worldObject, _player->GetGossipMenuForSource(worldObject), true);
- _player->SendPreparedGossip(worldObject);
- _player->PlayerTalkClass->GetInteractionData().IsLaunchedByQuest = true;
- };
-
- if (Creature* creature = object->ToCreature())
- launchGossip(creature);
- else if (GameObject* go = object->ToGameObject())
- launchGossip(go);
- }
- else
- _player->PlayerTalkClass->SendCloseGossip();
-
- return;
}
}
- CLOSE_GOSSIP_CLEAR_SHARING_INFO();
+ if (quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT) && !quest->HasFlagEx(QUEST_FLAGS_EX_SUPPRESS_GOSSIP_ACCEPT))
+ {
+ auto launchGossip = [&](WorldObject* worldObject)
+ {
+ _player->PlayerTalkClass->ClearMenus();
+ _player->PrepareGossipMenu(worldObject, _player->GetGossipMenuForSource(worldObject), true);
+ _player->SendPreparedGossip(worldObject);
+ _player->PlayerTalkClass->GetInteractionData().IsLaunchedByQuest = true;
+ };
+
+ if (Creature* creature = object->ToCreature())
+ launchGossip(creature);
+ else if (GameObject* go = object->ToGameObject())
+ launchGossip(go);
+ }
+ // do not close gossip if quest accept script started a new interaction
+ else if (!_player->PlayerTalkClass->GetInteractionData().IsInteractingWith(object->GetGUID(), PlayerInteractionType::QuestGiver))
+ _player->PlayerTalkClass->GetInteractionData().IsLaunchedByQuest = true;
+ else
+ _player->PlayerTalkClass->SendCloseGossip();
}
void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPackets::Quest::QuestGiverQueryQuest& packet)
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index c807e2cb4ed..5c8082bb9c5 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -23,6 +23,7 @@
#include "DatabaseEnv.h"
#include "DB2Stores.h"
#include "FlightPathMovementGenerator.h"
+#include "GossipDef.h"
#include "Log.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
@@ -96,6 +97,8 @@ void WorldSession::SendTaxiMenu(Creature* unit)
if (!curloc)
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.