Core/Quests: convert SMSG_QUEST_GIVER_STATUS and SMSG_QUEST_GIVER_QUEST_DETAILS to packet class

This commit is contained in:
Ovahlord
2020-01-05 15:57:52 +01:00
parent 8aa25d9721
commit bb2073c764
7 changed files with 283 additions and 65 deletions

View File

@@ -378,73 +378,67 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
void PlayerMenu::SendQuestGiverStatus(uint32 questStatus, ObjectGuid npcGUID) const
{
WorldPacket data(SMSG_QUESTGIVER_STATUS, 8 + 4);
data << uint64(npcGUID);
data << uint32(questStatus);
WorldPackets::Quest::QuestGiverStatus packet;
packet.QuestGiver.Guid = npcGUID;
packet.QuestGiver.Status = questStatus;
_session->SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC=%s, status=%u", npcGUID.ToString().c_str(), questStatus);
_session->SendPacket(packet.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_GIVER_STATUS Guid = %s, Status = %u", npcGUID.ToString().c_str(), questStatus);
}
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched, bool displayPopup) const
{
std::string questTitle = quest->GetTitle();
std::string questDetails = quest->GetDetails();
std::string questObjectives = quest->GetObjectives();
std::string questAreaDescription = quest->GetAreaDescription();
std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
std::string questGiverTargetName = quest->GetQuestGiverTargetName();
std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
std::string questTurnTargetName = quest->GetQuestTurnTargetName();
WorldPackets::Quest::QuestGiverQuestDetails packet;
packet.QuestTitle = quest->GetTitle();
packet.LogDescription = quest->GetDetails();
packet.Objectives = quest->GetObjectives();
packet.DescriptionText = quest->GetAreaDescription();
packet.PortraitGiverText = quest->GetQuestGiverTextWindow();
packet.PortraitGiverName = quest->GetQuestGiverTargetName();
packet.PortraitTurnInText = quest->GetQuestTurnTextWindow();
packet.PortraitTurnInName = quest->GetQuestTurnTargetName();
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->QuestGiverTextWindow, localeConstant, questGiverTextWindow);
ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, localeConstant, questGiverTargetName);
ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, localeConstant, questTurnTextWindow);
ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, localeConstant, questTurnTargetName);
ObjectMgr::GetLocaleString(localeData->Title, localeConstant, packet.QuestTitle);
ObjectMgr::GetLocaleString(localeData->Details, localeConstant, packet.LogDescription);
ObjectMgr::GetLocaleString(localeData->Objectives, localeConstant, packet.Objectives);
ObjectMgr::GetLocaleString(localeData->AreaDescription, localeConstant, packet.DescriptionText);
ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, localeConstant, packet.PortraitGiverText);
ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, localeConstant, packet.PortraitGiverName);
ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, localeConstant, packet.PortraitTurnInText);
ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, localeConstant, packet.PortraitTurnInName);
}
}
if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS))
AddQuestLevelToTitle(questTitle, quest->GetQuestLevel());
AddQuestLevelToTitle(packet.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 << questGiverTextWindow; // 4.x
data << questGiverTargetName; // 4.x
data << questTurnTextWindow; // 4.x
data << questTurnTargetName; // 4.x
data << uint32(quest->GetQuestGiverPortrait()); // 4.x
data << uint32(quest->GetQuestTurnInPortrait()); // 4.x
data << uint8(autoLaunched); // auto finish
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); // IsFinished? value is sent back to server in quest accept packet
data << uint8(displayPopup); // 4.x Starts at AreaTrigger?
data << uint32(quest->GetRequiredSpell()); // 4.x
packet.QuestGiverGUID = npcGUID;
packet.InformUnit = _session->GetPlayer()->GetPlayerSharingQuest();
packet.QuestID = quest->GetQuestId();
packet.PortraitGiver = quest->GetQuestGiverPortrait();
packet.PortraitTurnIn = quest->GetQuestTurnInPortrait();
packet.AutoLaunched = autoLaunched;
packet.DisplayPopup = displayPopup;
packet.QuestFlags = quest->GetFlags() & (sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? ~QUEST_FLAGS_AUTO_ACCEPT : ~0);
packet.SuggestedPartyMembers = quest->GetSuggestedPlayers();
packet.RequiredSpellID = quest->GetRequiredSpell();
quest->BuildExtraQuestInfo(data, _session->GetPlayer());
quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer());
data << uint32(QUEST_EMOTE_COUNT);
for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i)
packet.DescEmotes.resize(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)
packet.DescEmotes[i].Type = quest->DetailsEmote[i];
packet.DescEmotes[i].Delay = quest->DetailsEmoteDelay[i];
}
_session->SendPacket(&data);
_session->SendPacket(packet.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPC=%s, questid=%u", npcGUID.ToString().c_str(), quest->GetQuestId());
}

