Core/Quests: Implement SMSG_QUESTUPDATE_COMPLETE
Quests can now be completed (and it won't crash client)
This commit is contained in:
@@ -323,7 +323,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
|
||||
|
||||
WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size
|
||||
data << uint64(npcGUID);
|
||||
data << uint64(0); // wotlk, something todo with quest sharing?
|
||||
data << uint64(0); // either 0 or a npc guid (quest giver)
|
||||
data << uint32(quest->GetQuestId());
|
||||
data << questTitle;
|
||||
data << questDetails;
|
||||
@@ -341,81 +341,10 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID,
|
||||
data << uint8(0); // 4.x StartType, unknown enum
|
||||
data << uint32(quest->GetRequiredSpell()); // 4.x
|
||||
|
||||
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->GetRewChoiceItemsEffectiveCount());
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
data << uint32(quest->RewardChoiceItemId[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
data << uint32(quest->RewardChoiceItemCount[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
{
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i]))
|
||||
data << uint32(itemTemplate->DisplayInfoID);
|
||||
else
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
data << uint32(quest->GetRewChoiceItemsEffectiveCount());
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
data << uint32(quest->RewardItemId[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
data << uint32(quest->RewardItemIdCount[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
{
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i]))
|
||||
data << uint32(itemTemplate->DisplayInfoID);
|
||||
else
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
data << uint32(quest->GetRewOrReqMoney());
|
||||
data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST));
|
||||
}
|
||||
|
||||
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(quest->GetBonusTalents()); // bonus talents
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
|
||||
/* There are probably some of the unks above
|
||||
// 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.0f); // new 3.3.0, honor multiplier?
|
||||
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) // unk
|
||||
*/
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << uint32(quest->RewardFactionId[i]);
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << int32(quest->RewardFactionValueId[i]);
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << int32(quest->RewardFactionValueIdOverride[i]);
|
||||
|
||||
data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
|
||||
data << int32(quest->GetRewSpellCast()); // casted spell
|
||||
|
||||
for (uint8 i = 0; i < 4; i++)
|
||||
data << uint32(0); // 4.x Unk
|
||||
for (uint8 i = 0; i < 4; i++)
|
||||
data << uint32(0); // 4.x Unk
|
||||
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
quest->BuildExtraQuestInfo(data, _session->GetPlayer());
|
||||
|
||||
data << uint32(QUEST_EMOTE_COUNT);
|
||||
for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
|
||||
for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i)
|
||||
{
|
||||
data << uint32(quest->DetailsEmote[i]);
|
||||
data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms)
|
||||
|
||||
@@ -14779,7 +14779,7 @@ void Player::CompleteQuest(uint32 quest_id)
|
||||
if (qInfo->HasFlag(QUEST_FLAGS_AUTO_REWARDED))
|
||||
RewardQuest(qInfo, 0, this, false);
|
||||
else
|
||||
SendQuestComplete(quest_id);
|
||||
SendQuestComplete(qInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16082,15 +16082,56 @@ bool Player::HasQuestForItem(uint32 itemid) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void Player::SendQuestComplete(uint32 quest_id)
|
||||
void Player::SendQuestComplete(Quest const* quest)
|
||||
{
|
||||
if (quest_id)
|
||||
// SMSG_QUESTUPDATE_COMPLETE - whole new structure in 4.x
|
||||
|
||||
std::string title = quest->GetTitle();
|
||||
std::string completedText = quest->GetCompletedText();
|
||||
std::string questGiverTextWindow = quest->GetQuestGiverTextWindow();
|
||||
std::string questGiverTargetName = quest->GetQuestGiverTargetName();
|
||||
std::string questTurnTextWindow = quest->GetQuestTurnTextWindow();
|
||||
std::string questTurnTargetName = quest->GetQuestTurnTargetName();
|
||||
|
||||
int32 locale = GetSession()->GetSessionDbLocaleIndex();
|
||||
if (locale >= 0)
|
||||
{
|
||||
WorldPacket data(SMSG_QUESTUPDATE_COMPLETE, 4);
|
||||
data << uint32(quest_id);
|
||||
GetSession()->SendPacket(&data);
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id);
|
||||
if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(quest->GetQuestId()))
|
||||
{
|
||||
ObjectMgr::GetLocaleString(localeData->Title, locale, title);
|
||||
ObjectMgr::GetLocaleString(localeData->CompletedText, locale, completedText);
|
||||
ObjectMgr::GetLocaleString(localeData->QuestGiverTextWindow, locale, questGiverTextWindow);
|
||||
ObjectMgr::GetLocaleString(localeData->QuestGiverTargetName, locale, questGiverTargetName);
|
||||
ObjectMgr::GetLocaleString(localeData->QuestTurnTextWindow, locale, questTurnTextWindow);
|
||||
ObjectMgr::GetLocaleString(localeData->QuestTurnTargetName, locale, questTurnTargetName);
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_QUESTUPDATE_COMPLETE, 4);
|
||||
data << uint64(this->GetGUID());
|
||||
data << uint32(quest->GetQuestId());
|
||||
data << title;
|
||||
data << completedText;
|
||||
data << questGiverTextWindow;
|
||||
data << questGiverTargetName;
|
||||
data << questTurnTextWindow;
|
||||
data << questTurnTargetName;
|
||||
data << uint32(quest->GetQuestGiverPortrait());
|
||||
data << uint32(quest->GetQuestTurnInPortrait());
|
||||
data << int8(0); // Unk
|
||||
data << uint32(quest->GetFlags());
|
||||
data << int32(0); // Unk
|
||||
data << uint32(QUEST_EMOTE_COUNT);
|
||||
for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i)
|
||||
{
|
||||
data << uint32(quest->DetailsEmote[i]);
|
||||
data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms)
|
||||
}
|
||||
|
||||
quest->BuildExtraQuestInfo(data, this);
|
||||
|
||||
GetSession()->SendPacket(&data);
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest->GetQuestId());
|
||||
}
|
||||
|
||||
void Player::SendQuestReward(Quest const* quest, uint32 XP, Object* questGiver)
|
||||
|
||||
@@ -1500,7 +1500,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
void UpdateForQuestWorldObjects();
|
||||
bool CanShareQuest(uint32 quest_id) const;
|
||||
|
||||
void SendQuestComplete(uint32 quest_id);
|
||||
void SendQuestComplete(Quest const* quest);
|
||||
void SendQuestReward(Quest const* quest, uint32 XP, Object* questGiver);
|
||||
void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK);
|
||||
void SendQuestTimerFailed(uint32 quest_id);
|
||||
|
||||
@@ -266,6 +266,82 @@ uint32 Quest::GetRewItemsEffectiveCount() const
|
||||
return count;
|
||||
}
|
||||
|
||||
void Quest::BuildExtraQuestInfo(WorldPacket& data, Player* player) const
|
||||
{
|
||||
if (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(GetRewChoiceItemsEffectiveCount());
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
data << uint32(RewardChoiceItemId[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
data << uint32(RewardChoiceItemCount[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
{
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i]))
|
||||
data << uint32(itemTemplate->DisplayInfoID);
|
||||
else
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
data << uint32(GetRewChoiceItemsEffectiveCount());
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
data << uint32(RewardItemId[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
data << uint32(RewardItemIdCount[i]);
|
||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
{
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i]))
|
||||
data << uint32(itemTemplate->DisplayInfoID);
|
||||
else
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
data << uint32(GetRewOrReqMoney());
|
||||
data << uint32(XPValue(player) * sWorld->getRate(RATE_XP_QUEST));
|
||||
}
|
||||
|
||||
data << uint32(GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(GetBonusTalents()); // bonus talents
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
|
||||
/* These are probably some of the unks above
|
||||
// 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.0f); // new 3.3.0, honor multiplier?
|
||||
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) // unk
|
||||
*/
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << uint32(RewardFactionId[i]);
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << int32(RewardFactionValueId[i]);
|
||||
|
||||
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
data << int32(RewardFactionValueIdOverride[i]);
|
||||
|
||||
data << uint32(GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
|
||||
data << int32(GetRewSpellCast()); // casted spell
|
||||
|
||||
for (uint8 i = 0; i < 4; i++)
|
||||
data << uint32(0); // 4.x Unk
|
||||
for (uint8 i = 0; i < 4; i++)
|
||||
data << uint32(0); // 4.x Unk
|
||||
|
||||
data << uint32(0); // 4.x Unk
|
||||
data << uint32(0); // 4.x Unk
|
||||
}
|
||||
|
||||
bool Quest::IsAutoComplete() const
|
||||
{
|
||||
return Method == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE);
|
||||
|
||||
@@ -310,6 +310,8 @@ class Quest
|
||||
uint32 GetRewChoiceItemsEffectiveCount() const;
|
||||
uint32 GetRewItemsCount() const { return m_rewItemsCount; }
|
||||
|
||||
void BuildExtraQuestInfo(WorldPacket& data, Player* player) const;
|
||||
|
||||
typedef std::vector<int32> PrevQuests;
|
||||
PrevQuests prevQuests;
|
||||
typedef std::vector<uint32> PrevChainQuests;
|
||||
|
||||
@@ -470,7 +470,7 @@ void InitOpcodes()
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTLOG_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_FAILEDTIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_COMPLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_KILL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(SMSG_QUESTUPDATE_ADD_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
|
||||
//DEFINE_OPCODE_HANDLER(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept );
|
||||
|
||||
Reference in New Issue
Block a user