TrinityCore
Mail.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Mail.h"
19#include "AuctionHouseMgr.h"
20#include "BlackMarketMgr.h"
21#include "CalendarMgr.h"
22#include "CharacterCache.h"
23#include "DatabaseEnv.h"
24#include "GameTime.h"
25#include "Item.h"
26#include "Log.h"
27#include "Loot.h"
28#include "LootMgr.h"
29#include "ObjectAccessor.h"
30#include "ObjectMgr.h"
31#include "Player.h"
32#include "World.h"
33
34MailSender::MailSender(Object* sender, MailStationery stationery) : m_stationery(stationery)
35{
36 switch (sender->GetTypeId())
37 {
38 case TYPEID_UNIT:
40 m_senderId = uint64(sender->GetEntry());
41 break;
44 m_senderId = uint64(sender->GetEntry());
45 break;
46 /*case TYPEID_ITEM:
47 m_messageType = MAIL_ITEM;
48 m_senderId = sender->GetEntry();
49 break;*/
50 case TYPEID_PLAYER:
52 m_senderId = sender->GetGUID().GetCounter();
53 break;
54 default:
56 m_senderId = UI64LIT(0); // will show mail from non-existing player
57 TC_LOG_ERROR("misc", "MailSender::MailSender - Mail message contains unexpected sender typeid ({}).", sender->GetTypeId());
58 break;
59 }
60}
61
63 : m_messageType(MAIL_CALENDAR), m_senderId(sender->GetEventId()), m_stationery(MAIL_STATIONERY_DEFAULT) // what stationery we should use here?
64{
65}
66
68 : m_messageType(MAIL_AUCTION), m_senderId(uint64(sender->GetAuctionHouseId())), m_stationery(MAIL_STATIONERY_AUCTION) { }
69
71 : m_messageType(MAIL_BLACKMARKET), m_senderId(sender->GetTemplate()->SellerNPC), m_stationery(MAIL_STATIONERY_AUCTION) { }
72
74{
77 m_senderId = sender->GetGUID().GetCounter();
78}
79
81{
83 m_senderId = senderEntry;
85}
86
87MailReceiver::MailReceiver(Player* receiver) : m_receiver(receiver), m_receiver_lowguid(receiver->GetGUID().GetCounter()) { }
88
89MailReceiver::MailReceiver(Player* receiver, ObjectGuid::LowType receiver_lowguid) : m_receiver(receiver), m_receiver_lowguid(receiver_lowguid)
90{
91 ASSERT(!receiver || receiver->GetGUID().GetCounter() == receiver_lowguid);
92}
93
94MailReceiver::MailReceiver(Player* receiver, ObjectGuid receiverGuid) : m_receiver(receiver), m_receiver_lowguid(receiverGuid.GetCounter())
95{
96 ASSERT(!receiver || receiver->GetGUID() == receiverGuid);
97}
98
100{
101 m_items[item->GetGUID().GetCounter()] = item;
102 return *this;
103}
104
106{
108 return;
109
111
112 // The mail sent after turning in the quest The Good News and The Bad News contains 100g
113 if (m_mailTemplateId == 123)
114 m_money = 1000000;
115
116 Loot mailLoot(nullptr, ObjectGuid::Empty, LOOT_NONE, nullptr);
117
118 // can be empty
120
121 for (uint32 i = 0; m_items.size() < MAX_MAIL_ITEMS && i < mailLoot.items.size(); ++i)
122 {
123 if (LootItem* lootitem = mailLoot.LootItemInSlot(i, receiver))
124 {
125 if (Item* item = Item::CreateItem(lootitem->itemid, lootitem->count, lootitem->context, receiver))
126 {
127 item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted
128 AddItem(item);
129 }
130 }
131 }
132}
133
135{
136 for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
137 {
138 Item* item = mailItemIter->second;
139
140 if (inDB)
141 item->DeleteFromDB(trans);
142
143 delete item;
144 }
145
146 m_items.clear();
147}
148
150{
151 ObjectGuid receiverGuid = ObjectGuid::Create<HighGuid::Player>(receiver_guid);
152 Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid);
153
154 uint32 rc_account = 0;
155 if (!receiver)
156 rc_account = sCharacterCache->GetCharacterAccountIdByGuid(receiverGuid);
157
158 if (!receiver && !rc_account) // sender not exist
159 {
160 deleteIncludedItems(trans, true);
161 return;
162 }
163
164 // prepare mail and send in other case
165 bool needItemDelay = false;
166
167 if (!m_items.empty())
168 {
169 // if item send to character at another account, then apply item delivery delay
170 needItemDelay = sender_acc != rc_account;
171
172 // set owner to new receiver (to prevent delete item with sender char deleting)
173 for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
174 {
175 Item* item = mailItemIter->second;
176 item->SaveToDB(trans); // item not in inventory and can be save standalone
177 // owner in data will set at mail receive and item extracting
179 stmt->setUInt64(0, receiver_guid);
180 stmt->setUInt64(1, item->GetGUID().GetCounter());
181 trans->Append(stmt);
182 }
183 }
184
185 // If theres is an item, there is a one hour delivery delay.
186 uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
187
188 // will delete item or place to receiver mail list
189 SendMailTo(trans, MailReceiver(receiver, receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay);
190}
191
192void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay)
193{
194 Player* pReceiver = receiver.GetPlayer(); // can be NULL
195 Player* pSender = sender.GetMailMessageType() == MAIL_NORMAL ? ObjectAccessor::FindPlayer(ObjectGuid::Create<HighGuid::Player>(sender.GetSenderId())) : nullptr;
196
197 if (pReceiver)
198 prepareItems(pReceiver, trans); // generate mail template items
199
200 uint64 mailId = sObjectMgr->GenerateMailID();
201
202 time_t deliver_time = GameTime::GetGameTime() + deliver_delay;
203
204 //expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour
205 uint32 expire_delay;
206
207 // auction mail without any items and money
208 if (sender.GetMailMessageType() == MAIL_AUCTION && m_items.empty() && !m_money)
209 expire_delay = sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY);
210 // default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
211 else
212 {
213 if (m_COD)
214 expire_delay = 3 * DAY;
215 else
216 expire_delay = pSender && pSender->IsGameMaster() ? 90 * DAY : 30 * DAY;
217 }
218
219 time_t expire_time = deliver_time + expire_delay;
220
221 // Add to DB
222 uint8 index = 0;
224 stmt->setUInt64( index, mailId);
225 stmt->setUInt8 (++index, uint8(sender.GetMailMessageType()));
226 stmt->setInt8 (++index, int8(sender.GetStationery()));
227 stmt->setUInt16(++index, GetMailTemplateId());
228 stmt->setUInt64(++index, sender.GetSenderId());
229 stmt->setUInt64(++index, receiver.GetPlayerGUIDLow());
230 stmt->setString(++index, GetSubject());
231 stmt->setString(++index, GetBody());
232 stmt->setBool (++index, !m_items.empty());
233 stmt->setInt64 (++index, expire_time);
234 stmt->setInt64 (++index, deliver_time);
235 stmt->setUInt64(++index, m_money);
236 stmt->setUInt64(++index, m_COD);
237 stmt->setUInt8 (++index, uint8(checked));
238 trans->Append(stmt);
239
240 for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
241 {
242 Item* pItem = mailItemIter->second;
243 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM);
244 stmt->setUInt64(0, mailId);
245 stmt->setUInt64(1, pItem->GetGUID().GetCounter());
246 stmt->setUInt64(2, receiver.GetPlayerGUIDLow());
247 trans->Append(stmt);
248 }
249
250 // For online receiver update in game mail status and data
251 if (pReceiver)
252 {
253 pReceiver->AddNewMailDeliverTime(deliver_time);
254
255 Mail* m = new Mail;
256 m->messageID = mailId;
258 m->subject = GetSubject();
259 m->body = GetBody();
260 m->money = GetMoney();
261 m->COD = GetCOD();
262
263 for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
264 {
265 Item* item = mailItemIter->second;
266 m->AddItem(item->GetGUID().GetCounter(), item->GetEntry());
267 }
268
269 m->messageType = sender.GetMailMessageType();
270 m->stationery = sender.GetStationery();
271 m->sender = sender.GetSenderId();
272 m->receiver = receiver.GetPlayerGUIDLow();
273 m->expire_time = expire_time;
274 m->deliver_time = deliver_time;
275 m->checked = checked;
277
278 pReceiver->AddMail(m); // to insert new mail to beginning of maillist
279
280 if (!m_items.empty())
281 {
282 for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
283 pReceiver->AddMItem(mailItemIter->second);
284 }
285 }
286 else if (!m_items.empty())
287 {
290 }
291}
#define sCharacterCache
@ CHAR_UPD_ITEM_OWNER
@ CHAR_INS_MAIL_ITEM
@ CHAR_INS_MAIL
@ DAY
Definition: Common.h:31
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
uint64_t uint64
Definition: Define.h:141
#define UI64LIT(N)
Definition: Define.h:127
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false)
@ LOOT_NONE
Definition: Loot.h:99
MailCheckMask
Definition: Mail.h:51
@ MAIL_CHECK_MASK_RETURNED
Definition: Mail.h:54
@ MAIL_STATE_UNCHANGED
Definition: Mail.h:74
#define MAX_MAIL_ITEMS
Definition: Mail.h:35
MailStationery
Definition: Mail.h:62
@ MAIL_STATIONERY_GM
Definition: Mail.h:65
@ MAIL_STATIONERY_DEFAULT
Definition: Mail.h:64
@ MAIL_STATIONERY_AUCTION
Definition: Mail.h:66
@ MAIL_AUCTION
Definition: Mail.h:40
@ MAIL_BLACKMARKET
Definition: Mail.h:44
@ MAIL_GAMEOBJECT
Definition: Mail.h:42
@ MAIL_CREATURE
Definition: Mail.h:41
@ MAIL_CALENDAR
Definition: Mail.h:43
@ MAIL_NORMAL
Definition: Mail.h:39
@ TYPEID_GAMEOBJECT
Definition: ObjectGuid.h:43
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
#define sObjectMgr
Definition: ObjectMgr.h:1946
@ LOOT_MODE_DEFAULT
Definition: SharedDefines.h:77
Definition: Item.h:170
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition: Item.cpp:561
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition: Item.cpp:1088
static Item * CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const *player=nullptr, bool addDefaultBonuses=true)
Definition: Item.cpp:1625
uint64 GetCOD() const
Definition: Mail.h:140
void deleteIncludedItems(CharacterDatabaseTransaction trans, bool inDB=false)
Definition: Mail.cpp:134
uint64 m_money
Definition: Mail.h:163
MailItemMap m_items
Definition: Mail.h:161
std::string const & GetSubject() const
Definition: Mail.h:138
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const &receiver, MailSender const &sender, MailCheckMask checked=MAIL_CHECK_MASK_NONE, uint32 deliver_delay=0)
Definition: Mail.cpp:192
uint16 m_mailTemplateId
Definition: Mail.h:156
bool m_mailTemplateItemsNeed
Definition: Mail.h:157
void SendReturnToSender(uint32 sender_acc, ObjectGuid::LowType sender_guid, ObjectGuid::LowType receiver_guid, CharacterDatabaseTransaction trans)
Definition: Mail.cpp:149
uint16 GetMailTemplateId() const
Definition: Mail.h:137
void prepareItems(Player *receiver, CharacterDatabaseTransaction trans)
Definition: Mail.cpp:105
uint64 m_COD
Definition: Mail.h:164
MailDraft & AddItem(Item *item)
Definition: Mail.cpp:99
std::string const & GetBody() const
Definition: Mail.h:141
uint64 GetMoney() const
Definition: Mail.h:139
Player * GetPlayer() const
Definition: Mail.h:119
ObjectGuid::LowType GetPlayerGUIDLow() const
Definition: Mail.h:120
MailReceiver(ObjectGuid::LowType receiver_lowguid)
Definition: Mail.h:114
MailStationery m_stationery
Definition: Mail.h:108
ObjectGuid::LowType GetSenderId() const
Definition: Mail.h:103
MailSender(MailMessageType messageType, ObjectGuid::LowType sender_guidlow_or_entry, MailStationery stationery=MAIL_STATIONERY_DEFAULT)
Definition: Mail.h:91
MailMessageType m_messageType
Definition: Mail.h:106
MailMessageType GetMailMessageType() const
Definition: Mail.h:102
MailStationery GetStationery() const
Definition: Mail.h:104
ObjectGuid::LowType m_senderId
Definition: Mail.h:107
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
uint64 LowType
Definition: ObjectGuid.h:278
Definition: Object.h:150
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void AddNewMailDeliverTime(time_t deliver_time)
Definition: Player.cpp:2667
void AddMItem(Item *it)
Definition: Player.cpp:21862
void AddMail(Mail *mail)
Definition: Player.h:1763
bool IsGameMaster() const
Definition: Player.h:1178
void setUInt8(const uint8 index, const uint8 value)
void setInt64(const uint8 index, const int64 value)
void setBool(const uint8 index, const bool value)
void setUInt16(const uint8 index, const uint16 value)
void setString(const uint8 index, const std::string &value)
void setInt8(const uint8 index, const int8 value)
void setUInt64(const uint8 index, const uint64 value)
#define sWorld
Definition: World.h:931
@ CONFIG_MAIL_DELIVERY_DELAY
Definition: World.h:296
time_t GetGameTime()
Definition: GameTime.cpp:44
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
Definition: Loot.h:176
Definition: Loot.h:281
LootItem * LootItemInSlot(uint32 lootListId, Player const *player, NotNormalLootItem **ffaItem=nullptr)
Definition: Loot.cpp:917
std::vector< LootItem > items
Definition: Loot.h:284
bool FillLoot(uint32 lootId, LootStore const &store, Player *lootOwner, bool personal, bool noEmptyError=false, uint16 lootMode=LOOT_MODE_DEFAULT, ItemContext context=ItemContext::NONE)
Definition: Loot.cpp:759
Definition: Mail.h:175
uint64 messageID
Definition: Mail.h:176
ObjectGuid::LowType receiver
Definition: Mail.h:181
uint8 messageType
Definition: Mail.h:177
uint64 money
Definition: Mail.h:188
uint64 COD
Definition: Mail.h:189
time_t expire_time
Definition: Mail.h:186
uint8 stationery
Definition: Mail.h:178
ObjectGuid::LowType sender
Definition: Mail.h:180
std::string subject
Definition: Mail.h:182
std::string body
Definition: Mail.h:183
void AddItem(ObjectGuid::LowType itemGuidLow, uint32 item_template)
Definition: Mail.h:193
time_t deliver_time
Definition: Mail.h:187
uint32 checked
Definition: Mail.h:190
MailState state
Definition: Mail.h:191
uint16 mailTemplateId
Definition: Mail.h:179