From 221d67c4774bf41e6f2f0f73fb6914030e33bdde Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Thu, 22 Aug 2024 17:58:31 +0200 Subject: Fixed initialization of equipment backend For new characters (and in general, when logging in with a character that had nothing equipped), the equipment backend wasn't being initialized. This resulted in the equipment not being visible in the Equipment window. Fixes #83 --- NEWS | 1 + src/equipment.h | 18 ++--- src/gui/equipmentwindow.cpp | 122 ++++++++++++++++------------------ src/gui/equipmentwindow.h | 8 +-- src/net/inventoryhandler.h | 3 + src/net/manaserv/inventoryhandler.cpp | 22 ++---- src/net/manaserv/inventoryhandler.h | 6 +- src/net/tmwa/inventoryhandler.cpp | 24 ++----- src/net/tmwa/inventoryhandler.h | 40 +++++------ src/playerinfo.cpp | 10 ++- 10 files changed, 110 insertions(+), 144 deletions(-) diff --git a/NEWS b/NEWS index bd3be388..33d1130e 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,7 @@ - Fixed being popup getting stuck under the mouse - Fixed item links with empty item name to look up name from Item DB - Fixed spaces getting added to chat every 50 characters +- Fixed empty Equipment window on freshly created character - Updated to tmwAthena protocol changes - Updated to Manaserv protocol changes (specials, guilds, debug mode, skills, text particles) - CMake: Use GNUInstallDirs and made PKG_DATADIR / PKG_BINDIR paths modifiable diff --git a/src/equipment.h b/src/equipment.h index 726f7f5e..d40ca55d 100644 --- a/src/equipment.h +++ b/src/equipment.h @@ -29,8 +29,6 @@ class Item; class Equipment { public: - Equipment() = default; - class Backend { public: virtual Item *getEquipment(int slotIndex) const = 0; @@ -46,13 +44,17 @@ class Equipment {} }; + Equipment(Backend *backend) + : mBackend(backend) + {} + /** * Get equipment at the given slot. */ Item *getEquipment(int slotIndex) const { return mBackend ? mBackend->getEquipment(slotIndex) : nullptr; } - const std::string getSlotName(int slotIndex) const + std::string getSlotName(int slotIndex) const { return mBackend ? mBackend->getSlotName(slotIndex) : std::string(); } int getSlotNumber() const @@ -67,16 +69,8 @@ class Equipment void clear() { if (mBackend) mBackend->clear(); } - /** - * Set equipment at the given slot. - */ - void setEquipment(int index, int id, int quantity = 0); - - void setBackend(Backend *backend) - { mBackend = backend; } - private: - Backend *mBackend = nullptr; + Backend *mBackend; }; #endif diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index e6230aed..e7eeb048 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -76,28 +76,28 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment): add(playerBox); add(mUnequip); + + loadEquipBoxes(); } void EquipmentWindow::loadEquipBoxes() { - delete[] mEquipBox; - - // Load equipment boxes. - mBoxesNumber = mEquipment->getSlotNumber(); - mEquipBox = new EquipBox[mBoxesNumber]; + mBoxes.resize(mEquipment->getSlotNumber()); - for (int i = 0; i < mBoxesNumber; ++i) + for (size_t i = 0; i < mBoxes.size(); ++i) { + auto &box = mBoxes[i]; + Position boxPosition = Net::getInventoryHandler()->getBoxPosition(i); - mEquipBox[i].posX = boxPosition.x + getPadding(); - mEquipBox[i].posY = boxPosition.y + getTitleBarHeight(); + box.posX = boxPosition.x + getPadding(); + box.posY = boxPosition.y + getTitleBarHeight(); const std::string &backgroundFile = Net::getInventoryHandler()->getBoxBackground(i); if (!backgroundFile.empty()) { - mEquipBox[i].backgroundImage = + box.backgroundImage = Theme::instance()->getImageFromTheme(backgroundFile); } } @@ -106,65 +106,63 @@ void EquipmentWindow::loadEquipBoxes() EquipmentWindow::~EquipmentWindow() { delete mItemPopup; - delete[] mEquipBox; } void EquipmentWindow::draw(gcn::Graphics *graphics) { - // Draw window graphics Window::draw(graphics); - Window::drawChildren(graphics); // Draw equipment boxes auto *g = static_cast(graphics); - for (int i = 0; i < mBoxesNumber; i++) + for (size_t i = 0; i < mBoxes.size(); i++) { + const auto &box = mBoxes[i]; + // When there is a background image, draw it centered in the box: - if (mEquipBox[i].backgroundImage) + if (box.backgroundImage) { - int posX = mEquipBox[i].posX - + (BOX_WIDTH - mEquipBox[i].backgroundImage->getWidth()) / 2; - int posY = mEquipBox[i].posY - + (BOX_HEIGHT - mEquipBox[i].backgroundImage->getHeight()) / 2; - g->drawImage(mEquipBox[i].backgroundImage, posX, posY); + int posX = box.posX + + (BOX_WIDTH - box.backgroundImage->getWidth()) / 2; + int posY = box.posY + + (BOX_HEIGHT - box.backgroundImage->getHeight()) / 2; + g->drawImage(box.backgroundImage, posX, posY); } - if (i == mSelected) + const gcn::Rectangle tRect(box.posX, box.posY, + BOX_WIDTH, BOX_HEIGHT); + + if (static_cast(i) == mSelected) { const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT); // Set color to the highlight color g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha())); - g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, - mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT)); + g->fillRectangle(tRect); } - // Set color black + // Draw black box border g->setColor(gcn::Color(0, 0, 0)); - // Draw box border - g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT)); + g->drawRectangle(tRect); - Item *item = mEquipment->getEquipment(i); - if (item) + if (Item *item = mEquipment->getEquipment(i)) { // Draw Item. Image *image = item->getImage(); // Ensure the image is drawn with maximum opacity image->setAlpha(1.0f); g->drawImage(image, - mEquipBox[i].posX + 2, - mEquipBox[i].posY + 2); + box.posX + 2, + box.posY + 2); + if (i == TmwAthena::EQUIP_PROJECTILE_SLOT) { g->setColor(Theme::getThemeColor(Theme::TEXT)); graphics->drawText(toString(item->getQuantity()), - mEquipBox[i].posX + (BOX_WIDTH / 2), - mEquipBox[i].posY - getFont()->getHeight(), - gcn::Graphics::CENTER); + box.posX + (BOX_WIDTH / 2), + box.posY - getFont()->getHeight(), + gcn::Graphics::CENTER); } } } @@ -179,30 +177,35 @@ void EquipmentWindow::action(const gcn::ActionEvent &event) } } -Item *EquipmentWindow::getItem(int x, int y) const +/** + * Returns an index of an equipment box at the given position, or -1 if there + * is no box. + */ +int EquipmentWindow::getBoxIndex(int x, int y) const { - for (int i = 0; i < mBoxesNumber; ++i) + for (size_t i = 0; i < mBoxes.size(); ++i) { - gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT); + const auto &box = mBoxes[i]; + const gcn::Rectangle tRect(box.posX, box.posY, + BOX_WIDTH, BOX_HEIGHT); if (tRect.isPointInRect(x, y)) - return mEquipment->getEquipment(i); + return i; } - return nullptr; + + return -1; } -std::string EquipmentWindow::getSlotName(int x, int y) const +Item *EquipmentWindow::getItem(int x, int y) const { - for (int i = 0; i < mBoxesNumber; ++i) - { - gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT); + const int index = getBoxIndex(x, y); + return index != -1 ? mEquipment->getEquipment(index) : nullptr; +} - if (tRect.isPointInRect(x, y)) - return mEquipment->getSlotName(i); - } - return std::string(); +std::string EquipmentWindow::getSlotName(int x, int y) const +{ + const int index = getBoxIndex(x, y); + return index != -1 ? mEquipment->getSlotName(index) : std::string(); } void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent) @@ -213,18 +216,12 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent) const int y = mouseEvent.getY(); Item *item = nullptr; - // Checks if any of the presses were in the equip boxes. - for (int i = 0; i < mBoxesNumber; ++i) + const int index = getBoxIndex(x, y); + if (index != -1) { - item = mEquipment->getEquipment(i); - gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT); - - if (tRect.isPointInRect(x, y) && item) - { - setSelected(i); - break; - } + item = mEquipment->getEquipment(index); + if (item) + setSelected(index); } if (mouseEvent.getButton() == gcn::MouseEvent::RIGHT) @@ -252,11 +249,8 @@ void EquipmentWindow::mouseMoved(gcn::MouseEvent &event) { mItemPopup->setEquipmentText(slotName); - Item *item = getItem(x, y); - if (item) - { + if (Item *item = getItem(x, y)) mItemPopup->setItem(item->getInfo()); - } else mItemPopup->setNoItem(); diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h index 19630e0b..1b63c866 100644 --- a/src/gui/equipmentwindow.h +++ b/src/gui/equipmentwindow.h @@ -62,7 +62,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener /** * Returns the current selected slot or -1 if none. */ - int getSelected() + int getSelected() const { return mSelected; } protected: @@ -76,16 +76,16 @@ class EquipmentWindow : public Window, public gcn::ActionListener Image *backgroundImage = nullptr; }; - EquipBox *mEquipBox = nullptr; /**< Equipment Boxes. */ + std::vector mBoxes; /**< Equipment boxes. */ - int mSelected = -1; /**< Index of selected item. */ + int mSelected = -1; /**< Index of selected item. */ Equipment *mEquipment; - int mBoxesNumber = 0; /**< Number of equipment boxes to display */ private: void mouseExited(gcn::MouseEvent &event) override; void mouseMoved(gcn::MouseEvent &event) override; + int getBoxIndex(int x, int y) const; Item *getItem(int x, int y) const; std::string getSlotName(int x, int y) const; diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h index 497a4ecb..8a67a7db 100644 --- a/src/net/inventoryhandler.h +++ b/src/net/inventoryhandler.h @@ -22,6 +22,7 @@ #ifndef INVENTORYHANDLER_H #define INVENTORYHANDLER_H +#include "equipment.h" #include "inventory.h" #include "item.h" #include "position.h" @@ -78,6 +79,8 @@ class InventoryHandler virtual unsigned int getVisibleSlotsNumber() const { return 0; } + virtual Equipment::Backend *getEquipmentBackend() = 0; + virtual Position getBoxPosition(unsigned int slotIndex) const { if (slotIndex < (sizeof(fallBackBoxesPosition) diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index 8898db55..ac3e0f5b 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -24,8 +24,6 @@ #include "equipment.h" #include "inventory.h" #include "item.h" -#include "itemshortcut.h" -#include "localplayer.h" #include "log.h" #include "playerinfo.h" @@ -37,8 +35,6 @@ #include "net/manaserv/messageout.h" #include "net/manaserv/manaserv_protocol.h" -#include "resources/iteminfo.h" - #include "utils/stringutils.h" #define EQUIP_FILE "equip.xml" @@ -279,20 +275,20 @@ void EquipBackend::readBoxNode(xmlNodePtr slotNode) bool EquipBackend::isWeaponSlot(int slotTypeId) const { - for (const auto &slot : mSlots) + for (const auto &[_, slot] : mSlots) { - if (slot.second.slotTypeId == (unsigned)slotTypeId) - return slot.second.weaponSlot; + if (slot.slotTypeId == (unsigned)slotTypeId) + return slot.weaponSlot; } return false; } bool EquipBackend::isAmmoSlot(int slotTypeId) const { - for (const auto &slot : mSlots) + for (const auto &[_, slot] : mSlots) { - if (slot.second.slotTypeId == (unsigned)slotTypeId) - return slot.second.ammoSlot; + if (slot.slotTypeId == (unsigned)slotTypeId) + return slot.ammoSlot; } return false; } @@ -304,7 +300,7 @@ Position EquipBackend::getBoxPosition(unsigned int slotIndex) const return Position(0, 0); } -const std::string& EquipBackend::getBoxBackground(unsigned int slotIndex) const +const std::string &EquipBackend::getBoxBackground(unsigned int slotIndex) const { if (slotIndex < mBoxesBackgroundFile.size()) return mBoxesBackgroundFile.at(slotIndex); @@ -332,7 +328,6 @@ void InventoryHandler::handleMessage(MessageIn &msg) case GPMSG_INVENTORY_FULL: { PlayerInfo::clearInventory(); - PlayerInfo::getEquipment()->setBackend(&mEquipBackend); int count = msg.readInt16(); while (count--) { @@ -374,9 +369,6 @@ void InventoryHandler::handleMessage(MessageIn &msg) it->second.mAmountUsed, it->first); } - // The backend is ready, we can setup the equipment window. - if (equipmentWindow) - equipmentWindow->loadEquipBoxes(); } break; diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h index 452ccf3e..a0e978cd 100644 --- a/src/net/manaserv/inventoryhandler.h +++ b/src/net/manaserv/inventoryhandler.h @@ -22,7 +22,6 @@ #ifndef NET_MANASERV_INVENTORYHANDLER_H #define NET_MANASERV_INVENTORYHANDLER_H -#include "equipment.h" #include "eventlistener.h" #include "net/inventoryhandler.h" @@ -63,7 +62,7 @@ class EquipBackend final : public Equipment::Backend, public EventListener Position getBoxPosition(unsigned int slotIndex) const; - const std::string& getBoxBackground(unsigned int slotIndex) const; + const std::string &getBoxBackground(unsigned int slotIndex) const; private: void readEquipFile() override; @@ -133,6 +132,9 @@ class InventoryHandler final : public MessageHandler, Net::InventoryHandler, unsigned int getVisibleSlotsNumber() const override { return mEquipBackend.getVisibleSlotsNumber(); } + Equipment::Backend *getEquipmentBackend() override + { return &mEquipBackend; } + Position getBoxPosition(unsigned int slotIndex) const override { return mEquipBackend.getBoxPosition(slotIndex); } diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 0bc1f9c0..0fd4e933 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -30,8 +30,6 @@ #include "localplayer.h" #include "log.h" -#include "gui/equipmentwindow.h" - #include "net/tmwa/messagein.h" #include "net/tmwa/messageout.h" #include "net/tmwa/protocol.h" @@ -104,9 +102,6 @@ InventoryHandler::InventoryHandler() handledMessages = _messages; inventoryHandler = this; - mStorage = nullptr; - mStorageWindow = nullptr; - listen(Event::ItemChannel); } @@ -127,7 +122,6 @@ void InventoryHandler::handleMessage(MessageIn &msg) int index, amount, itemId, equipType; int identified, cards[4], itemType; Inventory *inventory = PlayerInfo::getInventory(); - PlayerInfo::getEquipment()->setBackend(&mEquips); switch (msg.getId()) { @@ -172,8 +166,8 @@ void InventoryHandler::handleMessage(MessageIn &msg) if (msg.getId() == SMSG_PLAYER_INVENTORY) inventory->setItem(index, itemId, amount); else - mInventoryItems.push_back(InventoryItem(index, itemId, - amount, false)); + mInventoryItems.push_back( + InventoryItem { index, itemId, amount, false }); } break; @@ -203,8 +197,8 @@ void InventoryHandler::handleMessage(MessageIn &msg) cards[0], cards[1], cards[2], cards[3]); } - mInventoryItems.push_back(InventoryItem(index, itemId, amount, - false)); + mInventoryItems.push_back( + InventoryItem { index, itemId, amount, false }); } break; @@ -309,10 +303,8 @@ void InventoryHandler::handleMessage(MessageIn &msg) if (!mStorage) mStorage = new Inventory(Inventory::STORAGE, size); - auto it = mInventoryItems.begin(); - auto it_end = mInventoryItems.end(); - for (; it != it_end; it++) - mStorage->setItem((*it).slot, (*it).id, (*it).quantity); + for (auto &item : mInventoryItems) + mStorage->setItem(item.slot, item.id, item.quantity); mInventoryItems.clear(); if (!mStorageWindow) @@ -385,10 +377,6 @@ void InventoryHandler::handleMessage(MessageIn &msg) { mEquips.setEquipment(getSlot(equipType), index); } - - // Load the equipment boxes - if (equipmentWindow) - equipmentWindow->loadEquipBoxes(); } break; diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h index 2df5a699..51a0fe51 100644 --- a/src/net/tmwa/inventoryhandler.h +++ b/src/net/tmwa/inventoryhandler.h @@ -22,7 +22,6 @@ #ifndef NET_TA_INVENTORYHANDLER_H #define NET_TA_INVENTORYHANDLER_H -#include "equipment.h" #include "eventlistener.h" #include "inventory.h" #include "log.h" @@ -128,8 +127,7 @@ class EquipBackend final : public Equipment::Backend void triggerUnequip(int slotIndex) const override { - Item *item = getEquipment(slotIndex); - if (item) + if (Item *item = getEquipment(slotIndex)) item->doEvent(Event::DoUnequip); } @@ -143,21 +141,12 @@ class EquipBackend final : public Equipment::Backend /** * Used to cache storage data until we get size data for it. */ -class InventoryItem +struct InventoryItem { - public: - int slot; - int id; - int quantity; - bool equip; - - InventoryItem(int slot, int id, int quantity, bool equip) - { - this->slot = slot; - this->id = id; - this->quantity = quantity; - this->equip = equip; - } + int slot; + int id; + int quantity; + bool equip; }; class InventoryHandler final : public MessageHandler, public Net::InventoryHandler, @@ -184,20 +173,25 @@ class InventoryHandler final : public MessageHandler, public Net::InventoryHandl // Note the slot type id is equal to the slot Index for tA. bool isWeaponSlot(unsigned int slotTypeId) const override { - return (slotTypeId == EQUIP_FIGHT1_SLOT - || slotTypeId == EQUIP_FIGHT1_SLOT); + return (slotTypeId == EQUIP_FIGHT1_SLOT || + slotTypeId == EQUIP_FIGHT1_SLOT); } bool isAmmoSlot(unsigned int slotTypeId) const override { - return (slotTypeId == EQUIP_PROJECTILE_SLOT); + return slotTypeId == EQUIP_PROJECTILE_SLOT; + } + + Equipment::Backend *getEquipmentBackend() override + { + return &mEquips; } private: EquipBackend mEquips; - std::list mInventoryItems; - Inventory *mStorage; - InventoryWindow *mStorageWindow; + std::vector mInventoryItems; + Inventory *mStorage = nullptr; + InventoryWindow *mStorageWindow = nullptr; }; } // namespace TmwAthena diff --git a/src/playerinfo.cpp b/src/playerinfo.cpp index 433f4f6b..4d5074ee 100644 --- a/src/playerinfo.cpp +++ b/src/playerinfo.cpp @@ -27,6 +27,9 @@ #include "eventlistener.h" #include "log.h" +#include "net/inventoryhandler.h" +#include "net/net.h" + namespace PlayerInfo { class PlayerLogic; @@ -193,11 +196,6 @@ Item *getEquipment(unsigned int slot) return mEquipment->getEquipment(slot); } -void setEquipmentBackend(Equipment::Backend *backend) -{ - mEquipment->setBackend(backend); -} - int getStorageCount() { return mStorageCount; @@ -351,7 +349,7 @@ public: if (mInventory == nullptr) { mInventory = new Inventory(Inventory::INVENTORY); - mEquipment = new Equipment(); + mEquipment = new Equipment(Net::getInventoryHandler()->getEquipmentBackend()); } } } -- cgit v1.2.3-70-g09d2