diff options
Diffstat (limited to 'src/game-server/inventory.cpp')
-rw-r--r-- | src/game-server/inventory.cpp | 244 |
1 files changed, 128 insertions, 116 deletions
diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index c3d2bfcb..e486f7c0 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -600,58 +600,66 @@ bool Inventory::equip(int inventorySlot) return false; // Test the equip requirements. If none, it's not an equipable item. - const ItemEquipsInfo &equipInfoList = - itemManager->getItem(it->second.itemId)->getItemEquipData(); - if (equipInfoList.empty()) + const ItemEquipRequirement &equipReq = + itemManager->getItem(it->second.itemId)->getItemEquipRequirement(); + if (!equipReq.equipSlotId) { LOG_DEBUG("No equip requirements for item id: " << it->second.itemId << " at slot: " << inventorySlot); return false; } - // Iterate through all slots requirements. - std::list<unsigned int> equipSlotsToUnequipFirst; - for (ItemEquipsInfo::const_iterator it2 = equipInfoList.begin(), - it2_end = equipInfoList.end(); it2 != it2_end; ++it2) - { - // We first check the equipment slots for: - // - 1. whether enough total equip slot space is available. - // - 2. whether some other equipment is to be unequipped first. + // List of potential unique itemInstances to unequip first. + std::set<unsigned int> equipInstancesToUnequipFirst; - // If not enough total space in the equipment slot is available, - // we cannot equip. - if (itemManager->getEquipSlotCapacity(it2->first) < it2->second) - { - LOG_DEBUG("Not enough equip capacity at slot: " << it2->first - << ", total available: " - << itemManager->getEquipSlotCapacity(it2->first) - << ", required: " << it2->second); - return false; - } + // We first check the equipment slots for: + // - 1. whether enough total equip slot space is available. + // - 2. whether some other equipment is to be unequipped first. + + // If not enough total space in the equipment slot is available, + // we cannot equip. + if (itemManager->getEquipSlotCapacity(equipReq.equipSlotId) + < equipReq.capacityRequired) + { + LOG_DEBUG("Not enough equip capacity at slot: " << equipReq.equipSlotId + << ", total available: " + << itemManager->getEquipSlotCapacity(equipReq.equipSlotId) + << ", required: " << equipReq.capacityRequired); + return false; + } - // Test whether some item(s) is(are) to be unequipped first. - if (!checkEquipmentCapacity(it2->first, it2->second)) + // Test whether some item(s) is(are) to be unequipped first. + if (!checkEquipmentCapacity(equipReq.equipSlotId, + equipReq.capacityRequired)) + { + // And test whether the unequip action would succeed first. + if (testUnequipScriptRequirements(equipReq.equipSlotId) + && hasInventoryEnoughSpace(equipReq.equipSlotId)) { - // And test whether the unequip action would succeed first. - if (testUnequipScriptRequirements(it2->first) - && hasInventoryEnoughSpace(it2->first)) - { - equipSlotsToUnequipFirst.push_back(it2->first); - } - else + // Then, we unequip each iteminstance of the equip slot + for (EquipData::iterator iter = + mPoss->equipSlots.begin(); + iter != mPoss->equipSlots.end(); ++iter) { - // Some non-unequippable equipment is to be unequipped first. - // Can be the case of cursed items, - // or when the inventory is full, for instance. - return false; + if (iter->first == equipReq.equipSlotId + && iter->second.itemInstance) + equipInstancesToUnequipFirst.insert( + iter->second.itemInstance); } } + else + { + // Some non-unequippable equipment is to be unequipped first. + // Can be the case of cursed items, + // or when the inventory is full, for instance. + return false; + } } // Potential Pre-unequipment process - for (std::list<unsigned int>::const_iterator it3 = - equipSlotsToUnequipFirst.begin(); - it3 != equipSlotsToUnequipFirst.end(); ++it3) + for (std::set<unsigned int>::const_iterator it3 = + equipInstancesToUnequipFirst.begin(); + it3 != equipInstancesToUnequipFirst.end(); ++it3) { if (!unequip(*it3)) { @@ -667,131 +675,135 @@ bool Inventory::equip(int inventorySlot) //W equip slot type count, W item id, { W equip slot, W capacity used}* MessageOut equipMsg(GPMSG_EQUIP); equipMsg.writeInt16(it->second.itemId); // Item Id - equipMsg.writeInt16(equipInfoList.size()); // Number of equip slot changed. + equipMsg.writeInt16(1); // Number of equip slot changed. // Compute an unique equip item Instance id (unicity is per character only.) int itemInstance = getNewEquipItemInstance(); - for (ItemEquipsInfo::const_iterator it2 = equipInfoList.begin(), - it2_end = equipInfoList.end(); it2 != it2_end; ++it2) + unsigned int capacityLeft = equipReq.capacityRequired; + unsigned int capacityUsed = 0; + // Apply equipment changes + for (EquipData::iterator it4 = mPoss->equipSlots.begin(), + it4_end = mPoss->equipSlots.end(); it4 != it4_end; ++it4) { - unsigned int capacityLeft = it2->second; - unsigned int capacityUsed = 0; - // Apply equipment changes - for (EquipData::iterator it4 = mPoss->equipSlots.begin(), - it4_end = mPoss->equipSlots.end(); it4 != it4_end; ++it4) - { - if (!capacityLeft) - break; + if (!capacityLeft) + break; - // We've found an existing equip slot - if (it4->first == it2->first) + // We've found an existing equip slot + if (it4->first == equipReq.equipSlotId) + { + // We've found an empty slot + if (it4->second.itemInstance == 0) { - // We've found an empty slot - if (it4->second.itemInstance == 0) - { - it4->second.itemId = it->second.itemId; - it4->second.itemInstance = itemInstance; - --capacityLeft; - } - else // The slot is already in use. - { - ++capacityUsed; - } + it4->second.itemId = it->second.itemId; + it4->second.itemInstance = itemInstance; + --capacityLeft; + } + else // The slot is already in use. + { + ++capacityUsed; } } + } - // When there is still something to apply even when out of that loop, - // It means that the equip multimapis missing empty slots. - // Hence, we add them back - if(capacityLeft) - { - unsigned int maxCapacity = - itemManager->getEquipSlotCapacity(it2->first); + // When there is still something to apply even when out of that loop, + // It means that the equip multimapis missing empty slots. + // Hence, we add them back + if(capacityLeft) + { + unsigned int maxCapacity = + itemManager->getEquipSlotCapacity(equipReq.equipSlotId); - // A should never happen case - assert(maxCapacity >= capacityUsed + capacityLeft); + // A should never happen case + assert(maxCapacity >= capacityUsed + capacityLeft); - while (capacityLeft) - { - EquipmentItem equipItem(it->second.itemId, itemInstance); - mPoss->equipSlots.insert( - std::make_pair<unsigned int, EquipmentItem> - (it2->first, equipItem)); - --capacityLeft; - } + while (capacityLeft) + { + EquipmentItem equipItem(it->second.itemId, itemInstance); + mPoss->equipSlots.insert( + std::make_pair<unsigned int, EquipmentItem> + (equipReq.equipSlotId, equipItem)); + --capacityLeft; } - - // Equip slot - equipMsg.writeInt16(it2->first); - // Capacity used - equipMsg.writeInt16(it2->second); - // Item instance - equipMsg.writeInt16(itemInstance); } + // Equip slot + equipMsg.writeInt16(equipReq.equipSlotId); + // Capacity used + equipMsg.writeInt16(equipReq.capacityRequired); + // Item instance + equipMsg.writeInt16(itemInstance); + // New item trigger updateEquipmentTrigger(0, it->second.itemId); // Remove item from inventory removeFromSlot(inventorySlot, 1); - if (equipMsg.getLength() > 2) - gameHandler->sendTo(mCharacter, equipMsg); + gameHandler->sendTo(mCharacter, equipMsg); + + // Update look when necessary + checkLookchanges(equipReq.equipSlotId); return true; } bool Inventory::unequip(unsigned int itemInstance) { - // map of { itemInstance, itemId } - std::map<unsigned int, unsigned int> itemIdListToInventory; + if (!itemInstance) + return false; MessageOut equipMsg(GPMSG_EQUIP); equipMsg.writeInt16(0); // Item Id, useless in case of unequip. + // The itemId to unequip + unsigned int itemId = 0; + unsigned int slotTypeId = 0; + // Empties all equip entries that point to the given equipment slot // The equipment slots should NEVER be erased after initialization! for (EquipData::iterator it = mPoss->equipSlots.begin(), it_end = mPoss->equipSlots.end(); it != it_end; ++it) { - if (it->second.itemInstance == itemInstance) + if (it->second.itemInstance == itemInstance && it->second.itemId) { // Add the item to the inventory list if not already present there - std::map<unsigned int, unsigned int>::const_iterator it2 = - itemIdListToInventory.find(it->second.itemInstance); - if (it2 == itemIdListToInventory.end()) - { - itemIdListToInventory.insert( - std::make_pair<unsigned int, unsigned int> - (it->second.itemInstance, it->second.itemId)); - } - + itemId = it->second.itemId; it->second.itemId = 0; it->second.itemInstance = 0; + + // We keep track of the slot type to be able to raise a potential + // change in the character sprite + slotTypeId = it->first; } } + // When there were no corresponding item id, it means no item was to + // be unequipped. + if (!itemId) + return false; + // Number of slot types touched, - equipMsg.writeInt16(itemIdListToInventory.size()); + equipMsg.writeInt16(1); - // Apply unequip trigger(s), and move the item(s) back to inventory. - for (std::map<unsigned int, unsigned int>::const_iterator it2 = - itemIdListToInventory.begin(), it2_end = itemIdListToInventory.end(); - it2 != it2_end; ++it2) - { - updateEquipmentTrigger(it2->second, 0); - insert(it2->second, 1); + // Move the item back to inventory. + insert(itemId, 1); - equipMsg.writeInt16(it2->first); - equipMsg.writeInt16(0); // Capacity used, set to 0 to unequip. - } + equipMsg.writeInt16(itemInstance); + equipMsg.writeInt16(0); // Capacity used, set to 0 to unequip. - if (equipMsg.getLength() > 2) - { - gameHandler->sendTo(mCharacter, equipMsg); - return true; - } + gameHandler->sendTo(mCharacter, equipMsg); + + // Apply unequip trigger + updateEquipmentTrigger(itemId, 0); - return false; + checkLookchanges(slotTypeId); + + return true; +} + +void Inventory::checkLookchanges(unsigned int slotTypeId) +{ + if (itemManager->isEquipSlotVisible(slotTypeId)) + mCharacter->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); } |