From 5cfc73dc5c0093a96c45f604a028ecca21a01af8 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 4 Nov 2015 02:03:03 +0300 Subject: Allow sell to npc many items at one time (hercules). --- src/gui/widgets/selldialog.cpp | 38 +++++++++++++++++++++----- src/gui/widgets/selldialog.h | 5 +++- src/gui/windows/buyingstoreselldialog.cpp | 2 +- src/gui/windows/eggselectiondialog.cpp | 2 +- src/gui/windows/insertcarddialog.cpp | 2 +- src/gui/windows/npcselldialog.cpp | 44 ++++++++++++++++++++++++++++--- src/gui/windows/npcselldialog.h | 4 +++ src/gui/windows/shopselldialog.cpp | 2 +- src/net/eathena/npchandler.cpp | 33 ++++++++++++++++++++++- src/net/eathena/npchandler.h | 2 ++ src/net/npchandler.h | 2 ++ src/net/tmwa/npchandler.cpp | 4 +++ src/net/tmwa/npchandler.h | 2 ++ 13 files changed, 126 insertions(+), 16 deletions(-) diff --git a/src/gui/widgets/selldialog.cpp b/src/gui/widgets/selldialog.cpp index 827d1c3ea..3ad8e5e7e 100644 --- a/src/gui/widgets/selldialog.cpp +++ b/src/gui/widgets/selldialog.cpp @@ -47,13 +47,15 @@ SellDialog::DialogList SellDialog::instances; -SellDialog::SellDialog(const bool isSell) : +SellDialog::SellDialog(const bool isSell, + const bool advanced) : // TRANSLATORS: sell dialog name Window(_("Sell"), Modal_false, nullptr, "sell.xml"), ActionListener(), SelectionListener(), mSellButton(nullptr), mQuitButton(nullptr), + mConfirmButton(nullptr), mAddMaxButton(nullptr), mIncreaseButton(nullptr), mDecreaseButton(nullptr), @@ -66,7 +68,8 @@ SellDialog::SellDialog(const bool isSell) : mPlayerMoney(0), mMaxItems(0), mAmountItems(0), - mIsSell(isSell) + mIsSell(isSell), + mAdvanced(advanced) { } @@ -86,6 +89,9 @@ void SellDialog::postInit() // Create a ShopItems instance, that is aware of duplicate entries. mShopItems = new ShopItems(true); + if (mAdvanced) + mShopItems->setMergeDuplicates(false); + mShopItemList = CREATEWIDGETR(ShopListBox, this, mShopItems, @@ -95,8 +101,11 @@ void SellDialog::postInit() getOptionBool("showbackground"), "sell_background.xml"); mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); - // TRANSLATORS: sell dialog button - mSellButton = new Button(this, _("Sell"), "presell", this); + mSellButton = new Button(this, + // TRANSLATORS: sell dialog button + mAdvanced ? _("Add") : _("Sell"), + "presell", + this); // TRANSLATORS: sell dialog button mQuitButton = new Button(this, _("Quit"), "quit", this); @@ -129,6 +138,12 @@ void SellDialog::postInit() // TRANSLATORS: sell dialog label mMoneyLabel = new Label(this, strprintf(_("Price: %s / Total: %s"), "", "")); + if (mAdvanced) + { + // TRANSLATORS: sell dialog button + mConfirmButton = new Button(this, _("Sell"), "confirm", this); + mConfirmButton->setEnabled(false); + } mDecreaseButton->adjustSize(); mDecreaseButton->setWidth(mIncreaseButton->getWidth()); @@ -145,7 +160,15 @@ void SellDialog::postInit() placer(5, 5, mQuantityLabel, 2); placer(7, 5, mAddMaxButton); placer(0, 6, mMoneyLabel, 8); - placer(6, 7, mSellButton); + if (mAdvanced) + { + placer(5, 7, mSellButton); + placer(6, 7, mConfirmButton); + } + else + { + placer(6, 7, mSellButton); + } placer(7, 7, mQuitButton); } else @@ -252,7 +275,10 @@ void SellDialog::action(const ActionEvent &event) mSlider->setValue(mAmountItems); updateButtonsAndLabels(); } - else if (eventId == "presell" || eventId == "sell" || eventId == "yes") + else if (eventId == "presell" || + eventId == "sell" || + eventId == "yes" || + eventId == "confirm") { sellAction(event); } diff --git a/src/gui/widgets/selldialog.h b/src/gui/widgets/selldialog.h index b5e91f67d..92008df38 100644 --- a/src/gui/widgets/selldialog.h +++ b/src/gui/widgets/selldialog.h @@ -51,7 +51,8 @@ class SellDialog notfinal : public Window, /** * Constructor. */ - explicit SellDialog(const bool isSell); + SellDialog(const bool isSell, + const bool advanced); A_DELETE_COPY(SellDialog) @@ -127,6 +128,7 @@ class SellDialog notfinal : public Window, Button *mSellButton A_NONNULLPOINTER; Button *mQuitButton A_NONNULLPOINTER; + Button *mConfirmButton A_NONNULLPOINTER; Button *mAddMaxButton; Button *mIncreaseButton; Button *mDecreaseButton; @@ -142,6 +144,7 @@ class SellDialog notfinal : public Window, int mAmountItems; bool mIsSell; + bool mAdvanced; }; #endif // GUI_WIDGETS_SELLDIALOG_H diff --git a/src/gui/windows/buyingstoreselldialog.cpp b/src/gui/windows/buyingstoreselldialog.cpp index 9de82994d..af3d9d8ff 100644 --- a/src/gui/windows/buyingstoreselldialog.cpp +++ b/src/gui/windows/buyingstoreselldialog.cpp @@ -38,7 +38,7 @@ BuyingStoreSellDialog::BuyingStoreSellDialog(const BeingId accountId, const int storeId) : - SellDialog(true), + SellDialog(true, false), mAccountId(accountId), mStoreId(storeId) { diff --git a/src/gui/windows/eggselectiondialog.cpp b/src/gui/windows/eggselectiondialog.cpp index 2b5f088be..266e3519b 100644 --- a/src/gui/windows/eggselectiondialog.cpp +++ b/src/gui/windows/eggselectiondialog.cpp @@ -36,7 +36,7 @@ #include "debug.h" EggSelectionDialog::EggSelectionDialog() : - SellDialog(false) + SellDialog(false, false) { // TRANSLATORS: egg selection dialog name setWindowName(_("Select egg")); diff --git a/src/gui/windows/insertcarddialog.cpp b/src/gui/windows/insertcarddialog.cpp index 570f87666..8620b06f7 100644 --- a/src/gui/windows/insertcarddialog.cpp +++ b/src/gui/windows/insertcarddialog.cpp @@ -38,7 +38,7 @@ InsertCardDialog::InsertCardDialog(const int itemIndex, const Item *const item) : - SellDialog(false), + SellDialog(false, false), mItemIndex(itemIndex) { // TRANSLATORS: insert card dialog name diff --git a/src/gui/windows/npcselldialog.cpp b/src/gui/windows/npcselldialog.cpp index 2645f4798..ab9ae47d0 100644 --- a/src/gui/windows/npcselldialog.cpp +++ b/src/gui/windows/npcselldialog.cpp @@ -28,12 +28,14 @@ #include "gui/models/shopitems.h" +#include "gui/widgets/button.h" #include "gui/widgets/createwidget.h" #include "gui/widgets/shoplistbox.h" #include "gui/widgets/slider.h" #include "net/buysellhandler.h" #include "net/npchandler.h" +#include "net/serverfeatures.h" #include "resources/iteminfo.h" @@ -43,23 +45,25 @@ #include "debug.h" NpcSellDialog::NpcSellDialog(const BeingId npcId) : - SellDialog(true), + SellDialog(true, + serverFeatures ? serverFeatures->haveAdvancedBuySell() : false), mNpcId(npcId) { } void NpcSellDialog::sellAction(const ActionEvent &event) { - if (mAmountItems <= 0 || mAmountItems > mMaxItems) - return; - const std::string &eventId = event.getId(); const int selectedItem = mShopItemList->getSelected(); ShopItem *const item = mShopItems->at(selectedItem); if (!item || PlayerInfo::isItemProtected(item->getId())) return; + if (eventId == "presell") { + if (mAmountItems <= 0 || mAmountItems > mMaxItems) + return; + const ItemInfo &info = ItemDB::get(item->getId()); if (info.isProtected()) { @@ -76,6 +80,38 @@ void NpcSellDialog::sellAction(const ActionEvent &event) return; } } + + if (mAdvanced) + sellManyItems(event.getId()); + else + sellOneItem(); +} + +void NpcSellDialog::sellManyItems(const std::string &eventId) +{ + if (eventId == "confirm") + { + npcHandler->sellItems(mShopItems->allItems()); + close(); + } + else + { + const int selectedItem = mShopItemList->getSelected(); + ShopItem *const item = mShopItems->at(selectedItem); + item->increaseUsedQuantity(mAmountItems); + item->update(); + if (mConfirmButton) + mConfirmButton->setEnabled(true); + } +} + +void NpcSellDialog::sellOneItem() +{ + if (mAmountItems <= 0 || mAmountItems > mMaxItems) + return; + + const int selectedItem = mShopItemList->getSelected(); + ShopItem *const item = mShopItems->at(selectedItem); // Attempt sell mPlayerMoney += mAmountItems * mShopItems->at(selectedItem)->getPrice(); mMaxItems -= mAmountItems; diff --git a/src/gui/windows/npcselldialog.h b/src/gui/windows/npcselldialog.h index af611f8f1..e50ec3fab 100644 --- a/src/gui/windows/npcselldialog.h +++ b/src/gui/windows/npcselldialog.h @@ -49,6 +49,10 @@ class NpcSellDialog final : public SellDialog protected: void sellAction(const ActionEvent &event) override final; + void sellOneItem(); + + void sellManyItems(const std::string &eventId); + BeingId mNpcId; }; diff --git a/src/gui/windows/shopselldialog.cpp b/src/gui/windows/shopselldialog.cpp index d4683eedf..081ffea7f 100644 --- a/src/gui/windows/shopselldialog.cpp +++ b/src/gui/windows/shopselldialog.cpp @@ -35,7 +35,7 @@ #include "debug.h" ShopSellDialog::ShopSellDialog(const std::string &nick) : - SellDialog(true), + SellDialog(true, false), mNick(nick) { } diff --git a/src/net/eathena/npchandler.cpp b/src/net/eathena/npchandler.cpp index dc01d512c..9b09d8799 100644 --- a/src/net/eathena/npchandler.cpp +++ b/src/net/eathena/npchandler.cpp @@ -187,10 +187,41 @@ void NpcHandler::sellItem(const BeingId beingId A_UNUSED, createOutPacket(CMSG_NPC_SELL_REQUEST); outMsg.writeInt16(8, "len"); outMsg.writeInt16(static_cast(itemId + INVENTORY_OFFSET), - "item id"); + "item index"); outMsg.writeInt16(static_cast(amount), "amount"); } +void NpcHandler::sellItems(std::vector &items) const +{ + const int pairSize = 4; + int cnt = 0; + + FOR_EACH (std::vector::iterator, it, items) + { + ShopItem *const item = *it; + const int usedQuantity = item->getUsedQuantity(); + if (!usedQuantity) + continue; + cnt ++; + } + + createOutPacket(CMSG_NPC_SELL_REQUEST); + outMsg.writeInt16(static_cast(4 + pairSize * cnt), "len"); + FOR_EACH (std::vector::iterator, it, items) + { + ShopItem *const item = *it; + const int usedQuantity = item->getUsedQuantity(); + if (!usedQuantity) + continue; + item->increaseUsedQuantity(-usedQuantity); + item->update(); + outMsg.writeInt16(static_cast( + item->getCurrentInvIndex() + INVENTORY_OFFSET), + "item index"); + outMsg.writeInt16(static_cast(usedQuantity), "amount"); + } +} + void NpcHandler::completeProgressBar() const { createOutPacket(CMSG_NPC_COMPLETE_PROGRESS_BAR); diff --git a/src/net/eathena/npchandler.h b/src/net/eathena/npchandler.h index 608c7d775..34855c802 100644 --- a/src/net/eathena/npchandler.h +++ b/src/net/eathena/npchandler.h @@ -65,6 +65,8 @@ class NpcHandler final : public Ea::NpcHandler const int itemId, const int amount) const override final; + void sellItems(std::vector &items) const override final; + void completeProgressBar() const override final; void produceMix(const int nameId, diff --git a/src/net/npchandler.h b/src/net/npchandler.h index cb7a088f1..5e5a674e5 100644 --- a/src/net/npchandler.h +++ b/src/net/npchandler.h @@ -82,6 +82,8 @@ class NpcHandler notfinal const int itemId, const int amount) const = 0; + virtual void sellItems(std::vector &items) const = 0; + virtual void completeProgressBar() const = 0; virtual void produceMix(const int nameId, diff --git a/src/net/tmwa/npchandler.cpp b/src/net/tmwa/npchandler.cpp index 57ad5850f..71b5ce1d2 100644 --- a/src/net/tmwa/npchandler.cpp +++ b/src/net/tmwa/npchandler.cpp @@ -145,6 +145,10 @@ void NpcHandler::sellItem(const BeingId beingId A_UNUSED, outMsg.writeInt16(static_cast(amount), "amount"); } +void NpcHandler::sellItems(std::vector &items A_UNUSED) const +{ +} + void NpcHandler::completeProgressBar() const { } diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h index 6eed8e81f..5275feeb4 100644 --- a/src/net/tmwa/npchandler.h +++ b/src/net/tmwa/npchandler.h @@ -65,6 +65,8 @@ class NpcHandler final : public Ea::NpcHandler const int itemId, const int amount) const override final; + void sellItems(std::vector &items) const override final; + void completeProgressBar() const override final; BeingId getNpc(Net::MessageIn &msg, -- cgit v1.2.3-70-g09d2