aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/Item.cpp30
-rw-r--r--src/game/Item.h6
-rw-r--r--src/game/Mail.cpp20
-rw-r--r--src/game/Player.cpp10
4 files changed, 49 insertions, 17 deletions
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index 5f281f6b98d..36ddcd16828 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -699,10 +699,11 @@ bool Item::IsEquipped() const
return !IsInBag() && m_slot < EQUIPMENT_SLOT_END;
}
-bool Item::CanBeTraded() const
+bool Item::CanBeTraded(bool mail) const
{
- if (IsSoulBound())
+ if ((!mail || !IsBoundAccountWide()) && IsSoulBound())
return false;
+
if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()) )
return false;
@@ -956,3 +957,28 @@ Item* Item::CloneItem( uint32 count, Player const* player ) const
return newItem;
}
+bool Item::IsBindedNotWith( Player const* player ) const
+{
+ // not binded item
+ if(!IsSoulBound())
+ return false;
+
+ // own item
+ if(GetOwnerGUID()== player->GetGUID())
+ return false;
+
+ // not BOA item case
+ if(!IsBoundAccountWide())
+ return true;
+
+ // online
+ if(Player* owner = objmgr.GetPlayer(GetOwnerGUID()))
+ {
+ return owner->GetSession()->GetAccountId() != player->GetSession()->GetAccountId();
+ }
+ // offline slow case
+ else
+ {
+ return objmgr.GetPlayerAccountIdByGUID(GetOwnerGUID()) != player->GetSession()->GetAccountId();
+ }
+}
diff --git a/src/game/Item.h b/src/game/Item.h
index 1b04dacbc3b..30cf1a595cb 100644
--- a/src/game/Item.h
+++ b/src/game/Item.h
@@ -217,8 +217,8 @@ class TRINITY_DLL_SPEC Item : public Object
void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); }
bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); }
- bool IsAccountBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); }
- bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; }
+ bool IsBoundAccountWide() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); }
+ bool IsBindedNotWith(Player const* player) const;
bool IsBoundByEnchant() const;
virtual void SaveToDB();
virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result = NULL);
@@ -227,7 +227,7 @@ class TRINITY_DLL_SPEC Item : public Object
bool IsBag() const { return GetProto()->InventoryType == INVTYPE_BAG; }
bool IsBroken() const { return GetUInt32Value(ITEM_FIELD_MAXDURABILITY) > 0 && GetUInt32Value(ITEM_FIELD_DURABILITY) == 0; }
- bool CanBeTraded() const;
+ bool CanBeTraded(bool mail = false) const;
void SetInTrade(bool b = true) { mb_in_trade = b; }
bool IsInTrade() const { return mb_in_trade; }
diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp
index 8e1077cef97..337604f2a2a 100644
--- a/src/game/Mail.cpp
+++ b/src/game/Mail.cpp
@@ -175,6 +175,12 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
return;
}
+ uint32 rc_account = 0;
+ if(receive)
+ rc_account = receive->GetSession()->GetAccountId();
+ else
+ rc_account = objmgr.GetPlayerAccountIdByGUID(rc);
+
if (items_count)
{
for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter)
@@ -195,12 +201,18 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
return;
}
- if(!mailItem.item->CanBeTraded())
+ if(!mailItem.item->CanBeTraded(true))
{
pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
return;
}
+ if(mailItem.item->IsBoundAccountWide() && mailItem.item->IsSoulBound() && pl->GetSession()->GetAccountId() != rc_account)
+ {
+ pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS);
+ return;
+ }
+
if (mailItem.item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || mailItem.item->GetUInt32Value(ITEM_FIELD_DURATION))
{
pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
@@ -229,12 +241,6 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
if(items_count > 0 || money > 0)
{
- uint32 rc_account = 0;
- if(receive)
- rc_account = receive->GetSession()->GetAccountId();
- else
- rc_account = objmgr.GetPlayerAccountIdByGUID(rc);
-
if (items_count > 0)
{
for(MailItemMap::iterator mailItemIter = mi.begin(); mailItemIter != mi.end(); ++mailItemIter)
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index b7a5698e998..7f0a7e78c54 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -9167,7 +9167,7 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED :EQUIP_ERR_ITEM_NOT_FOUND;
}
- if(pItem && pItem->IsBindedNotWith(GetGUID()))
+ if(pItem && pItem->IsBindedNotWith(this))
{
if(no_space_count)
*no_space_count = count;
@@ -9650,7 +9650,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
return EQUIP_ERR_ITEM_NOT_FOUND;
// item it 'bind'
- if(pItem->IsBindedNotWith(GetGUID()))
+ if(pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
Bag *pBag;
@@ -9852,7 +9852,7 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
ItemPrototype const *pProto = pItem->GetProto();
if( pProto )
{
- if(pItem->IsBindedNotWith(GetGUID()))
+ if(pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
// check count of items (skip for auto move for same player from bank)
@@ -10025,7 +10025,7 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
if (!pProto)
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
- if (pItem->IsBindedNotWith(GetGUID()))
+ if (pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
// check count of items (skip for auto move for same player from bank)
@@ -10205,7 +10205,7 @@ uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const
ItemPrototype const *pProto = pItem->GetProto();
if (pProto)
{
- if (pItem->IsBindedNotWith(GetGUID()))
+ if (pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0)