Skip to content

Commit

Permalink
Do not create temporary item in CanEquipNewItem.
Browse files Browse the repository at this point in the history
  • Loading branch information
ratkosrb committed Apr 18, 2024
1 parent a2054df commit 998823e
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 111 deletions.
217 changes: 107 additions & 110 deletions src/game/Objects/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10117,134 +10117,142 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
InventoryResult Player::CanEquipNewItem(uint8 slot, uint16& dest, uint32 item, bool swap) const
{
dest = 0;
Item* pItem = Item::CreateItem(item, 1, GetObjectGuid());
if (pItem)
if (ItemPrototype const* pProto = sObjectMgr.GetItemPrototype(item))
{
InventoryResult result = CanEquipItem(slot, dest, pItem, swap);
delete pItem;
InventoryResult result = CanEquipItem(slot, dest, pProto, nullptr, swap);
return result;
}

return EQUIP_ERR_ITEM_NOT_FOUND;
}

InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item const* pItem, bool swap, bool not_loading) const
{
dest = 0;
if (pItem)
return CanEquipItem(slot, dest, pItem->GetProto(), pItem, swap, not_loading);

return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
}

InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, ItemPrototype const* pProto, Item const* pItem, bool swap, bool not_loading) const
{
dest = 0;
if (pItem)
{
sLog.Out(LOG_BASIC, LOG_LVL_DEBUG, "STORAGE: CanEquipItem slot = %u, item = %u, count = %u", slot, pItem->GetEntry(), pItem->GetCount());
ItemPrototype const* pProto = pItem->GetProto();
if (pProto)
{
// item used
if (pItem->HasTemporaryLoot())
return EQUIP_ERR_ALREADY_LOOTED;
MANGOS_ASSERT(pProto == pItem->GetProto());

if (pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
// item used
if (pItem->HasTemporaryLoot())
return EQUIP_ERR_ALREADY_LOOTED;

// check count of items (skip for auto move for same player from bank)
InventoryResult res = CanTakeMoreSimilarItems(pItem);
if (res != EQUIP_ERR_OK)
return res;
if (pItem->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
}

if (pProto)
{
// check count of items (skip for auto move for same player from bank)
InventoryResult res = pItem ? CanTakeMoreSimilarItems(pItem) : CanTakeMoreSimilarItems(pProto->ItemId, 1);
if (res != EQUIP_ERR_OK)
return res;

// check this only in game
if (not_loading)
{
// May be here should be more stronger checks; STUNNED checked
// ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked.
if (HasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_PENDING_STUNNED))
return EQUIP_ERR_YOU_ARE_STUNNED;

// check this only in game
if (not_loading)
// do not allow equipping gear except weapons, offhands, projectiles, relics in
// - combat
if (!pProto->CanChangeEquipStateInCombat())
{
// May be here should be more stronger checks; STUNNED checked
// ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked.
if (HasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_PENDING_STUNNED))
return EQUIP_ERR_YOU_ARE_STUNNED;

// do not allow equipping gear except weapons, offhands, projectiles, relics in
// - combat
if (!pProto->CanChangeEquipStateInCombat())
{
if (IsInCombat())
return EQUIP_ERR_NOT_IN_COMBAT;
}
if (IsInCombat())
return EQUIP_ERR_NOT_IN_COMBAT;
}

// prevent equip item in process logout
if (GetSession()->IsLogingOut())
return EQUIP_ERR_YOU_ARE_STUNNED;
// prevent equip item in process logout
if (GetSession()->IsLogingOut())
return EQUIP_ERR_YOU_ARE_STUNNED;

if (IsInCombat() && pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer != 0)
return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err
if (IsInCombat() && pProto->Class == ITEM_CLASS_WEAPON && m_weaponChangeTimer != 0)
return EQUIP_ERR_CANT_DO_RIGHT_NOW; // maybe exist better err

// Check is possibly not in vanilla.
//if (IsNonMeleeSpellCasted(false, true, true))
// return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
// Check is possibly not in vanilla.
//if (IsNonMeleeSpellCasted(false, true, true))
// return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}

uint8 eslot = FindEquipSlot(pProto, slot, swap);
if (eslot == NULL_SLOT)
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
uint8 eslot = FindEquipSlot(pProto, slot, swap);
if (eslot == NULL_SLOT)
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;

InventoryResult msg = CanUseItem(pItem , not_loading);
if (msg != EQUIP_ERR_OK)
return msg;
if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot))
return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE;
InventoryResult msg = pItem ? CanUseItem(pItem , not_loading) : CanUseItem(pProto, not_loading);
if (msg != EQUIP_ERR_OK)
return msg;
if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot))
return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE;

