diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/GossipDef.cpp | 111 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.cpp | 49 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.h | 9 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QuestPackets.cpp | 60 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QuestPackets.h | 58 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.h | 2 |
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, |