void Inventory::checkSize() { /* * Check that the inventory size is greater than or equal to the size * needed. * If not, forcibly delete (drop?) items from the end until it is. * Check that inventory capacity is greater than or equal to zero. * If not, forcibly delete (drop?) items from the end until it is. */ while (mPoss->inventory.size() > INVENTORY_SLOTS || mClient->getModifiedAttribute(ATTR_INV_CAPACITY) < 0) { LOG_WARN("Inventory: oversize inventory! Deleting '" << mPoss->inventory.rbegin()->second.amount << "' items of type '" << mPoss->inventory.rbegin()->second.itemId << "' from slot '" << mPoss->inventory.rbegin()->first << "' of character '" << mClient->getName() << "'!"); // FIXME Should probably be dropped rather than deleted. removeFromSlot(mPoss->inventory.rbegin()->first, mPoss->inventory.rbegin()->second.amount); } }
bool Inventory::equip(int inventorySlot) { // Test inventory slot existence InventoryData::iterator it; if ((it = mPoss->inventory.find(inventorySlot)) == mPoss->inventory.end()) { LOG_DEBUG("No existing item in inventory at slot: " << inventorySlot); return false; } // Test the equipment scripted requirements if (!testEquipScriptRequirements(it->second.itemId)) return false; // Test the equip requirements. If none, it's not an equipable item. 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; } // List of potential unique itemInstances to unequip first. std::set<unsigned> equipInstancesToUnequipFirst; // 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(equipReq.equipSlotId, equipReq.capacityRequired)) { // And test whether the unequip action would succeed first. if (testUnequipScriptRequirements(equipReq.equipSlotId) && hasInventoryEnoughSpace(equipReq.equipSlotId)) { // Then, we unequip each iteminstance of the equip slot for (EquipData::iterator iter = mPoss->equipSlots.begin(); iter != mPoss->equipSlots.end(); ++iter) { 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::set<unsigned>::const_iterator it3 = equipInstancesToUnequipFirst.begin(); it3 != equipInstancesToUnequipFirst.end(); ++it3) { if (!unequip(*it3)) { // Something went wrong even when we tested the unequipment process. LOG_WARN("Unable to unequip even when unequip was tested. " "Character : " << mCharacter->getComponent<BeingComponent>()->getName() << ", unequip slot: " << *it3); return false; } } // Actually equip the item now that the requirements has met. //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(1); // Number of equip slot changed. // Compute an unique equip item Instance id (unicity is per character only.) int itemInstance = getNewEquipItemInstance(); unsigned capacityLeft = equipReq.capacityRequired; unsigned capacityUsed = 0; // Apply equipment changes for (EquipData::iterator it4 = mPoss->equipSlots.begin(), it4_end = mPoss->equipSlots.end(); it4 != it4_end; ++it4) { if (!capacityLeft) break; // We've found an existing equip slot if (it4->first == equipReq.equipSlotId) { // 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; } } } // 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 maxCapacity = itemManager->getEquipSlotCapacity(equipReq.equipSlotId); // A should never happen case assert(maxCapacity >= capacityUsed + capacityLeft); while (capacityLeft) { EquipmentItem equipItem(it->second.itemId, itemInstance); mPoss->equipSlots.insert( std::make_pair(equipReq.equipSlotId, equipItem)); --capacityLeft; } } // 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); gameHandler->sendTo(mCharacter, equipMsg); // Update look when necessary checkLookchanges(equipReq.equipSlotId); return true; }