View File

@@ -21,6 +21,7 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "QuestPackets.h"
#include "World.h"
Quest::Quest(Field* questRecord)
@@ -322,19 +323,6 @@ void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const
data << uint32(0); // unk
data << uint32(GetRewardReputationMask());
/* Pre cata struct, some of these unks might be the missing values in cata:
// rewarded honor points. Multiply with 10 to satisfy client
data << 10 * Trinity::Honor::hk_honor_at_level(_session->GetPlayer()->getLevel(), quest->GetRewHonorMultiplier());
data << float(0); // unk, honor multiplier?
data << uint32(0x08); // unused by client?
data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
data << int32(quest->GetRewSpellCast()); // casted spell
data << uint32(0); // unknown
data << uint32(quest->GetBonusTalents()); // bonus talents
data << uint32(quest->GetRewArenaPoints()); // arena points
data << uint32(0);
*/
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
data << uint32(RewardFactionId[i]);
@@ -357,6 +345,50 @@ void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const
data << uint32(GetRewardSkillPoints());
}
void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const
{
rewards.ChoiceItemCount = GetRewChoiceItemsCount();
rewards.ItemCount = GetReqItemsCount();
rewards.Money = GetRewOrReqMoney(player);
rewards.XP = GetXPReward(player) * sWorld->getRate(RATE_XP_QUEST);
rewards.Title = GetCharTitleId();
rewards.FactionFlags = GetRewardReputationMask();
rewards.SpellCompletionDisplayID = GetRewSpell();
rewards.SpellCompletionID = GetRewSpellCast();
rewards.SkillLineID = GetRewardSkillId();
rewards.NumSkillUps = GetRewardSkillPoints();
rewards.NumBonusTalents = GetBonusTalents();
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
rewards.ChoiceItems[i].ItemID = RewardChoiceItemId[i];
rewards.ChoiceItems[i].Quantity = RewardChoiceItemCount[i];
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i]))
rewards.ChoiceItems[i].DisplayID = itemTemplate->DisplayInfoID;
}
for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
{
rewards.ItemID[i] = RewardItemId[i];
rewards.ItemQty[i] = RewardItemIdCount[i];
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i]))
rewards.ItemDisplayID[i] = itemTemplate->DisplayInfoID;
}
for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
{
rewards.FactionID[i] = RewardFactionId[i];
rewards.FactionValue[i] = RewardFactionValueId[i];
rewards.FactionOverride[i] = RewardFactionValueIdOverride[i];
}
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
{
rewards.CurrencyID[i] = RewardCurrencyId[i];
rewards.CurrencyQty[i] = RewardCurrencyCount[i];
}
}
uint32 Quest::GetRewMoneyMaxLevel() const
{
// If Quest has flag to not give money on max level, it's 0

View File

@@ -27,6 +27,14 @@
class Player;
namespace WorldPackets
{
namespace Quest
{
struct QuestRewards;
}
}
#define MAX_QUEST_LOG_SIZE 25
#define QUEST_OBJECTIVES_COUNT 4
@@ -356,6 +364,7 @@ class TC_GAME_API Quest
uint16 GetEventIdForQuest() const { return _eventIdForQuest; }
void BuildExtraQuestInfo(WorldPacket& data, Player* player) const;
void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const;
typedef std::vector<int32> PrevQuests;
PrevQuests prevQuests;

View File

@@ -132,3 +132,95 @@ WorldPacket const* WorldPackets::Quest::QuestGiverQuestListMessage::Write()
return &_worldPacket;
}
WorldPacket const* WorldPackets::Quest::QuestGiverStatus::Write()
{
_worldPacket << QuestGiver.Guid;
_worldPacket << uint32(QuestGiver.Status);
return &_worldPacket;
}
WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write()
{
_worldPacket << QuestGiverGUID;
_worldPacket << InformUnit;
_worldPacket << uint32(QuestID);
_worldPacket << QuestTitle;
_worldPacket << LogDescription;
_worldPacket << Objectives;
_worldPacket << PortraitGiverText;
_worldPacket << PortraitGiverName;
_worldPacket << PortraitTurnInText;
_worldPacket << PortraitTurnInName;
_worldPacket << uint32(PortraitGiver);
_worldPacket << uint32(PortraitTurnIn);
_worldPacket << uint8(AutoLaunched);
_worldPacket << uint32(QuestFlags);
_worldPacket << uint32(SuggestedPartyMembers);
_worldPacket << uint8(StartCheat); // to-do: validate
_worldPacket << uint8(DisplayPopup);
_worldPacket << uint32(RequiredSpellID);
_worldPacket << Rewards;
_worldPacket << uint32(DescEmotes.size());
for (WorldPackets::Quest::QuestDescEmote const& emote : DescEmotes)
{
_worldPacket << uint32(emote.Type);
_worldPacket << uint32(emote.Delay);
}
return &_worldPacket;
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestRewards const& questRewards)
{
data << uint32(questRewards.ChoiceItemCount);
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
data << uint32(questRewards.ChoiceItems[i].ItemID);
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
data << uint32(questRewards.ChoiceItems[i].Quantity);
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
data << uint32(questRewards.ChoiceItems[i].DisplayID);
data << uint32(questRewards.ItemCount);
for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
data << uint32(questRewards.ItemID[i]);
for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
data << uint32(questRewards.ItemQty[i]);
for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
data << uint32(questRewards.ItemDisplayID[i]);
data << uint32(questRewards.Money);
data << uint32(questRewards.XP);
data << uint32(questRewards.Title);
data << uint32(0); // unkown
data << float(0.0f); // unknown
data << uint32(questRewards.NumBonusTalents);
data << uint32(0); // unkown
data << uint32(questRewards.FactionFlags);
for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
data << uint32(questRewards.FactionID[i]);
for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
data << int32(questRewards.FactionValue[i]);
for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
data << uint32(questRewards.FactionOverride[i]);
data << uint32(questRewards.SpellCompletionDisplayID);
data << uint32(questRewards.SpellCompletionID);
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
data << uint32(questRewards.CurrencyID[i]);
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
data << uint32(questRewards.CurrencyQty[i]);
data << uint32(questRewards.SkillLineID);
data << uint32(questRewards.NumSkillUps);
return data;
}

