diff options
Diffstat (limited to 'src/game-server')
-rw-r--r-- | src/game-server/gamehandler.cpp | 8 | ||||
-rw-r--r-- | src/game-server/inventory.cpp | 147 | ||||
-rw-r--r-- | src/game-server/inventory.hpp | 6 | ||||
-rw-r--r-- | src/game-server/state.cpp | 2 |
4 files changed, 161 insertions, 2 deletions
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index e01c4a9d..17ce6dee 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -259,6 +259,14 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) } } break; + case PGMSG_MOVE_ITEM: + { + int slot1 = message.readByte(); + int slot2 = message.readByte(); + int amount = message.readByte(); + Inventory(computer.character).move(slot1, slot2, amount); + } break; + case PGMSG_ATTACK: { LOG_DEBUG("Character " << computer.character->getPublicID() diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 50e229cc..49442a5c 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -162,12 +162,13 @@ int Inventory::getItem(int slot) const int Inventory::getIndex(int slot) const { int index = 0; + for (std::vector< InventoryItem >::const_iterator i = mPoss->inventory.begin(), i_end = mPoss->inventory.end(); i != i_end; ++i, ++index) { if (slot == 0) { - return index; + return i->itemId ? index : -1; } slot -= i->itemId ? 1 : i->amount; @@ -379,6 +380,150 @@ int Inventory::remove(int itemId, int amount) return amount; } +int Inventory::move(int slot1, int slot2, int amount) +{ + if (amount == 0 || slot2 >= INVENTORY_SLOTS) + { + return amount; + } + + int i1 = getIndex(slot1); + if (i1 < 0) + { + return amount; + } + + prepare(); + + InventoryItem &it1 = mPoss->inventory[i1]; + int i2 = getIndex(slot2); + + if (i2 >= 0) + { + InventoryItem &it2 = mPoss->inventory[i2]; + if (it1.itemId == it2.itemId) + { + // Move between two stacks of the same kind. + int nb = std::min(std::min(amount, (int)it1.amount), 255 - it2.amount); + if (nb == 0) + { + return amount; + } + + it1.amount -= nb; + it2.amount += nb; + amount -= nb; + + msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY); + if (it1.amount == 0) + { + msg.writeShort(0); + freeIndex(i1); + } + else + { + msg.writeShort(it1.itemId); + msg.writeByte(it1.amount); + } + + msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY); + msg.writeShort(it2.itemId); + msg.writeByte(it2.amount); + return amount; + } + + // Swap between two different stacks. + + if (it1.amount != amount) + { + return amount; + } + + std::swap(it1, it2); + + msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY); + msg.writeShort(it1.itemId); + msg.writeByte(it1.amount); + msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY); + msg.writeShort(it2.itemId); + msg.writeByte(it2.amount); + return 0; + } + + // Move some items to an empty slot. + int id = it1.itemId; + int nb = std::min((int)it1.amount, amount); + it1.amount -= nb; + amount -= nb; + + msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY); + if (it1.amount == 0) + { + msg.writeShort(0); + freeIndex(i1); + } + else + { + msg.writeShort(id); + msg.writeByte(it1.amount); + } + + // Fill second slot. + for (std::vector< InventoryItem >::iterator i = mPoss->inventory.begin(), + i_end = mPoss->inventory.end(); i != i_end; ++i) + { + if (i->itemId) + { + --slot2; + continue; + } + + if (slot2 >= i->amount) + { + slot2 -= i->amount; + continue; + } + + assert(slot2 >= 0 && i + 1 != i_end); + + if (i->amount == 1) + { + // One single empty slot in the range. + i->itemId = id; + i->amount = nb; + break; + } + + InventoryItem it = { id, nb }; + --i->amount; + + if (slot2 == 0) + { + // First slot in an empty range. + mPoss->inventory.insert(i + 1, it); + break; + } + + if (slot2 == i->amount) + { + // Last slot in an empty range. + mPoss->inventory.insert(i, it); + break; + } + + InventoryItem it3 = { 0, slot2 }; + i->amount -= slot2; + i = mPoss->inventory.insert(i, it); + mPoss->inventory.insert(i, it3); + break; + } + + msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY); + msg.writeShort(id); + msg.writeByte(nb); + return amount; +} + int Inventory::removeFromSlot(int slot, int amount) { if (amount == 0) diff --git a/src/game-server/inventory.hpp b/src/game-server/inventory.hpp index c9a2643d..1f2611eb 100644 --- a/src/game-server/inventory.hpp +++ b/src/game-server/inventory.hpp @@ -123,6 +123,12 @@ class Inventory int remove(int itemId, int amount); /** + * Moves some items from the first slot to the second one. + * @returns number of items not moved. + */ + int move(int slot1, int slot2, int amount); + + /** * Removes some items from inventory. * @return number of items not removed. */ diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 19c3ea60..513f7e6e 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -138,7 +138,7 @@ static void serializeLooks(Character *ch, MessageOut &msg, bool full) /* Bitmask enumerating the sent slots. Setting the upper bit tells the client to clear the slots beforehand. */ - int mask = full ? mask_full | (1 << 8) : mask_diff; + int mask = full ? mask_full | (1 << 7) : mask_diff; msg.writeByte(mask); for (int i = 0; i < nb_slots; ++i) |