// if swap ignore item (equipped also)
if (InventoryResult res2 = CanEquipUniqueItem(pItem, swap ? eslot : NULL_SLOT))
return res2;
// if swap ignore item (equipped also)
if (InventoryResult res2 = CanEquipUniqueItem(pProto, swap ? eslot : NULL_SLOT))
return res2;

// check unique-equipped special item classes
if (pProto->Class == ITEM_CLASS_QUIVER)
// check unique-equipped special item classes
if (pProto->Class == ITEM_CLASS_QUIVER)
{
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
{
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
{
if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pBag != pItem)
{
if (pBag != pItem)
if (ItemPrototype const* pBagProto = pBag->GetProto())
{
if (ItemPrototype const* pBagProto = pBag->GetProto())
{
if (pBagProto->Class == pProto->Class && (!swap || pBag->GetSlot() != eslot))
return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH
: EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
}
if (pBagProto->Class == pProto->Class && (!swap || pBag->GetSlot() != eslot))
return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH)
? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH
: EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER;
}
}
}
}
}

uint32 type = pProto->InventoryType;
uint32 type = pProto->InventoryType;

if (eslot == EQUIPMENT_SLOT_OFFHAND)
if (eslot == EQUIPMENT_SLOT_OFFHAND)
{
if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND)
{
if (!CanDualWield())
return EQUIP_ERR_CANT_DUAL_WIELD;
}
else if (type == INVTYPE_2HWEAPON)
if (!CanDualWield())
return EQUIP_ERR_CANT_DUAL_WIELD;

if (IsTwoHandUsed())
return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
}
else if (type == INVTYPE_2HWEAPON)
return EQUIP_ERR_CANT_DUAL_WIELD;

// equip two-hand weapon case (with possible unequip 2 items)
if (type == INVTYPE_2HWEAPON)
{
if (eslot != EQUIPMENT_SLOT_MAINHAND)
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;

// offhand item must can be stored in inventory for offhand item and it also must be unequipped
Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
ItemPosCountVec off_dest;
if (offItem && (!not_loading ||
CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND, false) != EQUIP_ERR_OK ||
CanStoreItem(NULL_BAG, NULL_SLOT, off_dest, offItem, false) != EQUIP_ERR_OK))
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL;
}
dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot);
return EQUIP_ERR_OK;
if (IsTwoHandUsed())
return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
}

// equip two-hand weapon case (with possible unequip 2 items)
if (type == INVTYPE_2HWEAPON)
{
if (eslot != EQUIPMENT_SLOT_MAINHAND)
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;

// offhand item must can be stored in inventory for offhand item and it also must be unequipped
Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
ItemPosCountVec off_dest;
if (offItem && (!not_loading ||
CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND, false) != EQUIP_ERR_OK ||
CanStoreItem(NULL_BAG, NULL_SLOT, off_dest, offItem, false) != EQUIP_ERR_OK))
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL;
}
dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot);
return EQUIP_ERR_OK;
}

return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED;
Expand Down Expand Up @@ -10498,15 +10506,6 @@ InventoryResult Player::CanUseItem(Item const* pItem, bool not_loading) const
if (msg != EQUIP_ERR_OK)
return msg;

