aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp111
-rw-r--r--src/server/game/Quests/QuestDef.cpp49
-rw-r--r--src/server/game/Quests/QuestDef.h9
-rw-r--r--src/server/game/Server/Packets/QuestPackets.cpp60
-rw-r--r--src/server/game/Server/Packets/QuestPackets.h58
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2
7 files changed, 198 insertions, 93 deletions
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 2be169bf9ce..df27e189e7c 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -20,6 +20,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "QuestDef.h"
+#include "QuestPackets.h"
#include "World.h"
#include "WorldSession.h"
@@ -400,110 +401,42 @@ void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, ObjectGuid npcGUID) con
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool activateAccept) const
{
- std::string questTitle = quest->GetTitle();
- std::string questDetails = quest->GetDetails();
- std::string questObjectives = quest->GetObjectives();
- std::string questAreaDescription = quest->GetAreaDescription();
+ WorldPackets::Quest::QuestGiverQuestDetails packet;
+
+ packet.Title = quest->GetTitle();
+ packet.Details = quest->GetDetails();
+ packet.Objectives = quest->GetObjectives();
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
if (localeConstant != LOCALE_enUS)
{
if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(quest->GetQuestId()))
{
- ObjectMgr::GetLocaleString(localeData->Title, localeConstant, questTitle);
- ObjectMgr::GetLocaleString(localeData->Details, localeConstant, questDetails);
- ObjectMgr::GetLocaleString(localeData->Objectives, localeConstant, questObjectives);
- ObjectMgr::GetLocaleString(localeData->AreaDescription, localeConstant, questAreaDescription);
+ ObjectMgr::GetLocaleString(localeData->Title, localeConstant, packet.Title);
+ ObjectMgr::GetLocaleString(localeData->Details, localeConstant, packet.Details);
+ ObjectMgr::GetLocaleString(localeData->Objectives, localeConstant, packet.Objectives);
}
}
if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS))
- Quest::AddQuestLevelToTitle(questTitle, quest->GetQuestLevel());
-
- WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size
- data << uint64(npcGUID);
- data << uint64(_session->GetPlayer()->GetPlayerSharingQuest());
- data << uint32(quest->GetQuestId());
- data << questTitle;
- data << questDetails;
- data << questObjectives;
- data << uint8(activateAccept ? 1 : 0); // CGQuestInfo::m_autoLaunched
- data << uint32(quest->GetFlags() & (sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? ~QUEST_FLAGS_AUTO_ACCEPT : ~0)); // 3.3.3 questFlags
- data << uint32(quest->GetSuggestedPlayers());
- data << uint8(0); // CGQuestInfo::m_startQuestCheat
-
- if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
- {
- data << uint32(0); // Rewarded chosen items hidden
- data << uint32(0); // Rewarded items hidden
- data << uint32(0); // Rewarded money hidden
- data << uint32(0); // Rewarded XP hidden
- }
- else
- {
- data << uint32(quest->GetRewChoiceItemsCount());
- for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- {
- if (!quest->RewardChoiceItemId[i])
- continue;
-
- data << uint32(quest->RewardChoiceItemId[i]);
- data << uint32(quest->RewardChoiceItemCount[i]);
-
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0x00);
- }
-
- data << uint32(quest->GetRewItemsCount());
-
- for (uint32 i=0; i < QUEST_REWARDS_COUNT; ++i)
- {
- if (!quest->RewardItemId[i])
- continue;
-
- data << uint32(quest->RewardItemId[i]);
- data << uint32(quest->RewardItemIdCount[i]);
+ Quest::AddQuestLevelToTitle(packet.Title, quest->GetQuestLevel());
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
- data << uint32(itemTemplate->DisplayInfoID);
- else
- data << uint32(0);
- }
-
- data << uint32(quest->GetRewOrReqMoney(_session->GetPlayer()));
- data << uint32(quest->GetXPReward(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
- }
+ packet.QuestGiverGUID = npcGUID;
+ packet.InformUnit = _session->GetPlayer()->GetPlayerSharingQuest();
+ packet.QuestID = quest->GetQuestId();
+ packet.AutoLaunched = activateAccept;
+ packet.Flags = quest->GetFlags() & (sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? ~QUEST_FLAGS_AUTO_ACCEPT : ~0);
+ packet.SuggestedGroupNum = quest->GetSuggestedPlayers();
- // rewarded honor points. Multiply with 10 to satisfy client
- data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest)));
- data << float(0.0f); // unk, honor multiplier?
- data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
- data << int32(quest->GetRewSpellCast()); // cast spell
- data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
- data << uint32(quest->GetBonusTalents()); // bonus talents
- data << uint32(quest->GetRewArenaPoints()); // reward arena points
- data << uint32(0); // unk
+ quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer());
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << uint32(quest->RewardFactionId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueId[i]);
-
- for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- data << int32(quest->RewardFactionValueIdOverride[i]);
-
- data << uint32(QUEST_EMOTE_COUNT);
+ packet.DescEmotes.reserve(QUEST_EMOTE_COUNT);
for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
- {
- data << uint32(quest->DetailsEmote[i]);
- data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms)
- }
- _session->SendPacket(&data);
+ packet.DescEmotes.emplace_back(quest->DetailsEmote[i], quest->DetailsEmoteDelay[i]);
+
+ _session->SendPacket(packet.Write());
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPC=%s, questid=%u", npcGUID.ToString().c_str(), quest->GetQuestId());
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_GIVER_QUEST_DETAILS NPC=%s, questid=%u", npcGUID.ToString().c_str(), quest->GetQuestId());
}
void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 1e0d30a6fe8..2d0040ae3c6 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -235,6 +235,55 @@ uint32 Quest::GetXPReward(Player const* player) const
return true;
}
+void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const
+{
+ if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
+ {
+ for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
+ {
+ if (!RewardChoiceItemId[i])
+ continue;
+
+ uint32 displayID = 0;
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i]))
+ displayID = itemTemplate->DisplayInfoID;
+
+ rewards.UnfilteredChoiceItems.emplace_back(RewardChoiceItemId[i], RewardChoiceItemCount[i], displayID);
+ }
+
+ for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
+ {
+ if (!RewardItemId[i])
+ continue;
+
+ uint32 displayID = 0;
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i]))
+ displayID = itemTemplate->DisplayInfoID;
+
+ rewards.UnfilteredChoiceItems.emplace_back(RewardItemId[i], RewardItemIdCount[i], displayID);
+ }
+
+ rewards.RewardMoney = GetRewOrReqMoney(player);
+ rewards.RewardXPDifficulty = GetXPReward(player) * sWorld->getRate(RATE_XP_QUEST);
+ }
+
+ rewards.RewardHonor = 10 * CalculateHonorGain(player->GetQuestLevel(this)); // rewarded honor points. Multiply with 10 to satisfy client
+ rewards.RewardDisplaySpell = GetRewSpell(); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
+ rewards.RewardSpell = GetRewSpellCast();
+ rewards.RewardTitleId = GetCharTitleId();
+ rewards.RewardTalents = GetBonusTalents();
+ rewards.RewardArenaPoints = GetRewArenaPoints();
+
+ for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
+ rewards.RewardFactionID[i] = RewardFactionId[i];
+
+ for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
+ rewards.RewardFactionValue[i] = RewardFactionValueId[i];
+
+ for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
+ rewards.RewardFactionValueOverride[i] = RewardFactionValueIdOverride[i];
+}
+
int32 Quest::GetRewOrReqMoney(Player const* player) const
{
// RequiredMoney: the amount is the negative copper sum.
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index e00a6d17ebb..d4f02053aab 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -27,6 +27,11 @@
class Player;
+namespace WorldPackets::Quest
+{
+ struct QuestRewards;
+}
+
#define MAX_QUEST_LOG_SIZE 25
#define QUEST_OBJECTIVES_COUNT 4
@@ -131,7 +136,7 @@ enum QuestFlags
QUEST_FLAGS_RAID = 0x00000040, // Can be completed while in raid
QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expansion enabled only
QUEST_FLAGS_NO_MONEY_FROM_XP = 0x00000100, // Not used currently: Experience is not converted to gold at max level
- QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
+ QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUEST_GIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
QUEST_FLAGS_TRACKING = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
QUEST_FLAGS_DEPRECATE_REPUTATION = 0x00000800, // Not used currently
QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
@@ -323,6 +328,8 @@ class TC_GAME_API Quest
void InitializeQueryData();
WorldPacket BuildQueryData(LocaleConstant loc) const;
+ void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const;
+
std::vector<uint32> DependentPreviousQuests;
std::vector<uint32> DependentBreadcrumbQuests;
WorldPacket QueryData[TOTAL_LOCALES];
diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp
index 4082533ce47..9bad6dd5b7b 100644
--- a/src/server/game/Server/Packets/QuestPackets.cpp
+++ b/src/server/game/Server/Packets/QuestPackets.cpp
@@ -59,7 +59,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
_worldPacket << uint32(Info.RequiredPlayerKills);
_worldPacket << uint32(Info.RewardTalents);
_worldPacket << uint32(Info.RewardArenaPoints);
- _worldPacket << uint32(0); // review rep show mask
+ _worldPacket << uint32(Info.RewardFactionFlags);
if ((Info.Flags & QUEST_FLAGS_HIDDEN_REWARDS) != 0)
{
@@ -126,3 +126,61 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write()
+{
+ _worldPacket << QuestGiverGUID;
+ _worldPacket << InformUnit;
+ _worldPacket << uint32(QuestID);
+ _worldPacket << Title;
+ _worldPacket << Details;
+ _worldPacket << Objectives;
+ _worldPacket << uint8(AutoLaunched);
+ _worldPacket << uint32(Flags);
+ _worldPacket << uint32(SuggestedGroupNum);
+ _worldPacket << uint8(StartCheat);
+
+ _worldPacket << uint32(Rewards.UnfilteredChoiceItems.size());
+ for (WorldPackets::Quest::QuestChoiceItem const& item : Rewards.UnfilteredChoiceItems)
+ {
+ _worldPacket << uint32(item.ItemID);
+ _worldPacket << uint32(item.Quantity);
+ _worldPacket << uint32(item.DisplayID);
+ }
+
+ _worldPacket << uint32(Rewards.RewardItems.size());
+ for (WorldPackets::Quest::QuestChoiceItem const& item : Rewards.RewardItems)
+ {
+ _worldPacket << uint32(item.ItemID);
+ _worldPacket << uint32(item.Quantity);
+ _worldPacket << uint32(item.DisplayID);
+ }
+
+ _worldPacket << uint32(Rewards.RewardMoney);
+ _worldPacket << uint32(Rewards.RewardXPDifficulty);
+ _worldPacket << uint32(Rewards.RewardHonor);
+ _worldPacket << float(Rewards.RewardKillHonor);
+ _worldPacket << uint32(Rewards.RewardDisplaySpell);
+ _worldPacket << int32(Rewards.RewardSpell);
+ _worldPacket << uint32(Rewards.RewardTitleId);
+ _worldPacket << uint32(Rewards.RewardTalents);
+ _worldPacket << uint32(Rewards.RewardArenaPoints);
+ _worldPacket << uint32(Rewards.RewardFactionFlags);
+
+ for (uint32 factionId : Rewards.RewardFactionID)
+ _worldPacket << uint32(factionId);
+
+ for (uint32 value : Rewards.RewardFactionValue)
+ _worldPacket << int32(value);
+
+ for (uint32 valueOverride : Rewards.RewardFactionValueOverride)
+ _worldPacket << int32(valueOverride);
+
+ for (QuestDescEmote const& emote : DescEmotes)
+ {
+ _worldPacket << uint32(emote.Type);
+ _worldPacket << uint32(emote.Delay);
+ }
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h
index 25e58382d2c..1d7248e7d82 100644
--- a/src/server/game/Server/Packets/QuestPackets.h
+++ b/src/server/game/Server/Packets/QuestPackets.h
@@ -18,6 +18,7 @@
#ifndef QuestPackets_h__
#define QuestPackets_h__
+#include "ObjectGuid.h"
#include "Packet.h"
#include "QuestDef.h"
@@ -69,6 +70,7 @@ namespace WorldPackets
uint32 RequiredPlayerKills = 0;
uint32 RewardTalents = 0;
int32 RewardArenaPoints = 0;
+ uint32 RewardFactionFlags = 0;
uint32 RewardItems[QUEST_REWARDS_COUNT] = { };
uint32 RewardAmount[QUEST_REWARDS_COUNT] = { };
@@ -108,6 +110,62 @@ namespace WorldPackets
QuestInfo Info;
};
+
+ struct QuestChoiceItem
+ {
+ QuestChoiceItem(uint32 itemID, uint32 quantity, uint32 displayID) : ItemID(itemID), Quantity(quantity),
+ DisplayID(displayID) { }
+ uint32 ItemID = 0;
+ uint32 Quantity = 0;
+ uint32 DisplayID = 0;
+ };
+
+ struct QuestRewards
+ {
+ std::vector<QuestChoiceItem> UnfilteredChoiceItems;
+ std::vector<QuestChoiceItem> RewardItems;
+ uint32 RewardMoney = 0;
+ uint32 RewardXPDifficulty = 0;
+ uint32 RewardHonor = 0;
+ float RewardKillHonor = 0.f;
+ uint32 RewardDisplaySpell = 0;
+ int32 RewardSpell = 0;
+ uint32 RewardTitleId = 0;
+ uint32 RewardTalents = 0;
+ uint32 RewardArenaPoints = 0;
+ uint32 RewardFactionFlags = 0;
+ std::array<uint32, QUEST_REPUTATIONS_COUNT> RewardFactionID = { };
+ std::array<int32, QUEST_REPUTATIONS_COUNT> RewardFactionValue = { };
+ std::array<int32, QUEST_REPUTATIONS_COUNT> RewardFactionValueOverride = { };
+ };
+
+ struct QuestDescEmote
+ {
+ QuestDescEmote(int32 type, uint32 delay) : Type(type), Delay(delay) { }
+ uint32 Type;
+ uint32 Delay;
+ };
+
+ class QuestGiverQuestDetails final : public ServerPacket
+ {
+ public:
+ QuestGiverQuestDetails() : ServerPacket(SMSG_QUEST_GIVER_QUEST_DETAILS, 1000) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid QuestGiverGUID;
+ ObjectGuid InformUnit;
+ uint32 QuestID = 0;
+ std::string Title;
+ std::string Details;
+ std::string Objectives;
+ bool AutoLaunched = false;
+ uint32 Flags = 0;
+ uint32 SuggestedGroupNum = 0;
+ bool StartCheat = false;
+ QuestRewards Rewards;
+ std::vector<QuestDescEmote> DescEmotes;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 50f9702cf12..a10e2af8f03 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -520,7 +520,7 @@ void OpcodeTable::Initialize()
/*0x185*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_LIST, STATUS_NEVER);
/*0x186*/ DEFINE_HANDLER(CMSG_QUESTGIVER_QUERY_QUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverQueryQuestOpcode);
/*0x187*/ DEFINE_HANDLER(CMSG_QUESTGIVER_QUEST_AUTOLAUNCH, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverQuestAutoLaunch );
- /*0x188*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER);
+ /*0x188*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_GIVER_QUEST_DETAILS, STATUS_NEVER);
/*0x189*/ DEFINE_HANDLER(CMSG_QUESTGIVER_ACCEPT_QUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverAcceptQuestOpcode);
/*0x18A*/ DEFINE_HANDLER(CMSG_QUESTGIVER_COMPLETE_QUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestgiverCompleteQuest );
/*0x18B*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_REQUEST_ITEMS, STATUS_NEVER);
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 47901cb2cc0..f5fdcb6e091 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -418,7 +418,7 @@ enum Opcodes : uint16
SMSG_QUESTGIVER_QUEST_LIST = 0x185,
CMSG_QUESTGIVER_QUERY_QUEST = 0x186,
CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187,
- SMSG_QUESTGIVER_QUEST_DETAILS = 0x188,
+ SMSG_QUEST_GIVER_QUEST_DETAILS = 0x188,
CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189,
CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A,
SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B,