mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-28 16:16:27 +00:00
First Commit
For Azeroth!
This commit is contained in:
286
src/server/game/Mails/Mail.cpp
Normal file
286
src/server/game/Mails/Mail.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Mail.h"
|
||||
#include "Log.h"
|
||||
#include "World.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "Unit.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "Item.h"
|
||||
#include "AuctionHouseMgr.h"
|
||||
#include "CalendarMgr.h"
|
||||
|
||||
MailSender::MailSender(Object* sender, MailStationery stationery) : m_stationery(stationery)
|
||||
{
|
||||
switch (sender->GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
m_messageType = MAIL_CREATURE;
|
||||
m_senderId = sender->GetEntry();
|
||||
break;
|
||||
case TYPEID_GAMEOBJECT:
|
||||
m_messageType = MAIL_GAMEOBJECT;
|
||||
m_senderId = sender->GetEntry();
|
||||
break;
|
||||
/*case TYPEID_ITEM:
|
||||
m_messageType = MAIL_ITEM;
|
||||
m_senderId = sender->GetEntry();
|
||||
break;*/
|
||||
case TYPEID_PLAYER:
|
||||
m_messageType = MAIL_NORMAL;
|
||||
m_senderId = sender->GetGUIDLow();
|
||||
break;
|
||||
default:
|
||||
m_messageType = MAIL_NORMAL;
|
||||
m_senderId = 0; // will show mail from not existed player
|
||||
sLog->outError("MailSender::MailSender - Mail have unexpected sender typeid (%u)", sender->GetTypeId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MailSender::MailSender(CalendarEvent* sender)
|
||||
: m_messageType(MAIL_CALENDAR), m_senderId(sender->GetEventId()), m_stationery(MAIL_STATIONERY_DEFAULT) // what stationery we should use here?
|
||||
{
|
||||
}
|
||||
|
||||
MailSender::MailSender(AuctionEntry* sender)
|
||||
: m_messageType(MAIL_AUCTION), m_senderId(sender->GetHouseId()), m_stationery(MAIL_STATIONERY_AUCTION)
|
||||
{
|
||||
}
|
||||
|
||||
MailSender::MailSender(Player* sender)
|
||||
{
|
||||
m_messageType = MAIL_NORMAL;
|
||||
m_stationery = sender->IsGameMaster() ? MAIL_STATIONERY_GM : MAIL_STATIONERY_DEFAULT;
|
||||
m_senderId = sender->GetGUIDLow();
|
||||
}
|
||||
|
||||
MailReceiver::MailReceiver(Player* receiver) : m_receiver(receiver), m_receiver_lowguid(receiver->GetGUIDLow())
|
||||
{
|
||||
}
|
||||
|
||||
MailReceiver::MailReceiver(Player* receiver, uint32 receiver_lowguid) : m_receiver(receiver), m_receiver_lowguid(receiver_lowguid)
|
||||
{
|
||||
ASSERT(!receiver || receiver->GetGUIDLow() == receiver_lowguid);
|
||||
}
|
||||
|
||||
MailDraft& MailDraft::AddItem(Item* item)
|
||||
{
|
||||
m_items[item->GetGUIDLow()] = item; return *this;
|
||||
}
|
||||
|
||||
void MailDraft::prepareItems(Player* receiver, SQLTransaction& trans)
|
||||
{
|
||||
if (!m_mailTemplateId || !m_mailTemplateItemsNeed)
|
||||
return;
|
||||
|
||||
m_mailTemplateItemsNeed = false;
|
||||
|
||||
Loot mailLoot;
|
||||
|
||||
// can be empty
|
||||
mailLoot.FillLoot(m_mailTemplateId, LootTemplates_Mail, receiver, true, true);
|
||||
|
||||
uint32 max_slot = mailLoot.GetMaxSlotInLootFor(receiver);
|
||||
for (uint32 i = 0; m_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(trans); // save for prevent lost at next mail load, if send fail then item will deleted
|
||||
AddItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MailDraft::deleteIncludedItems(SQLTransaction& trans, bool inDB /*= false*/ )
|
||||
{
|
||||
for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
|
||||
{
|
||||
Item* item = mailItemIter->second;
|
||||
|
||||
if (inDB)
|
||||
{
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
|
||||
stmt->setUInt32(0, item->GetGUIDLow());
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
delete item;
|
||||
}
|
||||
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction& trans)
|
||||
{
|
||||
Player* receiver = ObjectAccessor::FindPlayerInOrOutOfWorld(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
|
||||
|
||||
uint32 rc_account = 0;
|
||||
if (!receiver)
|
||||
rc_account = sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER));
|
||||
|
||||
if (!receiver && !rc_account) // sender not exist
|
||||
{
|
||||
deleteIncludedItems(trans, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_items.empty())
|
||||
{
|
||||
// if item send to character at another account, then apply item delivery delay
|
||||
//needItemDelay = sender_acc != rc_account;
|
||||
|
||||
// set owner to new receiver (to prevent delete item with sender char deleting)
|
||||
for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
|
||||
{
|
||||
Item* item = mailItemIter->second;
|
||||
item->SaveToDB(trans); // item not in inventory and can be save standalone
|
||||
// owner in data will set at mail receive and item extracting
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_OWNER);
|
||||
stmt->setUInt32(0, receiver_guid);
|
||||
stmt->setUInt32(1, item->GetGUIDLow());
|
||||
trans->Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: WowWiki: "Return mail arrives immediately."
|
||||
|
||||
// will delete item or place to receiver mail list
|
||||
SendMailTo(trans, MailReceiver(receiver, receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, 0);
|
||||
}
|
||||
|
||||
void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay)
|
||||
{
|
||||
Player* pReceiver = receiver.GetPlayer(); // can be NULL
|
||||
Player* pSender = ObjectAccessor::FindPlayerInOrOutOfWorld(MAKE_NEW_GUID(sender.GetSenderId(), 0, HIGHGUID_PLAYER));
|
||||
|
||||
if (pReceiver)
|
||||
prepareItems(pReceiver, trans); // generate mail template items
|
||||
|
||||
uint32 mailId = sObjectMgr->GenerateMailID();
|
||||
|
||||
time_t deliver_time = time(NULL) + deliver_delay;
|
||||
|
||||
//expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour
|
||||
uint32 expire_delay;
|
||||
|
||||
// auction mail without any items and money
|
||||
if (sender.GetMailMessageType() == MAIL_AUCTION && m_items.empty() && !m_money)
|
||||
expire_delay = sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY);
|
||||
// mail from battlemaster (rewardmarks) should last only one day
|
||||
else if (sender.GetMailMessageType() == MAIL_CREATURE && sBattlegroundMgr->GetBattleMasterBG(sender.GetSenderId()) != BATTLEGROUND_TYPE_NONE)
|
||||
expire_delay = DAY;
|
||||
// default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
|
||||
else
|
||||
{
|
||||
if (m_COD)
|
||||
expire_delay = 3 * DAY;
|
||||
else
|
||||
expire_delay = pSender && pSender->GetSession()->GetSecurity() ? 90 * DAY : 30 * DAY;
|
||||
}
|
||||
|
||||
time_t expire_time = deliver_time + expire_delay;
|
||||
|
||||
// Add to DB
|
||||
uint8 index = 0;
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL);
|
||||
stmt->setUInt32( index, mailId);
|
||||
stmt->setUInt8 (++index, uint8(sender.GetMailMessageType()));
|
||||
stmt->setInt8 (++index, int8(sender.GetStationery()));
|
||||
stmt->setUInt16(++index, GetMailTemplateId());
|
||||
stmt->setUInt32(++index, sender.GetSenderId());
|
||||
stmt->setUInt32(++index, receiver.GetPlayerGUIDLow());
|
||||
stmt->setString(++index, GetSubject());
|
||||
stmt->setString(++index, GetBody());
|
||||
stmt->setBool (++index, !m_items.empty());
|
||||
stmt->setUInt64(++index, uint64(expire_time));
|
||||
stmt->setUInt64(++index, uint64(deliver_time));
|
||||
stmt->setUInt32(++index, m_money);
|
||||
stmt->setUInt32(++index, m_COD);
|
||||
stmt->setUInt8 (++index, uint8(checked));
|
||||
trans->Append(stmt);
|
||||
|
||||
for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
|
||||
{
|
||||
Item* pItem = mailItemIter->second;
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM);
|
||||
stmt->setUInt32(0, mailId);
|
||||
stmt->setUInt32(1, pItem->GetGUIDLow());
|
||||
stmt->setUInt32(2, receiver.GetPlayerGUIDLow());
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
// xinef: update global data
|
||||
sWorld->UpdateGlobalPlayerMails(receiver.GetPlayerGUIDLow(), 1);
|
||||
|
||||
// For online receiver update in game mail status and data
|
||||
if (pReceiver)
|
||||
{
|
||||
pReceiver->AddNewMailDeliverTime(deliver_time);
|
||||
|
||||
if (pReceiver->IsMailsLoaded())
|
||||
{
|
||||
Mail* m = new Mail;
|
||||
m->messageID = mailId;
|
||||
m->mailTemplateId = GetMailTemplateId();
|
||||
m->subject = GetSubject();
|
||||
m->body = GetBody();
|
||||
m->money = GetMoney();
|
||||
m->COD = GetCOD();
|
||||
|
||||
for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
|
||||
{
|
||||
Item* item = mailItemIter->second;
|
||||
m->AddItem(item->GetGUIDLow(), item->GetEntry());
|
||||
}
|
||||
|
||||
m->messageType = sender.GetMailMessageType();
|
||||
m->stationery = sender.GetStationery();
|
||||
m->sender = sender.GetSenderId();
|
||||
m->receiver = receiver.GetPlayerGUIDLow();
|
||||
m->expire_time = expire_time;
|
||||
m->deliver_time = deliver_time;
|
||||
m->checked = checked;
|
||||
m->state = MAIL_STATE_UNCHANGED;
|
||||
|
||||
pReceiver->AddMail(m); // to insert new mail to beginning of maillist
|
||||
|
||||
if (!m_items.empty())
|
||||
{
|
||||
for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
|
||||
pReceiver->AddMItem(mailItemIter->second);
|
||||
}
|
||||
}
|
||||
else if (!m_items.empty())
|
||||
{
|
||||
SQLTransaction temp = SQLTransaction(NULL);
|
||||
deleteIncludedItems(temp);
|
||||
}
|
||||
}
|
||||
else if (!m_items.empty())
|
||||
{
|
||||
SQLTransaction temp = SQLTransaction(NULL);
|
||||
deleteIncludedItems(temp);
|
||||
}
|
||||
}
|
||||
207
src/server/game/Mails/Mail.h
Normal file
207
src/server/game/Mails/Mail.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C)
|
||||
* Copyright (C)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_MAIL_H
|
||||
#define TRINITY_MAIL_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <map>
|
||||
|
||||
struct AuctionEntry;
|
||||
struct CalendarEvent;
|
||||
class Item;
|
||||
class Object;
|
||||
class Player;
|
||||
|
||||
#define MAIL_BODY_ITEM_TEMPLATE 8383 // - plain letter, A Dusty Unsent Letter: 889
|
||||
#define MAX_MAIL_ITEMS 12
|
||||
|
||||
enum MailMessageType
|
||||
{
|
||||
MAIL_NORMAL = 0,
|
||||
MAIL_AUCTION = 2,
|
||||
MAIL_CREATURE = 3, // client send CMSG_CREATURE_QUERY on this mailmessagetype
|
||||
MAIL_GAMEOBJECT = 4, // client send CMSG_GAMEOBJECT_QUERY on this mailmessagetype
|
||||
MAIL_CALENDAR = 5
|
||||
};
|
||||
|
||||
enum MailCheckMask
|
||||
{
|
||||
MAIL_CHECK_MASK_NONE = 0x00,
|
||||
MAIL_CHECK_MASK_READ = 0x01,
|
||||
MAIL_CHECK_MASK_RETURNED = 0x02, /// This mail was returned. Do not allow returning mail back again.
|
||||
MAIL_CHECK_MASK_COPIED = 0x04, /// This mail was copied. Do not allow making a copy of items in mail.
|
||||
MAIL_CHECK_MASK_COD_PAYMENT = 0x08,
|
||||
MAIL_CHECK_MASK_HAS_BODY = 0x10, /// This mail has body text.
|
||||
};
|
||||
|
||||
// gathered from Stationery.dbc
|
||||
enum MailStationery
|
||||
{
|
||||
MAIL_STATIONERY_TEST = 1,
|
||||
MAIL_STATIONERY_DEFAULT = 41,
|
||||
MAIL_STATIONERY_GM = 61,
|
||||
MAIL_STATIONERY_AUCTION = 62,
|
||||
MAIL_STATIONERY_VAL = 64, // Valentine
|
||||
MAIL_STATIONERY_CHR = 65, // Christmas
|
||||
MAIL_STATIONERY_ORP = 67, // Orphan
|
||||
};
|
||||
|
||||
enum MailState
|
||||
{
|
||||
MAIL_STATE_UNCHANGED = 1,
|
||||
MAIL_STATE_CHANGED = 2,
|
||||
MAIL_STATE_DELETED = 3
|
||||
};
|
||||
|
||||
enum MailShowFlags
|
||||
{
|
||||
MAIL_SHOW_UNK0 = 0x0001,
|
||||
MAIL_SHOW_DELETE = 0x0002, // forced show delete button instead return button
|
||||
MAIL_SHOW_AUCTION = 0x0004, // from old comment
|
||||
MAIL_SHOW_UNK2 = 0x0008, // unknown, COD will be shown even without that flag
|
||||
MAIL_SHOW_RETURN = 0x0010,
|
||||
};
|
||||
|
||||
class MailSender
|
||||
{
|
||||
public: // Constructors
|
||||
MailSender(MailMessageType messageType, uint32 sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT)
|
||||
: m_messageType(messageType), m_senderId(sender_guidlow_or_entry), m_stationery(stationery)
|
||||
{
|
||||
}
|
||||
MailSender(Object* sender, MailStationery stationery = MAIL_STATIONERY_DEFAULT);
|
||||
MailSender(CalendarEvent* sender);
|
||||
MailSender(AuctionEntry* sender);
|
||||
MailSender(Player* sender);
|
||||
public: // Accessors
|
||||
MailMessageType GetMailMessageType() const { return m_messageType; }
|
||||
uint32 GetSenderId() const { return m_senderId; }
|
||||
MailStationery GetStationery() const { return m_stationery; }
|
||||
private:
|
||||
MailMessageType m_messageType;
|
||||
uint32 m_senderId; // player low guid or other object entry
|
||||
MailStationery m_stationery;
|
||||
};
|
||||
|
||||
class MailReceiver
|
||||
{
|
||||
public: // Constructors
|
||||
explicit MailReceiver(uint32 receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) {}
|
||||
MailReceiver(Player* receiver);
|
||||
MailReceiver(Player* receiver, uint32 receiver_lowguid);
|
||||
public: // Accessors
|
||||
Player* GetPlayer() const { return m_receiver; }
|
||||
uint32 GetPlayerGUIDLow() const { return m_receiver_lowguid; }
|
||||
private:
|
||||
Player* m_receiver;
|
||||
uint32 m_receiver_lowguid;
|
||||
};
|
||||
|
||||
class MailDraft
|
||||
{
|
||||
typedef std::map<uint32, Item*> MailItemMap;
|
||||
|
||||
public: // Constructors
|
||||
explicit MailDraft(uint16 mailTemplateId, bool need_items = true)
|
||||
: m_mailTemplateId(mailTemplateId), m_mailTemplateItemsNeed(need_items), m_money(0), m_COD(0)
|
||||
{}
|
||||
MailDraft(std::string const& subject, std::string const& body)
|
||||
: m_mailTemplateId(0), m_mailTemplateItemsNeed(false), m_subject(subject), m_body(body), m_money(0), m_COD(0) {}
|
||||
public: // Accessors
|
||||
uint16 GetMailTemplateId() const { return m_mailTemplateId; }
|
||||
std::string const& GetSubject() const { return m_subject; }
|
||||
uint32 GetMoney() const { return m_money; }
|
||||
uint32 GetCOD() const { return m_COD; }
|
||||
std::string const& GetBody() const { return m_body; }
|
||||
|
||||
public: // modifiers
|
||||
MailDraft& AddItem(Item* item);
|
||||
MailDraft& AddMoney(uint32 money) { m_money = money; return *this; }
|
||||
MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; }
|
||||
|
||||
public: // finishers
|
||||
void SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction& trans);
|
||||
void SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0);
|
||||
|
||||
private:
|
||||
void deleteIncludedItems(SQLTransaction& trans, bool inDB = false);
|
||||
void prepareItems(Player* receiver, SQLTransaction& trans); // called from SendMailTo for generate mailTemplateBase items
|
||||
|
||||
uint16 m_mailTemplateId;
|
||||
bool m_mailTemplateItemsNeed;
|
||||
std::string m_subject;
|
||||
std::string m_body;
|
||||
|
||||
MailItemMap m_items; // Keep the items in a map to avoid duplicate guids (which can happen), store only low part of guid
|
||||
|
||||
uint32 m_money;
|
||||
uint32 m_COD;
|
||||
};
|
||||
|
||||
struct MailItemInfo
|
||||
{
|
||||
uint32 item_guid;
|
||||
uint32 item_template;
|
||||
};
|
||||
typedef std::vector<MailItemInfo> MailItemInfoVec;
|
||||
|
||||
struct Mail
|
||||
{
|
||||
uint32 messageID;
|
||||
uint8 messageType;
|
||||
uint8 stationery;
|
||||
uint16 mailTemplateId;
|
||||
uint32 sender;
|
||||
uint32 receiver;
|
||||
std::string subject;
|
||||
std::string body;
|
||||
std::vector<MailItemInfo> items;
|
||||
std::vector<uint32> removedItems;
|
||||
time_t expire_time;
|
||||
time_t deliver_time;
|
||||
uint32 money;
|
||||
uint32 COD;
|
||||
uint32 checked;
|
||||
MailState state;
|
||||
|
||||
void AddItem(uint32 itemGuidLow, uint32 item_template)
|
||||
{
|
||||
MailItemInfo mii;
|
||||
mii.item_guid = itemGuidLow;
|
||||
mii.item_template = item_template;
|
||||
items.push_back(mii);
|
||||
}
|
||||
|
||||
bool RemoveItem(uint32 item_guid)
|
||||
{
|
||||
for (MailItemInfoVec::iterator itr = items.begin(); itr != items.end(); ++itr)
|
||||
{
|
||||
if (itr->item_guid == item_guid)
|
||||
{
|
||||
items.erase(itr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasItems() const { return !items.empty(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user