diff options
-rw-r--r-- | src/game/Item.cpp | 30 | ||||
-rw-r--r-- | src/game/Item.h | 6 | ||||
-rw-r--r-- | src/game/Mail.cpp | 20 | ||||
-rw-r--r-- | src/game/Player.cpp | 10 |
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) |