View File

@@ -207,7 +207,98 @@ namespace WorldPackets
std::vector<GossipText> QuestDataText;
std::string Greeting;
};
struct QuestGiverInfo
{
QuestGiverInfo() { }
QuestGiverInfo(ObjectGuid const& guid, uint32 status)
: Guid(guid), Status(status) { }
ObjectGuid Guid;
uint32 Status = DIALOG_STATUS_NONE;
};
class QuestGiverStatus final : public ServerPacket
{
public:
QuestGiverStatus() : ServerPacket(SMSG_QUEST_GIVER_STATUS, 12) { }
WorldPacket const* Write() override;
QuestGiverInfo QuestGiver;
};
struct QuestInfoChoiceItem
{
int32 ItemID = 0;
int32 Quantity = 0;
int32 DisplayID = 0;
};
struct QuestRewards
{
int32 ChoiceItemCount = 0;
int32 ItemCount = 0;
int32 Money = 0;
int32 XP = 0;
int32 Title = 0;
int32 FactionFlags = 0;
int32 SpellCompletionID = 0;
int32 SpellCompletionDisplayID = 0;
int32 SkillLineID = 0;
int32 NumSkillUps = 0;
int32 NumBonusTalents = 0;
QuestInfoChoiceItem ChoiceItems[QUEST_REWARD_CHOICES_COUNT];
int32 ItemID[QUEST_REWARDS_COUNT] = { };
int32 ItemQty[QUEST_REWARDS_COUNT] = { };
int32 ItemDisplayID[QUEST_REWARDS_COUNT] = { };
int32 FactionID[QUEST_REPUTATIONS_COUNT] = { };
int32 FactionValue[QUEST_REPUTATIONS_COUNT] = { };
int32 FactionOverride[QUEST_REPUTATIONS_COUNT] = { };
int32 CurrencyID[QUEST_REWARD_CURRENCY_COUNT] = { };
int32 CurrencyQty[QUEST_REWARD_CURRENCY_COUNT] = { };
};
struct QuestDescEmote
{
QuestDescEmote(int32 type = 0, uint32 delay = 0) : Type(type), Delay(delay) { }
int32 Type;
uint32 Delay;
};
class QuestGiverQuestDetails final : public ServerPacket
{
public:
QuestGiverQuestDetails() : ServerPacket(SMSG_QUEST_GIVER_QUEST_DETAILS, 100) { }
WorldPacket const* Write() override;
ObjectGuid QuestGiverGUID;
ObjectGuid InformUnit;
int32 QuestID = 0;
uint32 QuestFlags = 0;
int32 SuggestedPartyMembers = 0;
QuestRewards Rewards;
std::vector<QuestDescEmote> DescEmotes;
int32 PortraitTurnIn = 0;
int32 PortraitGiver = 0;
int32 QuestStartItemID = 0;
int32 RequiredSpellID = 0;
std::string PortraitGiverText;
std::string PortraitGiverName;
std::string PortraitTurnInText;
std::string PortraitTurnInName;
std::string QuestTitle;
std::string LogDescription;
std::string DescriptionText;
std::string Objectives;
bool DisplayPopup = false;
bool StartCheat = false;
bool AutoLaunched = false;
};
}
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Quest::QuestRewards const& questRewards);
#endif // SystemPackets_h__

