From 52b074828208d1a5ac9a3733d1f6e0529b639d74 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 14 Mar 2011 23:13:41 +0300 Subject: [PATCH] [11246] Provide mail template items for offline players Implemented generation mail template items at mails loading in case when original mail send in time when receiver has been offline. Before like receiver not receive items. Small change in mail.has_items meaning. Now it set also in cases when items generated for template but none items really added to mail. This not affect mostly existed code work aceept case when mail with template loading. --- src/game/CharacterHandler.cpp | 2 +- src/game/Mail.cpp | 61 ++++++++++++++++++++++++++++++++--- src/game/Mail.h | 17 +++++++--- src/game/Player.cpp | 11 +++++-- src/shared/revision_nr.h | 2 +- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 62683a309..92fdca2db 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -100,7 +100,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, "SELECT talent_id, current_rank, spec FROM character_talent WHERE guid = '%u'", m_guid.GetCounter()); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", m_guid.GetCounter()); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGLYPHS, "SELECT spec, slot, glyph FROM character_glyphs WHERE guid='%u'", m_guid.GetCounter()); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILS, "SELECT id,messageType,sender,receiver,subject,body,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId FROM mail WHERE receiver = '%u' ORDER BY id DESC", m_guid.GetCounter()); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILS, "SELECT id,messageType,sender,receiver,subject,body,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId,has_items FROM mail WHERE receiver = '%u' ORDER BY id DESC", m_guid.GetCounter()); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS, "SELECT data, text, mail_id, item_guid, item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE receiver = '%u'", m_guid.GetCounter()); return res; diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 762e9ab19..fa267e82d 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -873,10 +873,10 @@ MailDraft& MailDraft::AddItem( Item* item ) /** * Prepares the items in a MailDraft. */ -void MailDraft::prepareItems(Player* receiver) +bool MailDraft::prepareItems(Player* receiver) { if (!m_mailTemplateId || !m_mailTemplateItemsNeed) - return; + return false; m_mailTemplateItemsNeed = false; @@ -897,6 +897,8 @@ void MailDraft::prepareItems(Player* receiver) } } } + + return true; } /** * Deletes the items included in a MailDraft. @@ -1002,9 +1004,14 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende { Player* pReceiver = receiver.GetPlayer(); // can be NULL - if (pReceiver) - prepareItems(pReceiver); // generate mail template items + bool has_items = !m_items.empty(); + // generate mail template items for online player, for offline player items will generated at open + if (pReceiver) + { + if (prepareItems(pReceiver)) + has_items = true; + } uint32 mailId = sObjectMgr.GenerateMailID(); @@ -1030,7 +1037,7 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%s', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%u')", - mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGuid().GetCounter(), safe_subject.c_str(), safe_body.c_str(), (m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); + mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGuid().GetCounter(), safe_subject.c_str(), safe_body.c_str(), (has_items ? 1 : 0), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); for(MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { @@ -1079,4 +1086,48 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende else if (!m_items.empty()) deleteIncludedItems(); } + +/** + * Generate items from template at mails loading (this happens when mail with mail template items send in time when receiver has been offline) + * + * @param receiver reciver of mail + */ + +void Mail::prepareTemplateItems( Player* receiver ) +{ + if (!mailTemplateId || !items.empty()) + return; + + has_items = true; + + Loot mailLoot; + + // can be empty + mailLoot.FillLoot(mailTemplateId, LootTemplates_Mail, receiver, true, true); + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("UPDATE mail SET has_items = 1 WHERE id = %u", messageID); + + uint32 max_slot = mailLoot.GetMaxSlotInLootFor(receiver); + for(uint32 i = 0; items.size() < MAX_MAIL_ITEMS && i < max_slot; ++i) + { + if (LootItem* lootitem = mailLoot.LootItemInSlot(i, receiver)) + { + if (Item* item = Item::CreateItem(lootitem->itemid, lootitem->count, receiver)) + { + item->SaveToDB(); + + AddItem(item->GetGUIDLow(), item->GetEntry()); + + receiver->AddMItem(item); + + CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", + messageID, item->GetGUIDLow(), item->GetEntry(), receiver->GetGUIDLow()); + } + } + } + + CharacterDatabase.CommitTransaction(); +} + /*! @} */ diff --git a/src/game/Mail.h b/src/game/Mail.h index 8d845d858..7822e8856 100644 --- a/src/game/Mail.h +++ b/src/game/Mail.h @@ -249,7 +249,7 @@ class MailDraft MailDraft& operator=(MailDraft const&); // trap decl, no body, ...because items clone is high price operation void deleteIncludedItems(bool inDB = false); - void prepareItems(Player* receiver); ///< called from SendMailTo for generate mailTemplateBase items + bool prepareItems(Player* receiver); ///< called from SendMailTo for generate mailTemplateBase items /// The ID of the template associated with this MailDraft. uint16 m_mailTemplateId; @@ -298,6 +298,8 @@ struct Mail std::string subject; /// the body of the mail std::string body; + /// flag mark mail that already has items, or already generate none items for template + bool has_items; /// A vector containing Information about the items in this mail. MailItemInfoVec items; /// A vector containing Information about the items that where already take from this mail. @@ -331,6 +333,7 @@ struct Mail mii.item_guid = itemGuidLow; mii.item_template = item_template; items.push_back(mii); + has_items = true; } /** @@ -357,13 +360,19 @@ struct Mail } /* - * Checks whether a mail contains items or not. + * Checks whether a mail contains items (including case none items generated from template already) or not. * HasItems() checks whether the mail contains items or not. * - * @returns true if the mail contains items, false otherwise. + * @returns true if the mail contains items or template items already generated possible none, false otherwise. * */ - bool HasItems() const { return !items.empty(); } + bool HasItems() const { return has_items; } + + /* + * Generate items for template if items not genereated before (receiver has been offline, has_items == false) + * + */ + void prepareTemplateItems(Player* receiver); ///< called from _LoadMails for generate mailTemplateBase items not generated for offline player }; #endif diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d187d68f0..b049a13d7 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16328,8 +16328,8 @@ void Player::_LoadMailedItems(QueryResult *result) void Player::_LoadMails(QueryResult *result) { m_mail.clear(); - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - //"SELECT id,messageType,sender,receiver,subject,body,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId FROM mail WHERE receiver = '%u' ORDER BY id DESC", GetGUIDLow() + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + //"SELECT id,messageType,sender,receiver,subject,body,expire_time,deliver_time,money,cod,checked,stationery,mailTemplateId,has_items FROM mail WHERE receiver = '%u' ORDER BY id DESC", GetGUIDLow() if(!result) return; @@ -16350,8 +16350,9 @@ void Player::_LoadMails(QueryResult *result) m->checked = fields[10].GetUInt32(); m->stationery = fields[11].GetUInt8(); m->mailTemplateId = fields[12].GetInt16(); + m->has_items = fields[13].GetBool(); // true, if mail have items or mail have template and items generated (maybe none) - if(m->mailTemplateId && !sMailTemplateStore.LookupEntry(m->mailTemplateId)) + if (m->mailTemplateId && !sMailTemplateStore.LookupEntry(m->mailTemplateId)) { sLog.outError( "Player::_LoadMail - Mail (%u) have nonexistent MailTemplateId (%u), remove at load", m->messageID, m->mailTemplateId); m->mailTemplateId = 0; @@ -16360,6 +16361,10 @@ void Player::_LoadMails(QueryResult *result) m->state = MAIL_STATE_UNCHANGED; m_mail.push_back(m); + + if (m->mailTemplateId && !m->has_items) + m->prepareTemplateItems(this); + } while( result->NextRow() ); delete result; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 392b3cd3f..ef61ed31b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11245" + #define REVISION_NR "11246" #endif // __REVISION_NR_H__