diff options
-rw-r--r-- | src/game.cpp | 12 | ||||
-rw-r--r-- | src/net/manaserv/inventoryhandler.cpp | 161 | ||||
-rw-r--r-- | src/net/manaserv/inventoryhandler.h | 40 |
3 files changed, 171 insertions, 42 deletions
diff --git a/src/game.cpp b/src/game.cpp index ef930d92..6fda630e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -156,13 +156,11 @@ static void createGuiWindows() tradeWindow = new TradeWindow; switch (Net::getNetworkType()) { - case ServerInfo::TMWATHENA: - equipmentWindow = new TmwAthena::TaEquipmentWindow( - PlayerInfo::getEquipment()); - break; - case ServerInfo::MANASERV: - default: - equipmentWindow = new EquipmentWindow(PlayerInfo::getEquipment()); + case ServerInfo::TMWATHENA: + case ServerInfo::MANASERV: + default: + equipmentWindow = + new TmwAthena::TaEquipmentWindow(PlayerInfo::getEquipment()); break; } statusWindow = new StatusWindow; 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) { diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h index 2733f3da..255f601c 100644 --- a/src/net/manaserv/inventoryhandler.h +++ b/src/net/manaserv/inventoryhandler.h @@ -29,33 +29,35 @@ #include "net/manaserv/messagehandler.h" +#include <vector> + namespace ManaServ { -class EquipBackend : public Equipment::Backend +class EquipBackend : public Equipment::Backend, public EventListener { public: - EquipBackend() - { memset(mEquipment, 0, sizeof(mEquipment)); } - - Item *getEquipment(int index) const - { return 0; } + EquipBackend(); - void clear() - { - } + Item *getEquipment(int index) const; + void clear(); - void setEquipment(unsigned int slot, unsigned int used, int reference) - { - printf("Equip: %d at %dx%d\n", reference, slot, used); - } + void equip(int inventorySlot, int equipSlot, int amountUsed = 1); + void unequip(int inventorySlot); - void addEquipment(unsigned int slot, int reference) - { - printf("Equip: %d at %d\n", reference, slot); - } + void event(Event::Channel channel, const Event &event); private: - Item *mEquipment[EQUIPMENT_SIZE]; + void readEquipFile(); + + struct SlotType { + std::string name; + int count; + bool visible; + int firstIndex; + }; + + std::vector<Item*> mSlots; + std::vector<SlotType> mSlotTypes; }; class InventoryHandler : public MessageHandler, Net::InventoryHandler, @@ -73,7 +75,7 @@ class InventoryHandler : public MessageHandler, Net::InventoryHandler, size_t getSize(int type) const; private: - EquipBackend mEquips; + EquipBackend mEquipBackend; }; } // namespace ManaServ |