if (uint32 skill = pProto->GetProficiencySkill())
{
// Fist weapons use unarmed skill calculations, but we must query fist weapon skill presence to use this item
if (pProto->SubClass == ITEM_SUBCLASS_WEAPON_FIST)
skill = SKILL_FIST_WEAPONS;
if (!GetSkillValue(skill))
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
}

if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
#if SUPPORTED_CLIENT_BUILD > CLIENT_BUILD_1_6_1
return EQUIP_ERR_CANT_EQUIP_REPUTATION;
Expand Down Expand Up @@ -10548,6 +10547,15 @@ InventoryResult Player::CanUseItem(ItemPrototype const* pProto, bool not_loading
if (GetLevel() < pProto->RequiredLevel)
return EQUIP_ERR_CANT_EQUIP_LEVEL_I;

if (uint32 skill = pProto->GetProficiencySkill())
{
// Fist weapons use unarmed skill calculations, but we must query fist weapon skill presence to use this item
if (pProto->SubClass == ITEM_SUBCLASS_WEAPON_FIST)
skill = SKILL_FIST_WEAPONS;
if (!GetSkillValue(skill))
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
}

return EQUIP_ERR_OK;
}
return EQUIP_ERR_ITEM_NOT_FOUND;
Expand Down Expand Up @@ -20959,17 +20967,6 @@ void Player::LoadSkillsFromFields()
}
}

InventoryResult Player::CanEquipUniqueItem(Item const* pItem, uint8 eslot) const
{
ItemPrototype const* pProto = pItem->GetProto();

// proto based limitations
if (InventoryResult res = CanEquipUniqueItem(pProto, eslot))
return res;

return EQUIP_ERR_OK;
}

InventoryResult Player::CanEquipUniqueItem(ItemPrototype const* itemProto, uint8 except_slot) const
{
// check unique-equipped on item
Expand Down Expand Up @@ -22400,7 +22397,7 @@ void Player::AddGCD(SpellEntry const& spellEntry, uint32 /*forcedDuration = 0*/,
if (gcdDuration < 1)
return;

// Spell packets are handled on Map update to substract the update interval.
// Spell packets are handled on Map update so substract the update interval.
gcdDuration -= int32(sWorld.getConfig(CONFIG_UINT32_INTERVAL_MAPUPDATE));

if (gcdDuration < 1)
Expand Down
2 changes: 1 addition & 1 deletion src/game/Objects/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,6 @@ class Player final: public Unit
Item* _StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool update);
InventoryResult CanTakeMoreSimilarItems(Item const* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(), pItem->GetCount(), pItem); }
InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry, count, nullptr); }
InventoryResult CanEquipUniqueItem(Item const* pItem, uint8 except_slot = NULL_SLOT) const;
InventoryResult CanEquipUniqueItem(ItemPrototype const* itemProto, uint8 except_slot = NULL_SLOT) const;
InventoryResult _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item const* pItem, uint32* no_space_count = nullptr) const;
InventoryResult _CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item const* pItem = nullptr, bool swap = false, uint32* no_space_count = nullptr) const;
Expand Down Expand Up @@ -1138,6 +1137,7 @@ class Player final: public Unit
InventoryResult CanStoreItems(Item** pItem,int count) const;
InventoryResult CanEquipNewItem(uint8 slot, uint16& dest, uint32 item, bool swap) const;
InventoryResult CanEquipItem(uint8 slot, uint16& dest, Item const* pItem, bool swap, bool not_loading = true) const;
InventoryResult CanEquipItem(uint8 slot, uint16& dest, ItemPrototype const* pProto, Item const* pItem = nullptr, bool swap = false, bool not_loading = true) const;
InventoryResult CanUnequipItems(uint32 item, uint32 count) const;
InventoryResult CanUnequipItem(uint16 src, bool swap) const;
InventoryResult CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item const* pItem, bool swap, bool not_loading = true) const;
Expand Down

0 comments on commit 998823e

Please sign in to comment.