summaryrefslogtreecommitdiff
path: root/src/game-server
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-03-10 10:27:51 +0100
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-09-08 10:19:40 +0200
commitf712d68495dd8e040c32da3b1c85bcb7845543ec (patch)
treef1a314bc1ef895c31851428b4ceff8b63d209f66 /src/game-server
parent8ddda85d923a528c7497a628d2fe10fc40b80a1f (diff)
downloadmanaserv-f712d68495dd8e040c32da3b1c85bcb7845543ec.tar.gz
manaserv-f712d68495dd8e040c32da3b1c85bcb7845543ec.tar.bz2
manaserv-f712d68495dd8e040c32da3b1c85bcb7845543ec.tar.xz
manaserv-f712d68495dd8e040c32da3b1c85bcb7845543ec.zip
Cleaned up the inventory handling
Things done: - Removed the equips table and added another column which keeps track about whether the item is equipped or not - Added a message to notify the client about failing equips instead of hardcoding to chat notification - Removed the move possibillity. It was a quite long function and our future idea of the inventory does not need any moves - Removed the inInventory and inEquipment parameters from chr_inv_count, but added a equipped key to the table that chr_get_inventory returns This change makes equipped items still being in the inventory. This means in-inventory triggers are still active! However it makes no sense to disable this triggers during equipping since it will appear as still in the inventory to the client.
Diffstat (limited to 'src/game-server')
-rw-r--r--src/game-server/character.cpp48
-rw-r--r--src/game-server/gamehandler.cpp51
-rw-r--r--src/game-server/gamehandler.h1
-rw-r--r--src/game-server/inventory.cpp487
-rw-r--r--src/game-server/inventory.h36
-rw-r--r--src/game-server/state.cpp65
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);