mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 01:37:00 +00:00
[9501] Implement item limit category inventory mode.
* Now expected item limit categories (for example for item 5513 and related) correctly limited by its amount in inventory. * Provide and use additional arg in SendEquipError for alt. way get affected item prototype. This let send to function item id and prevent crash client at limit category equip errors that required item prototype data.
This commit is contained in:
parent
52ace6bcb7
commit
c71f79584d
16 changed files with 137 additions and 56 deletions
|
|
@ -7242,10 +7242,10 @@ void Player::CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 c
|
|||
uint32 learning_spell_id = proto->Spells[1].SpellId;
|
||||
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id);
|
||||
if(!spellInfo)
|
||||
if (!spellInfo)
|
||||
{
|
||||
sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id);
|
||||
SendEquipError(EQUIP_ERR_NONE,item,NULL);
|
||||
SendEquipError(EQUIP_ERR_NONE, item);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -8593,6 +8593,35 @@ uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) cons
|
|||
return count;
|
||||
}
|
||||
|
||||
uint32 Player::GetItemCountWithLimitCategory( uint32 limitCategory ) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
||||
if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetProto()->ItemLimitCategory == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
|
||||
if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetProto()->ItemLimitCategory == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
count += pBag->GetItemCountWithLimitCategory(limitCategory);
|
||||
|
||||
for(int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
|
||||
if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetProto()->ItemLimitCategory == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
count += pBag->GetItemCountWithLimitCategory(limitCategory);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Item* Player::GetItemByGuid( uint64 guid ) const
|
||||
{
|
||||
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
||||
|
|
@ -8981,16 +9010,40 @@ uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem,
|
|||
}
|
||||
|
||||
// no maximum
|
||||
if(pProto->MaxCount <= 0)
|
||||
return EQUIP_ERR_OK;
|
||||
|
||||
uint32 curcount = GetItemCount(pProto->ItemId,true,pItem);
|
||||
|
||||
if (curcount + count > uint32(pProto->MaxCount))
|
||||
if(pProto->MaxCount > 0)
|
||||
{
|
||||
if(no_space_count)
|
||||
*no_space_count = count +curcount - pProto->MaxCount;
|
||||
return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
|
||||
uint32 curcount = GetItemCount(pProto->ItemId,true,pItem);
|
||||
|
||||
if (curcount + count > uint32(pProto->MaxCount))
|
||||
{
|
||||
if(no_space_count)
|
||||
*no_space_count = count +curcount - pProto->MaxCount;
|
||||
return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS;
|
||||
}
|
||||
}
|
||||
|
||||
// check unique-equipped limit
|
||||
if (pProto->ItemLimitCategory)
|
||||
{
|
||||
ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(pProto->ItemLimitCategory);
|
||||
if (!limitEntry)
|
||||
{
|
||||
if(no_space_count)
|
||||
*no_space_count = count;
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
}
|
||||
|
||||
if (limitEntry->mode == ITEM_LIMIT_CATEGORY_MODE_HAVE)
|
||||
{
|
||||
uint32 curcount = GetItemCountWithLimitCategory(pProto->ItemLimitCategory);
|
||||
|
||||
if (curcount + count > uint32(limitEntry->maxCount))
|
||||
{
|
||||
if(no_space_count)
|
||||
*no_space_count = count + curcount - limitEntry->maxCount;
|
||||
return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EQUIP_ERR_OK;
|
||||
|
|
@ -10429,12 +10482,12 @@ void Player::SetAmmo( uint32 item )
|
|||
return;
|
||||
|
||||
// check ammo
|
||||
if(item)
|
||||
if (item)
|
||||
{
|
||||
uint8 msg = CanUseAmmo( item );
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, NULL, NULL );
|
||||
SendEquipError(msg, NULL, NULL, item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -10450,7 +10503,7 @@ void Player::RemoveAmmo()
|
|||
|
||||
m_ammoDPS = 0.0f;
|
||||
|
||||
if(CanModifyStats())
|
||||
if (CanModifyStats())
|
||||
UpdateDamagePhysical(RANGED_ATTACK);
|
||||
}
|
||||
|
||||
|
|
@ -11674,7 +11727,7 @@ void Player::RemoveItemFromBuyBackSlot( uint32 slot, bool del )
|
|||
}
|
||||
}
|
||||
|
||||
void Player::SendEquipError( uint8 msg, Item* pItem, Item *pItem2 )
|
||||
void Player::SendEquipError( uint8 msg, Item* pItem, Item *pItem2, uint32 itemid /*= 0*/ )
|
||||
{
|
||||
sLog.outDebug( "WORLD: Sent SMSG_INVENTORY_CHANGE_FAILURE (%u)", msg);
|
||||
WorldPacket data(SMSG_INVENTORY_CHANGE_FAILURE, 1+8+8+1);
|
||||
|
|
@ -11690,25 +11743,28 @@ void Player::SendEquipError( uint8 msg, Item* pItem, Item *pItem2 )
|
|||
{
|
||||
case EQUIP_ERR_CANT_EQUIP_LEVEL_I:
|
||||
case EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW:
|
||||
{
|
||||
ItemPrototype const* proto = pItem ? pItem->GetProto() : NULL;
|
||||
data << uint32(proto ? proto->RequiredLevel : 0);
|
||||
} break;
|
||||
{
|
||||
ItemPrototype const* proto = pItem ? pItem->GetProto() : sObjectMgr.GetItemPrototype(itemid);
|
||||
data << uint32(proto ? proto->RequiredLevel : 0);
|
||||
break;
|
||||
}
|
||||
case EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM: // no idea about this one...
|
||||
{
|
||||
data << uint64(0);
|
||||
data << uint32(0);
|
||||
data << uint64(0);
|
||||
} break;
|
||||
{
|
||||
data << uint64(0);
|
||||
data << uint32(0);
|
||||
data << uint64(0);
|
||||
break;
|
||||
}
|
||||
case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS:
|
||||
case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_SOCKETED_EXCEEDED_IS:
|
||||
case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS:
|
||||
{
|
||||
ItemPrototype const* proto = pItem ? pItem->GetProto() : NULL;
|
||||
data << uint32(proto ? proto->ItemLimitCategory : 0);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
{
|
||||
ItemPrototype const* proto = pItem ? pItem->GetProto() : sObjectMgr.GetItemPrototype(itemid);
|
||||
data << uint32(proto ? proto->ItemLimitCategory : 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
GetSession()->SendPacket(&data);
|
||||
|
|
@ -12888,7 +12944,7 @@ bool Player::CanAddQuest( Quest const *pQuest, bool msg )
|
|||
return true;
|
||||
else if( msg2 != EQUIP_ERR_OK )
|
||||
{
|
||||
SendEquipError( msg2, NULL, NULL );
|
||||
SendEquipError(msg2, NULL, NULL, srcitem);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -13000,7 +13056,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, bool msg )
|
|||
GetItemCount(pQuest->ReqItemId[i]) < pQuest->ReqItemCount[i] )
|
||||
{
|
||||
if(msg)
|
||||
SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
|
||||
SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL, pQuest->ReqItemId[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -13027,7 +13083,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg )
|
|||
uint8 res = CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] );
|
||||
if( res != EQUIP_ERR_OK )
|
||||
{
|
||||
SendEquipError( res, NULL, NULL );
|
||||
SendEquipError( res, NULL, NULL, pQuest->RewChoiceItemId[reward] );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -13725,7 +13781,7 @@ bool Player::GiveQuestSourceItem( Quest const *pQuest )
|
|||
else if( msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
|
||||
return true;
|
||||
else
|
||||
SendEquipError( msg, NULL, NULL );
|
||||
SendEquipError( msg, NULL, NULL, srcitem );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -13750,7 +13806,7 @@ bool Player::TakeQuestSourceItem( uint32 quest_id, bool msg )
|
|||
if(res != EQUIP_ERR_OK)
|
||||
{
|
||||
if(msg)
|
||||
SendEquipError( res, NULL, NULL );
|
||||
SendEquipError( res, NULL, NULL, srcitem );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -18056,7 +18112,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
|||
uint8 msg = CanStoreNewItem( bag, slot, dest, item, pProto->BuyCount * count );
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, NULL, NULL );
|
||||
SendEquipError( msg, NULL, NULL, item );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -18101,7 +18157,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
|||
uint8 msg = CanEquipNewItem( slot, dest, item, false );
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, NULL, NULL );
|
||||
SendEquipError( msg, NULL, NULL, item );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -20472,7 +20528,7 @@ void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore cons
|
|||
msg = CanStoreNewItem( NULL_BAG, NULL_SLOT,dest,lootItem->itemid,lootItem->count);
|
||||
if(msg != EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, NULL, NULL );
|
||||
SendEquipError( msg, NULL, NULL, lootItem->itemid );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -20689,14 +20745,16 @@ uint8 Player::CanEquipUniqueItem( ItemPrototype const* itemProto, uint8 except_s
|
|||
{
|
||||
ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(itemProto->ItemLimitCategory);
|
||||
if(!limitEntry)
|
||||
return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE;
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
|
||||
// NOTE: limitEntry->mode not checked because if item have have-limit then it applied and to equip case
|
||||
|
||||
if(limit_count > limitEntry->maxCount)
|
||||
return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE; // attempt add too many limit category items (gems)
|
||||
return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS;
|
||||
|
||||
// there is an equip limit on this item
|
||||
if(HasItemOrGemWithLimitCategoryEquipped(itemProto->ItemLimitCategory,limitEntry->maxCount-limit_count+1,except_slot))
|
||||
return EQUIP_ERR_ITEM_UNIQUE_EQUIPABLE;
|
||||
return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS;
|
||||
}
|
||||
|
||||
return EQUIP_ERR_OK;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue