2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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/>.
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2010-08-21 09:53:04 +02:00
#include "DatabaseEnv.h"
2008-10-02 16:23:55 -05:00
#include "Mail.h"
#include "Log.h"
#include "World.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "Unit.h"
2010-08-08 04:37:24 +02:00
#include "BattlegroundMgr.h"
2009-12-16 18:58:36 +02:00
#include "Item.h"
#include "AuctionHouseMgr.h"
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
MailSender :: MailSender ( Object * sender , MailStationery stationery ) : m_stationery ( stationery )
2009-12-16 18:58:36 +02:00
{
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 ;
}
}
2010-04-07 22:59:46 +02:00
MailSender :: MailSender ( AuctionEntry * sender )
2009-12-16 18:58:36 +02:00
: m_messageType ( MAIL_AUCTION ), m_senderId ( sender -> GetHouseId ()), m_stationery ( MAIL_STATIONERY_AUCTION )
{
}
2010-04-07 22:59:46 +02:00
MailReceiver :: MailReceiver ( Player * receiver ) : m_receiver ( receiver ), m_receiver_lowguid ( receiver -> GetGUIDLow ())
2009-12-16 18:58:36 +02:00
{
}
2010-04-07 22:59:46 +02:00
MailReceiver :: MailReceiver ( Player * receiver , uint32 receiver_lowguid ) : m_receiver ( receiver ), m_receiver_lowguid ( receiver_lowguid )
2009-12-16 18:58:36 +02:00
{
ASSERT ( ! receiver || receiver -> GetGUIDLow () == receiver_lowguid );
}
2010-04-07 22:59:46 +02:00
MailDraft & MailDraft :: AddItem ( Item * item )
2009-12-16 18:58:36 +02:00
{
m_items [ item -> GetGUIDLow ()] = item ; return * this ;
}
2010-08-21 03:19:25 +02:00
void MailDraft :: prepareItems ( Player * receiver , SQLTransaction & trans )
2008-10-02 16:23:55 -05:00
{
2009-12-16 18:58:36 +02:00
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 )
2009-01-20 16:44:05 -06:00
{
2009-12-16 18:58:36 +02:00
if ( LootItem * lootitem = mailLoot . LootItemInSlot ( i , receiver ))
2009-01-20 16:44:05 -06:00
{
2009-12-16 18:58:36 +02:00
if ( Item * item = Item :: CreateItem ( lootitem -> itemid , lootitem -> count , receiver ))
{
2010-08-21 03:19:25 +02:00
item -> SaveToDB ( trans ); // save for prevent lost at next mail load, if send fail then item will deleted
2009-12-16 18:58:36 +02:00
AddItem ( item );
}
2009-01-20 16:44:05 -06:00
}
2009-12-16 18:58:36 +02:00
}
}
2010-08-21 03:44:02 +02:00
void MailDraft :: deleteIncludedItems ( SQLTransaction & trans , bool inDB /*= false*/ )
2009-12-16 18:58:36 +02:00
{
for ( MailItemMap :: iterator mailItemIter = m_items . begin (); mailItemIter != m_items . end (); ++ mailItemIter )
{
Item * item = mailItemIter -> second ;
if ( inDB )
2010-09-21 21:55:16 +02:00
{
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_ITEM_INSTANCE );
stmt -> setUInt32 ( 0 , item -> GetGUIDLow ());
trans -> Append ( stmt );
}
2009-12-16 18:58:36 +02:00
delete item ;
}
m_items . clear ();
}
2010-04-07 22:59:46 +02:00
void MailDraft :: SendReturnToSender ( uint32 sender_acc , uint32 sender_guid , uint32 receiver_guid )
2009-12-16 18:58:36 +02:00
{
2010-08-08 05:25:45 +02:00
Player * receiver = sObjectMgr . GetPlayer ( MAKE_NEW_GUID ( receiver_guid , 0 , HIGHGUID_PLAYER ));
2009-12-16 18:58:36 +02:00
uint32 rc_account = 0 ;
if ( ! receiver )
2010-08-08 05:25:45 +02:00
rc_account = sObjectMgr . GetPlayerAccountIdByGUID ( MAKE_NEW_GUID ( receiver_guid , 0 , HIGHGUID_PLAYER ));
2009-12-16 18:58:36 +02:00
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2009-12-16 18:58:36 +02:00
if ( ! receiver && ! rc_account ) // sender not exist
{
2010-08-21 03:44:02 +02:00
deleteIncludedItems ( trans , true );
2009-01-20 16:44:05 -06:00
return ;
}
2009-12-16 18:58:36 +02:00
// prepare mail and send in other case
bool needItemDelay = false ;
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 ;
2010-08-21 03:19:25 +02:00
item -> SaveToDB ( trans ); // item not in inventory and can be save standalone
2009-12-16 18:58:36 +02:00
// owner in data will set at mail receive and item extracting
2010-08-21 03:19:25 +02:00
trans -> PAppend ( "UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'" , receiver_guid , item -> GetGUIDLow ());
2009-12-16 18:58:36 +02:00
}
}
// If theres is an item, there is a one hour delivery delay.
2010-08-23 19:56:47 -07:00
uint32 deliver_delay = needItemDelay ? sWorld . getIntConfig ( CONFIG_MAIL_DELIVERY_DELAY ) : 0 ;
2009-12-16 18:58:36 +02:00
// will delete item or place to receiver mail list
2010-08-21 03:19:25 +02:00
SendMailTo ( trans , MailReceiver ( receiver , receiver_guid ), MailSender ( MAIL_NORMAL , sender_guid ), MAIL_CHECK_MASK_RETURNED , deliver_delay );
CharacterDatabase . CommitTransaction ( trans );
2009-12-16 18:58:36 +02:00
}
2010-08-21 03:19:25 +02:00
void MailDraft :: SendMailTo ( SQLTransaction & trans , MailReceiver const & receiver , MailSender const & sender , MailCheckMask checked , uint32 deliver_delay )
2009-12-16 18:58:36 +02:00
{
Player * pReceiver = receiver . GetPlayer (); // can be NULL
2009-12-18 13:41:30 -08:00
2009-12-16 18:58:36 +02:00
if ( pReceiver )
2010-08-21 03:19:25 +02:00
prepareItems ( pReceiver , trans ); // generate mail template items
2009-12-16 18:58:36 +02:00
2010-08-08 05:25:45 +02:00
uint32 mailId = sObjectMgr . GenerateMailID ();
2009-10-17 15:51:44 -07:00
2009-12-24 10:20:15 +01:00
time_t deliver_time = time ( NULL ) + deliver_delay ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
//expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour
uint32 expire_delay ;
2009-12-16 18:58:36 +02:00
// auction mail without any items and money
if ( sender . GetMailMessageType () == MAIL_AUCTION && m_items . empty () && ! m_money )
2010-08-23 19:56:47 -07:00
expire_delay = sWorld . getIntConfig ( CONFIG_MAIL_DELIVERY_DELAY );
2009-12-16 18:58:36 +02:00
// mail from battlemaster (rewardmarks) should last only one day
2010-08-08 04:37:24 +02:00
else if ( sender . GetMailMessageType () == MAIL_CREATURE && sBattlegroundMgr . GetBattleMasterBG ( sender . GetSenderId ()) != BATTLEGROUND_TYPE_NONE )
2009-12-16 18:58:36 +02:00
expire_delay = DAY ;
// default case: expire time if COD 3 days, if no COD 30 days
2008-10-02 16:23:55 -05:00
else
2009-12-16 18:58:36 +02:00
expire_delay = ( m_COD > 0 ) ? 3 * DAY : 30 * DAY ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
time_t expire_time = deliver_time + expire_delay ;
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
// Add to DB
std :: string safe_subject = GetSubject ();
2010-04-11 20:20:38 +02:00
std :: string safe_body = GetBody ();
2010-08-21 03:19:25 +02:00
2010-05-06 00:35:09 +02:00
CharacterDatabase . escape_string ( safe_subject );
2010-04-11 20:20:38 +02:00
CharacterDatabase . escape_string ( safe_body );
2010-04-11 11:16:42 +04:00
2010-08-21 03:19:25 +02:00
trans -> PAppend ( "INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) "
2010-04-11 11:16:42 +04:00
"VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%s', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')" ,
mailId , sender . GetMailMessageType (), sender . GetStationery (), GetMailTemplateId (), sender . GetSenderId (), receiver . GetPlayerGUIDLow (), safe_subject . c_str (), safe_body . c_str (),( m_items . empty () ? 0 : 1 ), ( uint64 ) expire_time , ( uint64 ) deliver_time , m_money , m_COD , checked );
2009-12-16 18:58:36 +02:00
for ( MailItemMap :: const_iterator mailItemIter = m_items . begin (); mailItemIter != m_items . end (); ++ mailItemIter )
2008-10-02 16:23:55 -05:00
{
2009-12-16 18:58:36 +02:00
Item * item = mailItemIter -> second ;
2010-08-21 03:19:25 +02:00
trans -> PAppend ( "INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')" , mailId , item -> GetGUIDLow (), item -> GetEntry (), receiver . GetPlayerGUIDLow ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
// For online receiver update in game mail status and data
if ( pReceiver )
2008-10-02 16:23:55 -05:00
{
2009-12-16 18:58:36 +02:00
pReceiver -> AddNewMailDeliverTime ( deliver_time );
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
if ( pReceiver -> IsMailsLoaded ())
2008-10-02 16:23:55 -05:00
{
Mail * m = new Mail ;
m -> messageID = mailId ;
2009-12-16 18:58:36 +02:00
m -> mailTemplateId = GetMailTemplateId ();
m -> subject = GetSubject ();
2010-04-11 11:16:42 +04:00
m -> body = GetBody ();
2009-12-16 18:58:36 +02:00
m -> money = GetMoney ();
m -> COD = GetCOD ();
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
for ( MailItemMap :: const_iterator mailItemIter = m_items . begin (); mailItemIter != m_items . end (); ++ mailItemIter )
{
Item * item = mailItemIter -> second ;
m -> AddItem ( item -> GetGUIDLow (), item -> GetEntry ());
}
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
m -> messageType = sender . GetMailMessageType ();
m -> stationery = sender . GetStationery ();
m -> sender = sender . GetSenderId ();
m -> receiver = receiver . GetPlayerGUIDLow ();
2008-10-02 16:23:55 -05:00
m -> expire_time = expire_time ;
m -> deliver_time = deliver_time ;
m -> checked = checked ;
m -> state = MAIL_STATE_UNCHANGED ;
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
pReceiver -> AddMail ( m ); // to insert new mail to beginning of maillist
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
if ( ! m_items . empty ())
2008-10-02 16:23:55 -05:00
{
2009-12-16 18:58:36 +02:00
for ( MailItemMap :: iterator mailItemIter = m_items . begin (); mailItemIter != m_items . end (); ++ mailItemIter )
pReceiver -> AddMItem ( mailItemIter -> second );
2008-10-02 16:23:55 -05:00
}
}
2009-12-16 18:58:36 +02:00
else if ( ! m_items . empty ())
2010-08-21 11:36:52 +02:00
{
SQLTransaction temp = SQLTransaction ( NULL );
deleteIncludedItems ( temp );
}
2008-10-02 16:23:55 -05:00
}
2009-12-16 18:58:36 +02:00
else if ( ! m_items . empty ())
2010-08-21 11:36:52 +02:00
{
SQLTransaction temp = SQLTransaction ( NULL );
deleteIncludedItems ( temp );
}
2008-10-02 16:23:55 -05:00
}