Core/Quests: Implement SMSG_QUESTUPDATE_COMPLETE

Quests can now be completed (and it won't crash client)
This commit is contained in:
Nay
2011-12-21 23:26:10 +00:00
parent ed4a74690e
commit 770ff57101
6 changed files with 131 additions and 83 deletions
@@ -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)
+48 -7
View File
@@ -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)
+1 -1
View File
@@ -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);
+76
View File
@@ -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);
+2
View File
@@ -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;
+1 -1
View File
@@ -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 );