mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/Gossip: Track started interaction types and reset only questgiver on quest accept
Closes #31120
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
|
||||
if (!quest)
|
||||
return;
|
||||
|
||||
// prevent cheating
|
||||
if (!GetPlayer()->CanTakeQuest(quest, true))
|
||||
return;
|
||||
|
||||
if (!_player->GetPlayerSharingQuest().IsEmpty())
|
||||
{
|
||||
Player* player = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
|
||||
if (player)
|
||||
{
|
||||
player->SendPushToPartyResponse(_player, QuestPushReason::Accepted);
|
||||
_player->ClearQuestSharingInfo();
|
||||
}
|
||||
}
|
||||
|
||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID))
|
||||
if (!_player->CanAddQuest(quest, true))
|
||||
return;
|
||||
|
||||
(void)CLOSE_GOSSIP_CLEAR_SHARING_INFO.release();
|
||||
|
||||
_player->AddQuestAndCheckCompletion(quest, object);
|
||||
|
||||
if (quest->IsPushedToPartyOnAccept())
|
||||
{
|
||||
// prevent cheating
|
||||
if (!GetPlayer()->CanTakeQuest(quest, true))
|
||||
if (Group* group = _player->GetGroup())
|
||||
{
|
||||
CLOSE_GOSSIP_CLEAR_SHARING_INFO();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player->GetPlayerSharingQuest().IsEmpty())
|
||||
{
|
||||
Player* player = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
|
||||
if (player)
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
player->SendPushToPartyResponse(_player, QuestPushReason::Accepted);
|
||||
_player->ClearQuestSharingInfo();
|
||||
}
|
||||
}
|
||||
Player* player = itr->GetSource();
|
||||
|
||||
if (_player->CanAddQuest(quest, true))
|
||||
{
|
||||
_player->AddQuestAndCheckCompletion(quest, object);
|
||||
if (!player || player == _player || !player->IsInMap(_player)) // not self and in same map
|
||||
continue;
|
||||
|
||||
if (quest->IsPushedToPartyOnAccept())
|
||||
{
|
||||
if (Group* group = _player->GetGroup())
|
||||
if (player->CanTakeQuest(quest, true))
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* player = itr->GetSource();
|
||||
player->SetQuestSharingInfo(_player->GetGUID(), quest->GetQuestId());
|
||||
|
||||
if (!player || player == _player || !player->IsInMap(_player)) // not self and in same map
|
||||
continue;
|
||||
// need confirmation that any gossip window will close
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
|
||||
if (player->CanTakeQuest(quest, true))
|
||||
{
|
||||
player->SetQuestSharingInfo(_player->GetGUID(), quest->GetQuestId());
|
||||
|
||||
// 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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user