diff options
author | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2011-04-09 15:48:51 +0200 |
---|---|---|
committer | Thorbjørn Lindeijer <thorbjorn@lindeijer.nl> | 2011-06-02 16:41:35 +0200 |
commit | c2eab288ecc7d7c5e26d02ccecf285cbc0c218ed (patch) | |
tree | 37b755bc559a40209291e5ed4961de36fc7788dd /src/net/manaserv/inventoryhandler.cpp | |
parent | c5390a30868f7eb3b5337963dba20911ea7dc6ea (diff) | |
download | mana-c2eab288ecc7d7c5e26d02ccecf285cbc0c218ed.tar.gz mana-c2eab288ecc7d7c5e26d02ccecf285cbc0c218ed.tar.bz2 mana-c2eab288ecc7d7c5e26d02ccecf285cbc0c218ed.tar.xz mana-c2eab288ecc7d7c5e26d02ccecf285cbc0c218ed.zip |
Some work on the manaserv equipment backend
Currently the same equipment window is used as for tmwAthena so that at
least something is visible. This means the location of equipped items is
currently illogical.
It is now possible to equip and unequip items.
Mantis-issue: 164
Reviewed-by: Stefan Dombrowski
Diffstat (limited to 'src/net/manaserv/inventoryhandler.cpp')
-rw-r--r-- | src/net/manaserv/inventoryhandler.cpp | 161 |
1 files changed, 145 insertions, 16 deletions
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index ff9b69e6..c8dae1c3 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -26,8 +26,11 @@ #include "item.h" #include "itemshortcut.h" #include "localplayer.h" +#include "log.h" #include "playerinfo.h" +#include "gui/inventorywindow.h" + #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" @@ -41,6 +44,125 @@ namespace ManaServ { extern Connection *gameServerConnection; +EquipBackend::EquipBackend() +{ + listen(Event::ClientChannel); +} + +Item *EquipBackend::getEquipment(int index) const +{ + if (index < 0 || (unsigned) index >= mSlots.size()) + return 0; + return mSlots.at(index); +} + +void EquipBackend::clear() +{ + for (std::vector<Item*>::iterator i = mSlots.begin(), i_end = mSlots.end(); + i != i_end; ++i) + { + if (Item *item = *i) + item->setEquipped(false); + } + mSlots.assign(mSlots.size(), 0); +} + +void EquipBackend::equip(int inventorySlot, int equipSlot, int amountUsed) +{ + if (equipSlot < 0 || (unsigned) equipSlot >= mSlotTypes.size()) + { + logger->log("ManaServ::EquipBackend: Equipment slot out of range"); + return; + } + + const SlotType &slotType = mSlotTypes.at(equipSlot); + Item *item = PlayerInfo::getInventory()->getItem(inventorySlot); + + if (!item) + { + logger->log("ManaServ::EquipBackend: No item at index %d", + inventorySlot); + return; + } + + // Start at first index and search upwards for free slots to place the + // item at the given inventory slot in + int i = slotType.firstIndex; + const int end_i = i + slotType.count; + + for (; i < end_i && amountUsed > 0; ++i) + { + if (!mSlots.at(i)) + { + mSlots[i] = item; + --amountUsed; + + item->setEquipped(true); + inventoryWindow->updateButtons(); + } + } +} + +void EquipBackend::unequip(int inventorySlot) +{ + Item *item = PlayerInfo::getInventory()->getItem(inventorySlot); + + if (!item) + { + logger->log("ManaServ::EquipBackend: No item at index %d", + inventorySlot); + return; + } + + for (unsigned i = 0; i < mSlots.size(); ++i) + if (mSlots.at(i) == item) + mSlots[i] = 0; + + item->setEquipped(false); + inventoryWindow->updateButtons(); +} + +void EquipBackend::event(Event::Channel, const Event &event) +{ + if (event.getType() == Event::LoadingDatabases) + readEquipFile(); +} + +void EquipBackend::readEquipFile() +{ + mSlots.clear(); + mSlotTypes.clear(); + + XML::Document doc("equip.xml"); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equip-slots")) + { + logger->log("ManaServ::EquipBackend: Error while reading equip.xml!"); + return; + } + + int slotCount = 0; + + for_each_xml_child_node(childNode, rootNode) + { + if (!xmlStrEqual(childNode->name, BAD_CAST "slot")) + continue; + + SlotType slotType; + slotType.name = XML::getProperty(childNode, "name", std::string()); + slotType.count = XML::getProperty(childNode, "count", 1); + slotType.visible = XML::getBoolProperty(childNode, "visible", false); + slotType.firstIndex = slotCount; + + mSlotTypes.push_back(slotType); + slotCount += slotType.count; + } + + mSlots.resize(slotCount); +} + + InventoryHandler::InventoryHandler() { static const Uint16 _messages[] = { @@ -62,21 +184,21 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) case GPMSG_INVENTORY_FULL: { PlayerInfo::clearInventory(); - PlayerInfo::getEquipment()->setBackend(&mEquips); + PlayerInfo::getEquipment()->setBackend(&mEquipBackend); int count = msg.readInt16(); while (count--) { - unsigned int slot = msg.readInt16(); + int slot = msg.readInt16(); int id = msg.readInt16(); - unsigned int amount = msg.readInt16(); + int amount = msg.readInt16(); PlayerInfo::setInventoryItem(slot, id, amount); } while (msg.getUnreadLength()) { - unsigned int slot = msg.readInt8(); - unsigned int ref = msg.readInt16(); + int equipSlot = msg.readInt8(); + int inventorySlot = msg.readInt16(); - mEquips.addEquipment(slot, ref); + mEquipBackend.equip(inventorySlot, equipSlot); } } break; @@ -94,14 +216,25 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) case GPMSG_EQUIP: while (msg.getUnreadLength()) { - unsigned int ref = msg.readInt16(); - int count = msg.readInt8(); - while (count--) + int inventorySlot = msg.readInt16(); + int equipSlotCount = msg.readInt8(); + + if (equipSlotCount == 0) { - unsigned int slot = msg.readInt8(); - unsigned int used = msg.readInt8(); + // No slots means to unequip this item + mEquipBackend.unequip(inventorySlot); + } + else + { + // Otherwise equip the item in the given slots + while (equipSlotCount--) + { + unsigned int equipSlot = msg.readInt8(); + unsigned int amountUsed = msg.readInt8(); - mEquips.setEquipment(slot, used, ref); + mEquipBackend.equip(inventorySlot, equipSlot, + amountUsed); + } } } break; @@ -131,10 +264,6 @@ void InventoryHandler::event(Event::Channel channel, MessageOut msg(PGMSG_UNEQUIP); msg.writeInt8(index); gameServerConnection->send(msg); - - // Tidy equipment directly to avoid weapon still shown bug, - // for instance. - mEquips.setEquipment(index, 0, 0); } else if (event.getType() == Event::DoUse) { |