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__