summaryrefslogtreecommitdiff
path: root/src/game-server
diff options
context:
space:
mode:
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);