diff --git a/src/game/Group.cpp b/src/game/Group.cpp index abf51b2d9..1e37138bd 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -706,7 +706,7 @@ void Group::StartLootRool(Creature* lootTarget, Loot* loot, uint8 itemSlot, bool if(!playerToRoll || !playerToRoll->GetSession()) continue; - if ((!skipIfCanNotUse || playerToRoll->CanUseItem(item)) && lootItem.AllowedForPlayer(playerToRoll) ) + if ((!skipIfCanNotUse || playerToRoll->CanUseItem(item)==EQUIP_ERR_OK) && lootItem.AllowedForPlayer(playerToRoll) ) { if (playerToRoll->IsWithinDist(lootTarget, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) { diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 2c271c4f8..ff482f9a6 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -757,12 +757,26 @@ void WorldSession::SendListInventory(uint64 vendorguid) for(uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot ) { - if(VendorItem const* crItem = vItems->GetItem(vendorslot)) + if (VendorItem const* crItem = vItems->GetItem(vendorslot)) { - if(ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item)) + if (ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item)) { - if((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster()) - continue; + if (!_player->isGameMaster()) + { + // class wrong item skip only for bindable case + if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP) + continue; + + // race wrong item skip always + if ((pProto->Flags2 & ITEM_FLAGS2_HORDE_ONLY) && _player->GetTeam() != HORDE) + continue; + + if ((pProto->Flags2 & ITEM_FLAGS2_ALLIANCE_ONLY) && _player->GetTeam() != ALLIANCE) + continue; + + if ((pProto->AllowableRace & _player->getRaceMask()) == 0) + continue; + } ++count; diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 6002f4cd3..718b7b5a0 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -337,7 +337,18 @@ LootItem::LootItem(LootStoreItem const& li) bool LootItem::AllowedForPlayer(Player const * player) const { // DB conditions check - if ( !sObjectMgr.IsPlayerMeetToCondition(player,conditionId) ) + if (!sObjectMgr.IsPlayerMeetToCondition(player,conditionId)) + return false; + + ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(itemid); + if (!pProto) + return false; + + // not show loot for not own team + if ((pProto->Flags2 & ITEM_FLAGS2_HORDE_ONLY) && player->GetTeam() != HORDE) + return false; + + if ((pProto->Flags2 & ITEM_FLAGS2_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) return false; if ( needs_quest ) @@ -349,8 +360,7 @@ bool LootItem::AllowedForPlayer(Player const * player) const else { // Not quest only drop (check quest starting items for already accepted non-repeatable quests) - ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(itemid); - if (pProto && pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE && !player->HasQuestForItem(itemid)) + if (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE && !player->HasQuestForItem(itemid)) return false; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index bea43eaab..facd70bfa 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1809,6 +1809,25 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->Quality = ITEM_QUALITY_NORMAL; } + if (proto->Flags2 & ITEM_FLAGS2_HORDE_ONLY) + { + if (FactionEntry const* faction = sFactionStore.LookupEntry(HORDE)) + if ((proto->AllowableRace & faction->BaseRepRaceMask[0]) == 0) + sLog.outErrorDb("Item (Entry: %u) have in `AllowableRace` races (%u) only not compatible with ITEM_FLAGS2_HORDE_ONLY (%u) in Flags field, item any way will can't be equipped or use by this races.", + i, proto->AllowableRace, ITEM_FLAGS2_HORDE_ONLY); + + if (proto->Flags2 & ITEM_FLAGS2_ALLIANCE_ONLY) + sLog.outErrorDb("Item (Entry: %u) have in `Flags2` flags ITEM_FLAGS2_ALLIANCE_ONLY (%u) and ITEM_FLAGS2_HORDE_ONLY (%u) in Flags field, this is wrong combination.", + i, ITEM_FLAGS2_ALLIANCE_ONLY, ITEM_FLAGS2_HORDE_ONLY); + } + else if (proto->Flags2 & ITEM_FLAGS2_ALLIANCE_ONLY) + { + if (FactionEntry const* faction = sFactionStore.LookupEntry(ALLIANCE)) + if ((proto->AllowableRace & faction->BaseRepRaceMask[0]) == 0) + sLog.outErrorDb("Item (Entry: %u) have in `AllowableRace` races (%u) only not compatible with ITEM_FLAGS2_ALLIANCE_ONLY (%u) in Flags field, item any way will can't be equipped or use by this races.", + i, proto->AllowableRace, ITEM_FLAGS2_ALLIANCE_ONLY); + } + if(proto->BuyCount <= 0) { sLog.outErrorDb("Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).",i,proto->BuyCount); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 1b968ec41..2f6f87911 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -10477,8 +10477,9 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p if (slot - BANK_SLOT_BAG_START >= GetBankBagSlotCount()) return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; - if (uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK) - return cantuse; + res = CanUseItem( pItem, not_loading ); + if (res != EQUIP_ERR_OK) + return res; } res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); @@ -10641,8 +10642,9 @@ uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const if (pItem->IsBindedNotWith(this)) return EQUIP_ERR_DONT_OWN_THAT_ITEM; - if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0) - return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + uint8 msg = CanUseItem(pProto); + if (msg != EQUIP_ERR_OK) + return msg; if (uint32 item_use_skill = pItem->GetSkill()) { @@ -10682,52 +10684,47 @@ uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const } } - if (pProto->RequiredSkill != 0) - { - if (GetSkillValue( pProto->RequiredSkill ) == 0) - return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - - if (GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank) - return EQUIP_ERR_CANT_EQUIP_SKILL; - } - - if (pProto->RequiredSpell != 0 && !HasSpell(pProto->RequiredSpell)) - return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank) return EQUIP_ERR_CANT_EQUIP_REPUTATION; - if (getLevel() < pProto->RequiredLevel) - return EQUIP_ERR_CANT_EQUIP_LEVEL_I; - return EQUIP_ERR_OK; } } return EQUIP_ERR_ITEM_NOT_FOUND; } -bool Player::CanUseItem( ItemPrototype const *pProto ) +uint8 Player::CanUseItem( ItemPrototype const *pProto ) const { // Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player if( pProto ) { - if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) - return false; + if ((pProto->Flags2 & ITEM_FLAGS2_HORDE_ONLY) && GetTeam() != HORDE) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + + if ((pProto->Flags2 & ITEM_FLAGS2_ALLIANCE_ONLY) && GetTeam() != ALLIANCE) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + + if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + if( pProto->RequiredSkill != 0 ) { if( GetSkillValue( pProto->RequiredSkill ) == 0 ) - return false; + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) - return false; + return EQUIP_ERR_CANT_EQUIP_SKILL; } + if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) - return false; + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + if( getLevel() < pProto->RequiredLevel ) - return false; - return true; + return EQUIP_ERR_CANT_EQUIP_LEVEL_I; + + return EQUIP_ERR_OK; } - return false; + return EQUIP_ERR_ITEM_NOT_FOUND; } uint8 Player::CanUseAmmo( uint32 item ) const @@ -10742,22 +10739,14 @@ uint8 Player::CanUseAmmo( uint32 item ) const { if( pProto->InventoryType!= INVTYPE_AMMO ) return EQUIP_ERR_ONLY_AMMO_CAN_GO_HERE; - if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) - return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; - if( pProto->RequiredSkill != 0 ) - { - if( GetSkillValue( pProto->RequiredSkill ) == 0 ) - return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) - return EQUIP_ERR_CANT_EQUIP_SKILL; - } - if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) - return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - /*if( GetReputationMgr().GetReputation() < pProto->RequiredReputation ) + + uint8 msg = CanUseItem(pProto); + if (msg != EQUIP_ERR_OK) + return msg; + + /*if ( GetReputationMgr().GetReputation() < pProto->RequiredReputation ) return EQUIP_ERR_CANT_EQUIP_REPUTATION; */ - if( getLevel() < pProto->RequiredLevel ) - return EQUIP_ERR_CANT_EQUIP_LEVEL_I; // Requires No Ammo if(GetDummyAura(46699)) diff --git a/src/game/Player.h b/src/game/Player.h index e9b0a02e2..ef51208d5 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1266,7 +1266,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint8 CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, Item *pItem, bool swap, bool not_loading = true ) const; uint8 CanUseItem( Item *pItem, bool not_loading = true ) const; bool HasItemTotemCategory( uint32 TotemCategory ) const; - bool CanUseItem( ItemPrototype const *pItem ); + uint8 CanUseItem( ItemPrototype const *pItem ) const; uint8 CanUseAmmo( uint32 item ) const; Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 ); Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b53fdcf48..d8053679e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10205" + #define REVISION_NR "10206" #endif // __REVISION_NR_H__