View File

@@ -1135,12 +1135,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_COMPLETE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_DETAILS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_GIVER_QUEST_DETAILS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_QUEST_INVALID, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_GIVER_QUEST_LIST_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_GIVER_REQUEST_ITEMS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_GIVER_STATUS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_STATUS_MULTIPLE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTLOG_FULL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);

View File

@@ -1094,12 +1094,12 @@ enum OpcodeServer
SMSG_QUERY_TIME_RESPONSE = 0x2124,
SMSG_QUESTGIVER_OFFER_REWARD = 0x2427,
SMSG_QUESTGIVER_QUEST_COMPLETE = 0x55A4,
SMSG_QUESTGIVER_QUEST_DETAILS = 0x2425,
SMSG_QUEST_GIVER_QUEST_DETAILS = 0x2425,
SMSG_QUESTGIVER_QUEST_FAILED = 0x4236,
SMSG_QUESTGIVER_QUEST_INVALID = 0x4016,
SMSG_QUEST_GIVER_QUEST_LIST_MESSAGE = 0x0134,
SMSG_QUEST_GIVER_REQUEST_ITEMS = 0x6236,
SMSG_QUESTGIVER_STATUS = 0x2115,
SMSG_QUEST_GIVER_STATUS = 0x2115,
SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x4F25,
SMSG_QUESTLOG_FULL = 0x0E36,
SMSG_QUESTUPDATE_ADD_ITEM = 0x0000,
@@ -1394,7 +1394,7 @@ inline bool IsInstanceOnlyOpcode(uint32 opcode)
case SMSG_DUEL_INBOUNDS:
case SMSG_DUEL_OUTOFBOUNDS:
case SMSG_ITEM_PUSH_RESULT:
case SMSG_QUESTGIVER_STATUS:
case SMSG_QUEST_GIVER_STATUS:
case SMSG_QUERY_TIME_RESPONSE:
case SMSG_MOUNTRESULT:
case SMSG_DUEL_COMPLETE: