diff options
Diffstat (limited to 'src/game-server')
-rw-r--r-- | src/game-server/character.cpp | 48 | ||||
-rw-r--r-- | src/game-server/gamehandler.cpp | 51 | ||||
-rw-r--r-- | src/game-server/gamehandler.h | 1 | ||||
-rw-r--r-- | src/game-server/inventory.cpp | 487 | ||||
-rw-r--r-- | src/game-server/inventory.h | 36 | ||||
-rw-r--r-- | src/game-server/state.cpp | 65 |
6 files changed, 175 insertions, 513 deletions
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index 0944f757..ea9228a7 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -182,31 +182,23 @@ void CharacterComponent::deserialize(Entity &entity, MessageIn &msg) Possessions &poss = getPossessions(); - EquipData equipData; - int equipSlotsSize = msg.readInt16(); - unsigned eqSlot; - EquipmentItem equipItem; - for (int j = 0; j < equipSlotsSize; ++j) - { - eqSlot = msg.readInt16(); - equipItem.itemId = msg.readInt16(); - equipItem.itemInstance = msg.readInt16(); - equipData.insert(equipData.end(), - std::make_pair(eqSlot, equipItem)); - } - poss.setEquipment(equipData); // Loads inventory - must be last because size isn't transmitted InventoryData inventoryData; + EquipData equipmentData; while (msg.getUnreadLength()) { InventoryItem i; - int slotId = msg.readInt16(); - i.itemId = msg.readInt16(); - i.amount = msg.readInt16(); - inventoryData.insert(inventoryData.end(), std::make_pair(slotId, i)); + i.slot = msg.readInt16(); + i.itemId = msg.readInt16(); + i.amount = msg.readInt16(); + bool isEquipped = msg.readInt8() != 0; + inventoryData.insert(std::make_pair(i.slot, i)); + if (isEquipped) + equipmentData.insert(i.slot); } poss.setInventory(inventoryData); + poss.setEquipment(equipmentData); } void CharacterComponent::serialize(Entity &entity, MessageOut &msg) @@ -271,22 +263,18 @@ void CharacterComponent::serialize(Entity &entity, MessageOut &msg) // inventory - must be last because size isn't transmitted const Possessions &poss = getPossessions(); const EquipData &equipData = poss.getEquipment(); - msg.writeInt16(equipData.size()); // number of equipment - for (EquipData::const_iterator k = equipData.begin(), - k_end = equipData.end(); k != k_end; ++k) - { - msg.writeInt16(k->first); // Equip slot id - msg.writeInt16(k->second.itemId); // ItemId - msg.writeInt16(k->second.itemInstance); // Item Instance id - } const InventoryData &inventoryData = poss.getInventory(); - for (InventoryData::const_iterator j = inventoryData.begin(), - j_end = inventoryData.end(); j != j_end; ++j) + for (InventoryData::const_iterator itemIt = inventoryData.begin(), + itemIt_end = inventoryData.end(); itemIt != itemIt_end; ++itemIt) { - msg.writeInt16(j->first); // slot id - msg.writeInt16(j->second.itemId); // item id - msg.writeInt16(j->second.amount); // amount + msg.writeInt16(itemIt->first); // slot id + msg.writeInt16(itemIt->second.itemId); // item id + msg.writeInt16(itemIt->second.amount); // amount + if (equipData.find(itemIt->first) != equipData.end()) + msg.writeInt8(1); // equipped + else + msg.writeInt8(0); // not equipped } } diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 1a0ca158..fe274ace 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -249,10 +249,6 @@ void GameHandler::processMessage(NetComputer *computer, MessageIn &message) handleUnequip(client, message); break; - case PGMSG_MOVE_ITEM: - handleMoveItem(client, message); - break; - case PGMSG_USE_ABILITY_ON_BEING: handleUseAbilityOnBeing(client, message); break; @@ -628,42 +624,25 @@ void GameHandler::handleWalk(GameClient &client, MessageIn &message) void GameHandler::handleEquip(GameClient &client, MessageIn &message) { const int slot = message.readInt16(); - if (!Inventory(client.character).equip(slot)) - { - MessageOut msg(GPMSG_SAY); - msg.writeInt16(0); // From the server - msg.writeString("Unable to equip."); - client.send(msg); - } + MessageOut msg(GPMSG_EQUIP_RESPONSE); + if (Inventory(client.character).equip(slot)) + msg.writeInt8(ERRMSG_OK); + else + msg.writeInt8(ERRMSG_FAILURE); + msg.writeInt16(slot); + client.send(msg); } void GameHandler::handleUnequip(GameClient &client, MessageIn &message) { - const int itemInstance = message.readInt16(); - if (!Inventory(client.character).unequip(itemInstance)) - { - MessageOut msg(GPMSG_SAY); - msg.writeInt16(0); // From the server - msg.writeString("Unable to unequip."); - client.send(msg); - } -} - -void GameHandler::handleMoveItem(GameClient &client, MessageIn &message) -{ - const int slot1 = message.readInt16(); - const int slot2 = message.readInt16(); - const int amount = message.readInt16(); - - Inventory(client.character).move(slot1, slot2, amount); - // log transaction - std::stringstream str; - str << "User moved item " - << " from slot " << slot1 << " to slot " << slot2; - auto *characterComponent = - client.character->getComponent<CharacterComponent>(); - accountHandler->sendTransaction(characterComponent->getDatabaseID(), - TRANS_ITEM_MOVE, str.str()); + const int slot = message.readInt16(); + MessageOut msg(GPMSG_UNEQUIP_RESPONE); + if (Inventory(client.character).unequip(slot)) + msg.writeInt8(ERRMSG_OK); + else + msg.writeInt8(ERRMSG_FAILURE); + msg.writeInt16(slot); + client.send(msg); } void GameHandler::handleUseAbilityOnBeing(GameClient &client, MessageIn &message) diff --git a/src/game-server/gamehandler.h b/src/game-server/gamehandler.h index 2f44a3c9..f4995497 100644 --- a/src/game-server/gamehandler.h +++ b/src/game-server/gamehandler.h @@ -132,7 +132,6 @@ class GameHandler: public ConnectionHandler void handleEquip(GameClient &client, MessageIn &message); void handleUnequip(GameClient &client, MessageIn &message); - void handleMoveItem(GameClient &client, MessageIn &message); void handleUseAbilityOnBeing(GameClient &client, MessageIn &message); void handleUseAbilityOnPoint(GameClient &client, MessageIn &message); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index bec5961b..2f17af10 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -48,23 +48,14 @@ void Inventory::sendFull() const MessageOut m(GPMSG_INVENTORY_FULL); m.writeInt16(mPoss->inventory.size()); - for (InventoryData::const_iterator l = mPoss->inventory.begin(), - l_end = mPoss->inventory.end(); l != l_end; ++l) + for (InventoryData::const_iterator it = mPoss->inventory.begin(), + l_end = mPoss->inventory.end(); it != l_end; ++it) { - assert(l->second.itemId); - m.writeInt16(l->first); // Slot id - m.writeInt16(l->second.itemId); - m.writeInt16(l->second.amount); - } - - for (EquipData::const_iterator k = mPoss->equipSlots.begin(), - k_end = mPoss->equipSlots.end(); - k != k_end; - ++k) - { - m.writeInt16(k->first); // Equip slot id - m.writeInt16(k->second.itemId); // Item id - m.writeInt16(k->second.itemInstance); // Item instance + assert(it->second.itemId); + m.writeInt16(it->first); // slot + m.writeInt16(it->second.itemId); + m.writeInt16(it->second.amount); + m.writeInt16(it->second.equipmentSlot); } gameHandler->sendTo(mCharacter, m); @@ -73,73 +64,54 @@ void Inventory::sendFull() const void Inventory::initialize() { /* + * Set the equipment slots + */ + for (EquipData::iterator it = mPoss->equipment.begin(), + it_end = mPoss->equipment.end(); it != it_end; ++it) + { + InventoryData::iterator itemIt = mPoss->inventory.find(*it); + const ItemEquipRequirement &equipReq = itemManager->getItem( + itemIt->second.itemId)->getItemEquipRequirement(); + itemIt->second.equipmentSlot = equipReq.equipSlotId; + } + + /* * Construct a set of item Ids to keep track of duplicate item Ids. */ std::set<unsigned> itemIds; + std::set<unsigned> equipmentIds; /* * Construct a set of itemIds to keep track of duplicate itemIds. */ - InventoryData::iterator it1; - for (it1 = mPoss->inventory.begin(); it1 != mPoss->inventory.end();) + + for (InventoryData::iterator it = mPoss->inventory.begin(), + it_end = mPoss->inventory.end(); it != it_end;) { - ItemClass *item = itemManager->getItem(it1->second.itemId); + ItemClass *item = itemManager->getItem(it->second.itemId); if (item) { // If the insertion succeeded, it's the first time we're // adding the item in the inventory. Hence, we can trigger // item presence in inventory effect. - if (itemIds.insert(it1->second.itemId).second) + if (itemIds.insert(it->second.itemId).second) item->useTrigger(mCharacter, ITT_IN_INVY); - ++it1; - } - else - { - LOG_WARN("Inventory: deleting unknown item type " - << it1->second.itemId << " from the inventory of '" - << mCharacter->getComponent<BeingComponent>()->getName() - << "'!"); - mPoss->inventory.erase(it1++); - } - } - - itemIds.clear(); - /* - * Equipment effects can be cumulative if more than one item instance - * is equipped, but we check to trigger the item presence in equipment - * effect only based on the first item instance insertion. - */ - EquipData::iterator it2; - for (it2 = mPoss->equipSlots.begin(); it2 != mPoss->equipSlots.end();) - { - ItemClass *item = itemManager->getItem(it2->second.itemId); - if (item) - { - // TODO: Check equip conditions. - // If not all needed slots are there, put the item back - // in the inventory. + if (it->second.equipmentSlot != 0 && + equipmentIds.insert(it->second.itemId).second) + { + item->useTrigger(mCharacter, ITT_EQUIP); + } + ++it; } else { LOG_WARN("Equipment: deleting unknown item id " - << it2->second.itemId << " from the equipment of '" + << it->second.itemId << " from the equipment of '" << mCharacter->getComponent<BeingComponent>()->getName() << "'!"); - mPoss->equipSlots.erase(it2++); - continue; - } - - /* - * Apply all equip triggers at first item instance insertion - */ - if (itemIds.insert(it2->second.itemInstance).second) - { - itemManager->getItem(it2->second.itemId) - ->useTrigger(mCharacter, ITT_EQUIP); + mPoss->inventory.erase(it++); } - - ++it2; } } @@ -233,32 +205,14 @@ unsigned Inventory::insert(unsigned itemId, unsigned amount) return amount; } -unsigned Inventory::count(unsigned itemId, - bool inInventory, bool inEquipment) const +unsigned Inventory::count(unsigned itemId) const { unsigned nb = 0; - if (inInventory) - { - for (InventoryData::iterator it = mPoss->inventory.begin(), - it_end = mPoss->inventory.end(); it != it_end; ++it) - if (it->second.itemId == itemId) - nb += it->second.amount; - } - - if (inEquipment) + for (InventoryData::iterator it = mPoss->inventory.begin(), + it_end = mPoss->inventory.end(); it != it_end; ++it) { - std::set<unsigned> itemInstances; - for (EquipData::iterator it = mPoss->equipSlots.begin(), - it_end = mPoss->equipSlots.end(); it != it_end; ++it) - { - if (it->second.itemId != itemId || !it->second.itemInstance) - continue; - - // If the insertion was successful, then it was the first time, - // and can be counted. - if ((itemInstances.insert(it->second.itemInstance)).second) - ++nb; - } + if (it->second.itemId == itemId) + nb += it->second.amount; } return nb; @@ -336,131 +290,6 @@ unsigned Inventory::remove(unsigned itemId, unsigned amount) return amount; } -unsigned Inventory::move(unsigned slot1, unsigned slot2, - unsigned amount) -{ - LOG_DEBUG(amount << " item(s) requested to move from: " << slot1 << " to " - << slot2 << " for character: '" - << mCharacter->getComponent<BeingComponent>()->getName() << "'."); - - if (!amount || slot1 == slot2 || slot2 >= INVENTORY_SLOTS) - return amount; - - InventoryData::iterator it1 = mPoss->inventory.find(slot1), - it2 = mPoss->inventory.find(slot2), - inv_end = mPoss->inventory.end(); - - if (it1 == inv_end) - return amount; - - MessageOut invMsg(GPMSG_INVENTORY); - - unsigned nb = std::min(amount, it1->second.amount); - if (it2 == inv_end) - { - // Slot2 does not yet exist. - mPoss->inventory[slot2].itemId = it1->second.itemId; - nb = std::min(itemManager->getItem(it1->second.itemId)->getMaxPerSlot(), - nb); - - mPoss->inventory[slot2].amount = nb; - it1->second.amount -= nb; - amount -= nb; - - //Save the itemId in case of deletion of the iterator - unsigned itemId = it1->second.itemId; - invMsg.writeInt16(slot1); // Slot - if (it1->second.amount) - { - invMsg.writeInt16(it1->second.itemId); // Item Id - invMsg.writeInt16(it1->second.amount); // Amount - LOG_DEBUG("Left " << amount << " item(s) id:" - << it1->second.itemId << " into slot: " << slot1); - } - else - { - invMsg.writeInt16(0); - mPoss->inventory.erase(it1); - LOG_DEBUG("Slot: " << slot1 << " is now empty."); - } - invMsg.writeInt16(slot2); // Slot - invMsg.writeInt16(itemId); // Item Id (same as slot 1) - invMsg.writeInt16(nb); // Amount - LOG_DEBUG("Slot: " << slot2 << " has now " << nb << " of item id: " - << itemId); - } - else - { - // Slot2 exists. - if (it2->second.itemId != it1->second.itemId) - { - // Swap items when they are of a different type - // and when all the amount of slot 1 is moving onto slot 2. - if (amount >= it1->second.amount) - { - unsigned itemId = it1->second.itemId; - unsigned amount = it1->second.amount; - it1->second.itemId = it2->second.itemId; - it1->second.amount = it2->second.amount; - it2->second.itemId = itemId; - it2->second.amount = amount; - - // Sending swapped slots. - invMsg.writeInt16(slot1); - invMsg.writeInt16(it1->second.itemId); - invMsg.writeInt16(it1->second.amount); - invMsg.writeInt16(slot2); - invMsg.writeInt16(it2->second.itemId); - invMsg.writeInt16(it2->second.amount); - LOG_DEBUG("Swapping items in slots " << slot1 - << " and " << slot2); - } - else - { - // Cannot partially stack items of a different type. - LOG_DEBUG("Cannot move " << amount << " item(s) from slot " - << slot1 << " to " << slot2); - return amount; - } - } - else // Same item type on slot 2. - { - // Number of items moving - nb = std::min(itemManager->getItem( - it1->second.itemId)->getMaxPerSlot() - - it2->second.amount, nb); - - // If nothing can move, we can abort - if (!nb) - return amount; - - it1->second.amount -= nb; - it2->second.amount += nb; - amount -= nb; - - invMsg.writeInt16(slot1); // Slot - if (it1->second.amount) - { - invMsg.writeInt16(it1->second.itemId); // Item Id - invMsg.writeInt16(it1->second.amount); // Amount - } - else - { - invMsg.writeInt16(0); - mPoss->inventory.erase(it1); - } - invMsg.writeInt16(slot2); // Slot - invMsg.writeInt16(it2->second.itemId); // Item Id - invMsg.writeInt16(it2->second.amount); // Amount - } - } - - if (invMsg.getLength() > 2) - gameHandler->sendTo(mCharacter, invMsg); - - return amount; -} - unsigned Inventory::removeFromSlot(unsigned slot, unsigned amount) { InventoryData::iterator it = mPoss->inventory.find(slot); @@ -544,22 +373,6 @@ void Inventory::updateEquipmentTrigger(ItemClass *oldI, ItemClass *newI) newI->useTrigger(mCharacter, ITT_EQUIP); } -unsigned Inventory::getNewEquipItemInstance() -{ - std::set<int> alreadyUsed; - for (EquipData::const_iterator it = mPoss->equipSlots.begin(); - it != mPoss->equipSlots.end(); ++it) - { - alreadyUsed.insert(it->second.itemInstance); - } - - unsigned itemInstance = 1; - while (alreadyUsed.count(itemInstance)) - itemInstance++; - - return itemInstance; -} - bool Inventory::checkEquipmentCapacity(unsigned equipmentSlot, unsigned capacityRequested) { @@ -570,15 +383,15 @@ bool Inventory::checkEquipmentCapacity(unsigned equipmentSlot, return false; // Test whether the slot capacity requested is reached. - for (EquipData::const_iterator it = mPoss->equipSlots.begin(), - it_end = mPoss->equipSlots.end(); it != it_end; ++it) + for (EquipData::const_iterator it = mPoss->equipment.begin(), + it_end = mPoss->equipment.end(); it != it_end; ++it) { - if (it->first == equipmentSlot) + InventoryData::iterator itemIt = mPoss->inventory.find(*it); + if (itemIt->second.equipmentSlot == equipmentSlot) { - if (it->second.itemInstance != 0) - { - capacity--; - } + const int itemId = itemIt->second.itemId; + const ItemClass *item = itemManager->getItem(itemId); + capacity -= item->getItemEquipRequirement().capacityRequired; } } @@ -593,29 +406,35 @@ bool Inventory::checkEquipmentCapacity(unsigned equipmentSlot, bool Inventory::equip(int inventorySlot) { // Test inventory slot existence - InventoryData::iterator it; - if ((it = mPoss->inventory.find(inventorySlot)) == mPoss->inventory.end()) + InventoryData::iterator itemIt; + if ((itemIt = mPoss->inventory.find(inventorySlot)) == mPoss->inventory.end()) { LOG_DEBUG("No existing item in inventory at slot: " << inventorySlot); return false; } + InventoryItem &item = itemIt->second; + + // Already equipped? + if (item.equipmentSlot != 0) + return false; + // Test the equipment scripted requirements - if (!testEquipScriptRequirements(it->second.itemId)) + if (!testEquipScriptRequirements(item.itemId)) return false; // Test the equip requirements. If none, it's not an equipable item. const ItemEquipRequirement &equipReq = - itemManager->getItem(it->second.itemId)->getItemEquipRequirement(); + itemManager->getItem(item.itemId)->getItemEquipRequirement(); if (!equipReq.equipSlotId) { - LOG_DEBUG("No equip requirements for item id: " << it->second.itemId + LOG_DEBUG("No equip requirements for item id: " << item.itemId << " at slot: " << inventorySlot); return false; } // List of potential unique itemInstances to unequip first. - std::set<unsigned> equipInstancesToUnequipFirst; + std::set<unsigned> slotsToUnequipFirst; // We first check the equipment slots for: // - 1. whether enough total equip slot space is available. @@ -642,14 +461,15 @@ bool Inventory::equip(int inventorySlot) && hasInventoryEnoughSpace(equipReq.equipSlotId)) { // Then, we unequip each iteminstance of the equip slot - for (EquipData::iterator iter = - mPoss->equipSlots.begin(); - iter != mPoss->equipSlots.end(); ++iter) + for (EquipData::iterator it = mPoss->equipment.begin(), + it_end = mPoss->equipment.end(); it != it_end; ++it) { - if (iter->first == equipReq.equipSlotId - && iter->second.itemInstance) - equipInstancesToUnequipFirst.insert( - iter->second.itemInstance); + const unsigned slot = *it; + InventoryData::iterator itemIt = mPoss->inventory.find(slot); + assert(itemIt != mPoss->inventory.end()); + if (itemIt->second.equipmentSlot == equipReq.equipSlotId) { + slotsToUnequipFirst.insert(itemIt->first); + } } } else @@ -662,90 +482,33 @@ bool Inventory::equip(int inventorySlot) } // Potential Pre-unequipment process - for (std::set<unsigned>::const_iterator it3 = - equipInstancesToUnequipFirst.begin(); - it3 != equipInstancesToUnequipFirst.end(); ++it3) + for (std::set<unsigned>::const_iterator itemsToUnequip = + slotsToUnequipFirst.begin(), + itemsToUnequip_end = slotsToUnequipFirst.end(); + itemsToUnequip != itemsToUnequip_end; ++itemsToUnequip) { - if (!unequip(*it3)) + if (!unequip(*itemsToUnequip)) { // 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); + << mCharacter->getComponent<BeingComponent>()->getName() + << ", unequip slot: " << *itemsToUnequip); 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); + item.equipmentSlot = equipReq.equipSlotId; + mPoss->equipment.insert(inventorySlot); - // 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); + MessageOut equipMsg(GPMSG_EQUIP); + equipMsg.writeInt16(inventorySlot); + equipMsg.writeInt16(item.equipmentSlot); + gameHandler->sendTo(mCharacter, equipMsg); // New item trigger - updateEquipmentTrigger(0, it->second.itemId); - - // Remove item from inventory - removeFromSlot(inventorySlot, 1); - - gameHandler->sendTo(mCharacter, equipMsg); + updateEquipmentTrigger(0, item.itemId); // Update look when necessary checkLookchanges(equipReq.equipSlotId); @@ -753,87 +516,51 @@ bool Inventory::equip(int inventorySlot) return true; } -unsigned Inventory::getSlotItemInstance(unsigned slot) +bool Inventory::unequipAll(unsigned itemId) { - EquipData::iterator it = mPoss->equipSlots.find(slot); - if (it != mPoss->equipSlots.end()) - return it->second.itemInstance; - return 0; -} - -bool Inventory::unequipItem(unsigned itemId) -{ - std::set<unsigned> itemInstances; - for (EquipData::iterator it = mPoss->equipSlots.begin(), - it_end = mPoss->equipSlots.end(); it != it_end; ++it) + while (true) { - if (it->second.itemId == itemId) - itemInstances.insert(it->second.itemInstance); - } + const int slot = getFirstSlot(itemId); + // No item left + if (slot == -1) + return true; - // Nothing to do but it's a success - if (itemInstances.empty()) - return true; - - for (std::set<unsigned>::const_iterator it = itemInstances.begin(), - it_end = itemInstances.end(); it != it_end; ++it) - { - if (!unequip(*it)) + if (!unequip(slot)) return false; } - return true; + + // silence compiler warnings + assert(false); + return false; } -bool Inventory::unequip(unsigned itemInstance) +bool Inventory::unequip(unsigned itemSlot) { - if (!itemInstance) - return false; - - // The itemId to unequip - unsigned itemId = 0; - unsigned slotTypeId = 0; - - bool addedToInventory = false; - - // 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) + InventoryData::iterator it = mPoss->inventory.find(itemSlot); + if (it == mPoss->inventory.end()) { - if (it->second.itemInstance == itemInstance && it->second.itemId) - { - // Add the item to the inventory list if not already present there - itemId = it->second.itemId; + LOG_DEBUG("Tried to unequip invalid item at slot " << itemSlot); + return false; + } - // Move the item back to inventory and return false when it failed. - if (!addedToInventory && insert(itemId, 1) > 0) - return false; - else - addedToInventory = true; + InventoryItem &item = it->second; - it->second.itemId = 0; - it->second.itemInstance = 0; + // Item was not equipped + if (item.equipmentSlot == 0) + return false; - // We keep track of the slot type to be able to raise a potential - // change in the character sprite - slotTypeId = it->first; - } - } + const unsigned slotTypeId = item.equipmentSlot; - // When there were no corresponding item id, it means no item was to - // be unequipped. - if (!itemId) - return false; + // unequip + item.equipmentSlot = 0; + mPoss->equipment.erase(mPoss->equipment.find(itemSlot)); - MessageOut equipMsg(GPMSG_EQUIP); - equipMsg.writeInt16(0); // Item Id, useless in case of unequip. - equipMsg.writeInt16(1); // Number of slot types touched. - equipMsg.writeInt16(itemInstance); - equipMsg.writeInt16(0); // Capacity used, set to 0 to unequip. + MessageOut equipMsg(GPMSG_UNEQUIP); + equipMsg.writeInt16(itemSlot); gameHandler->sendTo(mCharacter, equipMsg); // Apply unequip trigger - updateEquipmentTrigger(itemId, 0); + updateEquipmentTrigger(item.itemId, 0); checkLookchanges(slotTypeId); diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index 1740a8d9..949471b6 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -65,26 +65,19 @@ class Inventory bool equip(int inventorySlot); /** - * Unequips all the items with the given item if - * from given equipment slot. + * Unequips all the items with the given item id * @param itemId The item Id to unequip. * @returns whether all item id could be unequipped. * @note returns true when no item with given ids were equipped. */ - bool unequipItem(unsigned itemId); + bool unequipAll(unsigned itemId); /** * Unequips item from given equipment slot. - * @param itemInstance The item instance id used to know what to unequip + * @param itemSlot The item slot used to know what to unequip * @returns Whether it was unequipped. */ - bool unequip(unsigned itemInstance); - - /** - * Gets the item instance from the given equipment slot. - * Return 0 if none. - */ - unsigned getSlotItemInstance(unsigned slot); + bool unequip(unsigned itemSlot); /** * Inserts some items into the inventory. @@ -99,13 +92,6 @@ class Inventory unsigned remove(unsigned itemId, unsigned amount); /** - * Moves some items from the first slot to the second one. - * @returns number of items not moved. - */ - unsigned move(unsigned slot1, unsigned slot2, - unsigned amount); - - /** * Removes some items from inventory. * @return number of items not removed. */ @@ -113,11 +99,9 @@ class Inventory /** * Counts number of items with given Id. - * @param inInventory Search in player's inventory. - * @param inEquipment Search in player's equipment. + * @param itemId The id to look for. */ - unsigned count(unsigned itemId, bool inInventory = true, - bool inEquipment = true) const; + unsigned count(unsigned itemId) const; /** * Gets the ID of the items in a given slot. @@ -163,14 +147,6 @@ class Inventory { return true; } /** - * Return an equip item instance id unique to the item used, - * per character. - * This is used to differenciate some items that can be equipped - * multiple times, like one-handed weapons for instance. - */ - unsigned getNewEquipItemInstance(); - - /** * Check the inventory is within the slot limit and capacity. * Forcibly delete items from the end if it is not. * @todo Drop items instead? diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index a7cac98c..b6528955 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -85,10 +85,8 @@ static void serializeLooks(Entity *ch, MessageOut &msg) msg.writeInt8(characterComponent->getHairColor()); const EquipData &equipData = characterComponent->getPossessions().getEquipment(); - - // We'll use a set to check whether we already sent the update for the given - // item instance. - std::set<unsigned> itemInstances; + const InventoryData &inventoryData = + characterComponent->getPossessions().getInventory(); // The map storing the info about the look changes to send //{ slot type id, item id } @@ -99,17 +97,14 @@ static void serializeLooks(Entity *ch, MessageOut &msg) for (EquipData::const_iterator it = equipData.begin(), it_end = equipData.end(); it != it_end; ++it) { - if (!itemManager->isEquipSlotVisible(it->first)) + InventoryData::const_iterator itemIt = inventoryData.find(*it); + + if (!itemManager->isEquipSlotVisible(itemIt->second.equipmentSlot)) continue; - if (!it->second.itemInstance - || itemInstances.insert(it->second.itemInstance).second) - { - // When the insertion succeeds, its the first time - // we encounter the item, so we can send the look change. - // We also send empty slots for unequipment handling. - lookChanges.insert(std::make_pair(it->first, it->second.itemId)); - } + lookChanges.insert(std::make_pair( + itemIt->second.equipmentSlot, + itemIt->second.itemId)); } if (!lookChanges.empty()) @@ -117,12 +112,12 @@ static void serializeLooks(Entity *ch, MessageOut &msg) // Number of look changes to send msg.writeInt8(lookChanges.size()); - for (std::map<unsigned, unsigned>::const_iterator it2 = - lookChanges.begin(), it2_end = lookChanges.end(); - it2 != it2_end; ++it2) + for (std::map<unsigned, unsigned>::const_iterator it = + lookChanges.begin(), it_end = lookChanges.end(); + it != it_end; ++it) { - msg.writeInt8(it2->first); - msg.writeInt16(it2->second); + msg.writeInt8(it->first); + msg.writeInt16(it->second); } } } @@ -170,20 +165,20 @@ static void informPlayer(MapComposite *map, Entity *p) // Send action change messages. if ((oflags & UPDATEFLAG_ACTIONCHANGE)) { - MessageOut ActionMsg(GPMSG_BEING_ACTION_CHANGE); - ActionMsg.writeInt16(oid); - ActionMsg.writeInt8( + MessageOut actionMsg(GPMSG_BEING_ACTION_CHANGE); + actionMsg.writeInt16(oid); + actionMsg.writeInt8( o->getComponent<BeingComponent>()->getAction()); - gameHandler->sendTo(p, ActionMsg); + gameHandler->sendTo(p, actionMsg); } // Send looks change messages. if (oflags & UPDATEFLAG_LOOKSCHANGE) { - MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE); - LooksMsg.writeInt16(oid); - serializeLooks(o, LooksMsg); - gameHandler->sendTo(p, LooksMsg); + MessageOut looksMsg(GPMSG_BEING_LOOKS_CHANGE); + looksMsg.writeInt16(oid); + serializeLooks(o, looksMsg); + gameHandler->sendTo(p, looksMsg); } // Send emote messages. @@ -193,21 +188,21 @@ static void informPlayer(MapComposite *map, Entity *p) o->getComponent<BeingComponent>()->getLastEmote(); if (emoteId > -1) { - MessageOut EmoteMsg(GPMSG_BEING_EMOTE); - EmoteMsg.writeInt16(oid); - EmoteMsg.writeInt16(emoteId); - gameHandler->sendTo(p, EmoteMsg); + MessageOut emoteMsg(GPMSG_BEING_EMOTE); + emoteMsg.writeInt16(oid); + emoteMsg.writeInt16(emoteId); + gameHandler->sendTo(p, emoteMsg); } } // Send direction change messages. if (oflags & UPDATEFLAG_DIRCHANGE) { - MessageOut DirMsg(GPMSG_BEING_DIR_CHANGE); - DirMsg.writeInt16(oid); - DirMsg.writeInt8( + MessageOut dirMsg(GPMSG_BEING_DIR_CHANGE); + dirMsg.writeInt16(oid); + dirMsg.writeInt8( o->getComponent<BeingComponent>()->getDirection()); - gameHandler->sendTo(p, DirMsg); + gameHandler->sendTo(p, dirMsg); } // Send ability uses @@ -279,8 +274,6 @@ static void informPlayer(MapComposite *map, Entity *p) { case OBJECT_CHARACTER: { - auto *characterComponent = - o->getComponent<CharacterComponent>(); enterMsg.writeString( o->getComponent<BeingComponent>()->getName()); serializeLooks(o, enterMsg); |